brianc / node-pg-types

Type parsing for node-postgres
268 stars 55 forks source link

array_agg returns array as a string #68

Closed gajus closed 6 years ago

gajus commented 6 years ago
SELECT
  c1.relname "tableName",
  c2.relname "indexName",
  i1.indisunique "indexIsUnique",
  array_agg(a1.attname) "columnNames"
FROM
  pg_class c1,
  pg_class c2,
  pg_index i1,
  pg_attribute a1
WHERE
  c1.oid = i1.indrelid
  AND c2.oid = i1.indexrelid
  AND a1.attrelid = c1.oid
  AND a1.attnum = ANY(i1.indkey)
  AND c1.relkind IN ('r', 'm')
GROUP BY
  c1.relname,
  c2.relname,
  i1.indisunique
ORDER BY
  c1.relname,
  c2.relname

Expecting columnNames to return an array.

Returns {foo, bar} instead of expected array.

I couldn't figure out how to configure setTypeParser to capture this expression.

charmander commented 6 years ago

attname is of type name:

=> \d pg_attribute
              Table "pg_catalog.pg_attribute"
    Column     |   Type    | Collation | Nullable | Default 
---------------+-----------+-----------+----------+---------
 attrelid      | oid       |           | not null | 
 attname       | name      |           | not null | 
⋮

Find the OID for an array of the type as described in the pg-types README:

=> SELECT typname, oid, typarray FROM pg_type WHERE typname = 'name';
 typname | oid | typarray 
---------+-----+----------
 name    |  19 |     1003
(1 row)

Set the parser:

const OID_ARRAY_TEXT = 1009;
const OID_ARRAY_NAME = 1003;

pg.types.setTypeParser(OID_ARRAY_NAME, pg.types.getTypeParser(OID_ARRAY_TEXT));

See also https://github.com/brianc/node-pg-types/issues/56#issuecomment-323223477.

You can just select it as an array of text, too.

SELECT …, array_agg(a1.attname)::text[] "columnNames", …
gajus commented 6 years ago

Thank you for taking time to explain.