You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
6.0 KiB
JavaScript
203 lines
6.0 KiB
JavaScript
|
|
// TableBuilder
|
|
|
|
// Takes the function passed to the "createTable" or "table/editTable"
|
|
// functions and calls it with the "TableBuilder" as both the context and
|
|
// the first argument. Inside this function we can specify what happens to the
|
|
// method, pushing everything we want to do onto the "allStatements" array,
|
|
// which is then compiled into sql.
|
|
// ------
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var helpers = require('../helpers');
|
|
|
|
function TableBuilder(client, method, tableName, fn) {
|
|
this.client = client;
|
|
this._fn = fn;
|
|
this._method = method;
|
|
this._schemaName = undefined;
|
|
this._tableName = tableName;
|
|
this._statements = [];
|
|
this._single = {};
|
|
}
|
|
|
|
TableBuilder.prototype.setSchema = function (schemaName) {
|
|
this._schemaName = schemaName;
|
|
};
|
|
|
|
// Convert the current tableBuilder object "toSQL"
|
|
// giving us additional methods if we're altering
|
|
// rather than creating the table.
|
|
TableBuilder.prototype.toSQL = function () {
|
|
if (this._method === 'alter') {
|
|
_.extend(this, AlterMethods);
|
|
}
|
|
this._fn.call(this, this);
|
|
return this.client.tableCompiler(this).toSQL();
|
|
};
|
|
|
|
_.each([
|
|
|
|
// Each of the index methods can be called individually, with the
|
|
// column name to be used, e.g. table.unique('column').
|
|
'index', 'primary', 'unique',
|
|
|
|
// Key specific
|
|
'dropPrimary', 'dropUnique', 'dropIndex', 'dropForeign'], function (method) {
|
|
TableBuilder.prototype[method] = function () {
|
|
this._statements.push({
|
|
grouping: 'alterTable',
|
|
method: method,
|
|
args: _.toArray(arguments)
|
|
});
|
|
return this;
|
|
};
|
|
});
|
|
|
|
// Warn if we're not in MySQL, since that's the only time these
|
|
// three are supported.
|
|
var specialMethods = ['engine', 'charset', 'collate'];
|
|
_.each(specialMethods, function (method) {
|
|
TableBuilder.prototype[method] = function (value) {
|
|
if (false) {
|
|
helpers.warn('Knex only supports ' + method + ' statement with mysql.');
|
|
}if (this._method === 'alter') {
|
|
helpers.warn('Knex does not support altering the ' + method + ' outside of the create table, please use knex.raw statement.');
|
|
}
|
|
this._single[method] = value;
|
|
};
|
|
});
|
|
|
|
// Each of the column types that we can add, we create a new ColumnBuilder
|
|
// instance and push it onto the statements array.
|
|
var columnTypes = [
|
|
|
|
// Numeric
|
|
'tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'decimal', 'float', 'double', 'real', 'bit', 'boolean', 'serial',
|
|
|
|
// Date / Time
|
|
'date', 'datetime', 'timestamp', 'time', 'year',
|
|
|
|
// String
|
|
'char', 'varchar', 'tinytext', 'tinyText', 'text', 'mediumtext', 'mediumText', 'longtext', 'longText', 'binary', 'varbinary', 'tinyblob', 'tinyBlob', 'mediumblob', 'mediumBlob', 'blob', 'longblob', 'longBlob', 'enum', 'set',
|
|
|
|
// Increments, Aliases, and Additional
|
|
'bool', 'dateTime', 'increments', 'bigincrements', 'bigIncrements', 'integer', 'biginteger', 'bigInteger', 'string', 'timestamps', 'json', 'jsonb', 'uuid', 'enu', 'specificType'];
|
|
|
|
// For each of the column methods, create a new "ColumnBuilder" interface,
|
|
// push it onto the "allStatements" stack, and then return the interface,
|
|
// with which we can add indexes, etc.
|
|
_.each(columnTypes, function (type) {
|
|
TableBuilder.prototype[type] = function () {
|
|
var args = _.toArray(arguments);
|
|
|
|
// The "timestamps" call is really a compound call to set the
|
|
// `created_at` and `updated_at` columns.
|
|
if (type === 'timestamps') {
|
|
if (args[0] === true) {
|
|
this.timestamp('created_at');
|
|
this.timestamp('updated_at');
|
|
} else {
|
|
this.datetime('created_at');
|
|
this.datetime('updated_at');
|
|
}
|
|
return;
|
|
}
|
|
var builder = this.client.columnBuilder(this, type, args);
|
|
|
|
this._statements.push({
|
|
grouping: 'columns',
|
|
builder: builder
|
|
});
|
|
return builder;
|
|
};
|
|
});
|
|
|
|
// Set the comment value for a table, they're only allowed to be called
|
|
// once per table.
|
|
TableBuilder.prototype.comment = function (value) {
|
|
this._single.comment = value;
|
|
};
|
|
|
|
// Set a foreign key on the table, calling
|
|
// `table.foreign('column_name').references('column').on('table').onDelete()...
|
|
// Also called from the ColumnBuilder context when chaining.
|
|
TableBuilder.prototype.foreign = function (column) {
|
|
var foreignData = { column: column };
|
|
this._statements.push({
|
|
grouping: 'alterTable',
|
|
method: 'foreign',
|
|
args: [foreignData]
|
|
});
|
|
var returnObj = {
|
|
references: function references(tableColumn) {
|
|
var pieces;
|
|
if (_.isString(tableColumn)) {
|
|
pieces = tableColumn.split('.');
|
|
}
|
|
if (!pieces || pieces.length === 1) {
|
|
foreignData.references = pieces ? pieces[0] : tableColumn;
|
|
return {
|
|
on: function on(tableName) {
|
|
foreignData.inTable = tableName;
|
|
return returnObj;
|
|
},
|
|
inTable: function inTable() {
|
|
return this.on.apply(this, arguments);
|
|
}
|
|
};
|
|
}
|
|
foreignData.inTable = pieces[0];
|
|
foreignData.references = pieces[1];
|
|
return returnObj;
|
|
},
|
|
onUpdate: function onUpdate(statement) {
|
|
foreignData.onUpdate = statement;
|
|
return returnObj;
|
|
},
|
|
onDelete: function onDelete(statement) {
|
|
foreignData.onDelete = statement;
|
|
return returnObj;
|
|
},
|
|
_columnBuilder: function _columnBuilder(builder) {
|
|
_.extend(builder, returnObj);
|
|
returnObj = builder;
|
|
return builder;
|
|
}
|
|
};
|
|
return returnObj;
|
|
};
|
|
|
|
var AlterMethods = {
|
|
|
|
// Renames the current column `from` the current
|
|
// TODO: this.column(from).rename(to)
|
|
renameColumn: function renameColumn(from, to) {
|
|
this._statements.push({
|
|
grouping: 'alterTable',
|
|
method: 'renameColumn',
|
|
args: [from, to]
|
|
});
|
|
return this;
|
|
},
|
|
|
|
dropTimestamps: function dropTimestamps() {
|
|
return this.dropColumns(['created_at', 'updated_at']);
|
|
}
|
|
|
|
// TODO: changeType
|
|
};
|
|
|
|
// Drop a column from the current table.
|
|
// TODO: Enable this.column(columnName).drop();
|
|
AlterMethods.dropColumn = AlterMethods.dropColumns = function () {
|
|
this._statements.push({
|
|
grouping: 'alterTable',
|
|
method: 'dropColumn',
|
|
args: _.toArray(arguments)
|
|
});
|
|
return this;
|
|
};
|
|
|
|
module.exports = TableBuilder; |