Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set schema with node-postgres

I'm trying to query against a schema called DOCUMENT in my postgres db using node-postgres.

I can't seem to get a query to run against the specified schema.

This query runs fine directly against postgres using psql

SELECT * FROM "DOCUMENT".document_metadata m 
LEFT OUTER JOIN "DOCUMENT".document_attributes a 
ON a.document_id = m.id

This code produces the error below

const query = `SELECT * FROM "DOCUMENT".document_metadata m 
               LEFT OUTER JOIN "DOCUMENT".document_attributes a 
               ON a.document_id = m.id`
const metadata = await db.query(query)

Error

error: relation "DOCUMENT.document_metadata" does not exist
    at Connection.parseE (/usr/src/app/node_modules/pg/lib/connection.js:602:11)
    at Connection.parseMessage (/usr/src/app/node_modules/pg/lib/connection.js:399:19)
    at Socket.<anonymous> (/usr/src/app/node_modules/pg/lib/connection.js:121:22)
    at Socket.emit (events.js:189:13)
    at addChunk (_stream_readable.js:284:12)
    at readableAddChunk (_stream_readable.js:265:11)
    at Socket.Readable.push (_stream_readable.js:220:10)
    at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)

I've also tried this

const query = `SET search_path TO 'DOCUMENT';
               SELECT * FROM document_metadata m 
               LEFT OUTER JOIN document_attributes a 
               ON a.document_id = m.id;`

const metadata = await db.query(query)

which produces the error

error: relation "document_metadata" does not exist
    at Connection.parseE (/usr/src/app/node_modules/pg/lib/connection.js:602:11)
    at Connection.parseMessage (/usr/src/app/node_modules/pg/lib/connection.js:399:19)
    at Socket.<anonymous> (/usr/src/app/node_modules/pg/lib/connection.js:121:22)
    at Socket.emit (events.js:189:13)
    at addChunk (_stream_readable.js:284:12)
    at readableAddChunk (_stream_readable.js:265:11)
    at Socket.Readable.push (_stream_readable.js:220:10)
    at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)

Update When I run these same queries directly in psql I see like 10 rows with table names. When I run this through my node code I see no rows:

const metadata4 = await db.query('SHOW search_path;')
console.log('search_path after setting = ', metadata4.rows) // prints [ { search_path: '"DOCUMENT"' } ]

const tables = await db.query(`SELECT * FROM information_schema.tables where table_schema = 'DOCUMENT';`)
console.log('tables = ', tables.rows) // prints []
like image 598
Catfish Avatar asked May 22 '19 17:05

Catfish


People also ask

How do I change the default schema in PostgreSQL?

SET search_path TO inventory, public; Now inventory is a default schema and you don't need to mention it explicitly to access it. You can change the name or the ownership of a schema by using ALTER SCHEMA. DROP SCHEMA [IF EXISTS] schema_name [CASCADE | RESTRICT];

How do I create a PostgreSQL schema?

PostgreSQL has a CREATE SCHEMA statement that is used to create a new schema in a database. Syntax: CREATE SCHEMA [IF NOT EXISTS] schema_name; Let's analyze the above syntax: First, specify the name of the schema after the CREATE SCHEMA keywords.

How do I connect to a different schema in PostgreSQL?

How to Use Schema With PostgreSQL. To access an object of a database schema, we must specify the schema's name before the name of a given database object that we want to use. For example, to query table product within schema store, we need to use the qualified name of the table: SELECT * FROM store.


3 Answers

just execute in a separated line:

db.query("SET search_path TO 'DOCUMENT';")

DOCUMENT is the name of your schema, then execute the normal query:

const query = `SELECT * FROM document_metadata m 
               LEFT OUTER JOIN document_attributes a 
               ON a.document_id = m.id;`

db.query(query)
like image 61
stackdave Avatar answered Oct 16 '22 18:10

stackdave


Maybe the uppercase is the problem. Did you tried with a lowercase schema name? Or add quotation marks around the table names:

const query = 'SELECT * FROM "DOCUMENT"."document_metadata" m 
               LEFT OUTER JOIN "DOCUMENT"."document_attributes" a 
               ON a.document_id = m.id'

Define the schema in an environment variable to the Client/Pool

Anyway, if you would like to define the schema in node js and no need to switching between different schemas, then this solution is a good choice. The default schema can come from environment variable.

const Pool = require('pg').Pool
const Client = require('pg').Client

class EnhancedClient extends Client {
  getStartupConf() {
    if (process.env.PG_OPTIONS) {
      try {
        const options = JSON.parse(process.env.PG_OPTIONS);
        return {
          ...super.getStartupConf(),
          ...options,
        };
      } catch (e) {
        console.error(e);
        // Coalesce to super.getStartupConf() on parse error
      }
    }

    return super.getStartupConf();
  }
}

const pool = new Pool({
  Client: EnhancedClient,
  user: 'postgres',
  host: 'localhost',
  database: 'postgres',
  password: 'postgres',
  port: 5432
})

In this example, PG_OPTIONS is stringified JSON, e.g. provided via the command line, a PM2 ecosystem file, etc.

For example: PG_OPTIONS='{"search_path":"DOCUMENT"}' node app.js

I start from windows command prompt (sorry for that :) )

SET PG_OPTIONS={"search_path":"DOCUMENT"}
node app.js
like image 38
Attila Molnar Avatar answered Oct 16 '22 20:10

Attila Molnar


if someone still interested in, you can do that using connection string and passing options, not just schema.

postgres://postgres:postgres@localhost:5432/my_db?options=-c search_path=my_schema
like image 1
Drilla Avatar answered Oct 16 '22 19:10

Drilla