{"id":31271688,"url":"https://github.com/PostgREST/pg_csv","last_synced_at":"2025-09-23T20:05:10.435Z","repository":{"id":307761619,"uuid":"1030628307","full_name":"PostgREST/pg_csv","owner":"PostgREST","description":"Flexible CSV processing for Postgres","archived":false,"fork":false,"pushed_at":"2025-09-09T17:50:07.000Z","size":31,"stargazers_count":24,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-09T21:04:55.155Z","etag":null,"topics":["csv","postgres","postgresql","postgresql-extension"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PostgREST.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-02T01:52:09.000Z","updated_at":"2025-09-09T17:50:11.000Z","dependencies_parsed_at":"2025-08-02T04:42:57.229Z","dependency_job_id":"f7917c2c-1895-4954-be14-713bcaf60260","html_url":"https://github.com/PostgREST/pg_csv","commit_stats":null,"previous_names":["postgrest/pg_csv"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/PostgREST/pg_csv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PostgREST%2Fpg_csv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PostgREST%2Fpg_csv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PostgREST%2Fpg_csv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PostgREST%2Fpg_csv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PostgREST","download_url":"https://codeload.github.com/PostgREST/pg_csv/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PostgREST%2Fpg_csv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276639739,"owners_count":25678179,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-23T02:00:09.130Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csv","postgres","postgresql","postgresql-extension"],"created_at":"2025-09-23T20:01:36.628Z","updated_at":"2025-09-23T20:05:10.418Z","avatar_url":"https://github.com/PostgREST.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# pg_csv\n\n![PostgreSQL version](https://img.shields.io/badge/postgresql-12+-blue.svg)\n[![Coverage Status](https://coveralls.io/repos/github/PostgREST/pg_csv/badge.svg)](https://coveralls.io/github/PostgREST/pg_csv)\n[![Tests](https://github.com/PostgREST/pg_csv/actions/workflows/ci.yaml/badge.svg)](https://github.com/PostgREST/pg_csv/actions)\n\nPostgres has CSV support on the [COPY](https://www.postgresql.org/docs/current/sql-copy.html) command, but `COPY` has problems:\n\n- It uses a special protocol, so it doesn't work with other standard features like [prepared statements](https://www.postgresql.org/docs/current/sql-prepare.html), [pipeline mode](https://www.postgresql.org/docs/current/libpq-pipeline-mode.html#LIBPQ-PIPELINE-USING) or [pgbench](https://www.postgresql.org/docs/current/pgbench.html).\n- Is not composable. You can't use COPY inside CTEs, subqueries, view definitions or as function arguments.\n\n`pg_csv` offers flexible CSV processing as a solution.\n\n- Includes a CSV aggregate that composes with SQL expressions.\n- Native C extension, x2 times faster than SQL queries that try to output CSV (see our [CI results](https://github.com/PostgREST/pg_csv/actions/runs/17367727912)).\n- No dependencies except Postgres.\n\n## Installation\n\nPostgreSQL \u003e= 12 is supported. Clone this repo and run:\n\n```bash\nmake \u0026\u0026 make install\n```\n\nTo install the extension:\n\n```psql\ncreate extension pg_csv;\n```\n\n## csv_agg\n\nAggregate that builds a CSV respecting [RFC 4180](https://www.ietf.org/rfc/rfc4180.txt), quoting as required.\n\n```sql\ncreate table projects as\nselect *\nfrom (\n  values\n    (1, 'Death Star OS', 1),\n    (2, 'Windows 95 Rebooted', 1),\n    (3, 'Project \"Comma,Please\"', 2),\n    (4, 'Escape \"\"Plan\"\"', 2),\n    (NULL, 'NULL \u0026 Void', NULL)\n) as _(id, name, client_id);\n```\n\n```sql\nselect csv_agg(x) from projects x;\n            csv_agg\n--------------------------------\n id,name,client_id             +\n 1,Death Star OS,1             +\n 2,Windows 95 Rebooted,1       +\n 3,\"Project \"\"Comma,Please\"\"\",2+\n 4,\"Escape \"\"\"\"Plan\"\"\"\"\",2     +\n ,NULL \u0026 Void,\n(1 row)\n```\n\n### Custom Delimiter\n\nCustom delimiters can be used to produce different formats like pipe-separated values, tab-separated values or semicolon-separated values.\n\n```sql\nselect csv_agg(x, csv_options(delimiter := '|')) from projects x;\n           csv_agg\n-----------------------------\n id|name|client_id          +\n 1|Death Star OS|1          +\n 2|Windows 95 Rebooted|1    +\n 3|Open Source Lightsabers|2+\n 4|Galactic Payroll System|2+\n 7|Bugzilla Revival|3\n(1 row)\n\nselect csv_agg(x, csv_options(delimiter := E'\\t')) from projects x;\n              csv_agg\n-----------------------------------\n id      name    client_id        +\n 1       Death Star OS   1        +\n 2       Windows 95 Rebooted     1+\n 3       Open Source Lightsabers 2+\n 4       Galactic Payroll System 2+\n 7       Bugzilla Revival        3\n(1 row)\n```\n\n\u003e [!NOTE]\n\u003e - Newline, carriage return and double quotes are not supported as delimiters to maintain the integrity of the separated values format.\n\u003e - The delimiter can only be a single char, if a longer string is specified only the first char will be used.\n\u003e - Why use a `csv_options` constructor function instead of extra arguments? Aggregates don't support named arguments in postgres, see a discussion on https://github.com/PostgREST/pg_csv/pull/2#issuecomment-3155740589.\n\n### BOM\n\nYou can include a byte-order mark (BOM) to make the CSV compatible with Excel.\n\n```sql\nselect csv_agg(x, csv_options(bom := true)) from projects x;\n\n      csv_agg\n-------------------\n﻿id,name,client_id+\n 1,Death Star OS,1\n 2,Windows 95 Rebooted,1\n 3,Open Source Lightsabers,2\n 4,Galactic Payroll System,2\n 5,Bugzilla Revival,3\n(1 row)\n```\n\n### Header\n\nYou can omit or include the CSV header.\n\n```sql\nselect csv_agg(x, csv_options(header := false)) from projects x;\n\n           csv_agg\n-----------------------------\n 1,Death Star OS,1          +\n 2,Windows 95 Rebooted,1    +\n 3,Open Source Lightsabers,2+\n 4,Galactic Payroll System,2+\n 7,Bugzilla Revival,3\n(1 row)\n```\n\n### Null string\n\nNULL values are represented by an empty string by default. This can be changed with the `nullstr` option.\n\n```sql\nSELECT csv_agg(x, csv_options(nullstr:='\u003cNULL\u003e')) AS body\nFROM   projects x;\n\n              body\n--------------------------------\n id,name,client_id             +\n 1,Death Star OS,1             +\n 2,Windows 95 Rebooted,1       +\n 3,\"Project \"\"Comma,Please\"\"\",2+\n 4,\"Escape \"\"\"\"Plan\"\"\"\"\",2     +\n \u003cNULL\u003e,NULL \u0026 Void,\u003cNULL\u003e\n(1 row)\n```\n\n## Limitations\n\n- For large bulk exports and imports, `COPY ... CSV` should still be preferred as its faster due to streaming support.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPostgREST%2Fpg_csv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPostgREST%2Fpg_csv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPostgREST%2Fpg_csv/lists"}