tablecompiler.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. 'use strict';
  2. exports.__esModule = true;
  3. var _getIterator2 = require('babel-runtime/core-js/get-iterator');
  4. var _getIterator3 = _interopRequireDefault(_getIterator2);
  5. var _isUndefined2 = require('lodash/isUndefined');
  6. var _isUndefined3 = _interopRequireDefault(_isUndefined2);
  7. var _isArray3 = require('lodash/isArray');
  8. var _isArray4 = _interopRequireDefault(_isArray3);
  9. var _indexOf2 = require('lodash/indexOf');
  10. var _indexOf3 = _interopRequireDefault(_indexOf2);
  11. var _isEmpty2 = require('lodash/isEmpty');
  12. var _isEmpty3 = _interopRequireDefault(_isEmpty2);
  13. var _tail2 = require('lodash/tail');
  14. var _tail3 = _interopRequireDefault(_tail2);
  15. var _first2 = require('lodash/first');
  16. var _first3 = _interopRequireDefault(_first2);
  17. var _map2 = require('lodash/map');
  18. var _map3 = _interopRequireDefault(_map2);
  19. var _reduce2 = require('lodash/reduce');
  20. var _reduce3 = _interopRequireDefault(_reduce2);
  21. var _groupBy2 = require('lodash/groupBy');
  22. var _groupBy3 = _interopRequireDefault(_groupBy2);
  23. var _helpers = require('./helpers');
  24. var _helpers2 = require('../helpers');
  25. var helpers = _interopRequireWildcard(_helpers2);
  26. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  27. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  28. /* eslint max-len:0 */
  29. // Table Compiler
  30. // -------
  31. function TableCompiler(client, tableBuilder) {
  32. this.client = client;
  33. this.tableBuilder = tableBuilder;
  34. this.method = tableBuilder._method;
  35. this.schemaNameRaw = tableBuilder._schemaName;
  36. this.tableNameRaw = tableBuilder._tableName;
  37. this.single = tableBuilder._single;
  38. this.grouped = (0, _groupBy3.default)(tableBuilder._statements, 'grouping');
  39. this.formatter = client.formatter(tableBuilder);
  40. this.sequence = [];
  41. this._formatting = client.config && client.config.formatting;
  42. }
  43. TableCompiler.prototype.pushQuery = _helpers.pushQuery;
  44. TableCompiler.prototype.pushAdditional = _helpers.pushAdditional;
  45. // Convert the tableCompiler toSQL
  46. TableCompiler.prototype.toSQL = function () {
  47. this[this.method]();
  48. return this.sequence;
  49. };
  50. TableCompiler.prototype.lowerCase = true;
  51. // Column Compilation
  52. // -------
  53. // If this is a table "creation", we need to first run through all
  54. // of the columns to build them into a single string,
  55. // and then run through anything else and push it to the query sequence.
  56. TableCompiler.prototype.createAlterTableMethods = null;
  57. TableCompiler.prototype.create = function (ifNot) {
  58. var columnBuilders = this.getColumns();
  59. var columns = columnBuilders.map(function (col) {
  60. return col.toSQL();
  61. });
  62. var columnTypes = this.getColumnTypes(columns);
  63. if (this.createAlterTableMethods) {
  64. this.alterTableForCreate(columnTypes);
  65. }
  66. this.createQuery(columnTypes, ifNot);
  67. this.columnQueries(columns);
  68. delete this.single.comment;
  69. this.alterTable();
  70. };
  71. // Only create the table if it doesn't exist.
  72. TableCompiler.prototype.createIfNot = function () {
  73. this.create(true);
  74. };
  75. // If we're altering the table, we need to one-by-one
  76. // go through and handle each of the queries associated
  77. // with altering the table's schema.
  78. TableCompiler.prototype.alter = function () {
  79. var addColBuilders = this.getColumns();
  80. var addColumns = addColBuilders.map(function (col) {
  81. return col.toSQL();
  82. });
  83. var alterColBuilders = this.getColumns('alter');
  84. var alterColumns = alterColBuilders.map(function (col) {
  85. return col.toSQL();
  86. });
  87. var addColumnTypes = this.getColumnTypes(addColumns);
  88. var alterColumnTypes = this.getColumnTypes(alterColumns);
  89. this.addColumns(addColumnTypes);
  90. this.alterColumns(alterColumnTypes, alterColBuilders);
  91. this.columnQueries(addColumns);
  92. this.columnQueries(alterColumns);
  93. this.alterTable();
  94. };
  95. TableCompiler.prototype.foreign = function (foreignData) {
  96. if (foreignData.inTable && foreignData.references) {
  97. var keyName = foreignData.keyName ? this.formatter.wrap(foreignData.keyName) : this._indexCommand('foreign', this.tableNameRaw, foreignData.column);
  98. var column = this.formatter.columnize(foreignData.column);
  99. var references = this.formatter.columnize(foreignData.references);
  100. var inTable = this.formatter.wrap(foreignData.inTable);
  101. var onUpdate = foreignData.onUpdate ? (this.lowerCase ? ' on update ' : ' ON UPDATE ') + foreignData.onUpdate : '';
  102. var onDelete = foreignData.onDelete ? (this.lowerCase ? ' on delete ' : ' ON DELETE ') + foreignData.onDelete : '';
  103. if (this.lowerCase) {
  104. this.pushQuery((!this.forCreate ? 'alter table ' + this.tableName() + ' add ' : '') + 'constraint ' + keyName + ' ' + 'foreign key (' + column + ') references ' + inTable + ' (' + references + ')' + onUpdate + onDelete);
  105. } else {
  106. this.pushQuery((!this.forCreate ? 'ALTER TABLE ' + this.tableName() + ' ADD ' : '') + 'CONSTRAINT ' + keyName + ' ' + 'FOREIGN KEY (' + column + ') REFERENCES ' + inTable + ' (' + references + ')' + onUpdate + onDelete);
  107. }
  108. }
  109. };
  110. // Get all of the column sql & bindings individually for building the table queries.
  111. TableCompiler.prototype.getColumnTypes = function (columns) {
  112. return (0, _reduce3.default)((0, _map3.default)(columns, _first3.default), function (memo, column) {
  113. memo.sql.push(column.sql);
  114. memo.bindings.concat(column.bindings);
  115. return memo;
  116. }, { sql: [], bindings: [] });
  117. };
  118. // Adds all of the additional queries from the "column"
  119. TableCompiler.prototype.columnQueries = function (columns) {
  120. var queries = (0, _reduce3.default)((0, _map3.default)(columns, _tail3.default), function (memo, column) {
  121. if (!(0, _isEmpty3.default)(column)) return memo.concat(column);
  122. return memo;
  123. }, []);
  124. for (var _iterator = queries, _isArray2 = Array.isArray(_iterator), _i = 0, _iterator = _isArray2 ? _iterator : (0, _getIterator3.default)(_iterator);;) {
  125. var _ref;
  126. if (_isArray2) {
  127. if (_i >= _iterator.length) break;
  128. _ref = _iterator[_i++];
  129. } else {
  130. _i = _iterator.next();
  131. if (_i.done) break;
  132. _ref = _i.value;
  133. }
  134. var q = _ref;
  135. this.pushQuery(q);
  136. }
  137. };
  138. // Add a new column.
  139. TableCompiler.prototype.addColumnsPrefix = 'add column ';
  140. // All of the columns to "add" for the query
  141. TableCompiler.prototype.addColumns = function (columns, prefix) {
  142. prefix = prefix || this.addColumnsPrefix;
  143. if (columns.sql.length > 0) {
  144. var columnSql = (0, _map3.default)(columns.sql, function (column) {
  145. return prefix + column;
  146. });
  147. this.pushQuery({
  148. sql: (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') + this.tableName() + ' ' + columnSql.join(', '),
  149. bindings: columns.bindings
  150. });
  151. }
  152. };
  153. // Alter column
  154. TableCompiler.prototype.alterColumnsPrefix = 'alter column ';
  155. TableCompiler.prototype.alterColumns = function (columns, colBuilders) {
  156. if (columns.sql.length > 0) {
  157. this.addColumns(columns, this.alterColumnsPrefix, colBuilders);
  158. }
  159. };
  160. // Compile the columns as needed for the current create or alter table
  161. TableCompiler.prototype.getColumns = function (method) {
  162. var _this = this;
  163. var columns = this.grouped.columns || [];
  164. method = method || 'add';
  165. var queryContext = this.tableBuilder.queryContext();
  166. return columns.filter(function (column) {
  167. return column.builder._method === method;
  168. }).map(function (column) {
  169. // pass queryContext down to columnBuilder but do not overwrite it if already set
  170. if (!(0, _isUndefined3.default)(queryContext) && (0, _isUndefined3.default)(column.builder.queryContext())) {
  171. column.builder.queryContext(queryContext);
  172. }
  173. return _this.client.columnCompiler(_this, column.builder);
  174. });
  175. };
  176. TableCompiler.prototype.tableName = function () {
  177. var name = this.schemaNameRaw ? this.schemaNameRaw + '.' + this.tableNameRaw : this.tableNameRaw;
  178. return this.formatter.wrap(name);
  179. };
  180. // Generate all of the alter column statements necessary for the query.
  181. TableCompiler.prototype.alterTable = function () {
  182. var alterTable = this.grouped.alterTable || [];
  183. for (var i = 0, l = alterTable.length; i < l; i++) {
  184. var statement = alterTable[i];
  185. if (this[statement.method]) {
  186. this[statement.method].apply(this, statement.args);
  187. } else {
  188. helpers.error('Debug: ' + statement.method + ' does not exist');
  189. }
  190. }
  191. for (var item in this.single) {
  192. if (typeof this[item] === 'function') this[item](this.single[item]);
  193. }
  194. };
  195. TableCompiler.prototype.alterTableForCreate = function (columnTypes) {
  196. this.forCreate = true;
  197. var savedSequence = this.sequence;
  198. var alterTable = this.grouped.alterTable || [];
  199. this.grouped.alterTable = [];
  200. for (var i = 0, l = alterTable.length; i < l; i++) {
  201. var statement = alterTable[i];
  202. if ((0, _indexOf3.default)(this.createAlterTableMethods, statement.method) < 0) {
  203. this.grouped.alterTable.push(statement);
  204. continue;
  205. }
  206. if (this[statement.method]) {
  207. this.sequence = [];
  208. this[statement.method].apply(this, statement.args);
  209. columnTypes.sql.push(this.sequence[0].sql);
  210. } else {
  211. helpers.error('Debug: ' + statement.method + ' does not exist');
  212. }
  213. }
  214. this.sequence = savedSequence;
  215. this.forCreate = false;
  216. };
  217. // Drop the index on the current table.
  218. TableCompiler.prototype.dropIndex = function (value) {
  219. this.pushQuery('drop index' + value);
  220. };
  221. // Drop the unique
  222. TableCompiler.prototype.dropUnique = TableCompiler.prototype.dropForeign = function () {
  223. throw new Error('Method implemented in the dialect driver');
  224. };
  225. TableCompiler.prototype.dropColumnPrefix = 'drop column ';
  226. TableCompiler.prototype.dropColumn = function () {
  227. var _this2 = this;
  228. var columns = helpers.normalizeArr.apply(null, arguments);
  229. var drops = (0, _map3.default)((0, _isArray4.default)(columns) ? columns : [columns], function (column) {
  230. return _this2.dropColumnPrefix + _this2.formatter.wrap(column);
  231. });
  232. this.pushQuery((this.lowerCase ? 'alter table ' : 'ALTER TABLE ') + this.tableName() + ' ' + drops.join(', '));
  233. };
  234. // If no name was specified for this index, we will create one using a basic
  235. // convention of the table name, followed by the columns, followed by an
  236. // index type, such as primary or index, which makes the index unique.
  237. TableCompiler.prototype._indexCommand = function (type, tableName, columns) {
  238. if (!(0, _isArray4.default)(columns)) columns = columns ? [columns] : [];
  239. var table = tableName.replace(/\.|-/g, '_');
  240. var indexName = (table + '_' + columns.join('_') + '_' + type).toLowerCase();
  241. return this.formatter.wrap(indexName);
  242. };
  243. exports.default = TableCompiler;
  244. module.exports = exports['default'];