diff --git a/clients/mysql.js b/clients/mysql.js index 6dd45ebf..f2bbddaf 100644 --- a/clients/mysql.js +++ b/clients/mysql.js @@ -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'; } } -}); \ No newline at end of file +}); diff --git a/clients/postgres.js b/clients/postgres.js index 73a58b64..6f651c66 100644 --- a/clients/postgres.js +++ b/clients/postgres.js @@ -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'; diff --git a/clients/sqlite3.js b/clients/sqlite3.js index 3c376517..6643ce15 100644 --- a/clients/sqlite3.js +++ b/clients/sqlite3.js @@ -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) { diff --git a/docs/knex.html b/docs/knex.html index 75671194..652de195 100644 --- a/docs/knex.html +++ b/docs/knex.html @@ -482,7 +482,7 @@ including any nested join queries.

    whereIn: function(qb, where) {
-      return this.wrap(where.column) + ' in (' + this.parameterize(where.values) + ')';
+      return this.wrap(where.column) + ' in (' + this.parameterize(where.value) + ')';
     },
@@ -499,7 +499,7 @@ including any nested join queries.

    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) + ')';
     },
@@ -672,16 +672,9 @@ 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 paramBlocks = [];
-      for (var i = 0, l = values.length; i < l; ++i) {
-        paramBlocks.push("(" + parameters + ")");
-      }
-
-      return "insert into " + table + " (" + columns + ") values " + paramBlocks.join(', ');
-    },
+ var columns = this.columnize(_.keys(values[0]).sort()); + var parameters = this.parameterize(_.values(values[0])); + var paramBlocks = []; @@ -692,12 +685,18 @@ inserts using a single query statement.

-

Compiles an insert, getting the id of the insert row.

+

If there are any "where" clauses, we need to omit +any bindings that may have been associated with them.

-
    compileInsertGetId: function(qb, values) {
-      return this.compileInsert(qb, values);
+            
      if (qb.wheres.length > 0) this._clearWhereBindings(qb);
+
+      for (var i = 0, l = values.length; i < l; ++i) {
+        paramBlocks.push("(" + parameters + ")");
+      }
+
+      return "insert into " + table + " (" + columns + ") values " + paramBlocks.join(', ');
     },
@@ -709,6 +708,37 @@ inserts using a single query statement.

+

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.

    @@ -725,11 +755,11 @@ inserts using a single query statement.

  • -
  • +
  • - +

    Compiles a delete query.

    @@ -744,11 +774,11 @@ inserts using a single query statement.

  • -
  • +
  • - +

    Compiles a truncate query.

    @@ -804,11 +834,11 @@ inserts using a single query statement.

  • -
  • +
  • - +

    Knex.Builder

    @@ -817,11 +847,11 @@ inserts using a single query statement.

  • -
  • +
  • - +
    @@ -835,11 +865,11 @@ inserts using a single query statement.

  • -
  • +
  • - +

    All operators used in the where clause generation.

    @@ -847,28 +877,7 @@ inserts using a single query statement.

      var operators = ['=', '<', '>', '<=', '>=', 'like', 'not like', 'between', 'ilike'];
     
    -  Builder.prototype = {
    -
    -    idAttr: 'id',
    - -
  • - - -
  • -
    - -
    - -
    -

    Sets the tableName on the query.

    - -
    - -
        from: function(tableName) {
    -      if (!tableName) return this.table;
    -      this.table = tableName;
    -      return this;
    -    },
    + Builder.prototype = {
  • @@ -879,12 +888,13 @@ inserts using a single query statement.

    -

    Set the idAttribute for the query.

    +

    Sets the tableName on the query.

    -
        idAttribute: function(id) {
    -      this.idAttr = id;
    +            
        from: function(tableName) {
    +      if (!tableName) return this.table;
    +      this.table = tableName;
           return this;
         },
    @@ -923,7 +933,7 @@ pieces that have been set thus far

        clone: function() {
           var item = new Builder(this.table);
           var items = [
    -        'isDistinct', 'idAttr', 'joins',
    +        'isDistinct', 'joins',
             'wheres', 'orders', 'columns', 'bindings',
             'grammar', 'connection', 'transaction'
           ];
    @@ -953,18 +963,16 @@ pieces that have been set thus far

    this.orders = []; this.columns = []; this.bindings = []; - this.idAttr = Builder.prototype.idAttr; this.isDistinct = false; }, - toJSON: function () { + toJSON: function() { return { joins: this.joins, wheres: this.wheres, order: this.orders, columns: this.columns, bindings: this.bindings, - idAttr: this.idAttr, isDistinct: this.isDistinct }; },
    @@ -1187,7 +1195,7 @@ where key = value.

    this.wheres.push({ type: (condition || 'In'), column: column, - values: values, + value: values, bool: bool }); push.apply(this.bindings, values); @@ -1621,23 +1629,19 @@ where key = value.

    -

    Performs an INSERT query, returning a promise.

    +

    Performs an insert query, returning a promise.

        insert: function(values, returning) {
    -      var str;
    -      returning || (returning = this.idAttr);
           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));
    -      }
    -      if (returning) {
    -        str = this.grammar.compileInsertGetId(this, values, returning);
    -      } else {
    -        str = this.grammar.compileInsert(this, values);
    +      for (var i = 0, l = values.length; i<l; i++) {
    +        var obj = sortObject(values[i]);
    +        for (var i2 = 0, l2 = obj.length; i2 < l2; i2++) {
    +          this.bindings.push(obj[i2][1]);
    +        }
           }
    +      var str = this.grammar.compileInsert(this, values);
           return Knex.runQuery(this, {sql: str, bindings: this._cleanBindings(), type: 'insert'});
         },
    @@ -1786,7 +1790,7 @@ the currently running transaction

    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; }, @@ -1907,9 +1911,7 @@ the currently running transaction

    -
      Knex.Transaction = function(container) {
    -
    -    var connection = Knex.client.getConnection();
    +
      Knex.Transaction = function(container) {
    @@ -1925,7 +1927,9 @@ transaction completes or fails, we know what to do.

    -
        var deferred = Q.defer();
    +
        var deferred = Q.defer();
    +
    +    Knex.client.beginTransaction(function(err, connection) {
    @@ -1940,11 +1944,11 @@ transaction completes or fails, we know what to do.

    -
        var finish = function(type, data) {
    -      this.connection.end();
    -      this.transaction.connection = null;
    -      deferred[type](data);
    -    };
    +
          var finish = function(type, data) {
    +        connection.end();
    +        this.connection = null;
    +        deferred[type](data);
    +      };
    @@ -1960,10 +1964,24 @@ commit & rollback objects

    -
        container({
    -      commit: function(data) { finish.call(this, 'resolve', data); },
    -      rollback: function(data) { finish.call(this, 'reject', data); },
    -      connection: connection
    +            
          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
    +      });
    +
         });
     
         return deferred.promise;
    @@ -2959,8 +2977,7 @@ the blueprint element, so we'll just call that compilers function.

        increments: function(column) {
    -      column || (column = 'id');
    -      return this._addColumn('integer', column, {autoIncrement: true});
    +      return this._addColumn('integer', (column || 'id'), {autoIncrement: true, length: 11});
         },
    @@ -2989,12 +3006,12 @@ the blueprint element, so we'll just call that compilers function.

    -

    Create a new text column on the table.

    +

    Alias varchar to string

    -
        text: function(column) {
    -      return this._addColumn('text', column);
    +            
        varchar: function(column, length) {
    +      return this.string(column, length);
         },
    @@ -3006,12 +3023,12 @@ the blueprint element, so we'll just call that compilers function.

    -

    Create a new integer column on the table.

    +

    Create a new text column on the table.

    -
        integer: function(column) {
    -      return this._addColumn('integer', column);
    +            
        text: function(column, length) {
    +      return this._addColumn('text', column, {length: (length || false)});
         },
    @@ -3023,6 +3040,57 @@ the blueprint element, so we'll just call that compilers function.

    +

    Create a new integer column on the table.

    + +
    + +
        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.

    @@ -3034,11 +3102,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new decimal column on the table.

    @@ -3051,28 +3119,28 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new boolean column on the table.

        boolean: function(column) {
    -      return this.bool(columns);
    +      return this._addColumn('boolean', column);
         },
  • -
  • +
  • - +

    Alias to "boolean".

    @@ -3085,11 +3153,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new date column on the table.

    @@ -3102,11 +3170,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new date-time column on the table.

    @@ -3119,11 +3187,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new time column on the table.

    @@ -3136,11 +3204,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new timestamp column on the table.

    @@ -3153,11 +3221,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Add creation and update timestamps to the table.

    @@ -3171,11 +3239,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new enum column on the table.

    @@ -3188,11 +3256,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Alias to enum.

    @@ -3205,11 +3273,28 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - + +
    +

    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.

    @@ -3222,11 +3307,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    @@ -3235,11 +3320,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    Create a new drop index command on the blueprint.

    @@ -3257,11 +3342,11 @@ the blueprint element, so we'll just call that compilers function.

  • -
  • +
  • - +

    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.

    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}); },
  • @@ -3283,11 +3368,11 @@ index type, such as primary or index, which makes the index unique.

    -
  • +
  • - +

    Add a new column to the blueprint.

    @@ -3304,11 +3389,11 @@ index type, such as primary or index, which makes the index unique.

  • -
  • +
  • - +

    Add a new command to the blueprint.

    @@ -3324,11 +3409,11 @@ index type, such as primary or index, which makes the index unique.

  • -
  • +
  • - +

    Chainable object used in creating SchemaBuilder commands.

    @@ -3343,11 +3428,11 @@ index type, such as primary or index, which makes the index unique.

  • -
  • +
  • - +

    Sets the default value for a column.

    @@ -3361,11 +3446,11 @@ index type, such as primary or index, which makes the index unique.

  • -
  • +
  • - +

    Sets an integer as unsigned, is a no-op if the column type is not an integer.

    @@ -3380,11 +3465,11 @@ if the column type is not an integer.

  • -
  • +
  • - +

    Allows the column to contain null values.

    @@ -3395,17 +3480,17 @@ if the column type is not an integer.

    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; } @@ -3414,16 +3499,22 @@ if the column type is not an integer.

    var capitalize = function(word) { return word.charAt(0).toUpperCase() + word.slice(1); + }; + + var sortObject = function(obj) { + return _.sortBy(_.pairs(obj), function(a) { + return a[0]; + }); };
  • -
  • +
  • - +

    Knex.Raw

    @@ -3432,11 +3523,11 @@ if the column type is not an integer.

  • -
  • +
  • - +
    @@ -3448,11 +3539,11 @@ if the column type is not an integer.

  • -
  • +
  • - +

    Knex.runQuery

    @@ -3461,11 +3552,11 @@ if the column type is not an integer.

  • -
  • +
  • - +

    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.

      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;
         }
         var deferred = Q.defer();
         Knex.client.query(data.sql, (data.bindings || []), function(err, resp) {
    @@ -3490,11 +3582,11 @@ and returns a deferred promise.

  • -
  • +
  • - +

    Export the Knex module

    diff --git a/index.html b/index.html index b1c63ffc..0a2845a4 100644 --- a/index.html +++ b/index.html @@ -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 @@