| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| // Setup is called with the context of the current client. | ||
| exports.setup = function(Client, name, options) { | ||
| if (!options.connection) { | ||
| throw new Error('The database connection properties must be specified.'); | ||
| } | ||
| this.name = name; | ||
| this.debug = options.debug; | ||
| this.connectionSettings = options.connection; | ||
| this.grammar = Client.grammar; | ||
| this.schemaGrammar = Client.schemaGrammar; | ||
| // Extend the genericPool with the options | ||
| // passed into the init under the "pool" option. | ||
| var instance = this; | ||
| this.pool = require('generic-pool').Pool(_.extend({ | ||
| name: 'pool-' + name, | ||
| min: 2, | ||
| max: 10, | ||
| log: false, | ||
| idleTimeoutMillis: 30000, | ||
| create: function(callback) { | ||
| var conn = instance.getRawConnection(); | ||
| conn.__cid = _.uniqueId('__cid'); | ||
| callback(null, conn); | ||
| }, | ||
| destroy: function(client) { client.end(); } | ||
| }, this.poolDefaults, options.pool)); | ||
| }; | ||
| exports.skim = function(data) { | ||
| return _.map(data, function(obj) { | ||
| return _.pick(obj, _.keys(obj)); | ||
| }); | ||
| }; | ||
| exports.debug = function(builder, conn) { | ||
| console.log({sql: builder.sql, bindings: builder.bindings, __cid: conn.__cid}); | ||
| }; | ||
| exports.protoProps = { | ||
| // Retrieves a connection from the connection pool, | ||
| // returning a promise. | ||
| getConnection: function() { | ||
| return Q.ninvoke(this.pool, 'acquire'); | ||
| }, | ||
| // Releases a connection from the connection pool, | ||
| // returning a promise. | ||
| releaseConnection: function(conn) { | ||
| return Q.ninvoke(this.pool, 'release', conn); | ||
| }, | ||
| // Begins a transaction statement on the instance, | ||
| // resolving with the connection of the current transaction. | ||
| startTransaction: function() { | ||
| return this.getConnection().then(function(connection) { | ||
| return Q.ninvoke(connection, 'query', 'begin;', []).then(function() { | ||
| return connection; | ||
| }); | ||
| }); | ||
| }, | ||
| finishTransaction: function(type, trans, dfd) { | ||
| Q.ninvoke(trans.connection, 'query', type + ';', []).then(function() { | ||
| if (type === 'commit') dfd.resolve(resp); | ||
| if (type === 'rollback') dfd.reject(resp); | ||
| }).fin(function() { | ||
| trans.connection.end(); | ||
| trans.connection = null; | ||
| }); | ||
| } | ||
| }; | ||
| exports.grammar = {}; | ||
| exports.schemaGrammar = { | ||
| // Compile a create table command. | ||
| compileCreateTable: function(blueprint, command) { | ||
| var columns = this.getColumns(blueprint).join(', '); | ||
| return 'create table ' + this.wrapTable(blueprint) + ' (' + columns + ')'; | ||
| }, | ||
| // Compile a drop table command. | ||
| compileDropTable: function(blueprint, command) { | ||
| return 'drop table ' + this.wrapTable(blueprint); | ||
| }, | ||
| // Compile a drop table (if exists) command. | ||
| compileDropTableIfExists: function(blueprint, command) { | ||
| return 'drop table if exists ' + this.wrapTable(blueprint); | ||
| } | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| it('should truncate a table with truncate', function(ok) { | ||
| Knex('test_table_two') | ||
| .truncate() | ||
| .then(handler(function() {}), ok) | ||
| .then(function() { | ||
| if (type === 'String') return ok(); | ||
| Knex('test_table_two') | ||
| .select('*') | ||
| .then(function(resp) { | ||
| if (resp.length === 0) return ok(); | ||
| ok(resp); | ||
| }); | ||
| }); | ||
| }); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| it('has a sum', function(ok) { | ||
| Knex('accounts') | ||
| .sum('logins') | ||
| .then(handler(ok), ok); | ||
| }); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| it('should delete an item', function(ok) { | ||
| Knex('accounts') | ||
| .where({'email':'test2@example.com'}) | ||
| .del() | ||
| .then(handler(ok), ok); | ||
| }); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| describe(dbName, function() { | ||
| it("should handle simple inserts", function(ok) { | ||
| Knex('accounts').insert({ | ||
| first_name: 'Test', | ||
| last_name: 'User', | ||
| email:'test@example.com', | ||
| logins: 1, | ||
| about: 'Lorem ipsum Dolore labore incididunt enim.', | ||
| created_at: new Date(), | ||
| updated_at: new Date() | ||
| }).then(handler(ok), ok).then(function() { | ||
| Knex('test_table_two').insert({ | ||
| account_id: 1, | ||
| details: 'Lorem ipsum Minim nostrud Excepteur consectetur enim ut qui sint in veniam in nulla anim do cillum sunt voluptate Duis non incididunt.' | ||
| }).exec(); | ||
| }); | ||
| }); | ||
| it('should handle multi inserts', function (ok) { | ||
| Knex('accounts') | ||
| .insert([{ | ||
| first_name: 'Test', | ||
| last_name: 'User', | ||
| email:'test2@example.com', | ||
| logins: 1, | ||
| about: 'Lorem ipsum Dolore labore incididunt enim.', | ||
| created_at: new Date(), | ||
| updated_at: new Date() | ||
| }, { | ||
| first_name: 'Test', | ||
| last_name: 'User', | ||
| email:'test3@example.com', | ||
| about: 'Lorem ipsum Dolore labore incididunt enim.', | ||
| logins: 2, | ||
| created_at: new Date(), | ||
| updated_at: new Date() | ||
| }]).then(handler(ok), ok); | ||
| }); | ||
| it('should take hashes passed into insert and keep them in the correct order', function(ok) { | ||
| Knex('accounts').insert([{ | ||
| first_name: 'Test', | ||
| last_name: 'User', | ||
| email:'test4@example.com', | ||
| about: 'Lorem ipsum Dolore labore incididunt enim.', | ||
| logins: 2, | ||
| created_at: new Date(), | ||
| updated_at: new Date() | ||
| },{ | ||
| first_name: 'Test', | ||
| about: 'Lorem ipsum Dolore labore incididunt enim.', | ||
| logins: 2, | ||
| created_at: new Date(), | ||
| updated_at: new Date(), | ||
| last_name: 'User', | ||
| email:'test5@example.com' | ||
| }]) | ||
| .then(handler(ok), ok); | ||
| }); | ||
| it('will fail when multple inserts are made into a unique column', function(ok) { | ||
| if (type === 'String') return ok(); | ||
| Knex('accounts') | ||
| .where('id', '>', 1) | ||
| .orWhere('x', 2) | ||
| .insert({ | ||
| first_name: 'Test', | ||
| last_name: 'User', | ||
| email:'test5@example.com', | ||
| about: 'Lorem ipsum Dolore labore incididunt enim.', | ||
| logins: 2, | ||
| created_at: new Date(), | ||
| updated_at: new Date() | ||
| }) | ||
| .then(ok, function() { | ||
| ok(); | ||
| }); | ||
| }); | ||
| it('should drop any where clause bindings', function(ok) { | ||
| Knex('accounts') | ||
| .where('id', '>', 1) | ||
| .orWhere('x', 2) | ||
| .insert({ | ||
| first_name: 'Test', | ||
| last_name: 'User', | ||
| email:'test6@example.com', | ||
| about: 'Lorem ipsum Dolore labore incididunt enim.', | ||
| logins: 2, | ||
| created_at: new Date(), | ||
| updated_at: new Date() | ||
| }) | ||
| .then(handler(ok), ok); | ||
| }); | ||
| }); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| describe(dbName, function() { | ||
| it('uses inner join by default', function(ok) { | ||
| Knex('accounts') | ||
| .join('test_table_two', 'accounts.id', '=', 'test_table_two.account_id') | ||
| .select('accounts.*', 'test_table_two.details') | ||
| .then(handler(ok), ok); | ||
| }); | ||
| it('takes a fifth parameter to specify the join type', function(ok) { | ||
| Knex('accounts') | ||
| .join('test_table_two', 'accounts.id', '=', 'test_table_two.account_id', 'left') | ||
| .select('accounts.*', 'test_table_two.details') | ||
| .then(handler(ok), ok); | ||
| }); | ||
| it('accepts a callback as the second argument for advanced joins', function(ok) { | ||
| Knex('accounts').join('test_table_two', function(join) { | ||
| join.on('accounts.id', '=', 'test_table_two.account_id'); | ||
| join.orOn('accounts.email', '=', 'test_table_two.details'); | ||
| }, 'left') | ||
| .select() | ||
| .then(handler(ok), ok); | ||
| }); | ||
| }); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, handler, error, type, db) { | ||
| var res = null; | ||
| return Q.all([ | ||
| Knex.Schema.dropTableIfExists('test_table_one'), | ||
| Knex.Schema.dropTableIfExists('test_table_two'), | ||
| Knex.Schema.dropTableIfExists('test_table_three'), | ||
| Knex.Schema.dropTableIfExists('accounts') | ||
| ]).then(function(resp) { | ||
| res = [resp[0]]; // only really need one of these for the test output. | ||
| return Q.all([ | ||
| Knex.Schema.createTable('test_table_one', function(table) { | ||
| table.increments('id'); | ||
| table.string('first_name'); | ||
| table.string('last_name'); | ||
| table.string('email').unique().nullable(); | ||
| table.integer('logins').defaultTo(1).index(); | ||
| table.text('about'); | ||
| table.timestamps(); | ||
| }), | ||
| Knex.Schema.createTable('test_table_two', function(t) { | ||
| t.increments(); | ||
| t.integer('account_id'); | ||
| t.text('details'); | ||
| }), | ||
| Knex.Schema.createTable('test_table_three', function(table) { | ||
| table.integer('main').primary(); | ||
| table.text('paragraph').defaultTo('Lorem ipsum Qui quis qui in.'); | ||
| }) | ||
| ]); | ||
| }) | ||
| .then(function(resp) { | ||
| // Edit test table one | ||
| res = res.concat(resp); | ||
| return Knex.Schema.table('test_table_one', function(t) { | ||
| t.string('phone').nullable(); | ||
| }); | ||
| }).then(function(resp) { | ||
| // conditionally drops tables with `dropTableIfExists` | ||
| res.push(resp); | ||
| return Knex.Schema.dropTableIfExists('items'); | ||
| }) | ||
| .then(function(resp) { | ||
| res.push(resp); | ||
| return Knex.Schema.hasTable('test_table_two'); | ||
| }) | ||
| .then(function(resp) { | ||
| res.push(resp); | ||
| return Knex.Schema.renameTable('test_table_one', 'accounts'); | ||
| }) | ||
| .then(function(resp) { | ||
| res.push(resp); | ||
| return Knex.Schema.dropTable('test_table_three'); | ||
| }) | ||
| .then(function(resp) { | ||
| res.push(resp); | ||
| return res; | ||
| }) | ||
| .then(handler, error); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| describe(dbName, function() { | ||
| it('runs with no conditions', function(ok) { | ||
| Knex('accounts').select().then(handler(ok), ok); | ||
| }); | ||
| it('uses `orderBy`', function(ok) { | ||
| Knex('accounts') | ||
| .select() | ||
| .orderBy('id', 'asc').then(handler(ok), ok); | ||
| }), | ||
| it('does simple "where" cases', function(ok) { | ||
| Q.all([ | ||
| Knex('accounts').where('id', 1).select('first_name', 'last_name'), | ||
| Knex('accounts').where('id', '>', 1).select(['email', 'logins']), | ||
| Knex('accounts').where({'id': 1}).select('*'), | ||
| Knex('accounts').where({'id': void 0}).select('*'), | ||
| Knex('accounts').where({'id': null}).select('first_name', 'email'), | ||
| Knex('accounts').where({'id': 0}).select() | ||
| ]).then(handler(ok, true), ok); | ||
| }); | ||
| it('has a "distinct" clause', function(ok) { | ||
| Q.all([ | ||
| Knex('accounts').select().distinct('email').where('logins', 2), | ||
| Knex('accounts').distinct('email').select() | ||
| ]).then(handler(ok, true), ok); | ||
| }); | ||
| it('does "orWhere" cases', function(ok) { | ||
| Q.all([ | ||
| Knex('accounts').where('id', 1).orWhere('id', '>', 2).select('first_name', 'last_name') | ||
| // More tests can be added here. | ||
| ]).then(handler(ok, true), ok); | ||
| }); | ||
| it('does "andWhere" cases', function(ok) { | ||
| Q.all([ | ||
| Knex('accounts').select('first_name', 'last_name', 'about').where('id', 1).andWhere('email', 'test@example.com') | ||
| ]).then(handler(ok, true), ok); | ||
| }); | ||
| it('takes a function to wrap nested where statements', function(ok) { | ||
| Q.all([ | ||
| Knex('accounts').where(function() { | ||
| this.where('id', 2); | ||
| this.orWhere('id', 3); | ||
| }).select('*') | ||
| ]).then(handler(ok, true), ok); | ||
| }); | ||
| it('handles "where in" cases', function(ok) { | ||
| Q.all([ | ||
| Knex('accounts').whereIn('id', [1, 2, 3]).select() | ||
| ]).then(handler(ok, true), ok); | ||
| }); | ||
| it('handles "or where in" cases', function(ok) { | ||
| Knex('accounts') | ||
| .where('email', 'test@example.com') | ||
| .orWhereIn('id', [2, 3, 4]) | ||
| .select() | ||
| .then(handler(ok), ok); | ||
| }); | ||
| it('handles "where exists"', function(ok) { | ||
| Knex('accounts') | ||
| .whereExists(function(qb) { | ||
| this.select('id').from('test_table_two').where({id: 1}); | ||
| }) | ||
| .select() | ||
| .then(handler(ok), ok); | ||
| }); | ||
| it('handles "where between"', function(ok) { | ||
| Knex('accounts').whereBetween('id', [1, 100]) | ||
| .select() | ||
| .then(handler(ok), ok); | ||
| }); | ||
| it('handles "or where between"', function(ok) { | ||
| Knex('accounts') | ||
| .whereBetween('id', [1, 100]) | ||
| .orWhereBetween('id', [200, 300]) | ||
| .select() | ||
| .then(handler(ok), ok); | ||
| }); | ||
| }); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| describe(dbName, function() { | ||
| it('handles unions', function(ok) { | ||
| Knex('accounts') | ||
| .select('*') | ||
| .where('id', '=', 1) | ||
| .union(function() { | ||
| this.select('*').from('accounts').where('id', 2); | ||
| }) | ||
| .then(handler(ok), ok); | ||
| }); | ||
| }); | ||
| }; |
| var Q = require('q'); | ||
| module.exports = function(Knex, dbName, handler, type) { | ||
| describe(dbName, function() { | ||
| it('should handle updates', function(ok) { | ||
| Knex('accounts') | ||
| .where('id', 1) | ||
| .update({ | ||
| first_name: 'User', | ||
| last_name: 'Test', | ||
| email:'test-updated@example.com' | ||
| }) | ||
| .then(handler(ok), ok); | ||
| }); | ||
| }); | ||
| }; |
+109
| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| var objectdump = require('objectdump'); | ||
| var dev = parseInt(process.env.KNEX_DEV, 10); | ||
| var out = (dev ? require('./index').output : require('./shared/output')); | ||
| var assert = require('assert'); | ||
| module.exports = function(Knex, type) { | ||
| describe('DB Tests - ' + type, function() { | ||
| describe('Knex.Builder', function() { | ||
| before(function(ok) { | ||
| var val = handler(type, 'schema'); | ||
| require('./lib/schema')(Knex, function() { | ||
| ok(); | ||
| }, function(err) { | ||
| throw new Error(err); | ||
| }, type); | ||
| }); | ||
| describe('Inserts', function() { | ||
| require('./lib/inserts')(Knex, type, handler(type, 'inserts'), 'DB'); | ||
| }); | ||
| describe('Updates', function() { | ||
| require('./lib/updates')(Knex, type, handler(type, 'updates'), 'DB'); | ||
| }); | ||
| describe('Selects', function() { | ||
| require('./lib/selects')(Knex, type, handler(type, 'selects'), 'DB'); | ||
| }); | ||
| describe('Aggregate', function() { | ||
| require('./lib/aggregate')(Knex, type, handler(type, 'aggregate'), 'DB'); | ||
| }); | ||
| describe('Joins', function() { | ||
| require('./lib/joins')(Knex, type, handler(type, 'joins'), 'DB'); | ||
| }); | ||
| describe('Deletes', function() { | ||
| require('./lib/deletes')(Knex, type, handler(type, 'deletes'), 'DB'); | ||
| }); | ||
| describe('Aggregates, Truncate', function() { | ||
| require('./lib/additional')(Knex, type, handler(type, 'additional'), 'DB'); | ||
| }); | ||
| describe('Deletes', function() { | ||
| require('./lib/unions')(Knex, type, handler(type, 'unions'), 'DB'); | ||
| }); | ||
| after(function(ok) { | ||
| if (dev) require('fs').writeFileSync('./test/shared/output.js', 'module.exports = ' + objectdump(out)); | ||
| ok(); | ||
| }); | ||
| }); | ||
| }); | ||
| }; | ||
| var handler = function(instance, section) { | ||
| var item = 1; | ||
| return function(resolver, isAll) { | ||
| var fn = function(data) { | ||
| var label = '' + section + '.' + item; | ||
| if (dev) { | ||
| if (_.isArray(data)) data = _.map(data, omitDates); | ||
| out['db'] = out['db'] || {}; | ||
| out['db'][label] = out['db'][label] || {}; | ||
| out['db'][label][instance] = data; | ||
| } else { | ||
| var checkData = out['db'][label][instance]; | ||
| if (_.isArray(data)) { | ||
| data = _.map(data, omitDates); | ||
| checkData = _.map(checkData, omitDates); | ||
| } | ||
| try { | ||
| assert.deepEqual(checkData, data); | ||
| } catch (e) { | ||
| //console.log([checkData, data]); | ||
| } | ||
| } | ||
| item++; | ||
| if (!isAll) resolver(); | ||
| }; | ||
| if (isAll) { | ||
| return function(data) { | ||
| _.map(data, fn); | ||
| resolver(); | ||
| }; | ||
| } else { | ||
| return fn; | ||
| } | ||
| }; | ||
| }; | ||
| var omitDates = function(item) { | ||
| if (_.isObject(item)) { | ||
| return _.omit(item, 'created_at', 'updated_at'); | ||
| } | ||
| return item; | ||
| }; | ||
| module.exports = { | ||
| mysql: { | ||
| database: 'knex_test', | ||
| user: 'root', | ||
| encoding: 'utf8' | ||
| }, | ||
| postgres: { | ||
| adapter: 'postgresql', | ||
| database: 'knex_test', | ||
| user: 'postgres' | ||
| }, | ||
| sqlite3: { | ||
| filename: ':memory:' | ||
| } | ||
| }; |
Sorry, the diff of this file is too big to display
+100
| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| var objectdump = require('objectdump'); | ||
| var dev = parseInt(process.env.KNEX_DEV, 10); | ||
| var out = (dev ? require('./index').output : require('./shared/output')); | ||
| var assert = require('assert'); | ||
| module.exports = function(Knex, type) { | ||
| var dfd = Q.defer(); | ||
| describe('String Tests', function() { | ||
| before(function(ok) { | ||
| var val = handler(type, 'schema'); | ||
| require('./lib/schema')(Knex, val(ok, true), function(err) { | ||
| throw new Error(err); | ||
| }, 'String'); | ||
| }); | ||
| describe('Knex.Builder', function() { | ||
| describe('Inserts', function() { | ||
| require('./lib/inserts')(Knex, type, handler(type, 'inserts'), 'String'); | ||
| }); | ||
| describe('Updates', function() { | ||
| require('./lib/updates')(Knex, type, handler(type, 'updates'), 'String'); | ||
| }); | ||
| describe('Selects', function() { | ||
| require('./lib/selects')(Knex, type, handler(type, 'selects'), 'String'); | ||
| }); | ||
| describe('Aggregate', function() { | ||
| require('./lib/aggregate')(Knex, type, handler(type, 'aggregate'), 'String'); | ||
| }); | ||
| describe('Joins', function() { | ||
| require('./lib/joins')(Knex, type, handler(type, 'joins'), 'String'); | ||
| }); | ||
| describe('Deletes', function() { | ||
| require('./lib/deletes')(Knex, type, handler(type, 'deletes'), 'String'); | ||
| }); | ||
| describe('Additional', function() { | ||
| require('./lib/additional')(Knex, type, handler(type, 'additional'), 'String'); | ||
| }); | ||
| describe('Deletes', function() { | ||
| require('./lib/unions')(Knex, type, handler(type, 'unions'), 'String'); | ||
| }); | ||
| after(function(ok) { | ||
| if (dev) require('fs').writeFileSync('./test/shared/output.js', 'module.exports = ' + objectdump(out)); | ||
| dfd.resolve(); | ||
| ok(); | ||
| }); | ||
| }); | ||
| }); | ||
| return dfd.promise; | ||
| }; | ||
| var handler = function(instance, section) { | ||
| var item = 1; | ||
| return function(resolver, isAll) { | ||
| var fn = function(data) { | ||
| var label = '' + section + '.' + item; | ||
| if (dev) { | ||
| out['string'] = out['string'] || {}; | ||
| out['string'][label] = out['string'][label] || {}; | ||
| out['string'][label][instance] = data; | ||
| } else { | ||
| var checkData = out['string'][label][instance]; | ||
| assert.deepEqual(checkData.sql, data.sql); | ||
| var a = _.map(checkData.bindings, function(val) { return (_.isDate(val) ? 'newDate' : val); }); | ||
| var b = _.map(data.bindings, function(val) { return (_.isDate(val) ? 'newDate' : val); }); | ||
| try { | ||
| assert.deepEqual(a, b); | ||
| } catch (e) { | ||
| //console.log([a, b]); | ||
| } | ||
| } | ||
| item++; | ||
| if (!isAll) resolver(); | ||
| }; | ||
| if (isAll) { | ||
| return function(data) { | ||
| _.map(data, fn); | ||
| resolver(); | ||
| }; | ||
| } else { | ||
| return fn; | ||
| } | ||
| }; | ||
| }; |
+7
-1
| # .travis.yml | ||
| language: node_js | ||
| node_js: | ||
| - 0.11 | ||
| - 0.10 | ||
| - 0.8 | ||
| - 0.6 | ||
| - 0.6 | ||
| before_script: | ||
| - psql -c 'create database knex_test;' -U postgres | ||
| - mysql -e 'create database knex_test;' |
+66
-118
@@ -1,112 +0,68 @@ | ||
| var mysql = require('mysql'); | ||
| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| var util = require('util'); | ||
| var genericPool = require('generic-pool'); | ||
| var base = require('./base'); | ||
| var mysql = require('mysql'); | ||
| // Constructor for the MysqlClient | ||
| var MysqlClient = module.exports = function(name, options) { | ||
| if (!options.connection) { | ||
| throw new Error('The database connection properties must be specified.'); | ||
| } | ||
| this.name = name; | ||
| this.debug = options.debug; | ||
| this.connectionSettings = options.connection; | ||
| // Extend the genericPool with the options | ||
| // passed into the init under the "pool" option | ||
| var instance = this; | ||
| this.pool = genericPool.Pool(_.extend({ | ||
| name : 'pool' + name, | ||
| create : function(callback) { | ||
| callback(null, instance.getConnection()); | ||
| }, | ||
| destroy : function(client) { | ||
| client.end(); | ||
| }, | ||
| max : 10, | ||
| min : 2, | ||
| idleTimeoutMillis: 30000, | ||
| log : false | ||
| }, options.pool)); | ||
| this.grammar = MysqlClient.grammar; | ||
| this.schemaGrammar = MysqlClient.schemaGrammar; | ||
| base.setup.call(this, MysqlClient, name, options); | ||
| }; | ||
| _.extend(MysqlClient.prototype, { | ||
| _.extend(MysqlClient.prototype, base.protoProps, { | ||
| // Execute a query on the database. | ||
| // If the fourth parameter is set, this will be used as the connection | ||
| // to the database. | ||
| query: function (data, connection) { | ||
| // Execute a query on the specified Builder or QueryBuilder | ||
| // interface. If a `connection` is specified, use it, otherwise | ||
| // acquire a connection, and then dispose of it when we're done. | ||
| query: function(builder) { | ||
| var emptyConnection = !builder._connection; | ||
| var debug = this.debug || builder._debug; | ||
| var instance = this; | ||
| return Q((builder._connection || this.getConnection())) | ||
| .then(function(conn) { | ||
| var dfd = Q.defer(); | ||
| var dfd = Q.defer(); | ||
| // If we have a debug flag set, console.log the query. | ||
| if (debug) base.debug(builder, conn); | ||
| // Call the querystring and then release the client | ||
| conn.query(builder.sql, builder.bindings, function (err, resp) { | ||
| if (err) { return dfd.reject(err); } | ||
| if (builder._source === 'SchemaBuilder') { | ||
| if (builder.type === 'tableExists') { | ||
| if (resp.length > 0) return dfd.resolve(_.pick(resp, _.keys(resp))); | ||
| return dfd.reject(new Error('Table does not exist:' + builder.sql)); | ||
| } else { | ||
| return dfd.resolve(null); | ||
| } | ||
| } | ||
| if (this.debug) { | ||
| if (connection) data.__cid = connection.__cid; | ||
| console.log(data); | ||
| } | ||
| if (builder.type === 'select') { | ||
| resp = base.skim(resp); | ||
| } else if (builder.type === 'insert') { | ||
| resp = [resp.insertId]; | ||
| } else if (builder.type === 'delete' || builder.type === 'update') { | ||
| resp = resp.affectedRows; | ||
| } else { | ||
| resp = ''; | ||
| } | ||
| // If there is a specific connection specified, use that. | ||
| if (connection) { | ||
| dfd.resolve(resp); | ||
| }); | ||
| connection.query(data.sql, (data.bindings || []), function(err, res) { | ||
| if (err) return dfd.reject(err); | ||
| dfd.resolve(res); | ||
| }); | ||
| } else { | ||
| // Acquire connection - callback function is called | ||
| // once a resource becomes available. | ||
| var instance = this; | ||
| this.pool.acquire(function(err, client) { | ||
| if (err) return dfd.reject(err); | ||
| // Make the query and then release the client. | ||
| client.query(data.sql, (data.bindings || []), function (err, res) { | ||
| instance.pool.release(client); | ||
| if (err) return dfd.reject(err); | ||
| dfd.resolve(res); | ||
| // Empty the connection after we run the query, unless one was specifically | ||
| // set (in the case of transactions, etc). | ||
| return dfd.promise.fin(function() { | ||
| if (emptyConnection) instance.pool.release(conn); | ||
| }); | ||
| }); | ||
| } | ||
| return dfd.promise; | ||
| }, | ||
| // Returns a mysql connection, with a __cid property uniquely | ||
| // identifying the connection. | ||
| getConnection: function () { | ||
| var connection = mysql.createConnection(this.connectionSettings); | ||
| connection.connect(); | ||
| connection.__cid = _.uniqueId('__cid'); | ||
| return connection; | ||
| }, | ||
| getRawConnection: function() { | ||
| var conn = mysql.createConnection(this.connectionSettings); | ||
| conn.connect(); | ||
| return conn; | ||
| } | ||
| // Begins a transaction statement on the instance, | ||
| // resolving with the connection of the current transaction. | ||
| startTransaction: function() { | ||
| var dfd = Q.defer(); | ||
| var connection = this.getConnection(); | ||
| connection.query('begin;', [], function(err) { | ||
| if (err) dfd.reject(err); | ||
| dfd.resolve(connection); | ||
| }); | ||
| return dfd.promise; | ||
| }, | ||
| finishTransaction: function(type, trans, promise) { | ||
| trans.connection.query(type + ';', [], function(err, resp) { | ||
| trans.connection.end(); | ||
| trans.connection = null; | ||
| if (type === 'commit') promise.resolve(resp); | ||
| if (type === 'rollback') promise.reject(resp); | ||
| }); | ||
| } | ||
| }); | ||
@@ -125,3 +81,3 @@ | ||
| // Grammar for the schema builder. | ||
| MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, { | ||
| MysqlClient.schemaGrammar = _.extend({}, base.schemaGrammar, MysqlClient.grammar, { | ||
@@ -132,12 +88,7 @@ // The possible column modifiers. | ||
| // Compile the query to determine if a table exists. | ||
| compileTableExists: function() { | ||
| compileTableExists: function(blueprint) { | ||
| blueprint.bindings.unshift(blueprint.client.connectionSettings.database); | ||
| return 'select * from information_schema.tables where table_schema = ? and table_name = ?'; | ||
| }, | ||
| // Compile a create table command. | ||
| compileCreateTable: function(blueprint, command) { | ||
| var columns = this.getColumns(blueprint).join(', '); | ||
| return 'create table ' + this.wrapTable(blueprint) + ' (' + columns + ')'; | ||
| }, | ||
| // Compile an add command. | ||
@@ -151,3 +102,3 @@ compileAdd: function(blueprint, command) { | ||
| compilePrimary: function(blueprint, command) { | ||
| command.name(null); | ||
| command.name = null; | ||
| return this.compileKey(blueprint, command, 'primary key'); | ||
@@ -172,12 +123,2 @@ }, | ||
| }, | ||
| // Compile a drop table command. | ||
| compileDropTable: function(blueprint, command) { | ||
| return 'drop table ' + this.wrapTable(blueprint); | ||
| }, | ||
| // Compile a drop table (if exists) command. | ||
| compileDropTableIfExists: function(blueprint, command) { | ||
| return 'drop table if exists ' + this.wrapTable(blueprint); | ||
| }, | ||
@@ -211,3 +152,3 @@ // Compile a drop column command. | ||
| // Compile a rename table command. | ||
| compileRename: function(blueprint, command) { | ||
| compileRenameTable: function(blueprint, command) { | ||
| return 'rename table ' + this.wrapTable(blueprint) + ' to ' + this.wrapTable(command.to); | ||
@@ -297,5 +238,3 @@ }, | ||
| modifyUnsigned: function(blueprint, column) { | ||
| if (column.type == 'integer' && column.isUnsigned) { | ||
| return ' unsigned'; | ||
| } | ||
| if (column.isUnsigned) return ' unsigned'; | ||
| }, | ||
@@ -310,3 +249,4 @@ | ||
| modifyDefault: function(blueprint, column) { | ||
| if (column.defaultValue) { | ||
| // TODO - no default on blob/text | ||
| if (column.defaultValue && column.type != 'blob' && column.type.indexOf('text') === -1) { | ||
| return " default '" + this.getDefaultValue(column.defaultValue) + "'"; | ||
@@ -321,3 +261,11 @@ } | ||
| } | ||
| }, | ||
| // Get the SQL for an "after" column modifier. | ||
| modifyAfter: function(blueprint, column) { | ||
| if (column.isAfter) { | ||
| return ' after ' + this.wrap(column.isAfter); | ||
| } | ||
| } | ||
| }); |
+83
-122
@@ -0,112 +1,80 @@ | ||
| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| var util = require('util'); | ||
| var base = require('./base'); | ||
| var pg = require('pg'); | ||
| var pg = require('pg'); | ||
| // Constructor for the PostgresClient | ||
| var PostgresClient = module.exports = function(name, options) { | ||
| base.setup.call(this, PostgresClient, name, options); | ||
| }; | ||
| var _ = require('underscore'); | ||
| var util = require('util'); | ||
| var genericPool = require('generic-pool'); | ||
| _.extend(PostgresClient.prototype, base.protoProps, { | ||
| var init, debug, pool, connection, connectionSettings; | ||
| // Execute a query on the specified Builder or QueryBuilder | ||
| // interface. If a `connection` is specified, use it, otherwise | ||
| // acquire a connection, and then dispose of it when we're done. | ||
| query: function(builder) { | ||
| var emptyConnection = !builder._connection; | ||
| var debug = this.debug || builder._debug; | ||
| var instance = this; | ||
| return Q((builder._connection || this.getConnection())) | ||
| .then(function(conn) { | ||
| var dfd = Q.defer(); | ||
| // Initializes the postgres module with an options hash, | ||
| // containing the connection settings, as well as the | ||
| // pool config settings | ||
| exports.initialize = function (options) { | ||
| // Bind all of the ? to numbered vars. | ||
| var questionCount = 0; | ||
| builder.sql = builder.sql.replace(/\?/g, function() { | ||
| questionCount++; | ||
| return '$' + questionCount; | ||
| }); | ||
| // If we have a debug flag set, console.log the query. | ||
| if (debug) base.debug(builder, conn); | ||
| // If there isn't a connection setting | ||
| if (!options.connection) return; | ||
| // Call the querystring and then release the client | ||
| conn.query(builder.sql, builder.bindings, function (err, resp) { | ||
| if (err) return dfd.reject(err); | ||
| resp || (resp = {}); | ||
| connectionSettings = options.connection; | ||
| debug = options.debug; | ||
| if (builder._source === 'SchemaBuilder') { | ||
| if (builder.type === 'tableExists') { | ||
| if (resp.rows.length > 0) return dfd.resolve(resp.rows[0]); | ||
| return dfd.reject(new Error('Table does not exist:' + builder.sql)); | ||
| } else { | ||
| return dfd.resolve(null); | ||
| } | ||
| } | ||
| // If pooling is disabled, set the query getter to | ||
| // something below and create a connection on the connection object | ||
| if (options.pool === false) { | ||
| pool = false; | ||
| connection = this.getConnection(); | ||
| return; | ||
| } | ||
| if (resp.command === 'SELECT') { | ||
| resp = resp.rows; | ||
| } else if (resp.command === 'INSERT') { | ||
| resp = _.map(resp.rows, function(row) { return row[builder._idAttribute]; }); | ||
| } else if (resp.command === 'UPDATE' || resp.command === 'DELETE') { | ||
| resp = resp.rowCount; | ||
| } else { | ||
| resp = ''; | ||
| } | ||
| dfd.resolve(resp); | ||
| }); | ||
| // Extend the genericPool with the options | ||
| // passed into the init under the "pool" option | ||
| pool = genericPool.Pool(_.extend({ | ||
| name : 'postgres', | ||
| create : function(callback) { | ||
| callback(null, exports.getConnection()); | ||
| }, | ||
| destroy : function(client) { | ||
| client.end(); | ||
| }, | ||
| max : 10, | ||
| min : 2, | ||
| idleTimeoutMillis: 30000, | ||
| log : false | ||
| }, options.pool)); | ||
| }; | ||
| // Empty the connection after we run the query, unless one was specifically | ||
| // set (in the case of transactions, etc). | ||
| return dfd.promise.fin(function() { | ||
| if (emptyConnection) instance.pool.release(conn); | ||
| }); | ||
| }); | ||
| }, | ||
| exports.beginTransaction = function(callback) { | ||
| var connection = this.getConnection(); | ||
| this.query("begin;", null, function(err) { | ||
| callback(err, connection); | ||
| }, connection); | ||
| }; | ||
| exports.commitTransaction = function(connection, callback) { | ||
| this.query("commit;", null, callback, connection); | ||
| }; | ||
| exports.rollbackTransaction = function(connection, callback) { | ||
| this.query("rollback;", null, callback, connection); | ||
| }; | ||
| // Execute a query on the database. | ||
| // If the fourth parameter is set, this will be used as the connection | ||
| // to the database. | ||
| exports.query = function (querystring, params, callback, connection) { | ||
| if (debug) console.log([querystring, params]); | ||
| // If there is a connection, use it. | ||
| if (connection) { | ||
| return connection.query(querystring, params, callback); | ||
| // Returns a connection from the `pg` lib. | ||
| getRawConnection: function() { | ||
| var conn = new pg.Client(this.connectionSettings); | ||
| conn.connect(); | ||
| return conn; | ||
| } | ||
| // Bind all of the ? to numbered vars. | ||
| var questionCount = 0; | ||
| querystring = querystring.replace(/\?/g, function () { | ||
| questionCount++; | ||
| return '$' + questionCount; | ||
| }); | ||
| }); | ||
| // Acquire connection - callback function is called | ||
| // once a resource becomes available. | ||
| pool.acquire(function(err, client) { | ||
| if (err) throw new Error(err); | ||
| // Call the querystring and then release the client | ||
| client.query(querystring, params, function (err, resp) { | ||
| pool.release(client); | ||
| resp || (resp = {}); | ||
| if (resp.command === 'INSERT' || resp.command === 'UPDATE') { | ||
| _.extend(resp, {insertId: resp.oid}); | ||
| callback.call(this, err, resp); | ||
| } else { | ||
| callback.call(this, err, resp.rows); | ||
| } | ||
| }); | ||
| }); | ||
| }; | ||
| // Returns a pg connection, with a __cid property uniquely | ||
| // identifying the connection. | ||
| exports.getConnection = function () { | ||
| var connection = new pg.Client(connectionSettings); | ||
| connection.connect(); | ||
| connection.__cid = _.uniqueId('__cid'); | ||
| return connection; | ||
| }; | ||
| // Extends the standard sql grammar. | ||
| var grammar = exports.grammar = { | ||
| PostgresClient.grammar = { | ||
@@ -118,11 +86,20 @@ // The keyword identifier wrapper format. | ||
| compileTruncate: function (qb) { | ||
| var query = {}; | ||
| query['truncate ' + this.wrapTable(qb.from) + ' restart identity'] = []; | ||
| return query; | ||
| compileTruncate: function(qb) { | ||
| return 'truncate ' + this.wrapTable(qb.table) + ' restart identity'; | ||
| }, | ||
| // Compiles an `insert` query, allowing for multiple | ||
| // inserts using a single query statement. | ||
| compileInsert: function(qb) { | ||
| var sql = require('../knex').Grammar.compileInsert.call(this, qb); | ||
| if (qb._idAttribute) { | ||
| sql += ' returning "' + qb._idAttribute + '"'; | ||
| } | ||
| return sql; | ||
| } | ||
| }; | ||
| // Grammar for the schema builder. | ||
| exports.schemaGrammar = _.extend({}, grammar, { | ||
| PostgresClient.schemaGrammar = _.extend({}, base.schemaGrammar, PostgresClient.grammar, { | ||
@@ -138,8 +115,2 @@ // The possible column modifiers. | ||
| // Compile a create table command. | ||
| compileCreateTable: function(blueprint, command) { | ||
| var columns = this.getColumns(blueprint).join(', '); | ||
| return 'create table ' + this.wrapTable(blueprint) + " (" + columns + ")"; | ||
| }, | ||
| // Compile a create table command. | ||
| compileAdd: function(blueprint, command) { | ||
@@ -161,3 +132,3 @@ var table = this.wrapTable(blueprint); | ||
| var columns = this.columnize(command.columns); | ||
| return 'alter table table add constraint ' + command.index + ' unique (' + columns + ')'; | ||
| return 'alter table ' + table + ' add constraint ' + command.index + ' unique (' + columns + ')'; | ||
| }, | ||
@@ -171,12 +142,2 @@ | ||
| // Compile a drop table command. | ||
| compileDropTable: function(blueprint, command) { | ||
| return 'drop table ' + this.wrapTable(blueprint); | ||
| }, | ||
| // Compile a drop table (if exists) command. | ||
| compileDropTableIfExists: function(blueprint, command) { | ||
| return 'drop table if exists ' + this.wrapTable(blueprint); | ||
| }, | ||
| // Compile a drop column command. | ||
@@ -213,3 +174,3 @@ compileDropColumn: function(blueprint, command) { | ||
| // Compile a rename table command. | ||
| compileRename: function(blueprint, command) { | ||
| compileRenameTable: function(blueprint, command) { | ||
| return 'alter table ' + this.wrapTable(blueprint) + ' rename to ' + this.wrapTable(command.to); | ||
@@ -255,3 +216,3 @@ }, | ||
| typeEnum: function(column) { | ||
| return 'varchar(255)'; | ||
| return "enum('" + column.allowed.join("', '") + "')"; | ||
| }, | ||
@@ -258,0 +219,0 @@ |
+76
-106
@@ -0,101 +1,79 @@ | ||
| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| var util = require('util'); | ||
| var base = require('./base'); | ||
| var sqlite3 = require('sqlite3'); | ||
| var sqlite3 = require('sqlite3'); | ||
| // Constructor for the Sqlite3Client | ||
| var Sqlite3Client = module.exports = function(name, options) { | ||
| base.setup.call(this, Sqlite3Client, name, options); | ||
| }; | ||
| var _ = require('underscore'); | ||
| var util = require('util'); | ||
| var genericPool = require('generic-pool'); | ||
| _.extend(Sqlite3Client.prototype, base.protoProps, { | ||
| var init, debug, pool, connection, connectionSettings; | ||
| // Execute a query on the specified Builder or QueryBuilder | ||
| // interface. If a `connection` is specified, use it, otherwise | ||
| // acquire a connection, and then dispose of it when we're done. | ||
| query: function(builder) { | ||
| var emptyConnection = !builder._connection; | ||
| var debug = this.debug || builder._debug; | ||
| var instance = this; | ||
| return Q((builder._connection || this.getConnection())) | ||
| .then(function(conn) { | ||
| var dfd = Q.defer(); | ||
| var method = (builder.type === 'insert' || builder.type === 'update') ? 'run' : 'all'; | ||
| // Initializes the sqlite3 module with an options hash, | ||
| // containing the connection settings, as well as the | ||
| // pool config settings | ||
| exports.initialize = function (options) { | ||
| // If we have a debug flag set, console.log the query. | ||
| if (debug) base.debug(builder, conn); | ||
| // Call the querystring and then release the client | ||
| conn[method](builder.sql, builder.bindings, function (err, resp) { | ||
| if (err) return dfd.reject(err); | ||
| // If there isn't a connection setting | ||
| if (!options.connection) return; | ||
| if (builder._source === 'SchemaBuilder') { | ||
| if (builder.type === 'tableExists') { | ||
| if (resp.length > 0) return dfd.resolve(_.pick(resp, _.keys(resp))); | ||
| return dfd.reject(new Error('Table does not exist:' + builder.sql)); | ||
| } else { | ||
| return dfd.resolve(null); | ||
| } | ||
| } | ||
| connectionSettings = options.connection; | ||
| debug = options.debug; | ||
| if (builder.type === 'select') { | ||
| resp = base.skim(resp); | ||
| } else if (builder.type === 'insert') { | ||
| resp = [this.lastID]; | ||
| } else if (builder.type === 'delete' || builder.type === 'update') { | ||
| resp = this.changes; | ||
| } else { | ||
| resp = ''; | ||
| } | ||
| // If pooling is disabled, set the query getter to | ||
| // something below and create a connection on the connection object | ||
| if (options.pool === false) { | ||
| pool = false; | ||
| connection = this.getConnection(); | ||
| return; | ||
| } | ||
| dfd.resolve(resp); | ||
| }); | ||
| // Extend the genericPool with the options | ||
| // passed into the init under the "pool" option | ||
| pool = genericPool.Pool(_.extend({ | ||
| name : 'sqlite3', | ||
| create : function(callback) { | ||
| var conn = exports.getConnection(); | ||
| // Set to allow multiple connections on the database. | ||
| conn.run("PRAGMA journal_mode=WAL;", function () { | ||
| callback(null, conn); | ||
| // Empty the connection after we run the query, unless one was specifically | ||
| // set (in the case of transactions, etc). | ||
| return dfd.promise.fin(function(resp) { | ||
| if (emptyConnection) instance.pool.release(conn); | ||
| return resp; | ||
| }); | ||
| }); | ||
| }, | ||
| destroy : function(client) { | ||
| client.close(); | ||
| }, | ||
| max : 1, | ||
| min : 1, | ||
| idleTimeoutMillis: 30000, | ||
| log : false | ||
| }, options.pool)); | ||
| }; | ||
| }, | ||
| exports.query = function (querystring, params, callback, connection, type) { | ||
| poolDefaults: { | ||
| max: 1, | ||
| min: 1, | ||
| destroy: function(client) { client.close(); } | ||
| }, | ||
| if (debug) console.log([querystring, params]); | ||
| // If there is a connection, use it. | ||
| if (connection) { | ||
| return connection.run(querystring, params, callback); | ||
| getRawConnection: function() { | ||
| return new sqlite3.Database(this.connectionSettings.filename); | ||
| } | ||
| // Acquire connection - callback function is called | ||
| // once a resource becomes available. | ||
| pool.acquire(function(err, client) { | ||
| }); | ||
| if (err) throw new Error(err); | ||
| var method = (type === 'insert' || type === 'update') ? 'run' : 'all'; | ||
| // Call the querystring and then release the client | ||
| client[method](querystring, params, function (err, resp) { | ||
| if (_.has(this, 'lastID')) resp = {insertId: this.lastID, changes: this.changes}; | ||
| pool.release(client); | ||
| callback.call(this, err, resp); | ||
| }); | ||
| }); | ||
| }; | ||
| exports.beginTransaction = function(callback) { | ||
| var connection = this.getConnection(); | ||
| this.query("begin;", null, function(err) { | ||
| callback(err, connection); | ||
| }, connection); | ||
| }; | ||
| exports.commitTransaction = function(connection, callback) { | ||
| this.query("commit;", null, callback, connection); | ||
| }; | ||
| exports.rollbackTransaction = function(connection, callback) { | ||
| this.query("rollback;", null, callback, connection); | ||
| }; | ||
| // Returns a mysql connection, with a __cid property uniquely | ||
| // identifying the connection. | ||
| exports.getConnection = function () { | ||
| var connection = new sqlite3.Database(connectionSettings.filename); | ||
| connection.__cid = _.uniqueId('__cid'); | ||
| return connection; | ||
| }; | ||
| // Extends the standard sql grammar. | ||
| var grammar = exports.grammar = { | ||
| Sqlite3Client.grammar = { | ||
@@ -116,4 +94,4 @@ // The keyword identifier wrapper format. | ||
| // Compile an insert statement into SQL. | ||
| compileInsert: function(qb, values) { | ||
| if (!_.isArray(values)) values = [values]; | ||
| compileInsert: function(qb) { | ||
| var values = qb.values; | ||
| var table = this.wrapTable(qb.table); | ||
@@ -127,6 +105,6 @@ var parameters = this.parameterize(values[0]); | ||
| if (values.length === 1) { | ||
| return require('../knex').Grammar.prototype.compileInsert.call(this, qb, values); | ||
| return require('../knex').Grammar.compileInsert.call(this, qb); | ||
| } | ||
| var keys = _.keys(values[0]); | ||
| var keys = _.keys(values[0]).sort(); | ||
| var names = this.columnize(keys); | ||
@@ -149,3 +127,3 @@ var columns = []; | ||
| return "insert into " + table + " (" + names + ") select " + columns.join(' union select '); | ||
| return "insert into " + table + " (" + names + ") select " + columns.join(' union all select '); | ||
| }, | ||
@@ -155,5 +133,6 @@ | ||
| compileTruncate: function (qb) { | ||
| var sql = {}; | ||
| sql['delete from sqlite_sequence where name = ?'] = [qb.from]; | ||
| sql['delete from ' + this.wrapTable(query.from)] = []; | ||
| var sql = []; | ||
| var table = this.wrapTable(qb.table); | ||
| sql.push('delete from sqlite_sequence where name = ' + table); | ||
| sql.push('delete from ' + table); | ||
| return sql; | ||
@@ -164,3 +143,3 @@ } | ||
| // Grammar for the schema builder. | ||
| exports.schemaGrammar = _.extend({}, grammar, { | ||
| Sqlite3Client.schemaGrammar = _.extend({}, base.schemaGrammar, Sqlite3Client.grammar, { | ||
@@ -186,2 +165,3 @@ // The possible column modifiers. | ||
| sql +=')'; | ||
| return sql; | ||
@@ -246,12 +226,2 @@ }, | ||
| // Compile a drop table command. | ||
| compileDropTable: function(blueprint, command) { | ||
| return 'drop table ' + this.wrapTable(blueprint); | ||
| }, | ||
| // Compile a drop table (if exists) command. | ||
| compileDropTableIfExists: function(blueprint, command) { | ||
| return 'drop table if exists ' + this.wrapTable(blueprint); | ||
| }, | ||
| // Compile a drop column command. | ||
@@ -273,3 +243,3 @@ compileDropColumn: function(blueprint, command) { | ||
| // Compile a rename table command. | ||
| compileRename: function(blueprint, command) { | ||
| compileRenameTable: function(blueprint, command) { | ||
| return 'alter table ' + this.wrapTable(blueprint) + ' rename to ' + this.wrapTable(command.to); | ||
@@ -345,3 +315,3 @@ }, | ||
| modifyNullable: function(blueprint, column) { | ||
| return column.nullable ? ' null' : ' not null'; | ||
| return ' null'; | ||
| }, | ||
@@ -348,0 +318,0 @@ |
+439
-291
@@ -1,2 +0,2 @@ | ||
| // Knex.js 0.1.0 | ||
| // Knex.js 0.0.0 | ||
| // | ||
@@ -19,3 +19,3 @@ // (c) 2013 Tim Griesser | ||
| var Knex = function(table) { | ||
| return new Knex.Builder(table, Knex.client); | ||
| return new Knex.Builder(table); | ||
| }; | ||
@@ -26,12 +26,77 @@ | ||
| // Methods common to both the `Grammar` and `SchemaGrammar` interfaces, | ||
| // used to generate the sql in one form or another. | ||
| var Common = { | ||
| _debug: false, | ||
| debug: function(val) { | ||
| this._debug = val; | ||
| return this; | ||
| }, | ||
| // For those who dislike promise interfaces. | ||
| exec: function(callback) { | ||
| var run = Knex.runQuery(this); | ||
| return run.nodeify(callback); | ||
| }, | ||
| // The promise interface for the query builder. | ||
| then: function(onFulfilled, onRejected) { | ||
| var run = Knex.runQuery(this); | ||
| return run.then(onFulfilled, onRejected); | ||
| }, | ||
| // Specifies to resolve the statement with the `data` rather | ||
| // than a promise... useful in testing/debugging. | ||
| toString: function() { | ||
| if (!this.type) { | ||
| throw new Error('Cannot be converted to string'); | ||
| } | ||
| var data = this.toSql(); | ||
| var builder = this; | ||
| if (!_.isArray(data)) data = [data]; | ||
| return _.map(data, function(str) { | ||
| var questionCount = 0; | ||
| return str.replace(/\?/g, function() { | ||
| return builder.bindings[questionCount++]; | ||
| }); | ||
| }).join('; '); | ||
| }, | ||
| // Sets the connection | ||
| connection: function(connection) { | ||
| this._connection = connection; | ||
| return this; | ||
| }, | ||
| // The connection the current query is being run on, optionally | ||
| // specified by the `connection` method. | ||
| _connection: false, | ||
| // Sets the "type" of the current query, so we can potentially place | ||
| // `select`, `update`, `del`, etc. anywhere in the query statement | ||
| // and have it come out fine. | ||
| _setType: function(type) { | ||
| if (this.type) { | ||
| throw new Error('The query type has already been set to ' + this.type); | ||
| } | ||
| this.type = type; | ||
| return this; | ||
| }, | ||
| // Returns all bindings excluding the `Knex.Raw` types. | ||
| _cleanBindings: function() { | ||
| var bindings = this.bindings; | ||
| var cleaned = []; | ||
| for (var i = 0, l = bindings.length; i < l; i++) { | ||
| if (!(bindings[i] instanceof Raw)) cleaned.push(bindings[i]); | ||
| } | ||
| return cleaned; | ||
| } | ||
| }; | ||
| // Grammar | ||
| // ------- | ||
| // Creates a new Grammar, with the mixins for the | ||
| // specified query dialect, which are defined in each | ||
| // client's `exports.grammar`. | ||
| var Grammar = function(mixins) { | ||
| _.extend(this, mixins); | ||
| }; | ||
| // The list of different components | ||
@@ -41,6 +106,6 @@ var components = [ | ||
| 'joins', 'wheres', 'groups', 'havings', | ||
| 'orders', 'limit', 'offset' | ||
| 'orders', 'limit', 'offset', 'unions' | ||
| ]; | ||
| Grammar.prototype = { | ||
| Knex.Grammar = { | ||
@@ -57,4 +122,5 @@ dateFormat: 'Y-m-d H:i:s', | ||
| var component = components[i]; | ||
| if (_.result(qb, component) != null) { | ||
| sql[component] = this['compile' + capitalize(component)](qb, _.result(qb, component)); | ||
| var result = _.result(qb, component); | ||
| if (result != null) { | ||
| sql[component] = this['compile' + capitalize(component)](qb, result); | ||
| } | ||
@@ -66,8 +132,8 @@ } | ||
| // Compiles an aggregate query. | ||
| compileAggregate: function(qb, aggregate) { | ||
| var column = this.columnize(aggregate.columns); | ||
| compileAggregate: function(qb) { | ||
| var column = this.columnize(qb.aggregate.columns); | ||
| if (qb.isDistinct && column !== '*') { | ||
| column = 'distinct ' + column; | ||
| } | ||
| return 'select ' + aggregate.type + '(' + column + ') as aggregate'; | ||
| return 'select ' + qb.aggregate.type + '(' + column + ') as aggregate'; | ||
| }, | ||
@@ -117,2 +183,12 @@ | ||
| // Compile the "union" queries attached to the main query. | ||
| compileUnions: function(qb) { | ||
| var sql = ''; | ||
| for (var i = 0, l = qb.unions.length; i < l; i++) { | ||
| var union = qb.unions[i]; | ||
| sql += (union.all ? 'union all ' : 'union ') + this.compileSelect(union.query); | ||
| } | ||
| return sql; | ||
| }, | ||
| // Compiles a nested where clause. | ||
@@ -188,4 +264,7 @@ whereNested: function(qb, where) { | ||
| return 'having ' + havings.map(function(having) { | ||
| if (having.type === 'raw') { | ||
| return having.bool + ' ' + having.sql; | ||
| } | ||
| return '' + this.wrap(having.column) + ' ' + having.operator + ' ' + this.parameter(having['value']); | ||
| }, this).join(' and').replace(/and /, ''); | ||
| }, this).join('and ').replace(/and /, ''); | ||
| }, | ||
@@ -214,3 +293,4 @@ | ||
| // inserts using a single query statement. | ||
| compileInsert: function(qb, values) { | ||
| compileInsert: function(qb) { | ||
| var values = qb.values; | ||
| var table = this.wrapTable(qb.table); | ||
@@ -252,7 +332,8 @@ var columns = this.columnize(_.keys(values[0]).sort()); | ||
| // Compiles an `update` query. | ||
| compileUpdate: function(qb, values) { | ||
| compileUpdate: function(qb) { | ||
| var values = qb.values; | ||
| var table = this.wrapTable(qb.table), columns = []; | ||
| for (var key in values) { | ||
| var value = values[key]; | ||
| columns.push(this.wrap(key) + ' = ' + this.parameter(value)); | ||
| for (var i=0, l = values.length; i < l; i++) { | ||
| var value = values[i]; | ||
| columns.push(this.wrap(value[0]) + ' = ' + this.parameter(value[1])); | ||
| } | ||
@@ -271,3 +352,3 @@ return 'update ' + table + ' set ' + columns.join(', ') + ' ' + this.compileWheres(qb); | ||
| compileTruncate: function(qb) { | ||
| return 'truncate ' + this.wrapTable(qb.from); | ||
| return 'truncate ' + this.wrapTable(qb.table); | ||
| }, | ||
@@ -277,3 +358,3 @@ | ||
| var segments; | ||
| if (value instanceof Knex.Raw) return value.value; | ||
| if (value instanceof Raw) return value.value; | ||
| if (_.isNumber(value)) return value; | ||
@@ -302,3 +383,3 @@ if (value.toLowerCase().indexOf(' as ') !== -1) { | ||
| wrapTable: function(table) { | ||
| if (table instanceof Knex.Raw) return table.value; | ||
| if (table instanceof Raw) return table.value; | ||
| return this.wrapValue(table); | ||
@@ -316,3 +397,3 @@ }, | ||
| parameter: function(value) { | ||
| return (value instanceof Knex.Raw ? value.value : '?'); | ||
| return (value instanceof Raw ? value.value : '?'); | ||
| } | ||
@@ -323,8 +404,16 @@ }; | ||
| // ------- | ||
| var Builder = Knex.Builder = function(table, client) { | ||
| client || (client = {}); | ||
| this.table = table; | ||
| var Builder = Knex.Builder = function(table) { | ||
| // We use this logic to create sub-builders | ||
| // for the advanced query statements. | ||
| if (table) { | ||
| if (_.isString(table)) { | ||
| this.table = table; | ||
| } else { | ||
| this.client = table.client; | ||
| this.grammar = table.grammar; | ||
| } | ||
| } | ||
| this.reset(); | ||
| this.client = client; | ||
| this.grammar = new Grammar(client.grammar); | ||
| }; | ||
@@ -335,4 +424,16 @@ | ||
| Builder.prototype = { | ||
| _.extend(Builder.prototype, Common, { | ||
| _source: 'Builder', | ||
| _idAttribute: 'id', | ||
| // Sets the `returning` for the query - only necessary | ||
| // to set the "returning" value for the postgres insert, | ||
| // defaults to `id`. | ||
| idAttribute: function(val) { | ||
| this._idAttribute = val; | ||
| return this; | ||
| }, | ||
| // Sets the `tableName` on the query. | ||
@@ -345,5 +446,5 @@ from: function(tableName) { | ||
| // Specifies to returns the statement as SQL rather than as a promise. | ||
| asSql: function() { | ||
| this.asSql = true; | ||
| // Select a `column` rather than | ||
| column: function(value) { | ||
| this.columns.push(value); | ||
| return this; | ||
@@ -353,3 +454,4 @@ }, | ||
| // Adds a `distinct` clause to the query. | ||
| distinct: function() { | ||
| distinct: function(column) { | ||
| this.column(column); | ||
| this.isDistinct = true; | ||
@@ -359,10 +461,15 @@ return this; | ||
| toSql: function() { | ||
| return this.grammar['compile' + capitalize(this.type)](this); | ||
| }, | ||
| // Clones the current query builder, including any | ||
| // pieces that have been set thus far | ||
| // pieces that have been set thus far. | ||
| clone: function() { | ||
| var item = new Builder(this.table); | ||
| item.client = this.client; | ||
| item.grammar = this.grammar; | ||
| var items = [ | ||
| 'isDistinct', 'joins', | ||
| 'wheres', 'orders', 'columns', 'bindings', | ||
| 'grammar', 'connection', 'transaction' | ||
| '_idAttribute', 'isDistinct', 'joins', 'wheres', 'orders', | ||
| 'columns', 'bindings', 'grammar', 'transaction', 'unions' | ||
| ]; | ||
@@ -378,6 +485,8 @@ for (var i = 0, l = items.length; i < l; i++) { | ||
| reset: function() { | ||
| this.joins = []; | ||
| this.wheres = []; | ||
| this.orders = []; | ||
| this.columns = []; | ||
| this.joins = []; | ||
| this.values = []; | ||
| this.unions = []; | ||
| this.wheres = []; | ||
| this.orders = []; | ||
| this.columns = []; | ||
| this.bindings = []; | ||
@@ -387,13 +496,2 @@ this.isDistinct = false; | ||
| toJSON: function() { | ||
| return { | ||
| joins: this.joins, | ||
| wheres: this.wheres, | ||
| order: this.orders, | ||
| columns: this.columns, | ||
| bindings: this.bindings, | ||
| isDistinct: this.isDistinct | ||
| }; | ||
| }, | ||
| // Adds a join clause to the query, allowing for advanced joins | ||
@@ -473,3 +571,3 @@ // with an anonymous function as the second argument. | ||
| whereExists: function(callback, bool, type) { | ||
| var query = new Builder(); | ||
| var query = new Builder(this); | ||
| query.isSubQuery = true; | ||
@@ -581,2 +679,14 @@ callback.call(query, query); | ||
| // Add a union statement to the query. | ||
| union: function(callback) { | ||
| this._union(callback, false); | ||
| return this; | ||
| }, | ||
| // Adds a union all statement to the query. | ||
| unionAll: function(callback) { | ||
| this._union(callback, true); | ||
| return this; | ||
| }, | ||
| // Adds a `having` clause to the query. | ||
@@ -589,2 +699,14 @@ having: function(column, operator, value) { | ||
| havingRaw: function(sql, bindings) { | ||
| this.havings.push({type: 'raw', sql: sql, bool: 'and'}); | ||
| this.bindings.push(bindings); | ||
| return this; | ||
| }, | ||
| orHavingRaw: function(sql, bindings) { | ||
| this.havings.push({type: 'raw', sql: sql, bool: 'or'}); | ||
| this.bindings.push(bindings); | ||
| return this; | ||
| }, | ||
| // ---------------------------------------------------------------------- | ||
@@ -608,5 +730,4 @@ | ||
| exists: function() { | ||
| return this.count().then(function(count) { | ||
| return (count > 0); | ||
| }); | ||
| this.count(); | ||
| return this.setType('exists'); | ||
| }, | ||
@@ -644,33 +765,31 @@ | ||
| // Performs a `select` query, returning a promise. | ||
| // Sets the values for a `select` query. | ||
| select: function(columns) { | ||
| this.columns = this.columns.concat(columns ? (_.isArray(columns) ? columns : _.toArray(arguments)) : '*'); | ||
| if (!this.isSubQuery) { | ||
| return Knex.runQuery(this, {sql: this.grammar.compileSelect(this), bindings: this._cleanBindings()}); | ||
| if (columns) { | ||
| this.columns = this.columns.concat(_.isArray(columns) ? columns : _.toArray(arguments)); | ||
| } | ||
| return this; | ||
| return this._setType('select'); | ||
| }, | ||
| // Performs an `insert` query, returning a promise. | ||
| insert: function(values, returning) { | ||
| if (!_.isArray(values)) values = values ? [values] : []; | ||
| for (var i = 0, l = values.length; i<l; i++) { | ||
| var obj = sortObject(values[i]); | ||
| for (var i2 = 0, l2 = obj.length; i2 < l2; i2++) { | ||
| this.bindings.push(obj[i2][1]); | ||
| } | ||
| } | ||
| var str = this.grammar.compileInsert(this, values); | ||
| return Knex.runQuery(this, {sql: str, bindings: this._cleanBindings(), type: 'insert'}); | ||
| // Sets the values for an `insert` query. | ||
| insert: function(values) { | ||
| this.values = this._prepValues(values); | ||
| return this._setType('insert'); | ||
| }, | ||
| // Performs an `update` query, returning a promise. | ||
| // Sets the values for an `update` query. | ||
| update: function(values) { | ||
| this.bindings = _.values(values).concat(this.bindings); | ||
| return Knex.runQuery(this, {sql: this.grammar.compileUpdate(this, values), bindings: this._cleanBindings(), type: 'update'}); | ||
| var obj = sortObject(values); | ||
| var bindings = []; | ||
| for (var i = 0, l = obj.length; i < l; i++) { | ||
| bindings[i] = obj[i][1]; | ||
| } | ||
| this.bindings = bindings.concat(this.bindings || []); | ||
| this.values = obj; | ||
| return this._setType('update'); | ||
| }, | ||
| // Alias to del | ||
| // Alias to del. | ||
| "delete": function() { | ||
| return this.del(); | ||
| return this._setType('delete'); | ||
| }, | ||
@@ -680,3 +799,3 @@ | ||
| del: function() { | ||
| return Knex.runQuery(this, {sql: this.grammar.compileDelete(this), bindings: this._cleanBindings()}); | ||
| return this._setType('delete'); | ||
| }, | ||
@@ -686,3 +805,3 @@ | ||
| truncate: function() { | ||
| return Knex.runQuery(this, {sql: this.grammar.compileTruncate(this)}); | ||
| return this._setType('truncate'); | ||
| }, | ||
@@ -703,5 +822,16 @@ | ||
| _prepValues: function(values) { | ||
| if (!_.isArray(values)) values = values ? [values] : []; | ||
| for (var i = 0, l = values.length; i<l; i++) { | ||
| var obj = sortObject(values[i]); | ||
| for (var i2 = 0, l2 = obj.length; i2 < l2; i2++) { | ||
| this.bindings.push(obj[i2][1]); | ||
| } | ||
| } | ||
| return values; | ||
| }, | ||
| _whereInSub: function(column, callback, bool, condition) { | ||
| var type = condition ? 'NotInSub' : 'InSub'; | ||
| var query = new Builder(); | ||
| var query = new Builder(this); | ||
| query.isSubQuery = true; | ||
@@ -715,3 +845,3 @@ callback.call(query, query); | ||
| _whereNested: function(callback, bool) { | ||
| var query = new Builder(); | ||
| var query = new Builder(this); | ||
| query.isSubQuery = true; | ||
@@ -726,3 +856,3 @@ query.table = this.table; | ||
| _whereSub: function(column, operator, callback, bool) { | ||
| var query = new Builder(); | ||
| var query = new Builder(this); | ||
| query.isSubQuery = true; | ||
@@ -742,4 +872,5 @@ callback.call(query, query); | ||
| _aggregate: function(type, columns) { | ||
| if (!_.isArray(columns)) columns = [columns]; | ||
| this.aggregate = {type: type, columns: columns}; | ||
| return this.get(columns); | ||
| return this._setType('select'); | ||
| }, | ||
@@ -749,14 +880,15 @@ | ||
| var sql = {}; | ||
| sql[column] = new Knex.Raw('' + this.grammar.wrap(column) + ' ' + (symbol || '+') + ' ' + amount); | ||
| return this.update(sql, callback); | ||
| sql[column] = new Raw('' + this.grammar.wrap(column) + ' ' + (symbol || '+') + ' ' + amount); | ||
| return this.update(sql); | ||
| }, | ||
| // Returns all bindings excluding the `Knex.Raw` types. | ||
| _cleanBindings: function() { | ||
| return _.map(this.bindings, function(binding) { | ||
| return (binding instanceof Knex.Raw ? void 0 : binding); | ||
| }); | ||
| _union: function(callback, bool) { | ||
| var query = new Builder(this); | ||
| query.isSubQuery = true; | ||
| callback.call(query, query); | ||
| this.unions.push({query: query, all: bool}); | ||
| push.apply(this.bindings, query.bindings); | ||
| } | ||
| }; | ||
| }); | ||
@@ -779,2 +911,7 @@ // Knex.JoinClause | ||
| andOn: function() { | ||
| this.on.apply(this, arguments); | ||
| return this; | ||
| }, | ||
| orOn: function(first, operator, second) { | ||
@@ -784,3 +921,2 @@ this.clauses.push({first: first, operator: operator, second: second, bool: 'or'}); | ||
| } | ||
| }; | ||
@@ -826,7 +962,10 @@ | ||
| // SchemaBuilder instance methods | ||
| _.each(['hasTable', 'createTable', 'table', 'dropTable', 'dropTableIfExists', 'transacting'], function(method) { | ||
| _.each(['hasTable', 'createTable', 'table', 'dropTable', 'renameTable', 'dropTableIfExists'], function(method) { | ||
| Schema[method] = function() { | ||
| var builder = new Knex.SchemaBuilder(client); | ||
| return builder[method].apply(builder, arguments); | ||
| var args = _.toArray(arguments); | ||
| var builder = new Knex.SchemaBuilder(args[0]); | ||
| builder.client = client; | ||
| builder.grammar = client.schemaGrammar; | ||
| return SchemaInterface[method].apply(builder, args.slice(1)); | ||
| }; | ||
@@ -837,187 +976,67 @@ }); | ||
| // Knex.SchemaBuilder | ||
| // -------- | ||
| // All of the Schame methods that should be called with a | ||
| // `SchemaBuilder` context, to disallow calling more than one method at once. | ||
| var SchemaInterface = { | ||
| // Modify a table on the schema. | ||
| table: function(callback) { | ||
| this.callback(callback); | ||
| return this._setType('table'); | ||
| }, | ||
| var SchemaBuilder = Knex.SchemaBuilder = function(client) { | ||
| this.client = client; | ||
| this.grammar = new SchemaGrammar(client.schemaGrammar); | ||
| }; | ||
| SchemaBuilder.prototype = { | ||
| // Create a new table on the schema. | ||
| createTable: function(table, callback) { | ||
| return new Blueprint(table, this.client).createTable().callback(callback).build(this.grammar); | ||
| createTable: function(callback) { | ||
| this._addCommand('createTable'); | ||
| this.callback(callback); | ||
| return this._setType('createTable'); | ||
| }, | ||
| // Modify a table on the schema. | ||
| table: function(table, callback) { | ||
| return new Blueprint(table, this.client).callback(callback).build(this.grammar); | ||
| }, | ||
| // Drop a table from the schema. | ||
| dropTable: function(table) { | ||
| return new Blueprint(table, this.client).dropTable().build(this.grammar); | ||
| dropTable: function() { | ||
| this._addCommand('dropTable'); | ||
| return this._setType('dropTable'); | ||
| }, | ||
| // Drop a table from the schema if it exists. | ||
| dropTableIfExists: function(table) { | ||
| return new Blueprint(table, this.client).dropTableIfExists().build(this.grammar); | ||
| dropTableIfExists: function() { | ||
| this._addCommand('dropTableIfExists'); | ||
| return this._setType('dropTableIfExists'); | ||
| }, | ||
| // Rename a table on the schema. | ||
| renameTable: function(from, to) { | ||
| return new Blueprint(from, this.client).renameTable(to).build(this.grammar); | ||
| renameTable: function(to) { | ||
| this._addCommand('renameTable', {to: to}); | ||
| return this._setType('renameTable'); | ||
| }, | ||
| // Determine if the given table exists. | ||
| // TODO: Bindings here need to be fixed for mysql, including `table`. | ||
| hasTable: function(table) { | ||
| var sql = this.grammar.compileTableExists(); | ||
| return Knex.runQuery(this, {sql: sql, bindings: [table]}).then(function(resp) { | ||
| return (resp.length > 0 ? resp : Q.reject('Table' + table + ' does not exist')); | ||
| }); | ||
| hasTable: function() { | ||
| this.bindings.push(this.table); | ||
| this._addCommand('tableExists'); | ||
| return this._setType('tableExists'); | ||
| } | ||
| }; | ||
| // SchemaGrammar | ||
| // Knex.SchemaBuilder | ||
| // -------- | ||
| var SchemaGrammar = function(mixins) { | ||
| _.extend(this, mixins); | ||
| }; | ||
| _.extend(SchemaGrammar.prototype, Grammar.prototype, { | ||
| // Compile a foreign key command. | ||
| compileForeign: function(blueprint, command) { | ||
| var table = this.wrapTable(blueprint); | ||
| var on = this.wrapTable(command.on); | ||
| // We need to prepare several of the elements of the foreign key definition | ||
| // before we can create the SQL, such as wrapping the tables and convert | ||
| // an array of columns to comma-delimited strings for the SQL queries. | ||
| var columns = this.columnize(command.columns); | ||
| var onColumns = this.columnize(command.references); | ||
| var sql = "alter table " + table + " add constraint " + command.index + " "; | ||
| sql += "foreign key (" + columns + ") references " + on + " (" + onColumns + ")"; | ||
| // Once we have the basic foreign key creation statement constructed we can | ||
| // build out the syntax for what should happen on an update or delete of | ||
| // the affected columns, which will get something like "cascade", etc. | ||
| if (command.onDelete) sql += " on delete " + command.onDelete; | ||
| if (command.onUpdate) sql += " on update " + command.onUpdate; | ||
| return sql; | ||
| }, | ||
| // Each of the column types have their own compiler functions which are | ||
| // responsible for turning the column definition into its SQL format | ||
| // for the platform. Then column modifiers are compiled and added. | ||
| getColumns: function(blueprint) { | ||
| var columns = []; | ||
| for (var i = 0, l = blueprint.columns.length; i < l; i++) { | ||
| var column = blueprint.columns[i]; | ||
| var sql = this.wrap(column) + ' ' + this.getType(column); | ||
| columns.push(this.addModifiers(sql, blueprint, column)); | ||
| } | ||
| return columns; | ||
| }, | ||
| // Add the column modifiers to the definition. | ||
| addModifiers: function(sql, blueprint, column) { | ||
| for (var i = 0, l = this.modifiers.length; i < l; i++) { | ||
| var modifier = this.modifiers[i]; | ||
| var method = "modify" + modifier; | ||
| if (_.has(this, method)) { | ||
| sql += this[method](blueprint, column) || ''; | ||
| } | ||
| } | ||
| return sql; | ||
| }, | ||
| // Get the primary key command if it exists on the blueprint. | ||
| getCommandByName: function(blueprint, name) { | ||
| var commands = this.getCommandsByName(blueprint, name); | ||
| if (commands.length > 0) return commands[0]; | ||
| }, | ||
| // Get all of the commands with a given name. | ||
| getCommandsByName: function(blueprint, name) { | ||
| return _.where(blueprint.commands, function(value) { return value.name == name; }); | ||
| }, | ||
| // Get the SQL for the column data type. | ||
| getType: function(column) { | ||
| return this["type" + capitalize(column.type)](column); | ||
| }, | ||
| // Add a prefix to an array of values, utilized in the client libs. | ||
| prefixArray: function(prefix, values) { | ||
| return _.map(values, function(value) { return prefix + ' ' + value; }); | ||
| }, | ||
| // Wrap a table in keyword identifiers. | ||
| wrapTable: function(table) { | ||
| if (table instanceof Blueprint) table = table.table; | ||
| return Grammar.prototype.wrapTable.call(this, table); | ||
| }, | ||
| // Wrap a value in keyword identifiers. | ||
| wrap: function(value) { | ||
| if (value instanceof Chainable) value = value.name; | ||
| return Grammar.prototype.wrap.call(this, value); | ||
| }, | ||
| // Format a value so that it can be used in "default" clauses. | ||
| getDefaultValue: function(value) { | ||
| if (value === true || value === false) { | ||
| return parseInt(value, 10); | ||
| } | ||
| return '' + value; | ||
| } | ||
| }); | ||
| // Knex.Blueprint | ||
| // ------ | ||
| var Blueprint = Knex.Blueprint = function(table, client) { | ||
| var SchemaBuilder = Knex.SchemaBuilder = function(table) { | ||
| this.table = table; | ||
| this.columns = []; | ||
| this.commands = []; | ||
| this.client = client; | ||
| this.bindings = []; | ||
| }; | ||
| Blueprint.prototype = { | ||
| _.extend(SchemaBuilder.prototype, Common, { | ||
| _source: 'SchemaBuilder', | ||
| // A callback from the table building `Knex.schemaBuilder` calls. | ||
| callback: function(callback) { | ||
| callback.call(this, this); | ||
| if (callback) callback.call(this, this); | ||
| return this; | ||
| }, | ||
| // Builds the schemaBuilder statements to be executed. | ||
| build: function(grammar) { | ||
| var statements = this.toSql(grammar); | ||
| var promises = []; | ||
| var dfd = Q.defer(); | ||
| var builder = this; | ||
| this.client.pool.acquire(function(err, connection) { | ||
| builder.connection = connection; | ||
| for (var i = 0, l = statements.length; i < l; i++) { | ||
| var statement = statements[i]; | ||
| promises.push(Knex.runQuery(builder, {sql: statement})); | ||
| } | ||
| // Ensures all queries for the same table | ||
| // are run on the same connection. | ||
| return Q.all(promises).then(dfd.resolve, dfd.reject).fin(function() { | ||
| builder.client.pool.release(connection); | ||
| }); | ||
| }); | ||
| return dfd.promise; | ||
| }, | ||
| // Get the raw sql statements for the blueprint. | ||
| toSql: function(grammar) { | ||
| toSql: function() { | ||
@@ -1064,5 +1083,5 @@ // Add the commands that are implied by the blueprint. | ||
| var method = 'compile' + capitalize(command.name); | ||
| if (_.has(grammar, method)) { | ||
| var sql = grammar[method](this, command); | ||
| statements.push(sql); | ||
| if (_.has(this.grammar, method)) { | ||
| var sql = this.grammar[method](this, command); | ||
| statements = statements.concat(sql); | ||
| } | ||
@@ -1084,20 +1103,2 @@ } | ||
| // Indicate that the table needs to be created. | ||
| createTable: function() { | ||
| this._addCommand('createTable'); | ||
| return this; | ||
| }, | ||
| // Indicate that the table should be dropped. | ||
| dropTable: function() { | ||
| this._addCommand('dropTable'); | ||
| return this; | ||
| }, | ||
| // Indicate that the table should be dropped if it exists. | ||
| dropTableIfExists: function() { | ||
| this._addCommand('dropTableIfExists'); | ||
| return this; | ||
| }, | ||
| // Indicate that the given columns should be dropped. | ||
@@ -1109,7 +1110,2 @@ dropColumn: function(columns) { | ||
| // Rename the table to a given name. | ||
| renameTable: function(to) { | ||
| return this._addCommand('renameTable', {to: to}); | ||
| }, | ||
| // Indicate that the given columns should be dropped. | ||
@@ -1310,3 +1306,3 @@ dropColumns: function() { | ||
| } | ||
| }; | ||
| }); | ||
@@ -1339,2 +1335,3 @@ // Chainable object used in creating SchemaBuilder commands. | ||
| // Adds an index on the specified column. | ||
| index: function(name) { | ||
@@ -1345,2 +1342,3 @@ this.isIndex = name || true; | ||
| // Sets this column as the primary key. | ||
| primary: function(name) { | ||
@@ -1351,5 +1349,13 @@ this.isPrimary = name || true; | ||
| // Sets this column as unique. | ||
| unique: function(name) { | ||
| this.isUnique = name || true; | ||
| return this; | ||
| }, | ||
| // Sets the column to be inserted after another, | ||
| // used in MySql alter tables. | ||
| after: function(name) { | ||
| this.isAfter = name; | ||
| return this; | ||
| } | ||
@@ -1359,2 +1365,95 @@ | ||
| Knex.SchemaGrammar = { | ||
| // Compile a foreign key command. | ||
| compileForeign: function(blueprint, command) { | ||
| var table = this.wrapTable(blueprint); | ||
| var on = this.wrapTable(command.on); | ||
| // We need to prepare several of the elements of the foreign key definition | ||
| // before we can create the SQL, such as wrapping the tables and convert | ||
| // an array of columns to comma-delimited strings for the SQL queries. | ||
| var columns = this.columnize(command.columns); | ||
| var onColumns = this.columnize(command.references); | ||
| var sql = "alter table " + table + " add constraint " + command.index + " "; | ||
| sql += "foreign key (" + columns + ") references " + on + " (" + onColumns + ")"; | ||
| // Once we have the basic foreign key creation statement constructed we can | ||
| // build out the syntax for what should happen on an update or delete of | ||
| // the affected columns, which will get something like "cascade", etc. | ||
| if (command.onDelete) sql += " on delete " + command.onDelete; | ||
| if (command.onUpdate) sql += " on update " + command.onUpdate; | ||
| return sql; | ||
| }, | ||
| // Each of the column types have their own compiler functions which are | ||
| // responsible for turning the column definition into its SQL format | ||
| // for the platform. Then column modifiers are compiled and added. | ||
| getColumns: function(blueprint) { | ||
| var columns = []; | ||
| for (var i = 0, l = blueprint.columns.length; i < l; i++) { | ||
| var column = blueprint.columns[i]; | ||
| var sql = this.wrap(column) + ' ' + this.getType(column); | ||
| columns.push(this.addModifiers(sql, blueprint, column)); | ||
| } | ||
| return columns; | ||
| }, | ||
| // Add the column modifiers to the definition. | ||
| addModifiers: function(sql, blueprint, column) { | ||
| for (var i = 0, l = this.modifiers.length; i < l; i++) { | ||
| var modifier = this.modifiers[i]; | ||
| var method = "modify" + modifier; | ||
| if (_.has(this, method)) { | ||
| sql += this[method](blueprint, column) || ''; | ||
| } | ||
| } | ||
| return sql; | ||
| }, | ||
| // Get the primary key command if it exists on the blueprint. | ||
| getCommandByName: function(blueprint, name) { | ||
| var commands = this.getCommandsByName(blueprint, name); | ||
| if (commands.length > 0) return commands[0]; | ||
| }, | ||
| // Get all of the commands with a given name. | ||
| getCommandsByName: function(blueprint, name) { | ||
| return _.where(blueprint.commands, function(value) { return value.name == name; }); | ||
| }, | ||
| // Get the SQL for the column data type. | ||
| getType: function(column) { | ||
| return this["type" + capitalize(column.type)](column); | ||
| }, | ||
| // Add a prefix to an array of values, utilized in the client libs. | ||
| prefixArray: function(prefix, values) { | ||
| return _.map(values, function(value) { return prefix + ' ' + value; }); | ||
| }, | ||
| // Wrap a table in keyword identifiers. | ||
| wrapTable: function(table) { | ||
| if (table instanceof SchemaBuilder) table = table.table; | ||
| return Knex.Grammar.wrapTable.call(this, table); | ||
| }, | ||
| // Wrap a value in keyword identifiers. | ||
| wrap: function(value) { | ||
| if (value instanceof Chainable) value = value.name; | ||
| return Knex.Grammar.wrap.call(this, value); | ||
| }, | ||
| // Format a value so that it can be used in "default" clauses. | ||
| getDefaultValue: function(value) { | ||
| if (value instanceof Raw) return value.value; | ||
| if (value === true || value === false) { | ||
| return parseInt(value, 10); | ||
| } | ||
| return '' + value; | ||
| } | ||
| }; | ||
| var capitalize = function(word) { | ||
@@ -1372,3 +1471,11 @@ return word.charAt(0).toUpperCase() + word.slice(1); | ||
| // ------- | ||
| // Helpful for injecting a snippet of raw SQL into a | ||
| // `Knex` block... in most cases, we'll check if the value | ||
| // is an instanceof Raw, and if it is, use the supplied value. | ||
| Knex.Raw = function(value) { | ||
| return new Raw(value); | ||
| }; | ||
| var Raw = function(value) { | ||
| this.value = value; | ||
@@ -1384,12 +1491,36 @@ }; | ||
| // and returns a deferred promise. | ||
| Knex.runQuery = function(builder, data) { | ||
| Knex.runQuery = function(builder) { | ||
| if (builder.transaction) { | ||
| if (!builder.transaction.connection) return Q.reject(new Error('The transaction has already completed.')); | ||
| builder.connection = builder.transaction.connection; | ||
| builder._connection = builder.transaction.connection; | ||
| } | ||
| // Query on the query builder, which should resolve with a promise, | ||
| // spreadable to include more information including the query. | ||
| return builder.client.query(data, builder.connection); | ||
| // Prep the SQL associated with the builder. | ||
| builder.sql = builder.toSql(); | ||
| builder.bindings = builder._cleanBindings(); | ||
| if (!_.isArray(builder.sql)) builder.sql = [builder.sql]; | ||
| var chain; | ||
| for (var i = 0, l = builder.sql.length; i < l; i++) { | ||
| if (chain) { | ||
| chain.then(multiQuery(builder, i, chain)); | ||
| } else { | ||
| chain = multiQuery(builder, i); | ||
| } | ||
| } | ||
| // Query on the query builder, which should resolve with a promise. | ||
| return chain; | ||
| }; | ||
| // Sets up a multi-query | ||
| var multiQuery = function(builder, i, chain) { | ||
| if (chain) { | ||
| return function() { | ||
| return multiQuery(builder, i); | ||
| }; | ||
| } | ||
| return builder.client.query(_.extend({}, builder, {sql: builder.sql[i]})); | ||
| }; | ||
| // Knex.Initialize | ||
@@ -1406,2 +1537,4 @@ // ------- | ||
| // A name for the connection isn't required in | ||
| // cases where there is only a single connection. | ||
| if (_.isObject(name)) { | ||
@@ -1436,12 +1569,20 @@ options = name; | ||
| // Setup the grammars specific to the client. | ||
| client.grammar = _.extend({}, Knex.Grammar, client.grammar); | ||
| client.schemaGrammar = _.extend({}, client.grammar, Knex.SchemaGrammar, client.schemaGrammar); | ||
| // If this is named "default" then we're setting this on the Knex | ||
| if (name === 'default') { | ||
| Target = Knex.Instances['default'] = Knex; | ||
| Target = Knex; | ||
| } else { | ||
| Target = Knex.Instances[name] = function(table) { | ||
| return new Knex.Builder(table, client); | ||
| Target = function(table) { | ||
| var builder = new Target.Builder(table); | ||
| builder.client = client; | ||
| builder.grammar = client.grammar; | ||
| return builder; | ||
| }; | ||
| // Inherit static properties. | ||
| _.extend(Target, _.omit(Knex, 'Initialize', 'Instances')); | ||
| // Inherit static properties, without any that don't apply except | ||
| // on the "root" `Knex`. | ||
| _.extend(Target, _.omit(Knex, 'Initialize', 'Instances', 'VERSION')); | ||
| } | ||
@@ -1454,2 +1595,8 @@ | ||
| Target.client = client; | ||
| Target.instanceName = name; | ||
| // Add this instance to the global `Knex` instances, and return. | ||
| Knex.Instances[name] = Target; | ||
| return Target; | ||
| }; | ||
@@ -1461,2 +1608,3 @@ | ||
| 'postgres' : './clients/postgres.js', | ||
| 'sqlite' : './clients/sqlite3.js', | ||
| 'sqlite3' : './clients/sqlite3.js' | ||
@@ -1463,0 +1611,0 @@ }; |
+11
-14
| { | ||
| "name": "knex", | ||
| "version": "0.0.1", | ||
| "version": "0.0.2", | ||
| "description": "a fun sql query builder", | ||
@@ -11,8 +11,11 @@ "main": "knex.js", | ||
| "mocha": "1.7.x", | ||
| "mysql": "~2.0.0-alpha5" | ||
| "objectdump": ">=0.3.0", | ||
| "mysql": "~2.0.0-alpha7", | ||
| "pg": "~1.1.0", | ||
| "sqlite3": "~2.1.7" | ||
| }, | ||
| "dependencies": { | ||
| "q": "0.9.x", | ||
| "underscore": "1.4.x", | ||
| "generic-pool": "2.0.x" | ||
| "q": "~0.9.3", | ||
| "underscore": "~1.4.4", | ||
| "generic-pool": "~2.0.3" | ||
| }, | ||
@@ -22,3 +25,3 @@ "scripts": { | ||
| }, | ||
| "repository": "", | ||
| "repository": "https://github.com/tgriesser/knex", | ||
| "keywords": [ | ||
@@ -29,10 +32,4 @@ "sql", | ||
| ], | ||
| "author": { | ||
| "name": "Tim Griesser" | ||
| }, | ||
| "license": "MIT", | ||
| "readme": "# Knex Query Builder", | ||
| "readmeFilename": "README.md", | ||
| "_id": "knex@0.0.1", | ||
| "_from": "knex@" | ||
| "author": "Tim Griesser", | ||
| "license": "MIT" | ||
| } |
+21
-1
@@ -1,1 +0,21 @@ | ||
| # Knex Query Builder | ||
| ``` | ||
| ._____. ______ | ||
| | | / / | ||
| | | / / | ||
| | | _____ ._____ ._____. ,_____________. ______ / / | ||
| | | / / | \ | | / \ \ \ / / | ||
| | | / / | \ | | / \ \ \ / / | ||
| | | / / | \ | | / ,______. \ \ \ / / | ||
| | | / / | \ | | / / \ \ \ \/ / | ||
| | |/ \ | \ | | | | ____\ | \ / | ||
| | |\ \ | \| | | | / | \ \ | ||
| | | \ \ | |\ | | | /__________| / \ | ||
| | | \ \ | | \ | \ \ / /\ \ | ||
| | | \ \ | | \ | \ \__________/\ / / \ \ | ||
| | | \ \ | | \ | \ \ / / \ \ | ||
| |_____| \_____\ |_____| \______| \_______________/ /_____/ \_____\ | ||
| ``` | ||
| Knex.js is a multi-dialect query builder for Node.js. | ||
| [http://knexjs.org](knexjs.org) |
+56
-4
@@ -0,6 +1,58 @@ | ||
| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| var Knex = require('../knex'); | ||
| var conn = require(process.env.KNEX_TEST || './shared/config'); | ||
| require('./mock'); | ||
| // The output goes here. | ||
| exports.output = {}; | ||
| // require('./mysql/index'); | ||
| // require('./sqlite3/index'); | ||
| // require('./postgres/index'); | ||
| var MySql = Knex.Initialize('mysql', { | ||
| client: 'mysql', | ||
| connection: conn.mysql | ||
| }); | ||
| var Sqlite3 = Knex.Initialize('sqlite3', { | ||
| client: 'sqlite3', | ||
| connection: conn.sqlite3 | ||
| }); | ||
| var Postgres = Knex.Initialize('postgres', { | ||
| client: 'postgres', | ||
| connection: conn.postgres | ||
| }); | ||
| var runQuery = Knex.runQuery; | ||
| Knex.runQuery = function(builder) { | ||
| if (builder.transaction) { | ||
| if (!builder.transaction.connection) return Q.reject(new Error('The transaction has already completed.')); | ||
| builder._connection = builder.transaction.connection; | ||
| } | ||
| // Query on the query builder, which should resolve with a promise. | ||
| return Q({ | ||
| sql: builder.toSql(), | ||
| bindings: builder._cleanBindings() | ||
| }); | ||
| }; | ||
| describe('Knex', function() { | ||
| var allDone; | ||
| Q.all([ | ||
| require('./string')(MySql, 'mysql'), | ||
| require('./string')(Postgres, 'postgres'), | ||
| require('./string')(Sqlite3, 'sqlite3') | ||
| ]).then(function() { | ||
| Knex.runQuery = runQuery; | ||
| return Q.all([ | ||
| require('./regular')(MySql, 'mysql'), | ||
| require('./regular')(Postgres, 'postgres'), | ||
| require('./regular')(Sqlite3, 'sqlite3') | ||
| ]); | ||
| }).then(function() { | ||
| allDone(); | ||
| }, allDone); | ||
| after(function(ok) { | ||
| allDone = ok; | ||
| }); | ||
| }); |
-150
| var Knex = require('../knex'); | ||
| var Q = require('q'); | ||
| var assert = require('assert'); | ||
| var equal = assert.equal; | ||
| var deepEqual = assert.deepEqual; | ||
| describe('Knex.Builder', function() { | ||
| describe('Selects', function() { | ||
| describe('basic', function() { | ||
| it('runs with no conditions', function(ok) { | ||
| Knex('tableName').select().spread(function(sql, bindings, connection) { | ||
| equal(sql, 'select * from `tableName`'); | ||
| deepEqual(bindings, []); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| }); | ||
| describe('where', function() { | ||
| it('handles simple "where"', function(ok) { | ||
| Knex('table').where('id', 1).select('column1', 'column2').spread(function(sql, bindings) { | ||
| equal(sql, 'select `column1`, `column2` from `table` where `id` = ?'); | ||
| deepEqual(bindings, [1]); | ||
| return Knex('table').where('id', '=', 'someValue').select(['column1', 'column2']); | ||
| }).spread(function(sql, bindings) { | ||
| equal(sql, 'select `column1`, `column2` from `table` where `id` = ?'); | ||
| deepEqual(bindings, ['someValue']); | ||
| return Knex('table').where({ | ||
| id: 1, | ||
| otherItem: 2 | ||
| }).andWhere('title', 'test').select(); | ||
| }).spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where `id` = ? and `otherItem` = ? and `title` = ?'); | ||
| deepEqual(bindings, [1, 2, 'test']); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('handles "or where"', function(ok) { | ||
| Knex('table').where('id', 1).orWhere({id: 2}).select().spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where `id` = ? or `id` = ?'); | ||
| deepEqual(bindings, [1, 2]); | ||
| return Knex('table').where('id', '=', 'someValue').orWhere('otherId', '>', 10).select(); | ||
| }).spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where `id` = ? or `otherId` > ?'); | ||
| deepEqual(bindings, ['someValue', 10]); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('handles "where exists"', function(ok) { | ||
| Knex('table').whereExists(function(qb) { | ||
| deepEqual(qb, this); | ||
| return qb.select('column1').from('table2').where({ | ||
| id: 1, | ||
| otherItem: 2 | ||
| }); | ||
| }).select().spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where exists (select `column1` from `table2` where `id` = ? and `otherItem` = ?)'); | ||
| deepEqual(bindings, [1, 2]); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('handles "where in"', function(ok) { | ||
| Knex('table').whereIn('id', [1, 2, 3]).select().spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where `id` in (?, ?, ?)'); | ||
| deepEqual(bindings, [1, 2, 3]); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('handles "or where in"', function(ok) { | ||
| Knex('table').where('id', 1).orWhereIn('name', ['Tim', 'Joe', 'Bill']).select().spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where `id` = ? or `name` in (?, ?, ?)'); | ||
| deepEqual(bindings, [1, 'Tim', 'Joe', 'Bill']); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('handles "where between"', function(ok) { | ||
| Knex('table').whereBetween('id', [1, 100]).select().spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where `id` between ? and ?'); | ||
| deepEqual(bindings, [1, 100]); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('handles "or where between"', function(ok) { | ||
| Knex('table').whereBetween('id', [1, 100]).orWhereBetween('id', [200, 300]).select().spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `table` where `id` between ? and ? or `id` between ? and ?'); | ||
| deepEqual(bindings, [1, 100, 200, 300]); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| }); | ||
| describe('joins', function() { | ||
| it('uses inner join by default', function(ok) { | ||
| Knex('tableName').join('otherTable', 'tableName.id', '=', 'otherTable.otherId').select('tableName.*', 'otherTable.name').spread(function(sql, bindings) { | ||
| equal(sql, 'select `tableName`.*, `otherTable`.`name` from `tableName` inner join `otherTable` on `tableName`.`id` = `otherTable`.`otherId`'); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('takes a fifth parameter to specify the join type', function(ok) { | ||
| Knex('tableName').join('otherTable', 'tableName.id', '=', 'otherTable.otherId', 'left').select('tableName.*', 'otherTable.name').spread(function(sql, bindings) { | ||
| equal(sql, 'select `tableName`.*, `otherTable`.`name` from `tableName` left join `otherTable` on `tableName`.`id` = `otherTable`.`otherId`'); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| it('accepts a callback as the second argument for advanced joins', function(ok) { | ||
| Knex('tableName').join('table2', function(join) { | ||
| join.on('tableName.one_id', '=', 'table2.tableName_id'); | ||
| join.orOn('tableName.other_id', '=', 'table2.tableName_id2'); | ||
| }, 'left').select().spread(function(sql, bindings) { | ||
| equal(sql, 'select * from `tableName` left join `table2` on `tableName`.`one_id` = `table2`.`tableName_id` or `tableName`.`other_id` = `table2`.`tableName_id2`'); | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('Inserts', function() { | ||
| it('Should take hashes passed into insert and keep them in the correct order', function(ok) { | ||
| Knex('tableName').insert([{ | ||
| firstName: 'Test', | ||
| lastName: 'User', | ||
| item: 0 | ||
| },{ | ||
| item: 1, | ||
| lastName: 'Item', | ||
| firstName: 'Person' | ||
| }]).spread(function(sql, bindings) { | ||
| equal(sql, 'insert into `tableName` (`firstName`, `item`, `lastName`) values (?, ?, ?), (?, ?, ?)'); | ||
| deepEqual(bindings, ['Test', 0, 'User', 'Person', 1, 'Item']); | ||
| ok(); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
-23
| var assert = require('assert'); | ||
| var Knex = require('../knex'); | ||
| var Q = require('q'); | ||
| var _ = require('underscore'); | ||
| Knex.Initialize({ | ||
| client: 'mysql', | ||
| connection: {} | ||
| }); | ||
| originalQuery = Knex.client.query; | ||
| Knex.client.query = function(data, connection) { | ||
| return Q.resolve([data.sql, data.bindings, connection]); | ||
| }; | ||
| describe('Knex', function() { | ||
| }); | ||
| // Standard query tests | ||
| require('./schemabuilder'); | ||
| require('./builder'); |
| describe('MySql Bindings', function () { | ||
| before(function (done) { | ||
| done(); | ||
| }); | ||
| it('has no tests yet'); | ||
| }); |
| describe('Postgresql Bindings', function () { | ||
| before(function (done) { | ||
| done(); | ||
| }); | ||
| it('has no tests yet'); | ||
| }); |
| var Knex = require('../knex'); | ||
| var Q = require('q'); | ||
| var assert = require('assert'); | ||
| var equal = assert.equal; | ||
| var deepEqual = assert.deepEqual; | ||
| describe('Knex.SchemaBuilder', function() { | ||
| it('creates new tables', function(ok) { | ||
| Knex.Schema.createTable('table', function(table) { | ||
| table.increments('id'); | ||
| table.string('first_name').nullable(); | ||
| table.string('last_name'); | ||
| table.integer('logins').defaultTo(1).index(); | ||
| table.text('about').defaultTo('My Bio.'); | ||
| table.timestamps(); | ||
| }).then(function() { | ||
| ok(); | ||
| }).done(); | ||
| }); | ||
| }); |
| describe('deletes', function () { | ||
| it("delete from `users` where `email` = 'new_email@gmail.com'", function() { | ||
| DB.table('users') | ||
| .where({ | ||
| 'email':'new_email@gmail.com' | ||
| })['delete'].then(function (resp) { | ||
| }); | ||
| }); | ||
| it('should alias del to delete', function () { | ||
| DB.table('users') | ||
| .where({'email':'new_email@gmail.com'}) | ||
| .del() | ||
| .then(function () { | ||
| }); | ||
| }); | ||
| }); |
| var DB = require('../../index'); | ||
| describe('Inserts', function() { | ||
| it("insert into `users` `email` = 'new_email@gmail.com' where `id` = 1", function() { | ||
| DB.table('users') | ||
| .insert({ | ||
| 'email':'new_email@gmail.com' | ||
| }).then(function () { | ||
| }); | ||
| }); | ||
| it('should handle multi inserts', function () { | ||
| DB.table('users') | ||
| .insert([{ | ||
| 'email':'new_email@gmail.com' | ||
| }, { | ||
| 'email':'other_new_email@gmail.com' | ||
| }]).then(function () { | ||
| }); | ||
| }); | ||
| }); |
| module.exports = function (connection) { | ||
| describe('Schema', function () { | ||
| it('Runs things'); | ||
| }); | ||
| }; | ||
| var DB = require('../index').Knex; | ||
| describe('Selects', function () { | ||
| it('select * from `u` where `id` > 1', function () { | ||
| DB.table('u') | ||
| .where('id', '>', 1) | ||
| .get() | ||
| .then(function () { | ||
| console.log(this); | ||
| console.log(arguments); | ||
| }); | ||
| }); | ||
| }); |
| var DB = require('../../index'); | ||
| describe('Updates', function() { | ||
| it("update `users` set `email` = 'new_email@gmail.com' where `id` = 1", function() { | ||
| DB.table('users') | ||
| .where('id', '=', 1) | ||
| .update({ | ||
| 'email':'new_email@gmail.com' | ||
| }, function () { | ||
| }); | ||
| }); | ||
| }); |
| describe('Sqlite3 Bindings', function () { | ||
| before(function (done) { | ||
| done(); | ||
| }); | ||
| it('has no tests yet'); | ||
| }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
162491
95.06%4838
118.22%21
2000%5
150%24
-4%11
37.5%1
Infinity%Updated
Updated
Updated