mirror of
https://github.com/knex/knex.git
synced 2025-12-27 15:08:47 +00:00
wip unit tests & refactoring
This commit is contained in:
parent
2bf076f15a
commit
faa2497ef1
@ -1,20 +0,0 @@
|
||||
(function(define) {
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports) {
|
||||
|
||||
var Helpers = require('../../lib/helpers').Helpers;
|
||||
|
||||
var Client = function(name, options) {};
|
||||
|
||||
Client.prototype = {};
|
||||
Client.extend = Helpers.extend;
|
||||
|
||||
exports.Client = Client;
|
||||
|
||||
});
|
||||
|
||||
})(
|
||||
typeof define === 'function' && define.amd ? define : function (factory) { factory(require, exports); }
|
||||
);
|
||||
@ -10,12 +10,10 @@ define(function(require, exports) {
|
||||
var Grammar = require('./grammar').Grammar;
|
||||
var SchemaGrammar = require('./schemagrammar').SchemaGrammar;
|
||||
|
||||
var Client = require('./client').Client;
|
||||
var Helpers = require('../../lib/helpers').Helpers;
|
||||
var ClientBase = require('../base').ClientBase;
|
||||
var Helpers = require('../../lib/helpers').Helpers;
|
||||
|
||||
var Sqlite3 = Client.extend({
|
||||
|
||||
});
|
||||
var Sqlite3 = ClientBase.extend({});
|
||||
|
||||
// Extends the standard sql grammar.
|
||||
Sqlite3.grammar = _.defaults({
|
||||
|
||||
@ -91,8 +91,9 @@ exports.protoProps = {
|
||||
});
|
||||
},
|
||||
|
||||
finishTransaction: function(type, trans, dfd, msg) {
|
||||
finishTransaction: function(type, transaction, msg) {
|
||||
var ctx = this;
|
||||
var dfd = transaction.dfd;
|
||||
nodefn.call(trans.connection.query.bind(trans.connection), type + ';', []).then(function(resp) {
|
||||
if (type === 'commit') dfd.resolve(msg || resp);
|
||||
if (type === 'rollback') dfd.reject(msg || resp);
|
||||
|
||||
@ -21,8 +21,8 @@ _.extend(MysqlClient.prototype, base.protoProps, {
|
||||
// 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;
|
||||
var debug = this.debug || builder._debug;
|
||||
var client = this;
|
||||
return when((builder._connection || this.getConnection()))
|
||||
.tap(this.checkSchema(builder))
|
||||
.then(function(conn) {
|
||||
@ -64,7 +64,7 @@ _.extend(MysqlClient.prototype, base.protoProps, {
|
||||
// Empty the connection after we run the query, unless one was specifically
|
||||
// set (in the case of transactions, etc).
|
||||
return dfd.promise.ensure(function() {
|
||||
if (emptyConnection) instance.pool.release(conn);
|
||||
if (emptyConnection) client.pool.release(conn);
|
||||
});
|
||||
}).otherwise(function(err) {
|
||||
throw new Error(err.toString() + ': ' + builder.sql);
|
||||
|
||||
46
knex.js
46
knex.js
@ -16,9 +16,11 @@ define(function(require, exports, module) {
|
||||
var Raw = require('./lib/raw').Raw;
|
||||
var Transaction = require('./lib/transaction').Transaction;
|
||||
var Builder = require('./lib/builder').Builder;
|
||||
var Interface = require('./lib/builder/interface').Interface;
|
||||
var Schema = require('./lib/schema').Schema;
|
||||
var ClientBase = require('./clients/clientbase').ClientBase;
|
||||
|
||||
// var Interface = require('./lib/builder/interface').Interface;
|
||||
var Schema = require('./lib/schemabuilder').SchemaBuilder;
|
||||
var SchemaInterface = require('./lib/schemainterface').SchemaInterface;
|
||||
var ClientBase = require('./clients/base').ClientBase;
|
||||
|
||||
// The `Knex` module, taking either a fully initialized
|
||||
// database client, or a configuration to initialize one. This is something
|
||||
@ -61,12 +63,12 @@ define(function(require, exports, module) {
|
||||
// `Knex.select('*').from('tableName').then(...`
|
||||
// `Knex.insert(values).into('tableName').then(...`
|
||||
// `Knex.update(values).then(...`
|
||||
_.each(Interface, function(val, key) {
|
||||
instance[key] = function() {
|
||||
var builder = new Builder(instance);
|
||||
return builder[key].apply(builder, arguments);
|
||||
};
|
||||
});
|
||||
// _.each(Interface, function(val, key) {
|
||||
// instance[key] = function() {
|
||||
// var builder = new Builder(instance);
|
||||
// return builder[key].apply(builder, arguments);
|
||||
// };
|
||||
// });
|
||||
|
||||
// Attach each of the `Schema` "interface" methods directly onto to `Knex.Schema` namespace:
|
||||
// `Knex.Schema.table('tableName', function() {...`
|
||||
@ -76,22 +78,21 @@ define(function(require, exports, module) {
|
||||
instance.schema[key] = function() {
|
||||
var schemaBuilder = new SchemaBuilder(instance);
|
||||
schemaBuilder.table = _.first(arguments);
|
||||
return schemaBuilder[key].apply(schemaBuilder, _.rest(arguments));
|
||||
return SchemaInterface[key].apply(schemaBuilder, _.rest(arguments));
|
||||
};
|
||||
});
|
||||
|
||||
// Attach each of the `Migrate` "interface" methods directly on to
|
||||
_.each(MigrateInterface, function(val, key) {
|
||||
instance.migrate[key] = function() {
|
||||
var migrateBuilder = new MigrateBuilder(instance);
|
||||
return MigrateBuilder[key].apply(migrateBuilder, arguments);
|
||||
};
|
||||
});
|
||||
// _.each(MigrateInterface, function(val, key) {
|
||||
// instance.migrate[key] = function() {
|
||||
// var migrateBuilder = new MigrateBuilder(instance);
|
||||
// return MigrateBuilder[key].apply(migrateBuilder, arguments);
|
||||
// };
|
||||
// });
|
||||
|
||||
// Method to run a new `Raw` query on the current client.
|
||||
instance.raw = function() {
|
||||
var raw = new Raw(instance);
|
||||
return raw.query.apply(raw, arguments);
|
||||
instance.raw = function(sql, bindings) {
|
||||
return new Raw(instance).query(sql, bindings);
|
||||
};
|
||||
|
||||
// Keep a reference to the current client.
|
||||
@ -102,8 +103,7 @@ define(function(require, exports, module) {
|
||||
|
||||
// Runs a new transaction, taking a container and
|
||||
instance.transaction = function(container) {
|
||||
var transaction = new Transaction(instance);
|
||||
return transaction.run(container);
|
||||
return new Transaction(instance).run(container);
|
||||
};
|
||||
|
||||
// Return the new Knex instance.
|
||||
@ -125,6 +125,10 @@ define(function(require, exports, module) {
|
||||
// finally, export the `Knex` object for node and the browser.
|
||||
module.exports = Knex;
|
||||
|
||||
Knex.initialize = function(config) {
|
||||
return Knex(config);
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
})(
|
||||
|
||||
@ -11,19 +11,15 @@ define(function(require, exports) {
|
||||
var Common = require('./common').Common;
|
||||
var Raw = require('./raw').Raw;
|
||||
var Helpers = require('./helpers').Helpers;
|
||||
var JoinClause = require('./joinclause').JoinClause;
|
||||
var JoinClause = require('./builder/joinclause').JoinClause;
|
||||
|
||||
var array = [];
|
||||
var push = array.push;
|
||||
|
||||
var Builder = function(client) {
|
||||
if (client instanceof Builder) {
|
||||
this.client = client.client;
|
||||
this.grammar = this.client.grammar;
|
||||
} else {
|
||||
this.client = client;
|
||||
this.grammar = client.grammar;
|
||||
}
|
||||
var Builder = function(instance) {
|
||||
this.knex = instance;
|
||||
this.client = instance.client;
|
||||
this.grammar = instance.grammar;
|
||||
this.reset();
|
||||
};
|
||||
|
||||
@ -64,7 +60,7 @@ define(function(require, exports) {
|
||||
// Clones the current query builder, including any
|
||||
// pieces that have been set thus far.
|
||||
clone: function() {
|
||||
var item = new Builder(this);
|
||||
var item = new Builder(this.knex);
|
||||
item.table = this.table;
|
||||
var items = [
|
||||
'isDistinct', 'joins', 'wheres', 'orders',
|
||||
@ -143,8 +139,8 @@ define(function(require, exports) {
|
||||
},
|
||||
|
||||
// Alias to `where`, for internal builder consistency.
|
||||
andWhere: function() {
|
||||
return this.where.apply(this, arguments);
|
||||
andWhere: function(column, operator, value) {
|
||||
return this.where(column, operator, value, 'and');
|
||||
},
|
||||
|
||||
// Adds an `or where` clause to the query.
|
||||
@ -167,7 +163,7 @@ define(function(require, exports) {
|
||||
|
||||
// Adds a `where exists` clause to the query.
|
||||
whereExists: function(callback, bool, type) {
|
||||
var query = new Builder(this);
|
||||
var query = new Builder(this.knex);
|
||||
callback.call(query, query);
|
||||
this.wheres.push({
|
||||
type: (type || 'Exists'),
|
||||
@ -385,7 +381,7 @@ define(function(require, exports) {
|
||||
for (var i = 0, l = obj.length; i < l; i++) {
|
||||
bindings[i] = obj[i][1];
|
||||
}
|
||||
this.bindings = bindings.concat(this.bindings || []);
|
||||
this.bindings = bindings.concat(this.bindings);
|
||||
this.values = obj;
|
||||
return this._setType('update');
|
||||
},
|
||||
@ -425,7 +421,7 @@ define(function(require, exports) {
|
||||
// Helper for compiling any advanced `where in` queries.
|
||||
_whereInSub: function(column, callback, bool, condition) {
|
||||
condition += 'Sub';
|
||||
var query = new Builder(this);
|
||||
var query = new Builder(this.knex);
|
||||
callback.call(query, query);
|
||||
this.wheres.push({type: condition, column: column, query: query, bool: bool});
|
||||
push.apply(this.bindings, query.bindings);
|
||||
@ -434,8 +430,7 @@ define(function(require, exports) {
|
||||
|
||||
// Helper for compiling any advanced `where` queries.
|
||||
_whereNested: function(callback, bool) {
|
||||
var query = new Builder(this);
|
||||
query.table = this.table;
|
||||
var query = new Builder(this.knex);
|
||||
callback.call(query, query);
|
||||
this.wheres.push({type: 'Nested', query: query, bool: bool});
|
||||
push.apply(this.bindings, query.bindings);
|
||||
@ -444,7 +439,7 @@ define(function(require, exports) {
|
||||
|
||||
// Helper for compiling any of the `where` advanced queries.
|
||||
_whereSub: function(column, operator, callback, bool) {
|
||||
var query = new Builder(this);
|
||||
var query = new Builder(this.knex);
|
||||
callback.call(query, query);
|
||||
this.wheres.push({
|
||||
type: 'Sub',
|
||||
@ -466,14 +461,12 @@ define(function(require, exports) {
|
||||
|
||||
// Helper for the incrementing/decrementing queries.
|
||||
_counter: function(column, amount, symbol) {
|
||||
var sql = {};
|
||||
sql[column] = new Raw('' + this.grammar.wrap(column) + ' ' + (symbol || '+') + ' ' + amount);
|
||||
return this.update(sql);
|
||||
return this.update({column: this.knex.raw('' + this.grammar.wrap(column) + ' ' + (symbol || '+') + ' ' + amount)});
|
||||
},
|
||||
|
||||
// Helper for compiling any `union` queries.
|
||||
_union: function(callback, bool) {
|
||||
var query = new Builder(this);
|
||||
var query = new Builder(this.knex);
|
||||
callback.call(query, query);
|
||||
this.unions.push({query: query, all: bool});
|
||||
push.apply(this.bindings, query.bindings);
|
||||
|
||||
@ -8,8 +8,8 @@ define(function(require, exports) {
|
||||
|
||||
var JoinClause = function(type, table) {
|
||||
this.clauses = [];
|
||||
this.type = type;
|
||||
this.table = table;
|
||||
this.type = type;
|
||||
this.table = table;
|
||||
};
|
||||
|
||||
JoinClause.prototype = {
|
||||
0
lib/chainable/column.js
Normal file
0
lib/chainable/column.js
Normal file
0
lib/chainable/foreign.js
Normal file
0
lib/chainable/foreign.js
Normal file
@ -16,12 +16,10 @@ define(function(require, exports) {
|
||||
// used to generate the sql in one form or another.
|
||||
exports.Common = {
|
||||
|
||||
_debug: false,
|
||||
|
||||
_promise: null,
|
||||
isDebugging: false,
|
||||
|
||||
debug: function() {
|
||||
this._debug = true;
|
||||
this.isDebugging = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -30,22 +28,28 @@ define(function(require, exports) {
|
||||
// if called more than once. Any unhandled errors will be thrown
|
||||
// after the last block.
|
||||
exec: function(callback) {
|
||||
this._promise || (this._promise = this.runQuery());
|
||||
this._promise || (this._promise = this.client.query(this));
|
||||
return this._promise.then(function(resp) {
|
||||
if (callback) callback(null, resp);
|
||||
}, function(err) {
|
||||
if (callback) callback(err, null);
|
||||
}).then(null, function(err) {
|
||||
}).otherwise(function(err) {
|
||||
setTimeout(function() { throw err; }, 0);
|
||||
});
|
||||
},
|
||||
|
||||
// The promise interface for the query builder.
|
||||
then: function(onFulfilled, onRejected) {
|
||||
this._promise || (this._promise = this.runQuery());
|
||||
this._promise || (this._promise = this.client.query(this));
|
||||
return this._promise.then(onFulfilled, onRejected);
|
||||
},
|
||||
|
||||
// Passthrough to the convenient `tap` mechanism of when.js
|
||||
tap: function(handler) {
|
||||
this._promise = this._promise || this.client.query(this);
|
||||
return this._promise.tap(handler);
|
||||
},
|
||||
|
||||
// Returns an array of query strings filled out with the
|
||||
// correct values based on bindings, etc. Useful for debugging.
|
||||
toString: function() {
|
||||
@ -63,13 +67,13 @@ define(function(require, exports) {
|
||||
|
||||
// Explicitly sets the connection.
|
||||
connection: function(connection) {
|
||||
this._connection = connection;
|
||||
this.usingConnection = connection;
|
||||
return this;
|
||||
},
|
||||
|
||||
// The connection the current query is being run on, optionally
|
||||
// specified by the `connection` method.
|
||||
_connection: false,
|
||||
usingConnection: false,
|
||||
|
||||
// Sets the "type" of the current query, so we can potentially place
|
||||
// `select`, `update`, `del`, etc. anywhere in the query statement
|
||||
@ -97,29 +101,33 @@ define(function(require, exports) {
|
||||
},
|
||||
|
||||
// Runs the query on the current builder instance and returns a promise.
|
||||
runQuery: function() {
|
||||
if (this.transaction) {
|
||||
if (!this.transaction.connection) {
|
||||
throw new Error('The transaction has already completed.');
|
||||
}
|
||||
this._connection = this.transaction.connection;
|
||||
}
|
||||
// runQuery: function() {
|
||||
// this.client.query(this);
|
||||
|
||||
// Prep the SQL associated with the this.
|
||||
this.sql = this.toSql();
|
||||
this.bindings = this._cleanBindings();
|
||||
if (!_.isArray(this.sql)) this.sql = [this.sql];
|
||||
// if (this.transaction) {
|
||||
// if (!this.transaction.connection) {
|
||||
// throw new Error('The transaction has already completed.');
|
||||
// }
|
||||
// this.usingConnection = this.transaction.connection;
|
||||
// }
|
||||
|
||||
var chain;
|
||||
for (var i = 0, l = this.sql.length; i < l; i++) {
|
||||
if (chain) {
|
||||
chain.then(Helpers.multiQuery(this, i, chain));
|
||||
} else {
|
||||
chain = Helpers.multiQuery(this, i);
|
||||
}
|
||||
}
|
||||
return chain;
|
||||
},
|
||||
// // Prep the SQL associated with the this.
|
||||
// this.sql = this.toSql();
|
||||
// this.bindings = this._cleanBindings();
|
||||
// if (!_.isArray(this.sql)) this.sql = [this.sql];
|
||||
|
||||
// ;
|
||||
|
||||
// var chain;
|
||||
// for (var i = 0, l = this.sql.length; i < l; i++) {
|
||||
// if (chain) {
|
||||
// chain.then(Helpers.multiQuery(this, i, chain));
|
||||
// } else {
|
||||
// chain = Helpers.multiQuery(this, i);
|
||||
// }
|
||||
// }
|
||||
// return chain;
|
||||
// },
|
||||
|
||||
// Sets the current Builder connection to that of the
|
||||
// the currently running transaction
|
||||
|
||||
@ -21,16 +21,6 @@ define(function(require, exports) {
|
||||
});
|
||||
},
|
||||
|
||||
// Sets up a multi-query to be executed with serial promises.
|
||||
multiQuery: function(builder, i, chain) {
|
||||
if (chain) {
|
||||
return function() {
|
||||
return Helpers.multiQuery(builder, i);
|
||||
};
|
||||
}
|
||||
return builder.client.query(_.extend({currentIndex: i}, builder, {sql: builder.sql[i]}));
|
||||
},
|
||||
|
||||
// The standard Backbone.js `extend` method.
|
||||
extend: function(protoProps, staticProps) {
|
||||
var parent = this;
|
||||
|
||||
@ -11,8 +11,8 @@ var sequence = require('when/sequence');
|
||||
// The new migration we're performing.
|
||||
// Takes a `config` object, which has the name
|
||||
// of the current migration (`main` if not otherwise specified)
|
||||
var Migrate = function(Instance) {
|
||||
this.Knex = Instance;
|
||||
var Migrate = function(instance) {
|
||||
this.knex = instance;
|
||||
_.bindAll(this, 'currentVersion', 'createMigrationTable', '_migrationData');
|
||||
};
|
||||
|
||||
|
||||
18
lib/raw.js
18
lib/raw.js
@ -7,15 +7,23 @@ define(function(require, exports) {
|
||||
var _ = require('underscore');
|
||||
var Common = require('./common').Common;
|
||||
|
||||
var Raw = function(sql, bindings) {
|
||||
this.bindings = (!_.isArray(bindings) ? (bindings ? [bindings] : []) : bindings);
|
||||
this.sql = sql;
|
||||
var Raw = function(instance) {
|
||||
this.knex = instance;
|
||||
};
|
||||
|
||||
_.extend(Raw.prototype, {
|
||||
_.extend(Raw.prototype, Common, {
|
||||
|
||||
_source: 'Raw',
|
||||
|
||||
// Set the sql and the bindings associated with the query, returning
|
||||
// the current raw object.
|
||||
query: function(sql, bindings) {
|
||||
this.bindings = _.isArray(bindings) ? bindings :
|
||||
bindings ? [bindings] : [];
|
||||
this.sql = sql;
|
||||
return this;
|
||||
},
|
||||
|
||||
// Returns the raw sql for the query.
|
||||
toSql: function() {
|
||||
return this.sql;
|
||||
@ -28,5 +36,5 @@ define(function(require, exports) {
|
||||
});
|
||||
|
||||
})(
|
||||
typeof define === 'function' && define.amd ? define : function (factory) { factory(require, exports, module); }
|
||||
typeof define === 'function' && define.amd ? define : function (factory) { factory(require, exports); }
|
||||
);
|
||||
@ -6,12 +6,13 @@ define(function(require, exports) {
|
||||
|
||||
var _ = require('underscore');
|
||||
|
||||
var Raw = require('./raw').Raw;
|
||||
var Common = require('./common').Common;
|
||||
var Helpers = require('./helpers').Helpers;
|
||||
|
||||
var SchemaBuilder = function(table) {
|
||||
this.table = table;
|
||||
var SchemaBuilder = function(instance) {
|
||||
this.knex = instance;
|
||||
this.client = instance.client;
|
||||
this.grammar = instance.schemaGrammar;
|
||||
this.columns = [];
|
||||
this.commands = [];
|
||||
this.bindings = [];
|
||||
@ -22,9 +23,8 @@ define(function(require, exports) {
|
||||
_source: 'SchemaBuilder',
|
||||
|
||||
instance: function() {
|
||||
var builder = new SchemaBuilder(this.table);
|
||||
builder.client = this.client;
|
||||
builder.grammar = this.grammar;
|
||||
var builder = new SchemaBuilder(this.knex);
|
||||
builder.table = this.table;
|
||||
return builder;
|
||||
},
|
||||
|
||||
|
||||
@ -8,27 +8,35 @@ define(function(require, exports) {
|
||||
var _ = require('underscore');
|
||||
|
||||
var Transaction = function(instance) {
|
||||
this.knex = instance;
|
||||
this.client = instance.client;
|
||||
};
|
||||
|
||||
Transaction.prototype.run = function(container) {
|
||||
Transaction.prototype = {
|
||||
|
||||
var client = this.knex.client;
|
||||
// Passed a `container` function, this method runs the current
|
||||
// transaction, returning a promise.
|
||||
run: function(container) {
|
||||
return this.client.startTransaction()
|
||||
.then(this.getContainerObject)
|
||||
.then(this.initiateDeferred(container));
|
||||
},
|
||||
|
||||
return client.startTransaction().then(function(connection) {
|
||||
getContainerObject: function(connection) {
|
||||
|
||||
// Initiate a deferred object, so we know when the
|
||||
// transaction completes or fails, we know what to do.
|
||||
var dfd = when.defer();
|
||||
// The client we need to call `finishTransaction` on.
|
||||
var client = this.client;
|
||||
|
||||
// The object passed around inside the transaction container.
|
||||
var containerObj = {
|
||||
commit: function(val) {
|
||||
client.finishTransaction('commit', this, dfd, val);
|
||||
|
||||
commit: function(message) {
|
||||
client.finishTransaction('commit', this, message);
|
||||
},
|
||||
rollback: function(err) {
|
||||
client.finishTransaction('rollback', this, dfd, err);
|
||||
|
||||
rollback: function(error) {
|
||||
client.finishTransaction('rollback', this, error);
|
||||
},
|
||||
|
||||
// "rollback to"?
|
||||
connection: connection
|
||||
};
|
||||
@ -36,12 +44,27 @@ define(function(require, exports) {
|
||||
// Ensure the transacting object methods are bound with the correct context.
|
||||
_.bindAll(containerObj, 'commit', 'rollback');
|
||||
|
||||
// Call the container with the transaction
|
||||
// commit & rollback objects.
|
||||
container(containerObj);
|
||||
},
|
||||
|
||||
initiateDeferred: function(container) {
|
||||
|
||||
return function(containerObj) {
|
||||
|
||||
// Initiate a deferred object, so we know when the
|
||||
// transaction completes or fails, we know what to do.
|
||||
var dfd = containerObj.dfd = when.defer();
|
||||
|
||||
// Call the container with the transaction
|
||||
// commit & rollback objects.
|
||||
container(containerObj);
|
||||
|
||||
// Return the promise for the entire transaction.
|
||||
return dfd.promise;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
return dfd.promise;
|
||||
});
|
||||
};
|
||||
|
||||
exports.Transaction = Transaction;
|
||||
|
||||
@ -7,14 +7,19 @@
|
||||
"test": "test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.12.0",
|
||||
"objectdump": "~0.3.0",
|
||||
"mysql": "~2.0.0-alpha7",
|
||||
"pg": "~2.3.1",
|
||||
"sqlite3": "~2.1.7",
|
||||
"node-uuid": "~1.4.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-release": "~0.5.1"
|
||||
"grunt-release": "~0.5.1",
|
||||
"sinon": "~1.7.3",
|
||||
"chai": "~1.7.2",
|
||||
"mocha-as-promised": "~1.4.0",
|
||||
"sinon-chai": "~2.4.0",
|
||||
"mocha": "~1.12.1",
|
||||
"chai-as-promised": "~3.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"when": "~2.3.0",
|
||||
|
||||
@ -1,71 +1,17 @@
|
||||
var equal = require('assert').equal;
|
||||
var When = require('when');
|
||||
var _ = require('underscore');
|
||||
var Knex = require('../knex');
|
||||
var conn = require(process.env.KNEX_TEST || './shared/config');
|
||||
require("mocha-as-promised")();
|
||||
|
||||
// The output goes here.
|
||||
exports.output = {};
|
||||
global.sinon = require("sinon");
|
||||
|
||||
var pool = {
|
||||
afterCreate: function(conn, done) {
|
||||
equal(_.has(conn, '__cid'), true);
|
||||
done();
|
||||
},
|
||||
beforeDestroy: function(conn, done) {
|
||||
equal(_.has(conn, '__cid'), true);
|
||||
done();
|
||||
}
|
||||
};
|
||||
var chai = global.chai = require("chai");
|
||||
chai.use(require("chai-as-promised"));
|
||||
chai.use(require("sinon-chai"));
|
||||
chai.should();
|
||||
|
||||
Knex.Initialize({
|
||||
client: 'mysql',
|
||||
connection: conn.mysql,
|
||||
pool: _.extend({}, pool, {
|
||||
afterCreate: function(conn, done) {
|
||||
conn.query("SET sql_mode='TRADITIONAL';", [], function(err) {
|
||||
done(err);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
var Sqlite3 = Knex.Initialize('sqlite3', {
|
||||
client: 'sqlite3',
|
||||
connection: conn.sqlite3,
|
||||
pool: pool
|
||||
});
|
||||
var Postgres = Knex.Initialize('postgres', {
|
||||
client: 'postgres',
|
||||
connection: conn.postgres,
|
||||
pool: pool
|
||||
});
|
||||
global._ = require('underscore');
|
||||
global.when = require('when');
|
||||
global.expect = chai.expect;
|
||||
global.AssertionError = chai.AssertionError;
|
||||
global.Assertion = chai.Assertion;
|
||||
global.assert = chai.assert;
|
||||
|
||||
var regularThen = Knex.Builder.prototype.then;
|
||||
var then = function(success, error) {
|
||||
var ctx = this;
|
||||
var bindings = ctx._cleanBindings();
|
||||
var chain = regularThen.call(this, function(resp) {
|
||||
return {
|
||||
object: resp,
|
||||
string: {
|
||||
sql: ctx.sql,
|
||||
bindings: bindings
|
||||
}
|
||||
};
|
||||
});
|
||||
return chain.then(success, error);
|
||||
};
|
||||
|
||||
describe('Knex', function() {
|
||||
|
||||
_.each(['Builder', 'SchemaBuilder', 'Raw'], function(item) {
|
||||
Knex[item].prototype.then = then;
|
||||
Postgres[item].prototype.then = then;
|
||||
Sqlite3[item].prototype.then = then;
|
||||
});
|
||||
|
||||
require('./regular')(Knex, 'mysql');
|
||||
require('./regular')(Postgres, 'postgres');
|
||||
require('./regular')(Sqlite3, 'sqlite3');
|
||||
|
||||
});
|
||||
require('./unit/builder')();
|
||||
64
test/integration/index-old.js
Normal file
64
test/integration/index-old.js
Normal file
@ -0,0 +1,64 @@
|
||||
var equal = require('assert').equal;
|
||||
var When = require('when');
|
||||
var _ = require('underscore');
|
||||
var Knex = require('../knex');
|
||||
var conn = require(process.env.KNEX_TEST || './shared/config');
|
||||
|
||||
// The output goes here.
|
||||
exports.output = {};
|
||||
|
||||
var pool = {
|
||||
afterCreate: function(conn, done) {
|
||||
equal(_.has(conn, '__cid'), true);
|
||||
done();
|
||||
},
|
||||
beforeDestroy: function(conn, done) {
|
||||
equal(_.has(conn, '__cid'), true);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
var MySQL = Knex.initialize({
|
||||
client: 'mysql',
|
||||
connection: conn.mysql,
|
||||
pool: _.extend({}, pool, {
|
||||
afterCreate: function(conn, done) {
|
||||
conn.query("SET sql_mode='TRADITIONAL';", [], function(err) {
|
||||
done(err);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
var SQLite3 = Knex.initialize('sqlite3', {
|
||||
client: 'sqlite3',
|
||||
connection: conn.sqlite3,
|
||||
pool: pool
|
||||
});
|
||||
var PostgreSQL = Knex.initialize('postgres', {
|
||||
client: 'postgres',
|
||||
connection: conn.postgres,
|
||||
pool: pool
|
||||
});
|
||||
|
||||
var regularThen = MySQL.builder.prototype.then;
|
||||
var then = function(success, error) {
|
||||
var ctx = this;
|
||||
var bindings = ctx._cleanBindings();
|
||||
var chain = regularThen.call(this, function(resp) {
|
||||
return {
|
||||
object: resp,
|
||||
string: {
|
||||
sql: ctx.sql,
|
||||
bindings: bindings
|
||||
}
|
||||
};
|
||||
});
|
||||
return chain.then(success, error);
|
||||
};
|
||||
|
||||
describe('Knex', function() {
|
||||
require('./regular')(MySQL, 'mysql');
|
||||
require('./regular')(PostgreSQL, 'postgres');
|
||||
require('./regular')(SQLite3, 'sqlite3');
|
||||
});
|
||||
|
||||
@ -1,12 +1,269 @@
|
||||
module.exports = function(client) {
|
||||
module.exports = function() {
|
||||
|
||||
var Builder = require('../../lib/builder');
|
||||
var when = require('when');
|
||||
var Builder = require('../../lib/builder').Builder;
|
||||
var Common = require('../../lib/common').Common;
|
||||
var Raw = require('../../lib/raw').Raw;
|
||||
|
||||
describe('Builder', function () {
|
||||
|
||||
it('should be a constructor, accepting the current Knex client');
|
||||
var builder;
|
||||
beforeEach(function() {
|
||||
builder = new Builder({
|
||||
query: function(obj) {
|
||||
return when.resolve(obj);
|
||||
},
|
||||
grammar: require('../../clients/server/mysql').grammar
|
||||
});
|
||||
});
|
||||
|
||||
describe('constructor', function () {
|
||||
|
||||
it('accepts the current Knex instance, attaching the client, and grammar', function() {
|
||||
var grammar = {some: 'grammar'};
|
||||
var client = {some: 'db'};
|
||||
var knex = {client: client, grammar: grammar};
|
||||
var reset = sinon.stub(Builder.prototype, 'reset');
|
||||
var builder = new Builder(knex);
|
||||
|
||||
expect(builder.knex).to.eql(knex);
|
||||
expect(builder.client).to.eql(client);
|
||||
expect(builder.grammar).to.eql(grammar);
|
||||
reset.should.have.been.calledOnce;
|
||||
reset.restore();
|
||||
});
|
||||
|
||||
it('has the Common methods mixed-in to the Builder.prototype', function() {
|
||||
_.each(Common, function(val, key) {
|
||||
expect(Builder.prototype[key]).to.equal(val);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('from', function() {
|
||||
|
||||
it('sets the tableName', function() {
|
||||
expect(builder.table).not.to.exist;
|
||||
var result = builder.from('myTable');
|
||||
expect(builder.table).to.equal('myTable');
|
||||
expect(result).to.equal(builder);
|
||||
});
|
||||
|
||||
it('returns the tableName when no arguments are passed', function() {
|
||||
expect(builder.table).not.to.exist;
|
||||
var result = builder.from('myTable');
|
||||
expect(builder.from()).to.equal('myTable');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('column', function() {
|
||||
|
||||
it('adds a value to the columns array', function() {
|
||||
expect(builder.columns).to.have.length(0);
|
||||
builder.column('myColumn');
|
||||
expect(builder.columns).to.have.length(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('distinct', function() {
|
||||
|
||||
it('sets the isDistinct flag to true', function() {
|
||||
builder.distinct('distinctCol');
|
||||
expect(builder.columns[0]).to.equal('distinctCol');
|
||||
});
|
||||
|
||||
it('adds the column to the columns array', function() {
|
||||
builder.distinct('distinctCol');
|
||||
expect(builder.isDistinct).to.be.true;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('toSql', function() {
|
||||
|
||||
it('sets the type to "select" if not otherwise set', function() {
|
||||
expect(builder.type).not.to.exist;
|
||||
builder.toSql();
|
||||
expect(builder.type).to.equal('select');
|
||||
});
|
||||
|
||||
it('compiles based on the type, passing the current context', function(done) {
|
||||
var compileSelect = builder.grammar.compileSelect;
|
||||
builder.grammar.compileSelect = function(ctx) {
|
||||
expect(ctx).to.eql(builder);
|
||||
builder.grammar.compileSelect = compileSelect;
|
||||
done();
|
||||
};
|
||||
builder.toSql();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('clone', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('reset', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('join', function() {
|
||||
|
||||
var JoinClause = require('../../lib/builder/joinclause').JoinClause;
|
||||
|
||||
it('accepts the joining table, the first column, operator, second column, and (optional) type', function() {
|
||||
expect(builder.joins).to.have.length(0);
|
||||
builder.from('users');
|
||||
builder.join('accounts', 'users.id', '=', 'accounts.id');
|
||||
expect(builder.joins).to.have.length(1);
|
||||
expect(builder.joins[0]).to.be.an.instanceOf(JoinClause);
|
||||
expect(builder.toString()).to.equal("select * from `users` inner join `accounts` on `users`.`id` = `accounts`.`id`");
|
||||
});
|
||||
|
||||
it('accepts a different join type as the fifth parameter', function() {
|
||||
builder.from('users');
|
||||
builder.join('accounts', 'users.id', '=', 'accounts.id', 'left outer');
|
||||
expect(builder.toString()).to.equal("select * from `users` left outer join `accounts` on `users`.`id` = `accounts`.`id`");
|
||||
});
|
||||
|
||||
it('may take a function as the second argument, for a grouped join', function() {
|
||||
|
||||
builder.join('accounts', function(join) {
|
||||
expect(builder.joins).to.have.length(0);
|
||||
expect(this).to.be.an.instanceOf(JoinClause);
|
||||
expect(join).to.be.an.instanceOf(JoinClause);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('where', function() {
|
||||
|
||||
describe('where', function() {
|
||||
|
||||
it('should allow a function as the first argument, for a grouped where clause', function() {
|
||||
builder.where('id', '=', 1);
|
||||
expect(builder.wheres).to.have.length(1);
|
||||
expect(builder.bindings).to.have.length(1);
|
||||
var subWhere = function(qb) {
|
||||
expect(this).to.equal(qb);
|
||||
expect(this).to.be.an.instanceOf(Builder);
|
||||
this.where({id: 3}).orWhere('id', 4);
|
||||
};
|
||||
builder.where(subWhere);
|
||||
expect(builder.bindings).to.have.length(3);
|
||||
expect(builder.wheres).to.have.length(2);
|
||||
expect(builder.from('test').toString()).to.equal("select * from `test` where `id` = 1 and (`id` = 3 or `id` = 4)");
|
||||
});
|
||||
|
||||
it('should allow a raw instance as the first argument, which will add a whereRaw clause', function() {
|
||||
builder.where(new Raw({}).query('id > ?', 2));
|
||||
expect(builder.wheres).to.have.length(1);
|
||||
expect(builder.bindings).to.have.length(1);
|
||||
expect(builder.bindings[0]).to.equal(2);
|
||||
});
|
||||
|
||||
it('should allow an object as the first argument, which will assume to be a k/v pair of where "="', function() {
|
||||
builder.where({id: 2, name: 'Test'});
|
||||
expect(builder.wheres).to.have.length(2);
|
||||
expect(builder.bindings).to.have.length(2);
|
||||
});
|
||||
|
||||
it('should assume that if the second argument is not an operator, it should be an "="', function() {
|
||||
builder.where('id', 2);
|
||||
expect(builder.wheres).to.have.length(1);
|
||||
expect(builder.bindings[0]).to.equal(2);
|
||||
});
|
||||
|
||||
it('should accept a function as the "value", for a sub select', function() {
|
||||
builder.where('id', '=', function(qb) {
|
||||
expect(this).to.equal(qb);
|
||||
expect(this).to.be.an.instanceOf(Builder);
|
||||
this.select('account_id').from('names').where('names.id', '>', 1).orWhere(function() {
|
||||
this.where('names.first_name', 'like', 'Tim%').andWhere('names.id', '>', 10);
|
||||
});
|
||||
});
|
||||
expect(builder.bindings).to.have.length(3);
|
||||
expect(builder.toString()).to.equal("select * where `id` = (select `account_id` from `names` where `names`.`id` > 1 or (`names`.`first_name` like Tim% and `names`.`id` > 10))");
|
||||
});
|
||||
|
||||
var arg1 = {}, arg2 = {}, arg3 = {}, arg4 = {};
|
||||
|
||||
it('is called by andWhere, passing the first three arguments and an "and"', function() {
|
||||
sinon.mock(builder).expects('where').withExactArgs(arg1, arg2, arg3, 'and');
|
||||
builder.andWhere(arg1, arg2, arg3, 'error');
|
||||
});
|
||||
|
||||
it('is called by orWhere, passing the first three arguments and an "or"', function() {
|
||||
sinon.mock(builder).expects('where').withExactArgs(arg1, arg2, arg3, 'or');
|
||||
builder.orWhere(arg1, arg2, arg3, 'error');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('whereRaw', function() {
|
||||
|
||||
it('is called by orWhereRaw, passing the sql, bindings, and "or"', function() {
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('whereExists', function() {
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('groupBy', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('orderBy', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('union', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('having', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('offset / limit', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('aggregate', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('select', function() {
|
||||
|
||||
it('should throw if a table has not been specified when compiling');
|
||||
|
||||
});
|
||||
|
||||
describe('insert', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('update', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('delete', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('truncate', function() {
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
66
test/unit/common.js
Normal file
66
test/unit/common.js
Normal file
@ -0,0 +1,66 @@
|
||||
module.exports = function(client) {
|
||||
|
||||
var Common = require('../../lib/common').Common;
|
||||
|
||||
var CommonStub = function(knex) {
|
||||
this.knex = knex;
|
||||
this.client = client;
|
||||
this.grammar = client.grammar;
|
||||
};
|
||||
CommonStub.prototype = Common;
|
||||
|
||||
describe('Common', function () {
|
||||
|
||||
var common;
|
||||
|
||||
beforeEach(function() {
|
||||
common = new CommonStub();
|
||||
});
|
||||
|
||||
describe('debug', function () {
|
||||
|
||||
it('should set the flag for the isDebugging property of the object');
|
||||
|
||||
});
|
||||
|
||||
describe('exec', function() {
|
||||
|
||||
it('should accept a callback, which provides an err / success');
|
||||
|
||||
it('should rethrow any error in the handler');
|
||||
|
||||
});
|
||||
|
||||
describe('then', function() {
|
||||
|
||||
it('should accept two functions, which are passed along to the promise handler');
|
||||
|
||||
});
|
||||
|
||||
describe('tap', function () {
|
||||
|
||||
it('is essentially a passthrough to the `tap` method of when.js');
|
||||
|
||||
});
|
||||
|
||||
describe('toString', function() {
|
||||
|
||||
it('turns the current query into a string value, based on the current client');
|
||||
|
||||
});
|
||||
|
||||
describe('connection', function() {
|
||||
|
||||
it('should set the usingConnection property of the current object');
|
||||
|
||||
});
|
||||
|
||||
describe('transacting', function () {
|
||||
|
||||
it('should set the transaction object');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
0
test/unit/knex.js
Normal file
0
test/unit/knex.js
Normal file
15
test/unit/raw.js
Normal file
15
test/unit/raw.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = function(client) {
|
||||
|
||||
var Raw = require('../../lib/raw').Raw;
|
||||
|
||||
describe('Raw', function () {
|
||||
|
||||
it('has the Common methods mixed-in to the Builder.prototype', function() {
|
||||
_.each(Common, function(val, key) {
|
||||
expect(Builder.prototype[key]).to.equal(val);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
@ -1,5 +0,0 @@
|
||||
var Sqlite3 = require('../../clients/base/sqlite3').Sqlite3;
|
||||
|
||||
describe('Sqlite3', function () {
|
||||
|
||||
});
|
||||
23
test/unit/transaction.js
Normal file
23
test/unit/transaction.js
Normal file
@ -0,0 +1,23 @@
|
||||
module.exports = function(client) {
|
||||
|
||||
var Transaction = require('../../lib/transaction').Transaction;
|
||||
|
||||
describe('Transaction', function () {
|
||||
|
||||
describe('Constructor', function() {
|
||||
|
||||
it('saves the current client off the knex instance', function() {
|
||||
|
||||
var knex = {client: {name: 'mysql'}};
|
||||
|
||||
var transaction = new Transaction(knex);
|
||||
|
||||
assert(transaction.client).should.eql(knex.client);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user