mirror of
https://github.com/knex/knex.git
synced 2025-07-07 00:51:30 +00:00
267 lines
5.6 KiB
JavaScript
267 lines
5.6 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.
|
||
|
// -------
|
||
|
var _ = require('lodash');
|
||
|
|
||
|
function TableBuilder(tableName) {
|
||
|
this._tableName = tableName;
|
||
|
this._statements = [];
|
||
|
this._single = {};
|
||
|
}
|
||
|
|
||
|
// Compile the "alter" query for the table.
|
||
|
// We attach any "alter" methods to the object
|
||
|
// before invoking the function, so as to
|
||
|
TableBuilder.prototype._alter = function(fn) {
|
||
|
this._method = 'alter';
|
||
|
_.extend(this, AlterMethods);
|
||
|
fn.call(this, this);
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
// Compile the "create" query for the table.
|
||
|
TableBuilder.prototype._create = function(fn) {
|
||
|
this._method = 'create';
|
||
|
fn.call(this, this);
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
var AlterMethods = {
|
||
|
|
||
|
// Renames the current column `from` the current
|
||
|
// TODO: this.column(from).rename(to)
|
||
|
renameColumn: function(from, to) {
|
||
|
this._statements.push({
|
||
|
grouping: 'alterColumns',
|
||
|
type: 'renameColumn',
|
||
|
args: [from, to]
|
||
|
});
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
dropTimestamps: function() {
|
||
|
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: 'alterColumns',
|
||
|
type: 'dropColumn',
|
||
|
args: Helpers.normalizeArr.apply(null, arguments)
|
||
|
});
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
_.each(['dropPrimary', 'dropUnique', 'dropIndex', 'dropForeign'], function(method) {
|
||
|
AlterMethods[method] = function() {
|
||
|
this._statements.push({
|
||
|
grouping: 'indexes',
|
||
|
type: 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) {
|
||
|
if (false) {
|
||
|
warn('Knex only supports ' + method + ' statement with mysql.');
|
||
|
} if (this.__method === 'alter') {
|
||
|
warn('Knex does not support altering the ' + method + ' outside of the create table, please use knex.raw statement.');
|
||
|
}
|
||
|
this._single[method] = value;
|
||
|
});
|
||
|
|
||
|
// For each of the column types that we can add, we just push it onto the "allStatements"
|
||
|
// stack and then return the appropriate chainable interface for the column.
|
||
|
var columnMethods = [
|
||
|
|
||
|
// 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',
|
||
|
'uuid',
|
||
|
'enu',
|
||
|
'specificType'
|
||
|
];
|
||
|
|
||
|
// "SPATIAL"
|
||
|
// geometry
|
||
|
// point
|
||
|
// linestring
|
||
|
// polygon
|
||
|
// multipoint
|
||
|
// multilinestring
|
||
|
// multipolygon
|
||
|
// geometrycollection
|
||
|
|
||
|
/*
|
||
|
// SQLITE3 Definitions:
|
||
|
|
||
|
// type: integer (1)
|
||
|
int
|
||
|
integer
|
||
|
tinyint
|
||
|
smallint
|
||
|
mediumint
|
||
|
bigint
|
||
|
unsigned BIG INT
|
||
|
int2
|
||
|
int8
|
||
|
|
||
|
// type: text (2)
|
||
|
character(20)
|
||
|
varchar(255)
|
||
|
varying CHARACTER(255)
|
||
|
nchar(55)
|
||
|
native CHARACTER(70)
|
||
|
nvarchar(100)
|
||
|
text
|
||
|
clob
|
||
|
|
||
|
// type: no datatype specified (none) (3)
|
||
|
blob
|
||
|
|
||
|
// type: float / real (4)
|
||
|
real
|
||
|
double
|
||
|
double precision
|
||
|
|
||
|
// type numeric (5)
|
||
|
numeric
|
||
|
decimal(10,5)
|
||
|
boolean
|
||
|
date
|
||
|
datetime
|
||
|
*/
|
||
|
|
||
|
// Alias a few methods for clarity when processing.
|
||
|
var aliasColumn = {
|
||
|
'float' : 'floating',
|
||
|
'enum' : 'enu',
|
||
|
'boolean': 'bool',
|
||
|
'string' : 'varchar',
|
||
|
'bigint' : 'bigInteger'
|
||
|
};
|
||
|
|
||
|
// 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(columnMethods, function(method) {
|
||
|
TableBuilder.prototype[method] = function() {
|
||
|
var args = _.toArray(arguments);
|
||
|
|
||
|
// The "timestamps" call is really a compound call to set the
|
||
|
// `created_at` and `updated_at` columns.
|
||
|
if (method === 'timestamps') {
|
||
|
if (args[0] === true) {
|
||
|
this.timestamp('created_at');
|
||
|
this.timestamp('updated_at');
|
||
|
} else {
|
||
|
this.datetime('created_at');
|
||
|
this.datetime('updated_at');
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var aliased = (aliasColumn[method] || method).toLowerCase();
|
||
|
var chainable = new ColumnBuilder(this, args[0]).type(aliased);
|
||
|
|
||
|
this._statements.push({
|
||
|
grouping: 'column',
|
||
|
method: aliased,
|
||
|
originalMethod: method,
|
||
|
args: args,
|
||
|
builder: builder
|
||
|
});
|
||
|
return chainable;
|
||
|
};
|
||
|
|
||
|
});
|
||
|
|
||
|
// Each of the index methods can be called individually, with the
|
||
|
// column name to be used, e.g. table.unique('column').
|
||
|
var indexMethods = ['index', 'primary', 'unique'];
|
||
|
|
||
|
_.each(indexMethods, function(method) {
|
||
|
TableBuilder.prototype[method] = function() {
|
||
|
this._statements.push({
|
||
|
type: 'indexes',
|
||
|
method: method,
|
||
|
args: _.toArray(arguments)
|
||
|
});
|
||
|
};
|
||
|
});
|
||
|
|
||
|
// 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;
|
||
|
};
|
||
|
|
||
|
module.exports = TableBuilder;
|