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, { MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
// The possible column modifiers. // The possible column modifiers.
modifiers: ['Unsigned', 'Nullable', 'Default', 'Increment'], modifiers: ['Unsigned', 'Nullable', 'Default', 'Increment', 'After'],
// Compile the query to determine if a table exists. // Compile the query to determine if a table exists.
compileTableExists: function() { compileTableExists: function() {
@ -188,7 +188,7 @@ MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
// Compile a rename table command. // Compile a rename table command.
compileRename: function(blueprint, 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. // 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. // Create the column definition for a text type.
typeText: function(column) { 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. // Create the column definition for a integer type.
typeInteger: function(column) { 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. // 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. // Create the column definition for a boolean type.
typeBoolean: function(column) { typeBoolean: function(column) {
return 'tinyint'; return 'tinyint(1)';
}, },
// Create the column definition for a enum type. // Create the column definition for a enum type.
@ -246,6 +260,11 @@ MysqlClient.schemaGrammar = _.extend({}, MysqlClient.grammar, {
return 'timestamp default 0'; 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. // Create the column definition for a binary type.
typeBinary: function(column) { typeBinary: function(column) {
return 'blob'; return 'blob';

View File

@ -43,16 +43,34 @@ exports.initialize = function (options) {
}, options.pool)); }, 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. // Execute a query on the database.
// If the fourth parameter is set, this will be used as the connection // If the fourth parameter is set, this will be used as the connection
// to the database. // to the database.
exports.query = function (querystring, params, callback, connection) { exports.query = function (querystring, params, callback, connection) {
if (debug) console.log([querystring, params]);
// If there is a connection, use it. // If there is a connection, use it.
if (connection) { if (connection) {
return connection.query(querystring, params, callback); return connection.query(querystring, params, callback);
} }
// Bind all of the ? to numbered vars.
var questionCount = 0; var questionCount = 0;
querystring = querystring.replace(/\?/g, function () { querystring = querystring.replace(/\?/g, function () {
questionCount++; questionCount++;
@ -192,8 +210,7 @@ exports.schemaGrammar = _.extend({}, grammar, {
// Compile a rename table command. // Compile a rename table command.
compileRename: function(blueprint, command) { compileRename: function(blueprint, command) {
var from = this.wrapTable(blueprint); return 'alter table ' + this.wrapTable(blueprint) + ' rename to ' + this.wrapTable(command.to);
return "alter table " + from + " rename to " + this.wrapTable(command.to);
}, },
// Create the column definition for a string type. // Create the column definition for a string type.
@ -256,6 +273,11 @@ exports.schemaGrammar = _.extend({}, grammar, {
return 'timestamp'; 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. // Create the column definition for a binary type.
typeBinary: function(column) { typeBinary: function(column) {
return 'bytea'; return 'bytea';

View File

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

View File

@ -482,7 +482,7 @@ including any nested join queries.</p>
</div> </div>
<div class="content"><div class='highlight'><pre> whereIn: <span class="keyword">function</span>(qb, where) { <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> },</pre></div></div>
</li> </li>
@ -499,7 +499,7 @@ including any nested join queries.</p>
</div> </div>
<div class="content"><div class='highlight'><pre> whereNotIn: <span class="keyword">function</span>(qb, where) { <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> },</pre></div></div>
</li> </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) { <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> 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> 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[<span class="number">0</span>]); <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>
<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>
</li> </li>
@ -692,12 +685,18 @@ inserts using a single query statement.</p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-35">&#182;</a> <a class="pilcrow" href="#section-35">&#182;</a>
</div> </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>
<div class="content"><div class='highlight'><pre> compileInsertGetId: <span class="keyword">function</span>(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">return</span> <span class="keyword">this</span>.compileInsert(qb, values);
<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> },</pre></div></div>
</li> </li>
@ -709,6 +708,37 @@ inserts using a single query statement.</p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-36">&#182;</a> <a class="pilcrow" href="#section-36">&#182;</a>
</div> </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> <p>Compiles an <code>update</code> query.</p>
</div> </div>
@ -725,11 +755,11 @@ inserts using a single query statement.</p>
</li> </li>
<li id="section-37"> <li id="section-38">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-37">&#182;</a> <a class="pilcrow" href="#section-38">&#182;</a>
</div> </div>
<p>Compiles a <code>delete</code> query.</p> <p>Compiles a <code>delete</code> query.</p>
@ -744,11 +774,11 @@ inserts using a single query statement.</p>
</li> </li>
<li id="section-38"> <li id="section-39">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-38">&#182;</a> <a class="pilcrow" href="#section-39">&#182;</a>
</div> </div>
<p>Compiles a <code>truncate</code> query.</p> <p>Compiles a <code>truncate</code> query.</p>
@ -804,11 +834,11 @@ inserts using a single query statement.</p>
</li> </li>
<li id="section-39"> <li id="section-40">
<div class="annotation"> <div class="annotation">
<div class="pilwrap for-h2"> <div class="pilwrap for-h2">
<a class="pilcrow" href="#section-39">&#182;</a> <a class="pilcrow" href="#section-40">&#182;</a>
</div> </div>
<h2>Knex.Builder</h2> <h2>Knex.Builder</h2>
@ -817,11 +847,11 @@ inserts using a single query statement.</p>
</li> </li>
<li id="section-40"> <li id="section-41">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-40">&#182;</a> <a class="pilcrow" href="#section-41">&#182;</a>
</div> </div>
</div> </div>
@ -835,11 +865,11 @@ inserts using a single query statement.</p>
</li> </li>
<li id="section-41"> <li id="section-42">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-41">&#182;</a> <a class="pilcrow" href="#section-42">&#182;</a>
</div> </div>
<p>All operators used in the <code>where</code> clause generation.</p> <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>]; <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 = { Builder.prototype = {</pre></div></div>
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>
</li> </li>
@ -879,12 +888,13 @@ inserts using a single query statement.</p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-43">&#182;</a> <a class="pilcrow" href="#section-43">&#182;</a>
</div> </div>
<p>Set the <code>idAttribute</code> for the query.</p> <p>Sets the <code>tableName</code> on the query.</p>
</div> </div>
<div class="content"><div class='highlight'><pre> idAttribute: <span class="keyword">function</span>(id) { <div class="content"><div class='highlight'><pre> from: <span class="keyword">function</span>(tableName) {
<span class="keyword">this</span>.idAttr = id; <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>; <span class="keyword">return</span> <span class="keyword">this</span>;
},</pre></div></div> },</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>() { <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> item = <span class="keyword">new</span> Builder(<span class="keyword">this</span>.table);
<span class="keyword">var</span> items = [ <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">'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> <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>.orders = [];
<span class="keyword">this</span>.columns = []; <span class="keyword">this</span>.columns = [];
<span class="keyword">this</span>.bindings = []; <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>; <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> { <span class="keyword">return</span> {
joins: <span class="keyword">this</span>.joins, joins: <span class="keyword">this</span>.joins,
wheres: <span class="keyword">this</span>.wheres, wheres: <span class="keyword">this</span>.wheres,
order: <span class="keyword">this</span>.orders, order: <span class="keyword">this</span>.orders,
columns: <span class="keyword">this</span>.columns, columns: <span class="keyword">this</span>.columns,
bindings: <span class="keyword">this</span>.bindings, bindings: <span class="keyword">this</span>.bindings,
idAttr: <span class="keyword">this</span>.idAttr,
isDistinct: <span class="keyword">this</span>.isDistinct isDistinct: <span class="keyword">this</span>.isDistinct
}; };
},</pre></div></div> },</pre></div></div>
@ -1187,7 +1195,7 @@ where key = value. </p>
<span class="keyword">this</span>.wheres.push({ <span class="keyword">this</span>.wheres.push({
type: (condition || <span class="string">'In'</span>), type: (condition || <span class="string">'In'</span>),
column: column, column: column,
values: values, value: values,
bool: bool bool: bool
}); });
push.apply(<span class="keyword">this</span>.bindings, values); push.apply(<span class="keyword">this</span>.bindings, values);
@ -1621,23 +1629,19 @@ where key = value. </p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-80">&#182;</a> <a class="pilcrow" href="#section-80">&#182;</a>
</div> </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>
<div class="content"><div class='highlight'><pre> insert: <span class="keyword">function</span>(values, returning) { <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">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">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">var</span> obj = sortObject(values[i]);
<span class="keyword">this</span>.bindings = <span class="keyword">this</span>.bindings.concat(_.values(record)); <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">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">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>}); <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> },</pre></div></div>
@ -1786,7 +1790,7 @@ the currently running transaction</p>
query.table = <span class="keyword">this</span>.table; query.table = <span class="keyword">this</span>.table;
callback.call(query, query); 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>.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>; <span class="keyword">return</span> <span class="keyword">this</span>;
}, },
@ -1907,9 +1911,7 @@ the currently running transaction</p>
</div> </div>
<div class="content"><div class='highlight'><pre> Knex.Transaction = <span class="keyword">function</span>(container) { <div class="content"><div class='highlight'><pre> Knex.Transaction = <span class="keyword">function</span>(container) {</pre></div></div>
<span class="keyword">var</span> connection = Knex.client.getConnection();</pre></div></div>
</li> </li>
@ -1925,7 +1927,9 @@ transaction completes or fails, we know what to do.</p>
</div> </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> </li>
@ -1940,11 +1944,11 @@ transaction completes or fails, we know what to do.</p>
</div> </div>
<div class="content"><div class='highlight'><pre> <span class="keyword">var</span> finish = <span class="keyword">function</span>(type, data) { <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(); connection.end();
<span class="keyword">this</span>.transaction.connection = <span class="literal">null</span>; <span class="keyword">this</span>.connection = <span class="literal">null</span>;
deferred[type](data); deferred[type](data);
};</pre></div></div> };</pre></div></div>
</li> </li>
@ -1960,10 +1964,24 @@ commit &amp; rollback objects</p>
</div> </div>
<div class="content"><div class='highlight'><pre> container({ <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); }, commit: <span class="keyword">function</span>(data) {
rollback: <span class="keyword">function</span>(data) { finish.call(<span class="keyword">this</span>, <span class="string">'reject'</span>, data); }, <span class="keyword">var</span> transaction = <span class="keyword">this</span>;
connection: connection 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; <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>
<div class="content"><div class='highlight'><pre> increments: <span class="keyword">function</span>(column) { <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 || <span class="string">'id'</span>), {autoIncrement: <span class="literal">true</span>, length: <span class="number">11</span>});
<span class="keyword">return</span> <span class="keyword">this</span>._addColumn(<span class="string">'integer'</span>, column, {autoIncrement: <span class="literal">true</span>});
},</pre></div></div> },</pre></div></div>
</li> </li>
@ -2989,12 +3006,12 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-151">&#182;</a> <a class="pilcrow" href="#section-151">&#182;</a>
</div> </div>
<p>Create a new text column on the table.</p> <p>Alias varchar to string</p>
</div> </div>
<div class="content"><div class='highlight'><pre> text: <span class="keyword">function</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>._addColumn(<span class="string">'text'</span>, column); <span class="keyword">return</span> <span class="keyword">this</span>.string(column, length);
},</pre></div></div> },</pre></div></div>
</li> </li>
@ -3006,12 +3023,12 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-152">&#182;</a> <a class="pilcrow" href="#section-152">&#182;</a>
</div> </div>
<p>Create a new integer column on the table.</p> <p>Create a new text column on the table.</p>
</div> </div>
<div class="content"><div class='highlight'><pre> integer: <span class="keyword">function</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">'integer'</span>, column); <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> },</pre></div></div>
</li> </li>
@ -3023,6 +3040,57 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-153">&#182;</a> <a class="pilcrow" href="#section-153">&#182;</a>
</div> </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> <p>Create a new float column on the table.</p>
</div> </div>
@ -3034,11 +3102,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li> </li>
<li id="section-154"> <li id="section-157">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-154">&#182;</a> <a class="pilcrow" href="#section-157">&#182;</a>
</div> </div>
<p>Create a new decimal column on the table.</p> <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>
<li id="section-155"> <li id="section-158">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-155">&#182;</a> <a class="pilcrow" href="#section-158">&#182;</a>
</div> </div>
<p>Create a new boolean column on the table.</p> <p>Create a new boolean column on the table.</p>
</div> </div>
<div class="content"><div class='highlight'><pre> boolean: <span class="keyword">function</span>(column) { <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> },</pre></div></div>
</li> </li>
<li id="section-156"> <li id="section-159">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-156">&#182;</a> <a class="pilcrow" href="#section-159">&#182;</a>
</div> </div>
<p>Alias to &quot;boolean&quot;.</p> <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>
<li id="section-157"> <li id="section-160">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-157">&#182;</a> <a class="pilcrow" href="#section-160">&#182;</a>
</div> </div>
<p>Create a new date column on the table.</p> <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>
<li id="section-158"> <li id="section-161">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-158">&#182;</a> <a class="pilcrow" href="#section-161">&#182;</a>
</div> </div>
<p>Create a new date-time column on the table.</p> <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>
<li id="section-159"> <li id="section-162">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-159">&#182;</a> <a class="pilcrow" href="#section-162">&#182;</a>
</div> </div>
<p>Create a new time column on the table.</p> <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>
<li id="section-160"> <li id="section-163">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-160">&#182;</a> <a class="pilcrow" href="#section-163">&#182;</a>
</div> </div>
<p>Create a new timestamp column on the table.</p> <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>
<li id="section-161"> <li id="section-164">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-161">&#182;</a> <a class="pilcrow" href="#section-164">&#182;</a>
</div> </div>
<p>Add creation and update timestamps to the table.</p> <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>
<li id="section-162"> <li id="section-165">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-162">&#182;</a> <a class="pilcrow" href="#section-165">&#182;</a>
</div> </div>
<p>Create a new enum column on the table.</p> <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>
<li id="section-163"> <li id="section-166">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-163">&#182;</a> <a class="pilcrow" href="#section-166">&#182;</a>
</div> </div>
<p>Alias to enum.</p> <p>Alias to enum.</p>
@ -3205,11 +3273,28 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li> </li>
<li id="section-164"> <li id="section-167">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <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> </div>
<p>Create a new binary column on the table.</p> <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>
<li id="section-165"> <li id="section-169">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-165">&#182;</a> <a class="pilcrow" href="#section-169">&#182;</a>
</div> </div>
<hr> <hr>
@ -3235,11 +3320,11 @@ the blueprint element, so we&#39;ll just call that compilers function.</p>
</li> </li>
<li id="section-166"> <li id="section-170">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-166">&#182;</a> <a class="pilcrow" href="#section-170">&#182;</a>
</div> </div>
<p>Create a new drop index command on the blueprint.</p> <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>
<li id="section-167"> <li id="section-171">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-167">&#182;</a> <a class="pilcrow" href="#section-171">&#182;</a>
</div> </div>
<p>Add a new index command to the blueprint. <p>Add a new index command to the blueprint.
If no name was specified for this index, we will create one using a basic 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> (!_.isArray(columns)) columns = columns ? [columns] : [];
<span class="keyword">if</span> (index === <span class="literal">null</span>) { <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>); <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}); <span class="keyword">return</span> <span class="keyword">this</span>._addCommand(type, {index: index, columns: columns});
},</pre></div></div> },</pre></div></div>
@ -3283,11 +3368,11 @@ index type, such as primary or index, which makes the index unique.</p>
</li> </li>
<li id="section-168"> <li id="section-172">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-168">&#182;</a> <a class="pilcrow" href="#section-172">&#182;</a>
</div> </div>
<p>Add a new column to the blueprint.</p> <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>
<li id="section-169"> <li id="section-173">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-169">&#182;</a> <a class="pilcrow" href="#section-173">&#182;</a>
</div> </div>
<p>Add a new command to the blueprint.</p> <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>
<li id="section-170"> <li id="section-174">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-170">&#182;</a> <a class="pilcrow" href="#section-174">&#182;</a>
</div> </div>
<p>Chainable object used in creating SchemaBuilder commands.</p> <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>
<li id="section-171"> <li id="section-175">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-171">&#182;</a> <a class="pilcrow" href="#section-175">&#182;</a>
</div> </div>
<p>Sets the default value for a column.</p> <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>
<li id="section-172"> <li id="section-176">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-172">&#182;</a> <a class="pilcrow" href="#section-176">&#182;</a>
</div> </div>
<p>Sets an integer as unsigned, is a no-op <p>Sets an integer as unsigned, is a no-op
if the column type is not an integer.</p> if the column type is not an integer.</p>
@ -3380,11 +3465,11 @@ if the column type is not an integer.</p>
</li> </li>
<li id="section-173"> <li id="section-177">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-173">&#182;</a> <a class="pilcrow" href="#section-177">&#182;</a>
</div> </div>
<p>Allows the column to contain null values.</p> <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>; <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">this</span>.isIndex = name || <span class="literal">true</span>;
<span class="keyword">return</span> <span class="keyword">this</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">this</span>.isPrimary = name || <span class="literal">true</span>;
<span class="keyword">return</span> <span class="keyword">this</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">this</span>.isUnique = name || <span class="literal">true</span>;
<span class="keyword">return</span> <span class="keyword">this</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">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">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> };</pre></div></div>
</li> </li>
<li id="section-174"> <li id="section-178">
<div class="annotation"> <div class="annotation">
<div class="pilwrap for-h2"> <div class="pilwrap for-h2">
<a class="pilcrow" href="#section-174">&#182;</a> <a class="pilcrow" href="#section-178">&#182;</a>
</div> </div>
<h2>Knex.Raw</h2> <h2>Knex.Raw</h2>
@ -3432,11 +3523,11 @@ if the column type is not an integer.</p>
</li> </li>
<li id="section-175"> <li id="section-179">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-175">&#182;</a> <a class="pilcrow" href="#section-179">&#182;</a>
</div> </div>
</div> </div>
@ -3448,11 +3539,11 @@ if the column type is not an integer.</p>
</li> </li>
<li id="section-176"> <li id="section-180">
<div class="annotation"> <div class="annotation">
<div class="pilwrap for-h2"> <div class="pilwrap for-h2">
<a class="pilcrow" href="#section-176">&#182;</a> <a class="pilcrow" href="#section-180">&#182;</a>
</div> </div>
<h2>Knex.runQuery</h2> <h2>Knex.runQuery</h2>
@ -3461,11 +3552,11 @@ if the column type is not an integer.</p>
</li> </li>
<li id="section-177"> <li id="section-181">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-177">&#182;</a> <a class="pilcrow" href="#section-181">&#182;</a>
</div> </div>
<p>Query runner, the context of this function is set to the caller, <p>Query runner, the context of this function is set to the caller,
(either Builder or SchemaBuilder). Checks and fails on an already (either Builder or SchemaBuilder). Checks and fails on an already
@ -3475,8 +3566,9 @@ and returns a deferred promise.</p>
</div> </div>
<div class="content"><div class='highlight'><pre> Knex.runQuery = <span class="keyword">function</span>(builder, data) { <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">if</span> (builder.transaction) {
<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.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(); <span class="keyword">var</span> deferred = Q.defer();
Knex.client.query(data.sql, (data.bindings || []), <span class="keyword">function</span>(err, resp) { 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>
<li id="section-178"> <li id="section-182">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-178">&#182;</a> <a class="pilcrow" href="#section-182">&#182;</a>
</div> </div>
<p>Export the Knex module</p> <p>Export the Knex module</p>

View File

@ -12,7 +12,7 @@
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
font-family: Helvetica Neue, Helvetica, Arial; font-family: Helvetica Neue, Helvetica, Arial;
background: #FEFFFC url(docs/images/background.png); background: #f7f7f7 url(docs/images/background.png);
} }
.interface { .interface {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
@ -336,6 +336,7 @@
<ul class="toc_section"> <ul class="toc_section">
<li> <a href="#Schema-connection">connection</a></li> <li> <a href="#Schema-connection">connection</a></li>
<li> <a href="#Schema-createTable">createTable</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-dropTable">dropTable</a></li>
<li> <a href="#Schema-dropTableIfExists">dropTableIfExists</a></li> <li> <a href="#Schema-dropTableIfExists">dropTableIfExists</a></li>
<li> <a href="#Schema-table">table</a></li> <li> <a href="#Schema-table">table</a></li>
@ -719,6 +720,36 @@ Knex('users')
</p> </p>
<pre> <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.Transaction(function (t) {
Knex('pieces') 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. // Compiles a where in clause.
whereIn: function(qb, where) { 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. // Compiles a where not in clause.
whereNotIn: function(qb, where) { 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. // Compiles a sub-where in clause.
@ -208,10 +208,14 @@
// inserts using a single query statement. // inserts using a single query statement.
compileInsert: function(qb, values) { compileInsert: function(qb, values) {
var table = this.wrapTable(qb.table); var table = this.wrapTable(qb.table);
var columns = this.columnize(_.keys(values[0])); var columns = this.columnize(_.keys(values[0]).sort());
var parameters = this.parameterize(values[0]); var parameters = this.parameterize(_.values(values[0]));
var paramBlocks = []; 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) { for (var i = 0, l = values.length; i < l; ++i) {
paramBlocks.push("(" + parameters + ")"); paramBlocks.push("(" + parameters + ")");
} }
@ -219,9 +223,23 @@
return "insert into " + table + " (" + columns + ") values " + paramBlocks.join(', '); return "insert into " + table + " (" + columns + ") values " + paramBlocks.join(', ');
}, },
// Compiles an `insert`, getting the id of the insert row. // Depending on the type of `where` clause, this will appropriately
compileInsertGetId: function(qb, values) { // remove any binding caused by "where" constraints, allowing the same
return this.compileInsert(qb, values); // 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. // Compiles an `update` query.
@ -349,7 +367,7 @@
this.isDistinct = false; this.isDistinct = false;
}, },
toJSON: function () { toJSON: function() {
return { return {
joins: this.joins, joins: this.joins,
wheres: this.wheres, wheres: this.wheres,
@ -470,7 +488,7 @@
this.wheres.push({ this.wheres.push({
type: (condition || 'In'), type: (condition || 'In'),
column: column, column: column,
values: values, value: values,
bool: bool bool: bool
}); });
push.apply(this.bindings, values); push.apply(this.bindings, values);
@ -610,17 +628,17 @@
return this; return this;
}, },
// Performs an `INSERT` query, returning a promise. // Performs an `insert` query, returning a promise.
insert: function(values, returning) { insert: function(values, returning) {
if (!_.isArray(values)) values = values ? [values] : []; if (!_.isArray(values)) values = values ? [values] : [];
for (var i = 0, l = values.length; i < l; i++) { for (var i = 0, l = values.length; i<l; i++) {
var record = values[i]; var obj = sortObject(values[i]);
this.bindings = this.bindings.concat(_.values(record)); for (var i2 = 0, l2 = obj.length; i2 < l2; i2++) {
this.bindings.push(obj[i2][1]);
}
} }
return Knex.runQuery(this, { var str = this.grammar.compileInsert(this, values);
sql: this.grammar.compileInsert(this, values), return Knex.runQuery(this, {sql: str, bindings: this._cleanBindings(), type: 'insert'});
bindings: this._cleanBindings(), type: 'insert'
});
}, },
// Performs an `update` query, returning a promise. // Performs an `update` query, returning a promise.
@ -673,7 +691,7 @@
query.table = this.table; query.table = this.table;
callback.call(query, query); callback.call(query, query);
this.wheres.push({type: 'Nested', query: query, bool: bool}); this.wheres.push({type: 'Nested', query: query, bool: bool});
this.bindings = this.bindings.concat(query.bindings); push.apply(this.bindings, query.bindings);
return this; return this;
}, },
@ -746,19 +764,35 @@
// transaction completes or fails, we know what to do. // transaction completes or fails, we know what to do.
var deferred = Q.defer(); var deferred = Q.defer();
// Finish the transaction connection Knex.client.beginTransaction(function(err, connection) {
var finish = function(type, data) {
this.connection.end(); // Finish the transaction connection
this.transaction.connection = null; var finish = function(type, data) {
deferred[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; return deferred.promise;
@ -1123,8 +1157,7 @@
// Create a new auto-incrementing column on the table. // Create a new auto-incrementing column on the table.
increments: function(column) { increments: function(column) {
column || (column = 'id'); return this._addColumn('integer', (column || 'id'), {autoIncrement: true, length: 11});
return this._addColumn('integer', column, {autoIncrement: true});
}, },
// Create a new string column on the table. // Create a new string column on the table.
@ -1132,29 +1165,50 @@
return this._addColumn('string', column, {length: (length || 255)}); 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. // Create a new text column on the table.
text: function(column) { text: function(column, length) {
return this._addColumn('text', column); return this._addColumn('text', column, {length: (length || false)});
}, },
// Create a new integer column on the table. // Create a new integer column on the table.
integer: function(column) { integer: function(column, length) {
return this._addColumn('integer', column); 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. // Create a new float column on the table.
float: function(column, total, places) { float: function(column, precision, scale) {
return this._addColumn('float', column, {total: (total || 8), places: (places || 2)}); return this._addColumn('float', column, {
precision: (precision == null ? 8 : precision),
scale: (scale == null ? 2 : scale)
});
}, },
// Create a new decimal column on the table. // Create a new decimal column on the table.
decimal: function(column, precision, scale) { 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. // Create a new boolean column on the table.
boolean: function(column) { boolean: function(column) {
return this.bool(columns); return this._addColumn('boolean', column);
}, },
// Alias to "boolean". // Alias to "boolean".
@ -1198,6 +1252,11 @@
return this._addColumn('enum', column, {allowed: allowed}); 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. // Create a new binary column on the table.
binary: function(column) { binary: function(column) {
return this._addColumn('binary', column); return this._addColumn('binary', column);
@ -1206,6 +1265,8 @@
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Create a new drop index command on the blueprint. // 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) { _dropIndexCommand: function(type, index) {
var columns = []; var columns = [];
if (_.isArray(index)) { if (_.isArray(index)) {
@ -1224,7 +1285,7 @@
if (!_.isArray(columns)) columns = columns ? [columns] : []; if (!_.isArray(columns)) columns = columns ? [columns] : [];
if (index === null) { if (index === null) {
var table = this.table.replace(/\.|-/g, '_'); 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}); return this._addCommand(type, {index: index, columns: columns});
}, },
@ -1272,17 +1333,17 @@
return this; return this;
}, },
index: function (name) { index: function(name) {
this.isIndex = name || true; this.isIndex = name || true;
return this; return this;
}, },
primary: function (name) { primary: function(name) {
this.isPrimary = name || true; this.isPrimary = name || true;
return this; return this;
}, },
unique: function (name) { unique: function(name) {
this.isUnique = name || true; this.isUnique = name || true;
return this; return this;
} }
@ -1293,6 +1354,12 @@
return word.charAt(0).toUpperCase() + word.slice(1); 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
// ------- // -------
Knex.Raw = function(value) { Knex.Raw = function(value) {
@ -1307,9 +1374,9 @@
// resolved transaction, otherwise calls the query on the specified client // resolved transaction, otherwise calls the query on the specified client
// and returns a deferred promise. // and returns a deferred promise.
Knex.runQuery = function(builder, data) { Knex.runQuery = function(builder, data) {
if (builder.transaction) {
if (builder.transaction && ! builder.transaction.connection) { if (!builder.transaction.connection) return Q.reject(new Error('The transaction has already completed.'));
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, // Query on the query builder, which should resolve with a promise,

View File

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