Description
Tool PGXLS is SQL schema with stored procedures for creating files (bytea type) in Excel format (.xlsx). Implemented dependence format on data type, conversion SQL query into sheet with autoformat and more (for more details, see Important qualities)
Usage method
A PL/pgSQL function is created that does:
1. Defines a variable of type pgxls.xls
2. Sets document cells via stored procedure calls
3. Builds file from variable and returns it
There is also a function that builds file by SQL query
Basic procedures
| pgxls.create | — | create document |
| pgxls.add_row | — | add row |
| pgxls.put_cell | — | fill cell: set value and format |
| pgxls.get_file | — | build and get file |
| pgxls.get_file_by_query | — | create file by SQL query (wrapper) |
| pgxls.save_file_by_query | — | save file by SQL query on server (call as superuser) |
More details on page Documentation
Get and save files in SQL manager
-- 1. Create and get file (bytea) by SQL query select pgxls.get_file_by_query('select * from pg_tables'); -- 2. Save Excel file on server by SQL query call pgxls.save_file_by_query('/tmp/top_relations_by_size.xlsx', 'select oid,relname,pg_relation_size(oid) from pg_class order by 3 desc limit 10'); -- 3. Create function that returns file (bytea) create or replace function excel_top_relations_by_size() returns bytea language plpgsql as $$ declare rec record; xls pgxls.xls; begin -- Create document, specify widths and captions of columns in parameters xls := pgxls.create(array[10,80,15], array['oid','Name','Size, bytes']); -- Select data in loop for rec in select oid,relname,pg_relation_size(oid) size from pg_class order by 3 desc limit 10 loop -- Add row call pgxls.add_row(xls); -- Set data from query into cells call pgxls.put_cell(xls, rec.oid); call pgxls.put_cell(xls, rec.relname); call pgxls.put_cell(xls, rec.size); end loop; -- Returns file(bytea) return pgxls.get_file(xls); end $$; -- Get file select excel_top_relations_by_size();
Save files on command line
The psql command line utility returns bytea in hex format, so the reverse conversion is required.
When using programming languages (such as Java, JavaScript, Python, etc.), conversion from hex is not required
Linux
#!/bin/bash
# Examples of saving files in Linux command line
# To convert hex to binary, use xxd utility
# When running psql on non-server, install postgres client and specify connection parameters via URI:
# psql postgres://[USERNAME]:[PASSWORD]@[SERVER]/[DATABASE] -Aqt -c "...
# 1. Create file by SQL query
psql -Aqt -c "select pgxls.get_file_by_query('select * from pg_tables')" | xxd -r -ps > pg_tables.xlsx
# 2. Save Excel file on server by SQL query
psql -c "call pgxls.save_file_by_query('/tmp/top_relations_by_size.xlsx', 'select oid,relname,pg_relation_size(oid) from pg_class order by 3 desc limit 10')"
# 3. Save file from SQL function
psql -Aqt -c "select excel_top_relations_by_size()" | xxd -r -ps > top_relations_by_size.xlsx
Windows
rem Examples of saving files in Windows command line
rem To convert hex to binary, use certutil utility and temporary file
rem When running psql on non-server, install postgres client and specify connection parameters via URI:
rem psql postgres://[USERNAME]:[PASSWORD]@[SERVER]/[DATABASE] -Aqt -c "...
rem 1. Create file by SQL query
psql -Aqt -c "select pgxls.get_file_by_query('select * from pg_tables')" -o hex.tmp
certutil -decodehex -f hex.tmp pg_tables.xlsx
rem 2. Save Excel file on server by SQL query
psql -c "call pgxls.save_file_by_query('/tmp/top_relations_by_size.xlsx', 'select oid,relname,pg_relation_size(oid) from pg_class order by 3 desc limit 10')"
rem 3. Save file from SQL function
psql -Aqt -c "select excel_top_relations_by_size()" -o hex.tmp
certutil -decodehex -f hex.tmp top_relations_by_size.xlsx
Large files
- data is inserted row by row into a temporary table, which does not require memory Separate function is implemented to get large fileAuto-format
- for each column, a format is configured depending on data typeSQL queries
- it is possible to add sheet with the results of SQL queryStyles
- for columns and cells, support format, font, border, fill and alignmentPrint setup
- for each sheet, the paper format and orientation, title, repeating rows (table header) and margins are specifiedParallelism
- it is possible to create several files in parallel in one session
PGXLS supports AI-driven report code generation.
Among publicly available neural networks (no registration or VPN required), Qwen generates complex, high-quality code, while Google AI can be used for simpler reports. General-purpose AI systems (Google AI, Alisa AI, etc.) tend to provide quick answers with assumptions; therefore, it is essential to explicitly specify the role, strict mode, and willingness to wait in the prompt.
Rules for writing AI prompts
- Explicitly provide a link to the documentation via https://pgxls.org/documentation/ or download the file pgxls-documentation.html
- Describe the table structure (e.g., using DDL commands) or explicitly list the fields in the SQL query, with the exception of system views (the AI already knows their structure)
It is impossible to provide a link to the documentation on GitHub: with the blob type, the HTML page is returned inside the UI, while with the raw type, it is returned as plain text (content-type: text/plain).
It is recommended to use interactive examples as templates for writing prompts — you can edit them and then ask the AI.
If Google AI fails to process the prompt via URL ("Cannot provide an answer"), you should copy and paste it using the clipboard.
Example prompt for creating a report on system views
Example prompt with formatting and complex logic
Example prompt for exporting large tables with a parameter
- Large projects - processing binary data in SQL is inefficient: reports take a long time to generate, and CPU consumption spikes significantly. As workloads grow, it is recommended to install the commercial PGXLS Highload Plugin, which shifts computations to a lower level (C language) and allows report generation on a replica
Compression not supported
- data copied, identical lines duplicatedRow height not optimal
- row height calculated with assumptions and may be not optimal
For high-load systems, a commercial binary modification of PGXLS has been developed. Its core functions are rewritten in C. For example, calculating a checksum over a byte array (bytea) is executed in C up to 800 times faster than in SQL.
PGXLS Highload Plugin is part of the PGSuite Highload Pack.
Advantages
- Execution on replicas — eliminating temporary tables allows you to generate reports on a standby replica
- Performance boost — actual report generation time (excluding data query) is reduced by 3–5 times
Architecture and Implementation
Intermediate temporary data handling in PGXLS is built on loose coupling principles, making the replacement of standard mechanisms completely transparent.
When a report is generated, a single temporary table is created to emulate a ZIP file:
create temp table pgxls_temp_zip_file(xls_id int, name varchar(32), part int, subpart bigserial, body bytea not null);All interaction with this table is fully localized within low-level stored procedures in the pgxls schema prefixed with _temp_zip: _temp_zip_create, _temp_zip_file_append, and so on.
When the commercial highload plugin is installed, these PL/pgSQL procedures are replaced by fast binary counterparts written in C, which redirect data streams into local files instead of the DBMS.
Engineering Manifesto of the Commercial Pack
- Full functionality in open source — the paid pack is created solely for performance optimization under extreme loads: it improves CPU utilization, shifts heavy tasks to a replica or a separate process, and reduces disk subsystem load (IOPS)
- Forward and backward compatibility — highload plugins do not alter function signatures and preserve the original application API. You can opt out of the plugins at any moment, seamlessly rolling back to the basic lightweight version
- No artificial limits — the basic version is free and has no limits on data volume, number of sessions, or similar constraints
- Task-focused purchasing — each plugin can be acquired separately and strictly within the scope of technical support, following workload and general task analysis
- Air-gapped security — complete autonomy: no cloud computing, no network license checks, and no external neural network models
- Giving up lightweight nature — the binary plugin requires high engineering qualifications, which is fully justified by the scale of the tasks being solved
- Source code delivery — the plugin's source code is provided for an additional fee for customization under a limited license
- Independent implementation — a detailed description of the architecture allows you to develop the plugin yourself
Review posted on YouTube