UNPKG

loopback-connector-postgresql-redshift

Version:
462 lines (403 loc) 13 kB
Forked from [strongloop/loopback-connector-postgresql 3.3.2](https://github.com/strongloop/loopback-connector-postgresql) added a hack for redshift compatibility in model autodiscovery. # loopback-connector-postgresql [PostgreSQL](https://www.postgresql.org/), is a popular open-source object-relational database. The `loopback-connector-postgresql` module is the PostgreSQL connector for the LoopBack framework. <div class="gh-only">For more information, see the <a href="http://loopback.io/doc/en/lb3/PostgreSQL-connector.html">documentation</a>. <br/><br/> NOTE: The PostgreSQL connector requires PostgreSQL 8.x or 9.x. </div> ## Installation In your application root directory, enter this command to install the connector: ```shell $ npm install loopback-connector-postgresql --save ``` This installs the module from npm and adds it as a dependency to the application's `package.json` file. If you create a PostgreSQL data source using the data source generator as described below, you don't have to do this, since the generator will run `npm install` for you. ## Creating a data source Use the [Data source generator](http://loopback.io/doc/en/lb3/Data-source-generator.html) to add a PostgreSQL data source to your application. The generator will prompt for the database server hostname, port, and other settings required to connect to a PostgreSQL database. It will also run the `npm install` command above for you. The entry in the application's `/server/datasources.json` will look like this: {% include code-caption.html content="/server/datasources.json" %} ```javascript "mydb": { "name": "mydb", "connector": "postgresql" "host": "mydbhost", "port": 5432, "url": "postgres://admin:admin@mydbhost:5432/db1?ssl=false", "database": "db1", "password": "admin", "user": "admin", "ssl": false } ``` Edit `datasources.json` to add other properties that enable you to connect the data source to a PostgreSQL database. ### Connection Pool Settings You can also specify connection pool settings in `datasources.json`. For instance you can specify the minimum and the maximum pool size, and the maximum pool client's idle time before closing the client. Example of `datasource.json`: ``` { "mypostgresdb": { "host": "mydbhost", "port": 5432, "url": "postgres://admin:password1@mydbhost:5432/db1?ssl=false", "database": "db1", "password": "password1", "name": "mypostgresdb", "user": "admin", "connector": "postgresql", "min": 5, "max": 200, "idleTimeoutMillis": 60000, "ssl": false } } ``` Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postgres pooling example](https://github.com/brianc/node-postgres#pooling-example) for more information. ### Properties <table> <thead> <tr> <th>Property</th> <th>Type</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>connector</td> <td>String</td> <td> Connector name, either "loopback-connector-postgresql" or "postgresql" </td> </tr> <tr> <td>database</td> <td>String</td> <td>Database name</td> </tr> <tr> <td>debug</td> <td>Boolean</td> <td>If true, turn on verbose mode to debug database queries and lifecycle.</td> </tr> <tr> <td>host</td> <td>String</td> <td>Database host name</td> </tr> <tr> <td>password</td> <td>String</td> <td>Password to connect to database</td> </tr> <tr> <td>port</td> <td>Number</td> <td>Database TCP port</td> </tr> <tr> <td>url</td> <td>String</td> <td>Use instead of the<code>host</code>,<code>port</code>,<code>user</code>,<code>password</code>, and<code>database</code>properties. For example:'postgres://test:mypassword@localhost:5432/dev'. </td> </tr> <tr> <td>username</td> <td>String</td> <td>Username to connect to database</td> </tr> <tr> <td>min</td> <td>Integer</td> <td>Minimum number of clients in the connection pool</td> </tr> <tr> <td>max</td> <td>Integer</td> <td>Maximum number of clients in the connection pool</td> </tr> <tr> <td>idleTimeoutMillis</td> <td>Integer</td> <td>Maximum time a client in the pool has to stay idle before closing it</td> </tr> <tr> <td>ssl</td> <td>Boolean</td> <td>Whether to try SSL/TLS to connect to server</td> </tr> </tbody> </table> **NOTE**: By default, the 'public' schema is used for all tables. The PostgreSQL connector uses [node-postgres](https://github.com/brianc/node-postgres) as the driver. For more information about configuration parameters, see [node-postgres documentation](https://github.com/brianc/node-postgres/wiki/Client#constructors). ### Connecting to UNIX domain socket A common PostgreSQL configuration is to connect to the UNIX domain socket `/var/run/postgresql/.s.PGSQL.5432` instead of using the TCP/IP port. For example: ```javascript { "postgres": { "host": "/var/run/postgresql/", "port": "5432", "database": "dbname", "username": "dbuser", "password": "dbpassword", "name": "postgres", "debug": true, "connector": "postgresql" } } ``` ## Defining models The model definition consists of the following properties. <table> <thead> <tr> <th>Property</th> <th>Default</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>name</td> <td>Camel-case of the database table name</td> <td>Name of the model.</td> </tr> <tr> <td>options</td> <td>N/A</td> <td>Model level operations and mapping to PostgreSQL schema/table</td> </tr> <tr> <td>properties</td> <td>N/A</td> <td>Property definitions, including mapping to PostgreSQL column</td> </tr> </tbody> </table> For example: {% include code-caption.html content="/common/models/model.json" %} ```javascript { "name": "Inventory", "options": { "idInjection": false, "postgresql": { "schema": "strongloop", "table": "inventory" } }, "properties": { "id": { "type": "String", "required": false, "length": 64, "precision": null, "scale": null, "postgresql": { "columnName": "id", "dataType": "character varying", "dataLength": 64, "dataPrecision": null, "dataScale": null, "nullable": "NO" } }, "productId": { "type": "String", "required": false, "length": 20, "precision": null, "scale": null, "id": 1, "postgresql": { "columnName": "product_id", "dataType": "character varying", "dataLength": 20, "dataPrecision": null, "dataScale": null, "nullable": "YES" } }, "locationId": { "type": "String", "required": false, "length": 20, "precision": null, "scale": null, "id": 1, "postgresql": { "columnName": "location_id", "dataType": "character varying", "dataLength": 20, "dataPrecision": null, "dataScale": null, "nullable": "YES" } }, "available": { "type": "Number", "required": false, "length": null, "precision": 32, "scale": 0, "postgresql": { "columnName": "available", "dataType": "integer", "dataLength": null, "dataPrecision": 32, "dataScale": 0, "nullable": "YES" } }, "total": { "type": "Number", "required": false, "length": null, "precision": 32, "scale": 0, "postgresql": { "columnName": "total", "dataType": "integer", "dataLength": null, "dataPrecision": 32, "dataScale": 0, "nullable": "YES" } } } } ``` ## Type mapping See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for details on LoopBack's data types. ### LoopBack to PostgreSQL types <table> <tbody> <tr> <th>LoopBack Type</th> <th>PostgreSQL Type</th> </tr> <tr> <td>String<br>JSON<br>Text<br>Default</td> <td> VARCHAR2<br/> Default length is 1024 </td> </tr> <tr> <td>Number</td> <td>INTEGER</td> </tr> <tr> <td>Date</td> <td>TIMESTAMP WITH TIME ZONE</td> </tr> <tr> <td>Boolean</td> <td>BOOLEAN</td> </tr> </tbody> </table> ### PostgreSQL types to LoopBack <table> <tbody> <tr> <th>PostgreSQL Type</th> <th>LoopBack Type</th> </tr> <tr> <td>BOOLEAN</td> <td>Boolean</td> </tr> <tr> <td> VARCHAR<br>CHARACTER VARYING<br>CHARACTER<br>CHAR<br>TEXT </td> <td>String</td> </tr> <tr> <td>BYTEA</td> <td>Node.js <a href="http://nodejs.org/api/buffer.html">Buffer object</a></td> </tr> <tr> <td>SMALLINT<br>INTEGER<br>BIGINT<br>DECIMAL<br>NUMERIC<br>REAL<br>DOUBLE<br>SERIAL<br>BIGSERIAL</td> <td>Number</td> </tr> <tr> <td>DATE<br>TIMESTAMP<br>TIME</td> <td>Date</td> </tr> <tr> <td>POINT</td> <td><a href="http://apidocs.strongloop.com/loopback-datasource-juggler/#geopoint">GeoPoint</a></td> </tr> </tbody> </table> ## Numeric Data Type **Note**: The [node.js driver for postgres](https://github.com/brianc/node-postgres) by default casts `Numeric` type as a string on `GET` operation. This is to avoid _data precision loss_ since `Numeric` types in postgres cannot be safely converted to JavaScript `Number`. For details, see the corresponding [driver issue](https://github.com/brianc/node-pg-types/issues/28). ## Querying JSON fields **Note** The fields you are querying should be setup to use the JSON postgresql data type - see Defining models Assuming a model such as this: ```json { "name": "Customer", "properties": { "address": { "type": "object", "postgresql": { "dataType": "json" } } } } ``` You can query the nested fields with dot notation: ```javascript Customer.find({ where: { 'address.state': 'California' }, order: 'address.city' }) ``` ## Discovery and auto-migration ### Model discovery The PostgreSQL connector supports _model discovery_ that enables you to create LoopBack models based on an existing database schema using the unified [database discovery API](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-discoverandbuildmodels). For more information on discovery, see [Discovering models from relational databases](https://loopback.io/doc/en/lb3/Discovering-models-from-relational-databases.html). ### Auto-migration The PostgreSQL connector also supports _auto-migration_ that enables you to create a database schema from LoopBack models using the [LoopBack automigrate method](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-automigrate). For more information on auto-migration, see [Creating a database schema from models](https://loopback.io/doc/en/lb3/Creating-a-database-schema-from-models.html) for more information. LoopBack PostgreSQL connector creates the following schema objects for a given model: a table, for example, PRODUCT under the 'public' schema within the database. The auto-migrate method: * Defines a primary key for the properties whose `id` property is true (or a positive number). * Creates a column with 'SERIAL' type if the `generated` property of the `id` property is true. Destroying models may result in errors due to foreign key integrity. First delete any related models by calling delete on models with relationships. ## Running tests ### Own instance If you have a local or remote PostgreSQL instance and would like to use that to run the test suite, use the following command: - Linux ```bash POSTGRESQL_HOST=<HOST> POSTGRESQL_PORT=<PORT> POSTGRESQL_USER=<USER> POSTGRESQL_PASSWORD=<PASSWORD> POSTGRESQL_DATABASE=<DATABASE> CI=true npm test ``` - Windows ```bash SET POSTGRESQL_HOST=<HOST> SET POSTGRESQL_PORT=<PORT> SET POSTGRESQL_USER=<USER> SET POSTGRESQL_PASSWORD=<PASSWORD> SET POSTGRESQL_DATABASE=<DATABASE> SET CI=true npm test ``` ### Docker If you do not have a local PostgreSQL instance, you can also run the test suite with very minimal requirements. - Assuming you have [Docker](https://docs.docker.com/engine/installation/) installed, run the following script which would spawn a PostgreSQL instance on your local: ```bash source setup.sh <HOST> <PORT> <USER> <PASSWORD> <DATABASE> ``` where `<HOST>`, `<PORT>`, `<USER>`, `<PASSWORD>` and `<DATABASE>` are optional parameters. The default values are `localhost`, `5432`, `root`, `pass` and `testdb` respectively. - Run the test: ```bash npm test ```