From a13c0e0edf39798427cab2c2994a32fb51a7e62b Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 11 Feb 2019 13:42:17 +0100 Subject: [PATCH] feat(defaultValue): add advanced handling for defaultValues This adds the possibility to pass raw defaultValues and special defaultValues such as CURRENT_TIMESTAMP. Signed-off-by: Tobias Gurtzick --- .travis.yml | 8 +- package-lock.json | 100 +-- package.json | 4 +- test/db.config.ci | 2 +- test/pg_schema_test.js | 307 ++++---- test/pg_test.js | 1532 ++++++++++++++++++++++++---------------- 6 files changed, 1165 insertions(+), 788 deletions(-) diff --git a/.travis.yml b/.travis.yml index 675dfdd..f39fe31 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ node_js: - 4 - 5 - 6 + - 8 + - node notifications: email: @@ -20,6 +22,8 @@ os: - linux matrix: + allow_failures: + - node_js: node fast_finish: true sudo: false @@ -40,5 +44,5 @@ before_install: - export CXX=g++-4.8; export CC=gcc-4.8; before_script: - - createdb db_migrate_test - - cp test/db.config.ci test/db.config.json + - createdb db_migrate_test + - cp test/db.config.ci test/db.config.json diff --git a/package-lock.json b/package-lock.json index 9f25fb6..43d97df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,9 @@ "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" }, "buffer-writer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", - "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, "db-meta": { "version": "0.4.1", @@ -21,11 +21,11 @@ "dev": true }, "db-migrate-base": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/db-migrate-base/-/db-migrate-base-1.5.3.tgz", - "integrity": "sha512-dbJHFVYIY75vSOL3MD4qbpjilcwrYn7ZnTqsdA2AGs6w1mYugspfWEBea+uMgJVH/YsUFxw2AYPKRHCHUjhirw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/db-migrate-base/-/db-migrate-base-1.6.3.tgz", + "integrity": "sha512-O6Kh72Yh0DfvRAKg9QKzu1KkMwI5iI0dFHO6RmDLvbiYvtRW3faFXJNFwJYeioVBx22QA3AkVFbDIcw4j4QxGw==", "requires": { - "bluebird": "3.5.1" + "bluebird": "^3.1.1" } }, "db-migrate-shared": { @@ -52,10 +52,10 @@ "integrity": "sha1-aVxQvdTi+1xdNwsJHziNNwfikac=", "dev": true, "requires": { - "graceful-fs": "3.0.11", - "inherits": "2.0.3", - "minimatch": "1.0.0", - "once": "1.4.0" + "graceful-fs": "^3.0.2", + "inherits": "2", + "minimatch": "^1.0.0", + "once": "^1.3.0" } }, "graceful-fs": { @@ -64,7 +64,7 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "1.1.1" + "natives": "^1.1.0" } }, "inherits": { @@ -73,11 +73,6 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=" - }, "lru-cache": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", @@ -90,8 +85,8 @@ "integrity": "sha1-4N0hILSeG3JM6NcUxSCCKpQ4V20=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "2", + "sigmund": "~1.0.0" } }, "natives": { @@ -106,7 +101,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "packet-reader": { @@ -115,17 +110,16 @@ "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=" }, "pg": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.4.1.tgz", - "integrity": "sha512-Pi5qYuXro5PAD9xXx8h7bFtmHgAQEG6/SCNyi7gS3rvb/ZQYDmxKchfB0zYtiSJNWq9iXTsYsHjrM+21eBcN1A==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.8.0.tgz", + "integrity": "sha512-yS3C9YD+ft0H7G47uU0eKajgTieggCXdA+Fxhm5G+wionY6kPBa8BEVDwPLMxQvkRkv3/LXiFEqjZm9gfxdW+g==", "requires": { - "buffer-writer": "1.0.1", - "js-string-escape": "1.0.1", + "buffer-writer": "2.0.0", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", - "pg-pool": "2.0.3", - "pg-types": "1.12.1", - "pgpass": "1.0.2", + "pg-pool": "^2.0.4", + "pg-types": "~2.0.0", + "pgpass": "1.x", "semver": "4.3.2" }, "dependencies": { @@ -141,20 +135,26 @@ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, "pg-pool": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.3.tgz", - "integrity": "sha1-wCIDLIlJ8xKk+R+2QJzgQHa+Mlc=" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-hod2zYQxM8Gt482q+qONGTYcg/qVcV32VHVPtktbBJs0us3Dj7xibISw0BAAXVMCzt8A/jhfJvpZaxUlqtqs0g==" }, "pg-types": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", - "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.0.0.tgz", + "integrity": "sha512-THUD7gQll5tys+5eQ8Rvs7DjHiIC3bLqixk3gMN9Hu8UrCBAOjf35FoI39rTGGc3lM2HU/R+Knpxvd11mCwOMA==", "requires": { - "postgres-array": "1.0.2", - "postgres-bytea": "1.0.0", - "postgres-date": "1.0.3", - "postgres-interval": "1.1.1" + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.0", + "postgres-interval": "^1.1.0" } }, "pgpass": { @@ -162,13 +162,13 @@ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", "requires": { - "split": "1.0.1" + "split": "^1.0.0" } }, "postgres-array": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz", - "integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" }, "postgres-bytea": { "version": "1.0.0", @@ -181,11 +181,11 @@ "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=" }, "postgres-interval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.1.tgz", - "integrity": "sha512-OkuCi9t/3CZmeQreutGgx/OVNv9MKHGIT5jH8KldQ4NLYXkvmT9nDVxEuCENlNwhlGPE374oA/xMqn05G49pHA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", + "integrity": "sha512-fC3xNHeTskCxL1dC8KOtxXt7YeFmlbTYtn7ul8MkVERuTmf7pI4DrkAxcw3kh1fQ9uz4wQmd03a1mRiXUZChfQ==", "requires": { - "xtend": "4.0.1" + "xtend": "^4.0.0" } }, "semver": { @@ -204,7 +204,7 @@ "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "requires": { - "through": "2.3.8" + "through": "2" } }, "through": { @@ -218,9 +218,9 @@ "integrity": "sha1-zQESKnGk+oU4chmBgtQQ3mw9uKM=", "dev": true, "requires": { - "diff": "1.0.8", - "eyes": "0.1.8", - "glob": "4.0.6" + "diff": "~1.0.8", + "eyes": "~0.1.6", + "glob": "~4.0.6" } }, "wrappy": { diff --git a/package.json b/package.json index 32de944..e0c1952 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ "homepage": "https://github.com/db-migrate/pg", "dependencies": { "bluebird": "^3.1.1", - "db-migrate-base": "^1.5.2", - "pg": "^7.4.1", + "db-migrate-base": "^1.6.3", + "pg": "^7.8.0", "semver": "^5.0.3" }, "devDependencies": { diff --git a/test/db.config.ci b/test/db.config.ci index 3a6cc4f..6bd9283 100644 --- a/test/db.config.ci +++ b/test/db.config.ci @@ -7,7 +7,7 @@ "pg": { "driver": "pg", "database": "db_migrate_test", - "username": "postgres" + "user": "postgres" }, "sqlite3": { "driver": "sqlite3", diff --git a/test/pg_schema_test.js b/test/pg_schema_test.js index 831fbad..c283a52 100644 --- a/test/pg_schema_test.js +++ b/test/pg_schema_test.js @@ -6,8 +6,12 @@ var pg = require('pg'); var dataType = require('db-migrate-shared').dataType; var driver = require('../'); var log = require('db-migrate-shared').log; - -var databaseUrl = 'postgres://localhost/db_migrate_test'; +var config = Object.assign( + { + schema: 'test_schema' + }, + require('./db.config.json').pg +); var internals = {}; internals.mod = { @@ -20,152 +24,185 @@ internals.interfaces = { }; internals.migrationTable = 'migrations'; -vows.describe('pg').addBatch({ +vows + .describe('pg') + .addBatch({ 'create schema which needs escaping and connect': { - topic: function() { - var callback = this.callback; - var client = new pg.Client(databaseUrl); - - client.connect(function (err) { - if (err) { return callback(err); } - client.query('CREATE SCHEMA "test-schema"', function(err) { - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test-schema' }, internals, function(err, db) { - callback(err, db, client); - }); - }); - }); - }, - - 'migrations': { - topic: function(db, client) { - var callback = this.callback; - - db.createMigrationsTable(function() { - client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test-schema\' AND table_name = \'migrations\'', function(err, result) { - callback(err, result); - }); - }); - }, - - 'is in test-schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); - } + topic: function() { + var callback = this.callback; + var client = new pg.Client(config); + + client.connect(function(err) { + if (err) { + return callback(err); + } + client.query('CREATE SCHEMA "test_schema"', function(err) { + driver.connect( + config, + internals, + function(err, db) { + callback(err, db, client); + } + ); + }); + }); + }, + + migrations: { + topic: function(db, client) { + var callback = this.callback; + + db.createMigrationsTable(function() { + client.query( + "SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", + function(err, result) { + callback(err, result); + } + ); + }); }, - teardown: function(db, client) { - var callback = this.callback; - client.query('DROP SCHEMA "test-schema" CASCADE', function (err) { - if (err) { return callback(err); } - client.end(); - callback(); - }); + 'is in test_schema': function(err, result) { + assert.isNull(err); + assert.isNotNull(result); + assert.equal(result.rowCount, 1); } + }, + + teardown: function(db, client) { + var callback = this.callback; + client.query('DROP SCHEMA "test_schema" CASCADE', function(err) { + if (err) { + return callback(err); + } + client.end(); + callback(); + }); + } } -}) -.addBatch({ + }) + .addBatch({ 'create schema and a public.migrations table and connect': { - topic: function() { - var callback = this.callback; - var client = new pg.Client(databaseUrl); - var query = Promise.promisify( client.query ).bind(client); - - client.connect(function (err) { - if (err) { return callback(err); } - Promise.all([ - query('CREATE SCHEMA test_schema'), - query('CREATE TABLE migrations ()') - ]) - .then( function() { - - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { - callback(err, db, client); - }); - }) - .catch( function(err) { - callback(err); - }); - }); - }, - - 'migrations table': { - topic: function(db, client) { - var callback = this.callback; - - db.createMigrationsTable(function() { - client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test_schema\' AND table_name = \'migrations\'', function(err, result) { - callback(err, result); - }); - }); - }, - - 'is in test_schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); - } - }, - - teardown: function(db, client) { - var callback = this.callback; - var query = Promise.promisify(client.query).bind(client); - - Promise.all([ - query('DROP SCHEMA test_schema CASCADE'), - query('DROP TABLE migrations') - ]) - .then(function (err) { - client.end(); - callback(); + topic: function() { + var callback = this.callback; + var client = new pg.Client(config); + var query = Promise.promisify(client.query).bind(client); + + client.connect(function(err) { + if (err) { + return callback(err); + } + Promise.all([ + query('CREATE SCHEMA test_schema'), + query('CREATE TABLE migrations ()') + ]) + .then(function() { + driver.connect( + config, + internals, + function(err, db) { + callback(err, db, client); + } + ); }) - .catch(function (err) { + .catch(function(err) { callback(err); }); + }); + }, + + 'migrations table': { + topic: function(db, client) { + var callback = this.callback; + + db.createMigrationsTable(function() { + client.query( + "SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", + function(err, result) { + callback(err, result); + } + ); + }); + }, + + 'is in test_schema': function(err, result) { + assert.isNull(err); + assert.isNotNull(result); + assert.equal(result.rowCount, 1); } + }, + + teardown: function(db, client) { + var callback = this.callback; + var query = Promise.promisify(client.query).bind(client); + + Promise.all([ + query('DROP SCHEMA test_schema CASCADE'), + query('DROP TABLE migrations') + ]) + .then(function(err) { + client.end(); + callback(); + }) + .catch(function(err) { + callback(err); + }); + } } -}) -.addBatch({ + }) + .addBatch({ 'create schema and connect': { - topic: function() { - var callback = this.callback; - var client = new pg.Client(databaseUrl); - - client.connect(function (err) { - if (err) { return callback(err); } - client.query('CREATE SCHEMA test_schema', function(err) { - driver.connect({ driver: 'pg', database: 'db_migrate_test', schema: 'test_schema' }, internals, function(err, db) { - callback(err, db, client); - }); - }); - }); - }, - - 'migrations table': { - topic: function(db, client) { - var callback = this.callback; - - db.createMigrationsTable(function() { - client.query('SELECT table_name FROM information_schema.tables WHERE table_schema = \'test_schema\' AND table_name = \'migrations\'', function(err, result) { - callback(err, result); - }); - }); - }, - - 'is in test_schema': function(err, result) { - assert.isNull(err); - assert.isNotNull(result); - assert.equal(result.rowCount, 1); - } + topic: function() { + var callback = this.callback; + var client = new pg.Client(config); + + client.connect(function(err) { + if (err) { + return callback(err); + } + client.query('CREATE SCHEMA test_schema', function(err) { + driver.connect( + config, + internals, + function(err, db) { + callback(err, db, client); + } + ); + }); + }); + }, + + 'migrations table': { + topic: function(db, client) { + var callback = this.callback; + + db.createMigrationsTable(function() { + client.query( + "SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_schema' AND table_name = 'migrations'", + function(err, result) { + callback(err, result); + } + ); + }); }, - teardown: function(db, client) { - var callback = this.callback; - client.query('DROP SCHEMA test_schema CASCADE', function (err) { - if (err) { return callback(err); } - client.end(); - callback(); - }); + 'is in test_schema': function(err, result) { + assert.isNull(err); + assert.isNotNull(result); + assert.equal(result.rowCount, 1); } + }, + + teardown: function(db, client) { + var callback = this.callback; + client.query('DROP SCHEMA test_schema CASCADE', function(err) { + if (err) { + return callback(err); + } + client.end(); + callback(); + }); + } } -}).export(module); + }) + .export(module); diff --git a/test/pg_test.js b/test/pg_test.js index d54d5d0..d852751 100644 --- a/test/pg_test.js +++ b/test/pg_test.js @@ -20,449 +20,669 @@ internals.interfaces = { internals.migrationTable = 'migrations'; log.silence(true); +vows + .describe('pg') + .addBatch({ + 'default connection': { + topic: function() { + driver.connect( + {}, + internals, + this.callback + ); + }, -vows.describe('pg').addBatch({ - 'default connection': { - - topic: function() { - driver.connect({}, internals, this.callback) - }, - - 'is connected': function(err, _db) { - assert.isNull(err); + 'is connected': function(err, _db) { + assert.isNull(err); + } } - } -}).addBatch({ - 'connect': { - - topic: function() { - driver.connect(config, internals, this.callback); - }, - - 'is connected': function(err, _db) { + }) + .addBatch({ + connect: { + topic: function() { + driver.connect( + config, + internals, + this.callback + ); + }, - assert.isNull(err); - db = _db; - } - } -}).addBatch({ - 'connect error': { - topic: function () { - driver.connect({host: 'fakehost'}, internals, this.callback); - }, - - 'shows connection error': function (err, _db) { - assert.isNotNull(err); + 'is connected': function(err, _db) { + assert.isNull(err); + db = _db; + } } - } -}).addBatch({ - 'createTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - str: { type: dataType.STRING, unique: true }, - txt: { type: dataType.TEXT, notNull: true, defaultValue: "foo" }, - chr: dataType.CHAR, - intg: dataType.INTEGER, - rel: dataType.REAL, - smalint: dataType.SMALLINT, - dt: dataType.DATE, - dti: dataType.DATE_TIME, - dti_tz: { type: dataType.DATE_TIME, timezone: true }, - bl: dataType.BOOLEAN - }, this.callback.bind(this)); - }, - - 'has table metadata': { + }) + .addBatch({ + 'connect error': { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); + driver.connect( + { host: 'fakehost' }, + internals, + this.callback + ); }, - 'containing the event table': function(err, tables) { - assert.equal(tables.length, 1); - assert.equal(tables[0].getName(), 'event'); + 'shows connection error': function(err, _db) { + assert.isNotNull(err); } - }, - - 'has column metadata for the event table': { + } + }) + .addBatch({ + createTable: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + str: { type: dataType.STRING, unique: true }, + txt: { type: dataType.TEXT, notNull: true, defaultValue: 'foo' }, + chr: dataType.CHAR, + intg: dataType.INTEGER, + rel: dataType.REAL, + smalint: dataType.SMALLINT, + dt: dataType.DATE, + dti: dataType.DATE_TIME, + dti_tz: { type: dataType.DATE_TIME, timezone: true }, + bl: dataType.BOOLEAN + }, + this.callback.bind(this) + ); }, - 'with 11 columns': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 11); - }, + 'has table metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getTables(this.callback); + }.bind(this) + ); + }, - 'that has integer id column that is primary key, non-nullable, and auto increments': function(err, columns) { - var column = findByName(columns, 'id'); - assert.equal(column.getDataType(), 'INTEGER'); - assert.equal(column.isPrimaryKey(), true); - assert.equal(column.isNullable(), false); - assert.equal(column.isAutoIncrementing(), true); + 'containing the event table': function(err, tables) { + assert.equal(tables.length, 1); + assert.equal(tables[0].getName(), 'event'); + } }, - 'that has text str column that is unique': function(err, columns) { - var column = findByName(columns, 'str'); - assert.equal(column.getDataType(), 'CHARACTER VARYING'); - assert.equal(column.isUnique(), true); - }, + 'has column metadata for the event table': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getColumns('event', this.callback); + }.bind(this) + ); + }, - 'that has text txt column that is non-nullable': function(err, columns) { - var column = findByName(columns, 'txt'); - assert.equal(column.getDataType(), 'TEXT'); - assert.equal(column.isNullable(), false); - // assert.equal(column.getDefaultValue(), 'foo'); - }, + 'with 11 columns': function(err, columns) { + assert.isNotNull(columns); + assert.equal(columns.length, 11); + }, - 'that has integer intg column': function(err, columns) { - var column = findByName(columns, 'intg'); - assert.equal(column.getDataType(), 'INTEGER'); - assert.equal(column.isNullable(), true); - }, + 'that has integer id column that is primary key, non-nullable, and auto increments': function( + err, + columns + ) { + var column = findByName(columns, 'id'); + assert.equal(column.getDataType(), 'INTEGER'); + assert.equal(column.isPrimaryKey(), true); + assert.equal(column.isNullable(), false); + assert.equal(column.isAutoIncrementing(), true); + }, - 'that has real rel column': function(err, columns) { - var column = findByName(columns, 'rel'); - assert.equal(column.getDataType(), 'REAL'); - assert.equal(column.isNullable(), true); - }, + 'that has text str column that is unique': function(err, columns) { + var column = findByName(columns, 'str'); + assert.equal(column.getDataType(), 'CHARACTER VARYING'); + assert.equal(column.isUnique(), true); + }, - 'that has integer dt column': function(err, columns) { - var column = findByName(columns, 'dt'); - assert.equal(column.getDataType(), 'DATE'); - assert.equal(column.isNullable(), true); - }, + 'that has text txt column that is non-nullable': function( + err, + columns + ) { + var column = findByName(columns, 'txt'); + assert.equal(column.getDataType(), 'TEXT'); + assert.equal(column.isNullable(), false); + // assert.equal(column.getDefaultValue(), 'foo'); + }, - 'that has integer dti column': function(err, columns) { - var column = findByName(columns, 'dti'); - assert.equal(column.getDataType(), 'TIMESTAMP WITHOUT TIME ZONE'); - assert.equal(column.isNullable(), true); - }, + 'that has integer intg column': function(err, columns) { + var column = findByName(columns, 'intg'); + assert.equal(column.getDataType(), 'INTEGER'); + assert.equal(column.isNullable(), true); + }, - 'that has timestamp with time zone column': function(err, columns) { - var column = findByName(columns, 'dti_tz'); - assert.equal(column.getDataType(), 'TIMESTAMP WITH TIME ZONE'); - assert.equal(column.isNullable(), true); - }, + 'that has real rel column': function(err, columns) { + var column = findByName(columns, 'rel'); + assert.equal(column.getDataType(), 'REAL'); + assert.equal(column.isNullable(), true); + }, - 'that has boolean bl column': function(err, columns) { - var column = findByName(columns, 'bl'); - assert.equal(column.getDataType(), 'BOOLEAN'); - assert.equal(column.isNullable(), true); - }, + 'that has integer dt column': function(err, columns) { + var column = findByName(columns, 'dt'); + assert.equal(column.getDataType(), 'DATE'); + assert.equal(column.isNullable(), true); + }, - 'that has character chr column': function(err, columns) { - var column = findByName(columns, 'chr'); - assert.equal(column.getDataType(), 'CHARACTER'); - assert.equal(column.isNullable(), true); - }, + 'that has integer dti column': function(err, columns) { + var column = findByName(columns, 'dti'); + assert.equal(column.getDataType(), 'TIMESTAMP WITHOUT TIME ZONE'); + assert.equal(column.isNullable(), true); + }, - 'that has small integer smalint column': function(err, columns) { - var column = findByName(columns, 'smalint'); - assert.equal(column.getDataType(), 'SMALLINT'); - assert.equal(column.isNullable(), true); - } - }, + 'that has timestamp with time zone column': function(err, columns) { + var column = findByName(columns, 'dti_tz'); + assert.equal(column.getDataType(), 'TIMESTAMP WITH TIME ZONE'); + assert.equal(column.isNullable(), true); + }, - teardown: function() { - db.dropTable('event', this.callback); - } - } -}).addBatch({ - 'dropTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function(err) { - if (err) { - return this.callback(err); + 'that has boolean bl column': function(err, columns) { + var column = findByName(columns, 'bl'); + assert.equal(column.getDataType(), 'BOOLEAN'); + assert.equal(column.isNullable(), true); + }, + + 'that has character chr column': function(err, columns) { + var column = findByName(columns, 'chr'); + assert.equal(column.getDataType(), 'CHARACTER'); + assert.equal(column.isNullable(), true); + }, + + 'that has small integer smalint column': function(err, columns) { + var column = findByName(columns, 'smalint'); + assert.equal(column.getDataType(), 'SMALLINT'); + assert.equal(column.isNullable(), true); } - db.dropTable('event', this.callback.bind(this, null)); - }.bind(this)); - }, + }, - 'has table metadata': { + teardown: function() { + db.dropTable('event', this.callback); + } + } + }) + .addBatch({ + dropTable: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + } + }, + function(err) { + if (err) { + return this.callback(err); + } + db.dropTable('event', this.callback.bind(this, null)); + }.bind(this) + ); }, - 'containing no tables': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 0); + 'has table metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getTables(this.callback); + }.bind(this) + ); + }, + + 'containing no tables': function(err, tables) { + assert.isNotNull(tables); + assert.equal(tables.length, 0); + } } } - } -}).addBatch({ - 'renameTable': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.renameTable('event', 'functions', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has table metadata': { + }) + .addBatch({ + renameTable: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + } + }, + function() { + db.renameTable( + 'event', + 'functions', + this.callback.bind(this, null) + ); + }.bind(this) + ); }, - 'containing the functions table': function(err, tables) { - assert.isNotNull(tables); - assert.equal(tables.length, 1); - assert.equal(tables[0].getName(), 'functions'); - } - }, + 'has table metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getTables(this.callback); + }.bind(this) + ); + }, - teardown: function() { - db.dropTable('functions', this.callback); + 'containing the functions table': function(err, tables) { + assert.isNotNull(tables); + assert.equal(tables.length, 1); + assert.equal(tables[0].getName(), 'functions'); + } + }, + + teardown: function() { + db.dropTable('functions', this.callback); + } } - } -}).addBatch({ - 'addColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has column metadata': { + }) + .addBatch({ + addColumn: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + } + }, + function() { + db.addColumn( + 'event', + 'title', + 'string', + this.callback.bind(this, null) + ); + }.bind(this) + ); }, - 'with additional title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 2); - var column = findByName(columns, 'title'); - assert.equal(column.getName(), 'title'); - assert.equal(column.getDataType(), 'CHARACTER VARYING'); - } - }, + 'has column metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getColumns('event', this.callback); + }.bind(this) + ); + }, - teardown: function() { - db.dropTable('event', this.callback); + 'with additional title column': function(err, columns) { + assert.isNotNull(columns); + assert.equal(columns.length, 2); + var column = findByName(columns, 'title'); + assert.equal(column.getName(), 'title'); + assert.equal(column.getDataType(), 'CHARACTER VARYING'); + } + }, + + teardown: function() { + db.dropTable('event', this.callback); + } } - } -}).addBatch({ - 'removeColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', function(err) { - db.removeColumn('event', 'title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - 'has column metadata': { + }) + .addBatch({ + removeColumn: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + } + }, + function() { + db.addColumn( + 'event', + 'title', + 'string', + function(err) { + db.removeColumn( + 'event', + 'title', + this.callback.bind(this, null) + ); + }.bind(this) + ); + }.bind(this) + ); }, - 'without title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 1); - assert.notEqual(columns[0].getName(), 'title'); - } - }, + 'has column metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getColumns('event', this.callback); + }.bind(this) + ); + }, + + 'without title column': function(err, columns) { + assert.isNotNull(columns); + assert.equal(columns.length, 1); + assert.notEqual(columns[0].getName(), 'title'); + } + }, - teardown: function() { - db.dropTable('event', this.callback); + teardown: function() { + db.dropTable('event', this.callback); + } } - } -}).addBatch({ - 'renameColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addColumn('event', 'title', 'string', function(err) { - db.renameColumn('event', 'title', 'new_title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - 'has column metadata': { + }) + .addBatch({ + renameColumn: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + } + }, + function() { + db.addColumn( + 'event', + 'title', + 'string', + function(err) { + db.renameColumn( + 'event', + 'title', + 'new_title', + this.callback.bind(this, null) + ); + }.bind(this) + ); + }.bind(this) + ); }, - 'with renamed title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 2); - var column = findByName(columns, 'new_title'); - assert.equal(column.getName(), 'new_title'); - } - }, + 'has column metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getColumns('event', this.callback); + }.bind(this) + ); + }, - teardown: function() { - db.dropTable('event', this.callback); + 'with renamed title column': function(err, columns) { + assert.isNotNull(columns); + assert.equal(columns.length, 2); + var column = findByName(columns, 'new_title'); + assert.equal(column.getName(), 'new_title'); + } + }, + + teardown: function() { + db.dropTable('event', this.callback); + } } - } -}).addBatch({ - 'changeColumn': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - txt: { type: dataType.TEXT, notNull: true, unique: true, defaultValue: "foo" }, - keep_id: { type: dataType.INTEGER, notNull: true, unique: true }, - type_test: {type:dataType.BLOB, notNull:true}, - type_length_test: {type:dataType.STRING, length: 50, notNull:true} - }, function() { - var spec = { notNull: false, defaultValue: "foo2", unique: false }, - spec2 = { notNull: true, unsigned: true}, - spec3 = { type:dataType.INTEGER, using:util.format('USING CAST(CAST("type_test" AS %s) AS %s)', dataType.TEXT, dataType.INTEGER) }, - spec4 = { type:dataType.STRING, length: 100 }; - - db.changeColumn('event', 'txt', spec, function() { - db.changeColumn('event', 'keep_id', spec2, function(){ - db.changeColumn('event', 'type_test', spec3, function(){ - db.changeColumn('event', 'type_length_test', spec4, this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }, - 'has column metadata': { + }) + .addBatch({ + changeColumn: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('event', this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + txt: { + type: dataType.TEXT, + notNull: true, + unique: true, + defaultValue: 'foo' + }, + keep_id: { type: dataType.INTEGER, notNull: true, unique: true }, + type_test: { type: dataType.BLOB, notNull: true }, + type_length_test: { + type: dataType.STRING, + length: 50, + notNull: true + } + }, + function() { + var spec = { notNull: false, defaultValue: 'foo2', unique: false }, + spec2 = { notNull: true, unsigned: true }, + spec3 = { + type: dataType.INTEGER, + using: util.format( + 'USING CAST(CAST("type_test" AS %s) AS %s)', + dataType.TEXT, + dataType.INTEGER + ) + }, + spec4 = { type: dataType.STRING, length: 100 }; + + db.changeColumn( + 'event', + 'txt', + spec, + function() { + db.changeColumn( + 'event', + 'keep_id', + spec2, + function() { + db.changeColumn( + 'event', + 'type_test', + spec3, + function() { + db.changeColumn( + 'event', + 'type_length_test', + spec4, + this.callback.bind(this, null) + ); + }.bind(this) + ); + }.bind(this) + ); + }.bind(this) + ); + }.bind(this) + ); }, + 'has column metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getColumns('event', this.callback); + }.bind(this) + ); + }, - 'with changed title column': function(err, columns) { - assert.isNotNull(columns); - assert.equal(columns.length, 5); + 'with changed title column': function(err, columns) { + assert.isNotNull(columns); + assert.equal(columns.length, 5); - var column = findByName(columns, 'txt'); - assert.equal(column.getName(), 'txt'); - assert.equal(column.isNullable(), true); - assert.equal(column.getDefaultValue(), "'foo2'::text"); - assert.equal(column.isUnique(), false); + var column = findByName(columns, 'txt'); + assert.equal(column.getName(), 'txt'); + assert.equal(column.isNullable(), true); + assert.equal(column.getDefaultValue(), "'foo2'::text"); + assert.equal(column.isUnique(), false); - column = findByName(columns, 'keep_id'); - assert.equal(column.getName(), 'keep_id'); - assert.equal(column.isNullable(), false); - assert.equal(column.isUnique(), true); + column = findByName(columns, 'keep_id'); + assert.equal(column.getName(), 'keep_id'); + assert.equal(column.isNullable(), false); + assert.equal(column.isUnique(), true); - column = findByName(columns, 'type_test'); - assert.equal(column.getName(), 'type_test'); - assert.equal(dataType[column.getDataType()], dataType.INTEGER); + column = findByName(columns, 'type_test'); + assert.equal(column.getName(), 'type_test'); + assert.equal(dataType[column.getDataType()], dataType.INTEGER); - column = findByName(columns, 'type_length_test'); - assert.equal(column.getName(), 'type_length_test'); - assert.equal(column.getDataType(), 'CHARACTER VARYING'); - assert.equal(column.meta.character_maximum_length, 100); - } - }, + column = findByName(columns, 'type_length_test'); + assert.equal(column.getName(), 'type_length_test'); + assert.equal(column.getDataType(), 'CHARACTER VARYING'); + assert.equal(column.meta.character_maximum_length, 100); + } + }, - teardown: function() { - db.dropTable('event', this.callback); + teardown: function() { + db.dropTable('event', this.callback); + } } - } -}).addBatch({ - 'addIndex': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function() { - db.addIndex('event', 'event_title', 'title', this.callback.bind(this, null)); - }.bind(this)); - }, - - 'has resulting index metadata': { + }) + .addBatch({ + addIndex: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + title: { type: dataType.STRING } + }, + function() { + db.addIndex( + 'event', + 'event_title', + 'title', + this.callback.bind(this, null) + ); + }.bind(this) + ); }, - 'with additional index': function(err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 2); - var index = findByName(indexes, 'event_title'); - assert.equal(index.getName(), 'event_title'); - assert.equal(index.getTableName(), 'event'); - assert.equal(index.getColumnName(), 'title'); - } - }, + 'has resulting index metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getIndexes('event', this.callback); + }.bind(this) + ); + }, - teardown: function() { - db.dropTable('event', this.callback); + 'with additional index': function(err, indexes) { + assert.isNotNull(indexes); + assert.equal(indexes.length, 2); + var index = findByName(indexes, 'event_title'); + assert.equal(index.getName(), 'event_title'); + assert.equal(index.getTableName(), 'event'); + assert.equal(index.getColumnName(), 'title'); + } + }, + + teardown: function() { + db.dropTable('event', this.callback); + } } - } -}).addBatch({ - 'addForeignKey': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - // lowercase table names because they are quoted in the function - // and pg uses lowercase internally - db.addForeignKey('event', 'event_type', 'fk_event_event_type', { - 'event_id': 'id' - }, { - onDelete: 'CASCADE' - }, this.callback); - }.bind(this)); - }.bind(this)); - }, - - 'sets usage and constraints': { + }) + .addBatch({ + addForeignKey: { topic: function() { - var metaQuery = ['SELECT', + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + event_id: { type: dataType.INTEGER, notNull: true }, + title: { type: dataType.STRING } + }, + function() { + db.createTable( + 'event_type', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + title: { type: dataType.STRING } + }, + function() { + // lowercase table names because they are quoted in the function + // and pg uses lowercase internally + db.addForeignKey( + 'event', + 'event_type', + 'fk_event_event_type', + { + event_id: 'id' + }, + { + onDelete: 'CASCADE' + }, + this.callback + ); + }.bind(this) + ); + }.bind(this) + ); + }, + + 'sets usage and constraints': { + topic: function() { + var metaQuery = [ + 'SELECT', ' tc.table_schema, tc.table_name as ortn, kcu.column_name orcn, ccu.table_name,', ' ccu.column_name,', ' cstr.update_rule,', @@ -479,65 +699,101 @@ vows.describe('pg').addBatch({ 'WHERE', ' tc.table_schema = ?', ' AND tc.table_name = ?', - ' AND kcu.column_name = ?'].join('\n'); + ' AND kcu.column_name = ?' + ].join('\n'); db.runSql(metaQuery, ['public', 'event', 'event_id'], this.callback); - }, + }, - 'with correct references': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.table_name, 'event_type'); - assert.equal(row.column_name, 'id'); + 'with correct references': function(err, result) { + var rows = result.rows; + assert.isNotNull(rows); + assert.equal(rows.length, 1); + var row = rows[0]; + assert.equal(row.table_name, 'event_type'); + assert.equal(row.column_name, 'id'); + }, + + 'and correct rules': function(err, result) { + var rows = result.rows; + assert.isNotNull(rows); + assert.equal(rows.length, 1); + var row = rows[0]; + assert.equal(row.update_rule, 'NO ACTION'); + assert.equal(row.delete_rule, 'CASCADE'); + } }, - 'and correct rules': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.update_rule, 'NO ACTION'); - assert.equal(row.delete_rule, 'CASCADE'); + teardown: function() { + db.dropTable('event') + .then(function() { + return db.dropTable('event_type'); + }) + .nodeify(this.callback); } - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); } - } -}).addBatch({ - 'removeForeignKey': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.addForeignKey('event', 'event_type', 'fk_event_event_type', { - 'event_id': 'id' - }, { - onDelete: 'CASCADE' - }, function () { - db.removeForeignKey('event', 'fk_event_event_type', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }, - - teardown: function() { - db.dropTable('event'); - db.dropTable('event_type', this.callback); - }, - - 'removes usage and constraints': { + }) + .addBatch({ + removeForeignKey: { topic: function() { - var metaQuery = ['SELECT', + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + event_id: { type: dataType.INTEGER, notNull: true }, + title: { type: dataType.STRING } + }, + function() { + db.createTable( + 'event_type', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + title: { type: dataType.STRING } + }, + function() { + db.addForeignKey( + 'event', + 'event_type', + 'fk_event_event_type', + { + event_id: 'id' + }, + { + onDelete: 'CASCADE' + }, + function() { + db.removeForeignKey( + 'event', + 'fk_event_event_type', + this.callback.bind(this, null) + ); + }.bind(this) + ); + }.bind(this) + ); + }.bind(this) + ); + }, + + teardown: function() { + db.dropTable('event') + .then(function() { + return db.dropTable('event_type'); + }) + .nodeify(this.callback); + }, + + 'removes usage and constraints': { + topic: function() { + var metaQuery = [ + 'SELECT', ' tc.table_schema, tc.table_name as ortn, kcu.column_name orcn, ccu.table_name,', ' ccu.column_name,', ' cstr.update_rule,', @@ -554,53 +810,80 @@ vows.describe('pg').addBatch({ 'WHERE', ' tc.table_schema = ?', ' AND tc.table_name = ?', - ' AND kcu.column_name = ?'].join('\n'); + ' AND kcu.column_name = ?' + ].join('\n'); db.runSql(metaQuery, ['public', 'event', 'event_id'], this.callback); - }, + }, - 'completely': function(err, result) { - assert.isNotNull(result.rows); - assert.equal(result.rows.length, 0); + completely: function(err, result) { + assert.isNotNull(result.rows); + assert.equal(result.rows.length, 0); + } } } - } -}).addBatch({ - 'addForeign by addcolumn with spec': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - event_id: { type: dataType.INTEGER, notNull: true }, - title: { type: dataType.STRING } - }, function() { - db.createTable('event_type', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function () { - db.addColumn('event_type', 'event_id', { - type: dataType.INTEGER, - notNull: true, - foreignKey: { - name: 'primary_event_id_fk', - table: 'event', - rules: { - onDelete: 'CASCADE', - onUpdate: 'RESTRICT' + }) + .addBatch({ + 'addForeign by addcolumn with spec': { + topic: function() { + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + event_id: { type: dataType.INTEGER, notNull: true }, + title: { type: dataType.STRING } + }, + function() { + db.createTable( + 'event_type', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + title: { type: dataType.STRING } }, - mapping: 'id' - } - }, this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, + function() { + db.addColumn( + 'event_type', + 'event_id', + { + type: dataType.INTEGER, + notNull: true, + foreignKey: { + name: 'primary_event_id_fk', + table: 'event', + rules: { + onDelete: 'CASCADE', + onUpdate: 'RESTRICT' + }, + mapping: 'id' + } + }, + this.callback.bind(this, null) + ); + }.bind(this) + ); + }.bind(this) + ); + }, - teardown: function() { - db.dropTable('event_type'); - db.dropTable('event', this.callback); - }, + teardown: function() { + db.dropTable('event_type') + .then(function(data) { + return db.dropTable('event'); + }) + .nodeify(this.callback); + }, - 'sets usage and constraints': { - topic: function() { - var metaQuery = ['SELECT', + 'sets usage and constraints': { + topic: function() { + var metaQuery = [ + 'SELECT', ' tc.table_schema, tc.table_name as ortn, kcu.column_name orcn, ccu.table_name,', ' ccu.column_name,', ' cstr.update_rule,', @@ -617,157 +900,210 @@ vows.describe('pg').addBatch({ 'WHERE', ' tc.table_schema = ?', ' AND tc.table_name = ?', - ' AND kcu.column_name = ?'].join('\n'); - db.runSql(metaQuery, ['public', 'event_type', 'event_id'], this.callback); - }, - - 'with correct references': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.table_name, 'event'); - assert.equal(row.column_name, 'id'); - }, - - 'and correct rules': function(err, result) { - var rows = result.rows; - assert.isNotNull(rows); - assert.equal(rows.length, 1); - var row = rows[0]; - assert.equal(row.update_rule, 'RESTRICT'); - assert.equal(row.delete_rule, 'CASCADE'); + ' AND kcu.column_name = ?' + ].join('\n'); + db.runSql( + metaQuery, + ['public', 'event_type', 'event_id'], + this.callback + ); + }, + + 'with correct references': function(err, result) { + var rows = result.rows; + assert.isNotNull(rows); + assert.equal(rows.length, 1); + var row = rows[0]; + assert.equal(row.table_name, 'event'); + assert.equal(row.column_name, 'id'); + }, + + 'and correct rules': function(err, result) { + var rows = result.rows; + assert.isNotNull(rows); + assert.equal(rows.length, 1); + var row = rows[0]; + assert.equal(row.update_rule, 'RESTRICT'); + assert.equal(row.delete_rule, 'CASCADE'); + } } } - } -}).addBatch({ - 'insert': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function(err) { - db.insert('event', ['id','title'], [2,'title'], this.callback.bind(this, null)); - }.bind(this)); - }, - - 'with additional row' : function() { - db.runSql("SELECT * from event", function(err, data) { + }) + .addBatch({ + insert: { + topic: function() { + db.createTable('event', { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + title: { type: dataType.STRING } + }) + .then(function() { + return db.insert('event', ['id', 'title'], [2, 'title']); + }) + .then(function() { + return db.runSql('SELECT * from event'); + }) + .nodeify(this.callback); + }, + + 'with additional row': function(err, data) { assert.equal(data.rowCount, 1); - }); - }, + }, - teardown: function() { - db.dropTable('event', this.callback); + teardown: function() { + db.dropTable('event', this.callback); + } } - } -}).addBatch({ - 'insertWithSingleQuotes': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: dataType.STRING } - }, function(err) { - db.insert('event', ['id','title'], [2,"Bill's Mother's House"], this.callback.bind(this, null)); - }.bind(this)); - }, - - 'with additional row' : function() { - db.runSql("SELECT * from event", function(err, data) { + }) + .addBatch({ + insertWithSingleQuotes: { + topic: function() { + db.createTable('event', { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + }, + title: { type: dataType.STRING } + }) + .then(function() { + return db.insert( + 'event', + ['id', 'title'], + [2, "Bill's Mother's House"] + ); + }) + .then(function() { + return db.runSql('SELECT * from event'); + }) + .nodeify(this.callback); + }, + + 'with additional row': function(err, data) { assert.equal(data.rowCount, 1); - }); - }, + }, - teardown: function() { - db.dropTable('event', this.callback); + teardown: function() { + db.dropTable('event', this.callback); + } } - } -}).addBatch({ - 'removeIndex': { - topic: function() { - db.createTable('event', { - id: { type: dataType.INTEGER, primaryKey: true, autoIncrement: true } - }, function() { - db.addIndex('event', 'event_title', 'title', function(err) { - db.removeIndex('event_title', this.callback.bind(this, null)); - }.bind(this)); - }.bind(this)); - }, - - 'has resulting index metadata': { + }) + .addBatch({ + removeIndex: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getIndexes('event', this.callback); - }.bind(this)); + db.createTable( + 'event', + { + id: { + type: dataType.INTEGER, + primaryKey: true, + autoIncrement: true + } + }, + function() { + db.addIndex( + 'event', + 'event_title', + 'title', + function(err) { + db.removeIndex('event_title', this.callback.bind(this, null)); + }.bind(this) + ); + }.bind(this) + ); }, - 'without index': function(err, indexes) { - assert.isNotNull(indexes); - assert.equal(indexes.length, 1); // first index is primary key - } - }, + 'has resulting index metadata': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getIndexes('event', this.callback); + }.bind(this) + ); + }, - teardown: function() { - db.dropTable('event', this.callback); - } - } -}).addBatch({ - 'createMigrationsTable': { - topic: function() { - db.createMigrationsTable(this.callback.bind(this, null)); - }, + 'without index': function(err, indexes) { + assert.isNotNull(indexes); + assert.equal(indexes.length, 1); // first index is primary key + } + }, - 'has migrations table': { + teardown: function() { + db.dropTable('event', this.callback); + } + } + }) + .addBatch({ + createMigrationsTable: { topic: function() { - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getTables(this.callback); - }.bind(this)); + db.createMigrationsTable(this.callback.bind(this, null)); }, - 'has migrations table' : function(err, tables) { - assert.isNull(err); - assert.isNotNull(tables); - assert.equal(tables.length,1); - assert.equal(tables[0].getName(), 'migrations'); - }, + 'has migrations table': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getTables(this.callback); + }.bind(this) + ); + }, - 'that has columns':{ - topic:function(){ - dbmeta('pg', { connection:db.connection}, function (err, meta) { - if (err) { - return this.callback(err); - } - meta.getColumns('migrations', this.callback); - }.bind(this)); + 'has migrations table': function(err, tables) { + assert.isNull(err); + assert.isNotNull(tables); + assert.equal(tables.length, 1); + assert.equal(tables[0].getName(), 'migrations'); }, - 'with names': function(err, columns){ - assert.isNotNull(columns); - assert.equal(columns.length, 3); - var column = findByName(columns, 'id'); - assert.equal(column.getName(), 'id'); - assert.equal(column.getDataType(), 'INTEGER'); - column = findByName(columns, 'name'); - assert.equal(column.getName(), 'name'); - assert.equal(column.getDataType(), 'CHARACTER VARYING'); - column = findByName(columns, 'run_on'); - assert.equal(column.getName(), 'run_on'); - assert.equal(column.getDataType(), 'TIMESTAMP WITHOUT TIME ZONE'); + 'that has columns': { + topic: function() { + dbmeta( + 'pg', + { connection: db.connection }, + function(err, meta) { + if (err) { + return this.callback(err); + } + meta.getColumns('migrations', this.callback); + }.bind(this) + ); + }, + + 'with names': function(err, columns) { + assert.isNotNull(columns); + assert.equal(columns.length, 3); + var column = findByName(columns, 'id'); + assert.equal(column.getName(), 'id'); + assert.equal(column.getDataType(), 'INTEGER'); + column = findByName(columns, 'name'); + assert.equal(column.getName(), 'name'); + assert.equal(column.getDataType(), 'CHARACTER VARYING'); + column = findByName(columns, 'run_on'); + assert.equal(column.getName(), 'run_on'); + assert.equal(column.getDataType(), 'TIMESTAMP WITHOUT TIME ZONE'); + } } - } - }, + }, - teardown: function() { - db.dropTable('migrations', this.callback); + teardown: function() { + db.dropTable('migrations', this.callback); + } } - } -}).export(module); + }) + .export(module); function findByName(columns, name) { for (var i = 0; i < columns.length; i++) {