knex/lib/schema/tablecompiler.js

144 lines
4.9 KiB
JavaScript
Raw Normal View History

2013-12-27 14:44:21 -05:00
// Table Compiler
// -------
var _ = require('lodash');
var Raw = require('../raw');
var util = require('../util');
function TableCompiler(schemaCompiler, tableBuilder) {
this.schemaCompiler = schemaCompiler;
this.formatter = schemaCompiler.formatter;
this.tableBuilder = tableBuilder;
this.tableNameRaw = tableBuilder.tableName;
this.grouped = _.groupBy(schemaCompiler._statements, 'grouping');
this.single = schemaCompiler._single;
}
// Push onto the schemaCompiler's stack of queries
TableCompiler.prototype.push = function(obj) {
this.schemaCompiler.push(obj);
this.formatter = this.schemaCompiler.formatter;
return this;
};
TableCompiler.prototype.create = function() {
this.push('create table ' + this.tableName() + ' (' + this.getColumns().join(', ') + ')');
this.alterColumns();
this.addIndexes();
};
TableCompiler.prototype.alter = function() {
this.addColumns();
this.alterColumns();
this.addIndexes();
};
TableCompiler.prototype.tableName = function() {
return this.formatter.wrap(this.tableNameRaw);
};
TableCompiler.prototype.addColumnsPrefix = 'add column ';
// All of the columns to "add" for the query
TableCompiler.prototype.addColumns = function() {
var columns = this.getColumns();
if (columns.length > 0) {
columns = _.map(columns, function(column) {
return this.addColumnsPrefix + column;
2013-12-27 14:44:21 -05:00
}, this);
this.push('alter table ' + this.tableName() + ' ' + columns.join(', '));
2013-12-27 14:44:21 -05:00
}
};
// Generate all of the alter column statements necessary for the query.
TableCompiler.prototype.alterColumns = function() {
var alterColumns = _.where(this.statements, {type: 'alterColumns'});
for (var i = 0, l = alterColumns.length; i < l; i++) {
var statement = alterColumns[i];
this.push(this[statement.method].apply(this, statement.args));
}
};
// Add indexes on the statements.
TableCompiler.prototype.addIndexes = function() {
var indexStatements = _.where(this.statements, {type: 'indexes'});
for (var i = 0, l = indexStatements.length; i < l; i++) {
var statement = indexStatements[i];
var obj = this.keys[statement.method].apply(this, statement.args);
if (obj) this.push(obj);
}
};
2013-12-27 14:44:21 -05:00
// Compile the columns as needed for the current create or alter table
TableCompiler.prototype.getColumns = function() {
var compiledColumns = [], columns = this.columns;
for (var i = 0, l = columns.length; i < l; i++) {
compiledColumns.push(this.compileColumn(columns[i]));
}
return compiledColumns;
};
TableCompiler.prototype.compileColumn = function(column) {
return this.formatter.wrap(this.getColumnName(column)) + ' ' + this.getColumnType(column) + this.getModifiers(column);
};
TableCompiler.prototype.getColumnType = function(column) {
var type = this.types[column.method];
return _.isFunction(type) ? type.apply(this, _.rest(column.args)) : type;
};
TableCompiler.prototype.getModifiers = function(column) {
var modifiers = [];
if (column.method !== 'timestamps' && column.method.indexOf('increments') === -1) {
var modifierTypes = this.modifierTypes;
var statements = column.chainable.__modifiers;
for (var i = 0, l = modifierTypes.length; i < l; i++) {
var modifier = modifierTypes[i];
var statement = statements[modifier];
if (statement) {
var val = this.modifiers[modifier].apply(this, statement);
if (val) modifiers.push(val);
2013-12-27 14:44:21 -05:00
}
}
}
return modifiers.length > 0 ? ' ' + modifiers.join(' ') : '';
};
// Assumes that the autoincrementing key is named `id` if not otherwise specified.
TableCompiler.prototype.getColumnName = function(column) {
var value = _.first(column.args);
if (value) return value;
if (column.method === 'timestamps') return '';
if (column.method.indexOf('increments') !== -1) {
return 'id';
} else {
throw new Error('You did not specify a column name for the ' + column.originalMethod + 'column on ' + this.tableName());
}
};
TableCompiler.prototype.dropUnique = function(value) {
this.push('drop index ' + value);
};
// dropColumnPrefix: 'drop column ',
TableCompiler.prototype.dropColumn = function() {
var columns = util.normalizeArr.apply(null, arguments);
var drops = _.map(_.isArray(columns) ? columns : [columns], function(column) {
return this.dropColumnPrefix + this.formatter.wrap(column);
}, this);
this.push('alter table ' + this.tableName() + ' ' + drops.join(', '));
};
// If no name was specified for this index, we will create one using a basic
// convention of the table name, followed by the columns, followed by an
// index type, such as primary or index, which makes the index unique.
TableCompiler.prototype._indexCommand = function(type, tableName, columns) {
if (!_.isArray(columns)) columns = columns ? [columns] : [];
var table = tableName.replace(/\.|-/g, '_');
return (table + '_' + columns.join('_') + '_' + type).toLowerCase();
};
module.exports = TableCompiler;