PGAdapter supports the node-postgres driver version 8.8.0 and higher.
First start PGAdapter:
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
docker pull gcr.io/cloud-spanner-pg-adapter/pgadapter
docker run \
-d -p 5432:5432 \
-v ${GOOGLE_APPLICATION_CREDENTIALS}:${GOOGLE_APPLICATION_CREDENTIALS}:ro \
-e GOOGLE_APPLICATION_CREDENTIALS \
gcr.io/cloud-spanner-pg-adapter/pgadapter \
-p my-project -i my-instance \
-xThen connect to PGAdapter using TCP like this:
const { Client } = require('pg');
const client = new Client({
host: 'localhost',
port: 5432,
database: 'my-database',
});
await client.connect();
const res = await client.query("select 'Hello world!' as hello");
console.log(res.rows[0].hello);
await client.end();You can also connect to PGAdapter using Unix Domain Sockets if PGAdapter is running on the same host
as the client application, or the /tmp directory in the Docker container has been mapped to a
directory on the local machine:
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
docker pull gcr.io/cloud-spanner-pg-adapter/pgadapter
docker run \
-d -p 5432:5432 \
-v /tmp:/tmp
-v ${GOOGLE_APPLICATION_CREDENTIALS}:${GOOGLE_APPLICATION_CREDENTIALS}:ro \
-e GOOGLE_APPLICATION_CREDENTIALS \
gcr.io/cloud-spanner-pg-adapter/pgadapter \
-p my-project -i my-instance \
-xconst { Client } = require('pg');
const client = new Client({
host: '/tmp',
port: 5432,
database: 'my-database',
});
await client.connect();
const res = await client.query("select 'Hello world!' as hello");
console.log(res.rows[0].hello);
await client.end();This example uses the pre-built Docker image to run PGAdapter. See README for more options for how to run PGAdapter.
node-postgres by default returns int8 / bigint values as strings. This is because Javascript
does not support 64-bit integers. You can override this behavior and instruct node-postgres to
return int8 / bigint values as 32-bit Javascript integers by adding this configuration to your
code:
var types = require('pg').types
// '20' on the following line is the PostgreSQL type code (OID) for `int8`.
types.setTypeParser(20, function(val) {
return parseInt(val, 10)
})See https://github.com/brianc/node-pg-types for more information.
The following will give you the best possible performance when using node-postgres with PGAdapter.
Use Unix Domain Socket connections for the lowest possible latency when PGAdapter and the client application are running on the same host. See https://node-postgres.com/features/connecting for more information on connection options for node-postgres.
Use the batching options that are available as SQL commands in PGAdapter to batch DDL or DML statements. PGAdapter will combine DML and DDL statements that are executed in a batch into a single request on Cloud Spanner. This can significantly reduce the overhead of executing multiple DML or DDL statements.
Example for DML statements:
const sql = "insert into test (id, value) values ($1, $2)";
// This will start a DML batch for this client. All subsequent
// DML statements will be cached locally until RUN BATCH is executed.
await client.query("start batch dml");
await client.query({text: sql, values: [1, 'One']});
await client.query({text: sql, values: [2, 'Two']});
await client.query({text: sql, values: [3, 'Three']});
// This will send the DML statements to Cloud Spanner as one batch.
const res = await client.query("run batch");
console.log(res);Example for DDL statements:
// This will start a DDL batch for this client. All subsequent
// DDL statements will be cached locally until RUN BATCH is executed.
await client.query("start batch ddl");
await client.query("create table my_table1 (key varchar primary key, value varchar)");
await client.query("create table my_table2 (key varchar primary key, value varchar)");
await client.query("create index my_index1 on my_table1 (value)");
// This will send the DDL statements to Cloud Spanner as one batch.
const res = await client.query("run batch");
console.log(res);node-postgresalways uses untyped query parameters encoded as strings. Cloud Spanner requires query parameters to be typed. PGAdapter therefore infers the types of the query parameters the first time it sees a given SQL string by analyzing the SQL statement and caching the result on the connection. This means that the first execution of a SQL statement with query parameters on a connection will be slightly slower than the following executions.