fixing merge conflict while working on multi-instance

This commit is contained in:
Tim Griesser 2013-04-30 18:32:13 -04:00
commit bd4256de4f
9 changed files with 480 additions and 207 deletions

View File

@ -108,7 +108,7 @@ MysqlClient.grammar = {
MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
// The possible column modifiers.
modifiers: ['Unsigned', 'Nullable', 'Default', 'Increment'],
modifiers: ['Unsigned', 'Nullable', 'Default', 'Increment', 'After'],
// Compile the query to determine if a table exists.
compileTableExists: function() {
@ -188,7 +188,7 @@ MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
// Compile a rename table command.
compileRename: function(blueprint, command) {
return "rename table " + this.wrapTable(blueprint) + " to " + this.wrapTable(command.to);
return 'rename table ' + this.wrapTable(blueprint) + ' to ' + this.wrapTable(command.to);
},
// Create the column definition for a string type.
@ -198,12 +198,26 @@ MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
// Create the column definition for a text type.
typeText: function(column) {
return 'text';
switch (column.length) {
case 'medium':
case 'mediumtext':
return 'mediumtext';
case 'long':
case 'longtext':
return 'longtext';
default:
return 'text';
}
},
// Create the column definition for a integer type.
typeInteger: function(column) {
return 'int';
return 'int(' + column.length + ')';
},
// Create the column definition for a tiny integer type.
typeTinyInteger: function() {
return 'tinyint';
},
// Create the column definition for a float type.
@ -218,7 +232,7 @@ MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
// Create the column definition for a boolean type.
typeBoolean: function(column) {
return 'tinyint';
return 'tinyint(1)';
},
// Create the column definition for a enum type.
@ -246,6 +260,11 @@ MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
return 'timestamp default 0';
},
// Create the column definition for a bit type.
typeBit: function(column) {
return column.length !== false ? 'bit(' + column.length + ')' : 'bit';
},
// Create the column definition for a binary type.
typeBinary: function(column) {
return 'blob';
@ -276,4 +295,4 @@ MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
return ' auto_increment primary key';
}
}
});
});

View File

@ -43,16 +43,34 @@ exports.initialize = function (options) {
}, options.pool));
};
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);
}
// Bind all of the ? to numbered vars.
var questionCount = 0;
querystring = querystring.replace(/\?/g, function () {
questionCount++;
@ -192,8 +210,7 @@ exports.schemaGrammar = _.extend({}, grammar, {
// Compile a rename table command.
compileRename: function(blueprint, command) {
var from = this.wrapTable(blueprint);
return "alter table " + from + " rename to " + this.wrapTable(command.to);
return 'alter table ' + this.wrapTable(blueprint) + ' rename to ' + this.wrapTable(command.to);
},
// Create the column definition for a string type.
@ -256,6 +273,11 @@ exports.schemaGrammar = _.extend({}, grammar, {
return 'timestamp';
},
// Create the column definition for a bit type.
typeBit: function(column) {
return column.length !== false ? 'bit(' + column.length + ')' : 'bit';
},
// Create the column definition for a binary type.
typeBinary: function(column) {
return 'bytea';

View File

@ -40,8 +40,8 @@ exports.initialize = function (options) {
destroy : function(client) {
client.close();
},
max : 10,
min : 2,
max : 1,
min : 1,
idleTimeoutMillis: 30000,
log : false
}, options.pool));
@ -49,6 +49,8 @@ exports.initialize = function (options) {
exports.query = function (querystring, params, callback, connection, type) {
if (debug) console.log([querystring, params]);
// If there is a connection, use it.
if (connection) {
return connection.run(querystring, params, callback);
@ -69,7 +71,21 @@ exports.query = function (querystring, params, callback, connection, type) {
});
});
};
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
@ -280,6 +296,11 @@ exports.schemaGrammar = _.extend({}, grammar, {
typeBoolean: function(column) {
return 'tinyint';
},
// Create the column definition for a tinyint type.
typeTinyInteger: function() {
return 'tinyint';
},
// Create the column definition for a enum type.
typeEnum: function(column) {

View File

@ -482,7 +482,7 @@ including any nested join queries.</p>
</div>
<div class="content"><div class='highlight'><pre> whereIn: <span class="keyword">function</span>(qb, where) {
<span class="keyword">return</span> <span class="keyword">this</span>.wrap(where.column) + <span class="string">' in ('</span> + <span class="keyword">this</span>.parameterize(where.values) + <span class="string">')'</span>;
<span class="keyword">return</span> <span class="keyword">this</span>.wrap(where.column) + <span class="string">' in ('</span> + <span class="keyword">this</span>.parameterize(where.value) + <span class="string">')'</span>;
},</pre></div></div>
</li>
@ -499,7 +499,7 @@ including any nested join queries.</p>
</div>
<div class="content"><div class='highlight'><pre> whereNotIn: <span class="keyword">function</span>(qb, where) {
<span class="keyword">return</span> <span class="keyword">this</span>.wrap(where.column) + <span class="string">' not in ('</span> + <span class="keyword">this</span>.parameterize(where.values) + <span class="string">')'</span>;
<span class="keyword">return</span> <span class="keyword">this</span>.wrap(where.column) + <span class="string">' not in ('</span> + <span class="keyword">this</span>.parameterize(where.value) + <span class="string">')'</span>;
},</pre></div></div>
</li>
@ -672,16 +672,9 @@ inserts using a single query statement.</p>
<div class="content"><div class='highlight'><pre> compileInsert: <span class="keyword">function</span>(qb, values) {
<span class="keyword">var</span> table = <span class="keyword">this</span>.wrapTable(qb.table);
<span class="keyword">var</span> columns = <span class="keyword">this</span>.columnize(_.keys(values[<span class="number">0</span>]));
<span class="keyword">var</span> parameters = <span class="keyword">this</span>.parameterize(values[<span class="number">0</span>]);
<span class="keyword">var</span> paramBlocks = [];
<span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, l = values.length; i &lt; l; ++i) {
paramBlocks.push(<span class="string">"("</span> + parameters + <span class="string">")"</span>);
}
<span class="keyword">return</span> <span class="string">"insert into "</span> + table + <span class="string">" ("</span> + columns + <span class="string">") values "</span> + paramBlocks.join(<span class="string">', '</span>);
},</pre></div></div>
<span class="keyword">var</span> columns = <span class="keyword">this</span>.columnize(_.keys(values[<span class="number">0</span>]).sort());
<span class="keyword">var</span> parameters = <span class="keyword">this</span>.parameterize(_.values(values[<span class="number">0</span>]));
<span class="keyword">var</span> paramBlocks = [];</pre></div></div>
</li>
@ -692,12 +685,18 @@ inserts using a single query statement.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-35">&#182;</a>
</div>
<p>Compiles an <code>insert</code>, getting the id of the insert row.</p>
<p>If there are any &quot;where&quot; clauses, we need to omit
any bindings that may have been associated with them.</p>
</div>
<div class="content"><div class='highlight'><pre> compileInsertGetId: <span class="keyword">function</span>(qb, values) {
<span class="keyword">return</span> <span class="keyword">this</span>.compileInsert(qb, values);
<div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (qb.wheres.length &gt; <span class="number">0</span>) <span class="keyword">this</span>._clearWhereBindings(qb);
<span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, l = values.length; i &lt; l; ++i) {
paramBlocks.push(<span class="string">"("</span> + parameters + <span class="string">")"</span>);
}
<span class="keyword">return</span> <span class="string">"insert into "</span> + table + <span class="string">" ("</span> + columns + <span class="string">") values "</span> + paramBlocks.join(<span class="string">', '</span>);
},</pre></div></div>
</li>
@ -709,6 +708,37 @@ inserts using a single query statement.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-36">&#182;</a>
</div>
<p>Depending on the type of <code>where</code> clause, this will appropriately
remove any binding caused by &quot;where&quot; constraints, allowing the same
query to be used for <code>insert</code> and <code>update</code> without issue.</p>
</div>
<div class="content"><div class='highlight'><pre> _clearWhereBindings: <span class="keyword">function</span>(qb) {
<span class="keyword">var</span> wheres = qb.wheres;
<span class="keyword">var</span> bindingCount = <span class="number">0</span>;
<span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, l = wheres.length; i&lt;l; i++) {
<span class="keyword">var</span> where = wheres[i];
<span class="keyword">if</span> (_.isArray(where.value)) {
bindingCount += where.value.length;
} <span class="keyword">else</span> <span class="keyword">if</span> (where.query) {
bindingCount += where.query.bindings.length;
} <span class="keyword">else</span> {
bindingCount += <span class="number">1</span>;
}
}
qb.bindings = qb.bindings.slice(bindingCount);
},</pre></div></div>
</li>
<li id="section-37">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-37">&#182;</a>
</div>
<p>Compiles an <code>update</code> query.</p>
</div>
@ -725,11 +755,11 @@ inserts using a single query statement.</p>
</li>
<li id="section-37">
<li id="section-38">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-37">&#182;</a>
<a class="pilcrow" href="#section-38">&#182;</a>
</div>
<p>Compiles a <code>delete</code> query.</p>
@ -744,11 +774,11 @@ inserts using a single query statement.</p>
</li>
<li id="section-38">
<li id="section-39">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-38">&#182;</a>
<a class="pilcrow" href="#section-39">&#182;</a>
</div>
<p>Compiles a <code>truncate</code> query.</p>
@ -804,11 +834,11 @@ inserts using a single query statement.</p>
</li>
<li id="section-39">
<li id="section-40">
<div class="annotation">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-39">&#182;</a>
<a class="pilcrow" href="#section-40">&#182;</a>
</div>
<h2>Knex.Builder</h2>
@ -817,11 +847,11 @@ inserts using a single query statement.</p>
</li>
<li id="section-40">
<li id="section-41">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-40">&#182;</a>
<a class="pilcrow" href="#section-41">&#182;</a>
</div>
</div>
@ -835,11 +865,11 @@ inserts using a single query statement.</p>
</li>
<li id="section-41">
<li id="section-42">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-41">&#182;</a>
<a class="pilcrow" href="#section-42">&#182;</a>
</div>
<p>All operators used in the <code>where</code> clause generation.</p>
@ -847,28 +877,7 @@ inserts using a single query statement.</p>
<div class="content"><div class='highlight'><pre> <span class="keyword">var</span> operators = [<span class="string">'='</span>, <span class="string">'&lt;'</span>, <span class="string">'&gt;'</span>, <span class="string">'&lt;='</span>, <span class="string">'&gt;='</span>, <span class="string">'like'</span>, <span class="string">'not like'</span>, <span class="string">'between'</span>, <span class="string">'ilike'</span>];
Builder.prototype = {
idAttr: <span class="string">'id'</span>,</pre></div></div>
</li>
<li id="section-42">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-42">&#182;</a>
</div>
<p>Sets the <code>tableName</code> on the query.</p>
</div>
<div class="content"><div class='highlight'><pre> from: <span class="keyword">function</span>(tableName) {
<span class="keyword">if</span> (!tableName) <span class="keyword">return</span> <span class="keyword">this</span>.table;
<span class="keyword">this</span>.table = tableName;
<span class="keyword">return</span> <span class="keyword">this</span>;
},</pre></div></div>
Builder.prototype = {</pre></div></div>
</li>
@ -879,12 +888,13 @@ inserts using a single query statement.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-43">&#182;</a>
</div>
<p>Set the <code>idAttribute</code> for the query.</p>
<p>Sets the <code>tableName</code> on the query.</p>
</div>
<div class="content"><div class='highlight'><pre> idAttribute: <span class="keyword">function</span>(id) {
<span class="keyword">this</span>.idAttr = id;
<div class="content"><div class='highlight'><pre> from: <span class="keyword">function</span>(tableName) {
<span class="keyword">if</span> (!tableName) <span class="keyword">return</span> <span class="keyword">this</span>.table;
<span class="keyword">this</span>.table = tableName;
<span class="keyword">return</span> <span class="keyword">this</span>;
},</pre></div></div>
@ -923,7 +933,7 @@ pieces that have been set thus far</p>
<div class="content"><div class='highlight'><pre> clone: <span class="keyword">function</span>() {
<span class="keyword">var</span> item = <span class="keyword">new</span> Builder(<span class="keyword">this</span>.table);
<span class="keyword">var</span> items = [
<span class="string">'isDistinct'</span>, <span class="string">'idAttr'</span>, <span class="string">'joins'</span>,
<span class="string">'isDistinct'</span>, <span class="string">'joins'</span>,
<span class="string">'wheres'</span>, <span class="string">'orders'</span>, <span class="string">'columns'</span>, <span class="string">'bindings'</span>,
<span class="string">'grammar'</span>, <span class="string">'connection'</span>, <span class="string">'transaction'</span>
];
@ -953,18 +963,16 @@ pieces that have been set thus far</p>
<span class="keyword">this</span>.orders = [];
<span class="keyword">this</span>.columns = [];
<span class="keyword">this</span>.bindings = [];
<span class="keyword">this</span>.idAttr = Builder.prototype.idAttr;
<span class="keyword">this</span>.isDistinct = <span class="literal">false</span>;
},
toJSON: <span class="function"><span class="keyword">function</span> <span class="params">()</span> {</span>
toJSON: <span class="keyword">function</span>() {
<span class="keyword">return</span> {
joins: <span class="keyword">this</span>.joins,
wheres: <span class="keyword">this</span>.wheres,
order: <span class="keyword">this</span>.orders,
columns: <span class="keyword">this</span>.columns,
bindings: <span class="keyword">this</span>.bindings,
idAttr: <span class="keyword">this</span>.idAttr,
isDistinct: <span class="keyword">this</span>.isDistinct
};
},</pre></div></div>
@ -1187,7 +1195,7 @@ where key = value. </p>
<span class="keyword">this</span>.wheres.push({
type: (condition || <span class="string">'In'</span>),
column: column,
values: values,
value: values,
bool: bool
});
push.apply(<span class="keyword">this</span>.bindings, values);
@ -1621,23 +1629,19 @@ where key = value. </p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-80">&#182;</a>
</div>
<p>Performs an <code>INSERT</code> query, returning a promise.</p>
<p>Performs an <code>insert</code> query, returning a promise.</p>
</div>
<div class="content"><div class='highlight'><pre> insert: <span class="keyword">function</span>(values, returning) {
<span class="keyword">var</span> str;
returning || (returning = <span class="keyword">this</span>.idAttr);
<span class="keyword">if</span> (!_.isArray(values)) values = values ? [values] : [];
<span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, l = values.length; i &lt; l; i++) {
<span class="keyword">var</span> record = values[i];
<span class="keyword">this</span>.bindings = <span class="keyword">this</span>.bindings.concat(_.values(record));
}
<span class="keyword">if</span> (returning) {
str = <span class="keyword">this</span>.grammar.compileInsertGetId(<span class="keyword">this</span>, values, returning);
} <span class="keyword">else</span> {
str = <span class="keyword">this</span>.grammar.compileInsert(<span class="keyword">this</span>, values);
<span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, l = values.length; i&lt;l; i++) {
<span class="keyword">var</span> obj = sortObject(values[i]);
<span class="keyword">for</span> (<span class="keyword">var</span> i2 = <span class="number">0</span>, l2 = obj.length; i2 &lt; l2; i2++) {
<span class="keyword">this</span>.bindings.push(obj[i2][<span class="number">1</span>]);
}
}
<span class="keyword">var</span> str = <span class="keyword">this</span>.grammar.compileInsert(<span class="keyword">this</span>, values);
<span class="keyword">return</span> Knex.runQuery(<span class="keyword">this</span>, {sql: str, bindings: <span class="keyword">this</span>._cleanBindings(), type: <span class="string">'insert'</span>});
},</pre></div></div>
@ -1786,7 +1790,7 @@ the currently running transaction</p>
query.table = <span class="keyword">this</span>.table;
callback.call(query, query);
<span class="keyword">this</span>.wheres.push({type: <span class="string">'Nested'</span>, query: query, bool: bool});
<span class="keyword">this</span>.bindings = <span class="keyword">this</span>.bindings.concat(query.bindings);
push.apply(<span class="keyword">this</span>.bindings, query.bindings);
<span class="keyword">return</span> <span class="keyword">this</span>;
},
@ -1907,9 +1911,7 @@ the currently running transaction</p>
</div>
<div class="content"><div class='highlight'><pre> Knex.Transaction = <span class="keyword">function</span>(container) {
<span class="keyword">var</span> connection = Knex.client.getConnection();</pre></div></div>
<div class="content"><div class='highlight'><pre> Knex.Transaction = <span class="keyword">function</span>(container) {</pre></div></div>
</li>
@ -1925,7 +1927,9 @@ transaction completes or fails, we know what to do.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="keyword">var</span> deferred = Q.defer();</pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">var</span> deferred = Q.defer();
Knex.client.beginTransaction(<span class="keyword">function</span>(err, connection) {</pre></div></div>
</li>
@ -1940,11 +1944,11 @@ transaction completes or fails, we know what to do.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="keyword">var</span> finish = <span class="keyword">function</span>(type, data) {
<span class="keyword">this</span>.connection.end();
<span class="keyword">this</span>.transaction.connection = <span class="literal">null</span>;
deferred[type](data);
};</pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">var</span> finish = <span class="keyword">function</span>(type, data) {
connection.end();
<span class="keyword">this</span>.connection = <span class="literal">null</span>;
deferred[type](data);
};</pre></div></div>
</li>
@ -1960,10 +1964,24 @@ commit &amp; rollback objects</p>
</div>
<div class="content"><div class='highlight'><pre> container({
commit: <span class="keyword">function</span>(data) { finish.call(<span class="keyword">this</span>, <span class="string">'resolve'</span>, data); },
rollback: <span class="keyword">function</span>(data) { finish.call(<span class="keyword">this</span>, <span class="string">'reject'</span>, data); },
connection: connection
<div class="content"><div class='highlight'><pre> container({
commit: <span class="keyword">function</span>(data) {
<span class="keyword">var</span> transaction = <span class="keyword">this</span>;
Knex.client.commitTransaction(connection, <span class="keyword">function</span>(err) {
<span class="keyword">if</span> (err) <span class="keyword">throw</span> <span class="keyword">new</span> Error(err);
finish.call(transaction, <span class="string">'resolve'</span>, data);
});
},
rollback: <span class="keyword">function</span>(data) {
<span class="keyword">var</span> transaction = <span class="keyword">this</span>;
Knex.client.rollbackTransaction(connection, <span class="keyword">function</span>(err) {
<span class="keyword">if</span> (err) <span class="keyword">throw</span> <span class="keyword">new</span> Error(err);
finish.call(transaction, <span class="string">'reject'</span>, data);
});
},
connection: connection
});
});
<span class="keyword">return</span> deferred.promise;
@ -2959,8 +2977,7 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</div>
<div class="content"><div class='highlight'><pre> increments: <span class="keyword">function</span>(column) {
column || (column = <span class="string">'id'</span>);
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'integer'</span>, column, {autoIncrement: <span class="literal">true</span>});
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'integer'</span>, (column || <span class="string">'id'</span>), {autoIncrement: <span class="literal">true</span>, length: <span class="number">11</span>});
},</pre></div></div>
</li>
@ -2989,12 +3006,12 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-151">&#182;</a>
</div>
<p>Create a new text column on the table.</p>
<p>Alias varchar to string</p>
</div>
<div class="content"><div class='highlight'><pre> text: <span class="keyword">function</span>(column) {
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'text'</span>, column);
<div class="content"><div class='highlight'><pre> varchar: <span class="keyword">function</span>(column, length) {
<span class="keyword">return</span> <span class="keyword">this</span>.string(column, length);
},</pre></div></div>
</li>
@ -3006,12 +3023,12 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-152">&#182;</a>
</div>
<p>Create a new integer column on the table.</p>
<p>Create a new text column on the table.</p>
</div>
<div class="content"><div class='highlight'><pre> integer: <span class="keyword">function</span>(column) {
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'integer'</span>, column);
<div class="content"><div class='highlight'><pre> text: <span class="keyword">function</span>(column, length) {
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'text'</span>, column, {length: (length || <span class="literal">false</span>)});
},</pre></div></div>
</li>
@ -3023,6 +3040,57 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-153">&#182;</a>
</div>
<p>Create a new integer column on the table.</p>
</div>
<div class="content"><div class='highlight'><pre> integer: <span class="keyword">function</span>(column, length) {
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'integer'</span>, column, {length: (length || <span class="number">11</span>)});
},</pre></div></div>
</li>
<li id="section-154">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-154">&#182;</a>
</div>
<p>Create a new tinyinteger column on the table.</p>
</div>
<div class="content"><div class='highlight'><pre> tinyInteger: <span class="keyword">function</span>(column) {
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'tinyInteger'</span>, column);
},</pre></div></div>
</li>
<li id="section-155">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-155">&#182;</a>
</div>
<p>Alias for tinyinteger column.</p>
</div>
<div class="content"><div class='highlight'><pre> tinyint: <span class="keyword">function</span>(column) {
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'tinyInteger'</span>, column);
},</pre></div></div>
</li>
<li id="section-156">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-156">&#182;</a>
</div>
<p>Create a new float column on the table.</p>
</div>
@ -3034,11 +3102,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-154">
<li id="section-157">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-154">&#182;</a>
<a class="pilcrow" href="#section-157">&#182;</a>
</div>
<p>Create a new decimal column on the table.</p>
@ -3051,28 +3119,28 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-155">
<li id="section-158">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-155">&#182;</a>
<a class="pilcrow" href="#section-158">&#182;</a>
</div>
<p>Create a new boolean column on the table.</p>
</div>
<div class="content"><div class='highlight'><pre> boolean: <span class="keyword">function</span>(column) {
<span class="keyword">return</span> <span class="keyword">this</span>.bool(columns);
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'boolean'</span>, column);
},</pre></div></div>
</li>
<li id="section-156">
<li id="section-159">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-156">&#182;</a>
<a class="pilcrow" href="#section-159">&#182;</a>
</div>
<p>Alias to &quot;boolean&quot;.</p>
@ -3085,11 +3153,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-157">
<li id="section-160">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-157">&#182;</a>
<a class="pilcrow" href="#section-160">&#182;</a>
</div>
<p>Create a new date column on the table.</p>
@ -3102,11 +3170,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-158">
<li id="section-161">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-158">&#182;</a>
<a class="pilcrow" href="#section-161">&#182;</a>
</div>
<p>Create a new date-time column on the table.</p>
@ -3119,11 +3187,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-159">
<li id="section-162">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-159">&#182;</a>
<a class="pilcrow" href="#section-162">&#182;</a>
</div>
<p>Create a new time column on the table.</p>
@ -3136,11 +3204,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-160">
<li id="section-163">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-160">&#182;</a>
<a class="pilcrow" href="#section-163">&#182;</a>
</div>
<p>Create a new timestamp column on the table.</p>
@ -3153,11 +3221,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-161">
<li id="section-164">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-161">&#182;</a>
<a class="pilcrow" href="#section-164">&#182;</a>
</div>
<p>Add creation and update timestamps to the table.</p>
@ -3171,11 +3239,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-162">
<li id="section-165">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-162">&#182;</a>
<a class="pilcrow" href="#section-165">&#182;</a>
</div>
<p>Create a new enum column on the table.</p>
@ -3188,11 +3256,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-163">
<li id="section-166">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-163">&#182;</a>
<a class="pilcrow" href="#section-166">&#182;</a>
</div>
<p>Alias to enum.</p>
@ -3205,11 +3273,28 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-164">
<li id="section-167">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-164">&#182;</a>
<a class="pilcrow" href="#section-167">&#182;</a>
</div>
<p>Create a new bit column on the table.</p>
</div>
<div class="content"><div class='highlight'><pre> bit: <span class="keyword">function</span>(column, length) {
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'bit'</span>, column, {length: (length || <span class="literal">false</span>)});
},</pre></div></div>
</li>
<li id="section-168">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-168">&#182;</a>
</div>
<p>Create a new binary column on the table.</p>
@ -3222,11 +3307,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-165">
<li id="section-169">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-165">&#182;</a>
<a class="pilcrow" href="#section-169">&#182;</a>
</div>
<hr>
@ -3235,11 +3320,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-166">
<li id="section-170">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-166">&#182;</a>
<a class="pilcrow" href="#section-170">&#182;</a>
</div>
<p>Create a new drop index command on the blueprint.</p>
@ -3257,11 +3342,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li>
<li id="section-167">
<li id="section-171">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-167">&#182;</a>
<a class="pilcrow" href="#section-171">&#182;</a>
</div>
<p>Add a new index command to the blueprint.
If no name was specified for this index, we will create one using a basic
@ -3275,7 +3360,7 @@ index type, such as primary or index, which makes the index unique.</p>
<span class="keyword">if</span> (!_.isArray(columns)) columns = columns ? [columns] : [];
<span class="keyword">if</span> (index === <span class="literal">null</span>) {
<span class="keyword">var</span> table = <span class="keyword">this</span>.table.replace(<span class="regexp">/\.|-/g</span>, <span class="string">'_'</span>);
index = (table + <span class="string">'_'</span> + _.map(columns, <span class="function"><span class="keyword">function</span> <span class="params">(col)</span> {</span> <span class="keyword">return</span> col.name; }).join(<span class="string">'_'</span>) + <span class="string">'_'</span> + type).toLowerCase();
index = (table + <span class="string">'_'</span> + _.map(columns, <span class="keyword">function</span>(col) { <span class="keyword">return</span> col.name; }).join(<span class="string">'_'</span>) + <span class="string">'_'</span> + type).toLowerCase();
}
<span class="keyword">return</span> <span class="keyword">this</span>._addCommand(type, {index: index, columns: columns});
},</pre></div></div>
@ -3283,11 +3368,11 @@ index type, such as primary or index, which makes the index unique.</p>
</li>
<li id="section-168">
<li id="section-172">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-168">&#182;</a>
<a class="pilcrow" href="#section-172">&#182;</a>
</div>
<p>Add a new column to the blueprint.</p>
@ -3304,11 +3389,11 @@ index type, such as primary or index, which makes the index unique.</p>
</li>
<li id="section-169">
<li id="section-173">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-169">&#182;</a>
<a class="pilcrow" href="#section-173">&#182;</a>
</div>
<p>Add a new command to the blueprint.</p>
@ -3324,11 +3409,11 @@ index type, such as primary or index, which makes the index unique.</p>
</li>
<li id="section-170">
<li id="section-174">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-170">&#182;</a>
<a class="pilcrow" href="#section-174">&#182;</a>
</div>
<p>Chainable object used in creating SchemaBuilder commands.</p>
@ -3343,11 +3428,11 @@ index type, such as primary or index, which makes the index unique.</p>
</li>
<li id="section-171">
<li id="section-175">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-171">&#182;</a>
<a class="pilcrow" href="#section-175">&#182;</a>
</div>
<p>Sets the default value for a column.</p>
@ -3361,11 +3446,11 @@ index type, such as primary or index, which makes the index unique.</p>
</li>
<li id="section-172">
<li id="section-176">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-172">&#182;</a>
<a class="pilcrow" href="#section-176">&#182;</a>
</div>
<p>Sets an integer as unsigned, is a no-op
if the column type is not an integer.</p>
@ -3380,11 +3465,11 @@ if the column type is not an integer.</p>
</li>
<li id="section-173">
<li id="section-177">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-173">&#182;</a>
<a class="pilcrow" href="#section-177">&#182;</a>
</div>
<p>Allows the column to contain null values.</p>
@ -3395,17 +3480,17 @@ if the column type is not an integer.</p>
<span class="keyword">return</span> <span class="keyword">this</span>;
},
index: <span class="function"><span class="keyword">function</span> <span class="params">(name)</span> {</span>
index: <span class="keyword">function</span>(name) {
<span class="keyword">this</span>.isIndex = name || <span class="literal">true</span>;
<span class="keyword">return</span> <span class="keyword">this</span>;
},
primary: <span class="function"><span class="keyword">function</span> <span class="params">(name)</span> {</span>
primary: <span class="keyword">function</span>(name) {
<span class="keyword">this</span>.isPrimary = name || <span class="literal">true</span>;
<span class="keyword">return</span> <span class="keyword">this</span>;
},
unique: <span class="function"><span class="keyword">function</span> <span class="params">(name)</span> {</span>
unique: <span class="keyword">function</span>(name) {
<span class="keyword">this</span>.isUnique = name || <span class="literal">true</span>;
<span class="keyword">return</span> <span class="keyword">this</span>;
}
@ -3414,16 +3499,22 @@ if the column type is not an integer.</p>
<span class="keyword">var</span> capitalize = <span class="keyword">function</span>(word) {
<span class="keyword">return</span> word.charAt(<span class="number">0</span>).toUpperCase() + word.slice(<span class="number">1</span>);
};
<span class="keyword">var</span> sortObject = <span class="keyword">function</span>(obj) {
<span class="keyword">return</span> _.sortBy(_.pairs(obj), <span class="keyword">function</span>(a) {
<span class="keyword">return</span> a[<span class="number">0</span>];
});
};</pre></div></div>
</li>
<li id="section-174">
<li id="section-178">
<div class="annotation">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-174">&#182;</a>
<a class="pilcrow" href="#section-178">&#182;</a>
</div>
<h2>Knex.Raw</h2>
@ -3432,11 +3523,11 @@ if the column type is not an integer.</p>
</li>
<li id="section-175">
<li id="section-179">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-175">&#182;</a>
<a class="pilcrow" href="#section-179">&#182;</a>
</div>
</div>
@ -3448,11 +3539,11 @@ if the column type is not an integer.</p>
</li>
<li id="section-176">
<li id="section-180">
<div class="annotation">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-176">&#182;</a>
<a class="pilcrow" href="#section-180">&#182;</a>
</div>
<h2>Knex.runQuery</h2>
@ -3461,11 +3552,11 @@ if the column type is not an integer.</p>
</li>
<li id="section-177">
<li id="section-181">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-177">&#182;</a>
<a class="pilcrow" href="#section-181">&#182;</a>
</div>
<p>Query runner, the context of this function is set to the caller,
(either Builder or SchemaBuilder). Checks and fails on an already
@ -3475,8 +3566,9 @@ and returns a deferred promise.</p>
</div>
<div class="content"><div class='highlight'><pre> Knex.runQuery = <span class="keyword">function</span>(builder, data) {
<span class="keyword">if</span> (builder.transaction &amp;&amp; ! builder.transaction.connection) {
<span class="keyword">return</span> Q.reject(<span class="keyword">new</span> Error(<span class="string">'The transaction has already completed.'</span>));
<span class="keyword">if</span> (builder.transaction) {
<span class="keyword">if</span> (!builder.transaction.connection) <span class="keyword">return</span> Q.reject(<span class="keyword">new</span> Error(<span class="string">'The transaction has already completed.'</span>));
builder.connection = builder.transaction.connection;
}
<span class="keyword">var</span> deferred = Q.defer();
Knex.client.query(data.sql, (data.bindings || []), <span class="keyword">function</span>(err, resp) {
@ -3490,11 +3582,11 @@ and returns a deferred promise.</p>
</li>
<li id="section-178">
<li id="section-182">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-178">&#182;</a>
<a class="pilcrow" href="#section-182">&#182;</a>
</div>
<p>Export the Knex module</p>

View File

@ -12,7 +12,7 @@
font-size: 14px;
line-height: 22px;
font-family: Helvetica Neue, Helvetica, Arial;
background: #FEFFFC url(docs/images/background.png);
background: #f7f7f7 url(docs/images/background.png);
}
.interface {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
@ -336,6 +336,7 @@
<ul class="toc_section">
<li> <a href="#Schema-connection">connection</a></li>
<li> <a href="#Schema-createTable">createTable</a></li>
<li> <a href="#Schema-renameTable">createTable</a></li>
<li> <a href="#Schema-dropTable">dropTable</a></li>
<li> <a href="#Schema-dropTableIfExists">dropTableIfExists</a></li>
<li> <a href="#Schema-table">table</a></li>
@ -719,6 +720,36 @@ Knex('users')
</p>
<pre>
Knex.Transaction(function(t) {
Knex('books')
.transacting(t)
.insert({name: 'Old Books'})
.then(function(row) {
return Q.all(_.map([
{title: 'Canterbury Tales'},
{title: 'Moby Dick'},
{title: 'Hamlet'}
], function(info) {
info.row_id = row.id;
// Some validation could take place here.
return Knex('book').transacting(t).insert(info);
}));
})
.then(t.commit, t.rollback);
}).then(function() {
console.log('3 new books saved.');
}, function() {
console.log('Error saving the books.');
});
Knex.Transaction(function (t) {
Knex('pieces')

View File

@ -1 +0,0 @@
module.exports = require('./knex');

163
knex.js
View File

@ -138,12 +138,12 @@
// Compiles a where in clause.
whereIn: function(qb, where) {
return this.wrap(where.column) + ' in (' + this.parameterize(where.values) + ')';
return this.wrap(where.column) + ' in (' + this.parameterize(where.value) + ')';
},
// Compiles a where not in clause.
whereNotIn: function(qb, where) {
return this.wrap(where.column) + ' not in (' + this.parameterize(where.values) + ')';
return this.wrap(where.column) + ' not in (' + this.parameterize(where.value) + ')';
},
// Compiles a sub-where in clause.
@ -208,10 +208,14 @@
// inserts using a single query statement.
compileInsert: function(qb, values) {
var table = this.wrapTable(qb.table);
var columns = this.columnize(_.keys(values[0]));
var parameters = this.parameterize(values[0]);
var columns = this.columnize(_.keys(values[0]).sort());
var parameters = this.parameterize(_.values(values[0]));
var paramBlocks = [];
// If there are any "where" clauses, we need to omit
// any bindings that may have been associated with them.
if (qb.wheres.length > 0) this._clearWhereBindings(qb);
for (var i = 0, l = values.length; i < l; ++i) {
paramBlocks.push("(" + parameters + ")");
}
@ -219,9 +223,23 @@
return "insert into " + table + " (" + columns + ") values " + paramBlocks.join(', ');
},
// Compiles an `insert`, getting the id of the insert row.
compileInsertGetId: function(qb, values) {
return this.compileInsert(qb, values);
// Depending on the type of `where` clause, this will appropriately
// remove any binding caused by "where" constraints, allowing the same
// query to be used for `insert` and `update` without issue.
_clearWhereBindings: function(qb) {
var wheres = qb.wheres;
var bindingCount = 0;
for (var i = 0, l = wheres.length; i<l; i++) {
var where = wheres[i];
if (_.isArray(where.value)) {
bindingCount += where.value.length;
} else if (where.query) {
bindingCount += where.query.bindings.length;
} else {
bindingCount += 1;
}
}
qb.bindings = qb.bindings.slice(bindingCount);
},
// Compiles an `update` query.
@ -349,7 +367,7 @@
this.isDistinct = false;
},
toJSON: function () {
toJSON: function() {
return {
joins: this.joins,
wheres: this.wheres,
@ -470,7 +488,7 @@
this.wheres.push({
type: (condition || 'In'),
column: column,
values: values,
value: values,
bool: bool
});
push.apply(this.bindings, values);
@ -610,17 +628,17 @@
return this;
},
// Performs an `INSERT` query, returning a promise.
// 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 record = values[i];
this.bindings = this.bindings.concat(_.values(record));
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 Knex.runQuery(this, {
sql: this.grammar.compileInsert(this, values),
bindings: this._cleanBindings(), type: 'insert'
});
var str = this.grammar.compileInsert(this, values);
return Knex.runQuery(this, {sql: str, bindings: this._cleanBindings(), type: 'insert'});
},
// Performs an `update` query, returning a promise.
@ -673,7 +691,7 @@
query.table = this.table;
callback.call(query, query);
this.wheres.push({type: 'Nested', query: query, bool: bool});
this.bindings = this.bindings.concat(query.bindings);
push.apply(this.bindings, query.bindings);
return this;
},
@ -746,19 +764,35 @@
// transaction completes or fails, we know what to do.
var deferred = Q.defer();
// Finish the transaction connection
var finish = function(type, data) {
this.connection.end();
this.transaction.connection = null;
deferred[type](data);
};
Knex.client.beginTransaction(function(err, connection) {
// Finish the transaction connection
var finish = function(type, data) {
connection.end();
this.connection = null;
deferred[type](data);
};
// Call the container with the transaction
// commit & rollback objects
container({
commit: function(data) {
var transaction = this;
Knex.client.commitTransaction(connection, function(err) {
if (err) throw new Error(err);
finish.call(transaction, 'resolve', data);
});
},
rollback: function(data) {
var transaction = this;
Knex.client.rollbackTransaction(connection, function(err) {
if (err) throw new Error(err);
finish.call(transaction, 'reject', data);
});
},
connection: connection
});
// Call the container with the transaction
// commit & rollback objects
container({
commit: function(data) { finish.call(this, 'resolve', data); },
rollback: function(data) { finish.call(this, 'reject', data); },
connection: connection
});
return deferred.promise;
@ -1123,8 +1157,7 @@
// Create a new auto-incrementing column on the table.
increments: function(column) {
column || (column = 'id');
return this._addColumn('integer', column, {autoIncrement: true});
return this._addColumn('integer', (column || 'id'), {autoIncrement: true, length: 11});
},
// Create a new string column on the table.
@ -1132,29 +1165,50 @@
return this._addColumn('string', column, {length: (length || 255)});
},
// Alias varchar to string
varchar: function(column, length) {
return this.string(column, length);
},
// Create a new text column on the table.
text: function(column) {
return this._addColumn('text', column);
text: function(column, length) {
return this._addColumn('text', column, {length: (length || false)});
},
// Create a new integer column on the table.
integer: function(column) {
return this._addColumn('integer', column);
integer: function(column, length) {
return this._addColumn('integer', column, {length: (length || 11)});
},
// Create a new tinyinteger column on the table.
tinyInteger: function(column) {
return this._addColumn('tinyInteger', column);
},
// Alias for tinyinteger column.
tinyint: function(column) {
return this._addColumn('tinyInteger', column);
},
// Create a new float column on the table.
float: function(column, total, places) {
return this._addColumn('float', column, {total: (total || 8), places: (places || 2)});
float: function(column, precision, scale) {
return this._addColumn('float', column, {
precision: (precision == null ? 8 : precision),
scale: (scale == null ? 2 : scale)
});
},
// Create a new decimal column on the table.
decimal: function(column, precision, scale) {
return this._addColumn('decimal', column, {precision: (precision || 8), scale: (scale || 2)});
return this._addColumn('decimal', column, {
precision: (precision == null ? 8 : precision),
scale: (scale == null ? 2 : scale)
});
},
// Create a new boolean column on the table.
boolean: function(column) {
return this.bool(columns);
return this._addColumn('boolean', column);
},
// Alias to "boolean".
@ -1198,6 +1252,11 @@
return this._addColumn('enum', column, {allowed: allowed});
},
// Create a new bit column on the table.
bit: function(column, length) {
return this._addColumn('bit', column, {length: (length || false)});
},
// Create a new binary column on the table.
binary: function(column) {
return this._addColumn('binary', column);
@ -1206,6 +1265,8 @@
// ----------------------------------------------------------------------
// Create a new drop index command on the blueprint.
// If the index is an array of columns, the developer means
// to drop an index merely by specifying the columns involved.
_dropIndexCommand: function(type, index) {
var columns = [];
if (_.isArray(index)) {
@ -1224,7 +1285,7 @@
if (!_.isArray(columns)) columns = columns ? [columns] : [];
if (index === null) {
var table = this.table.replace(/\.|-/g, '_');
index = (table + '_' + _.map(columns, function (col) { return col.name; }).join('_') + '_' + type).toLowerCase();
index = (table + '_' + _.map(columns, function(col) { return col.name; }).join('_') + '_' + type).toLowerCase();
}
return this._addCommand(type, {index: index, columns: columns});
},
@ -1272,17 +1333,17 @@
return this;
},
index: function (name) {
index: function(name) {
this.isIndex = name || true;
return this;
},
primary: function (name) {
primary: function(name) {
this.isPrimary = name || true;
return this;
},
unique: function (name) {
unique: function(name) {
this.isUnique = name || true;
return this;
}
@ -1293,6 +1354,12 @@
return word.charAt(0).toUpperCase() + word.slice(1);
};
var sortObject = function(obj) {
return _.sortBy(_.pairs(obj), function(a) {
return a[0];
});
};
// Knex.Raw
// -------
Knex.Raw = function(value) {
@ -1307,9 +1374,9 @@
// resolved transaction, otherwise calls the query on the specified client
// and returns a deferred promise.
Knex.runQuery = function(builder, data) {
if (builder.transaction && ! builder.transaction.connection) {
return Q.reject(new Error('The transaction has already completed.'));
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,

View File

@ -2,7 +2,7 @@
"name": "knex",
"version": "0.0.0",
"description": "a fun sql query builder",
"main": "index.js",
"main": "knex.js",
"directories": {
"test": "test"
},
@ -11,7 +11,7 @@
"mysql": "~2.0.0-alpha5"
},
"dependencies": {
"q": "0.8.x",
"q": "0.9.x",
"underscore": "1.4.x",
"generic-pool": "2.0.x"
},

View File

@ -125,4 +125,26 @@ describe('Knex.Builder', function() {
});
});
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();
});
});
});
});