@dbml/core 2.3.1 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/lib/export/DbmlExporter.js +11 -6
  2. package/lib/export/MysqlExporter.js +127 -48
  3. package/lib/export/PostgresExporter.js +142 -55
  4. package/lib/export/SqlServerExporter.js +130 -52
  5. package/lib/export/utils.js +40 -0
  6. package/lib/model_structure/database.js +53 -12
  7. package/lib/model_structure/endpoint.js +2 -2
  8. package/lib/model_structure/field.js +31 -1
  9. package/lib/model_structure/ref.js +1 -2
  10. package/lib/model_structure/schema.js +3 -19
  11. package/lib/model_structure/tableGroup.js +1 -1
  12. package/lib/model_structure/utils.js +5 -0
  13. package/lib/parse/dbml/parser.pegjs +74 -24
  14. package/lib/parse/dbmlParser.js +1275 -886
  15. package/lib/parse/mssql/fk_definition/actions.js +10 -3
  16. package/lib/parse/mssql/keyword_parsers.js +12 -1
  17. package/lib/parse/mssql/statements/actions.js +37 -6
  18. package/lib/parse/mssql/statements/index.js +1 -1
  19. package/lib/parse/mssql/statements/statement_types/alter_table/actions.js +11 -5
  20. package/lib/parse/mssql/statements/statement_types/comments/actions.js +57 -0
  21. package/lib/parse/mssql/statements/statement_types/comments/index.js +97 -0
  22. package/lib/parse/mssql/statements/statement_types/create_index/actions.js +6 -1
  23. package/lib/parse/mssql/statements/statement_types/create_table/actions.js +11 -9
  24. package/lib/parse/mssql/statements/statement_types/index.js +4 -1
  25. package/lib/parse/mssql/utils.js +15 -0
  26. package/lib/parse/mysql/parser.pegjs +55 -20
  27. package/lib/parse/mysqlParser.js +479 -308
  28. package/lib/parse/postgresParser.js +15 -14
  29. package/lib/parse/postgresql/Base_rules.pegjs +24 -3
  30. package/lib/parse/postgresql/Commands/Alter_table/Alter_table.pegjs +49 -4
  31. package/lib/parse/postgresql/Commands/Comment.pegjs +18 -6
  32. package/lib/parse/postgresql/Commands/Create_table/Create_table_normal.pegjs +5 -3
  33. package/lib/parse/postgresql/Commands/Create_table/Create_table_of.pegjs +1 -1
  34. package/lib/parse/postgresql/Commands/Create_table/Create_table_partition_of.pegjs +1 -1
  35. package/lib/parse/postgresql/Commands/Create_type/Create_type_enum.pegjs +2 -2
  36. package/lib/parse/postgresql/Commands/Ignore_syntax.pegjs +10 -1
  37. package/lib/parse/postgresql/InitializerUtils.pegjs +14 -2
  38. package/lib/parse/postgresql/Keywords.pegjs +5 -1
  39. package/lib/parse/postgresql/parser.pegjs +22 -8
  40. package/package.json +2 -2
@@ -9,6 +9,8 @@ var _lodash = _interopRequireDefault(require("lodash"));
9
9
 
10
10
  var _utils = require("./utils");
11
11
 
12
+ var _config = require("../model_structure/config");
13
+
12
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13
15
 
14
16
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -55,7 +57,13 @@ var DbmlExporter = /*#__PURE__*/function () {
55
57
  var table = model.tables[tableId];
56
58
  var lines = table.fieldIds.map(function (fieldId) {
57
59
  var field = model.fields[fieldId];
58
- var line = "\"".concat(field.name, "\" ").concat(DbmlExporter.hasWhiteSpace(field.type.type_name) || DbmlExporter.hasSquareBracket(field.type.type_name) ? "\"".concat(field.type.type_name, "\"") : field.type.type_name);
60
+ var schemaName = '';
61
+
62
+ if (field.type.schemaName && field.type.schemaName !== _config.DEFAULT_SCHEMA_NAME) {
63
+ schemaName = DbmlExporter.hasWhiteSpace(field.type.schemaName) ? "\"".concat(field.type.schemaName, "\".") : "".concat(field.type.schemaName, ".");
64
+ }
65
+
66
+ var line = "\"".concat(field.name, "\" ").concat(schemaName).concat(DbmlExporter.hasWhiteSpace(field.type.type_name) || DbmlExporter.hasSquareBracket(field.type.type_name) ? "\"".concat(field.type.type_name, "\"") : field.type.type_name);
59
67
  var constraints = [];
60
68
 
61
69
  if (field.unique) {
@@ -185,10 +193,6 @@ var DbmlExporter = /*#__PURE__*/function () {
185
193
  settingStr += "headerColor: ".concat(table.headerColor).concat(settingSep);
186
194
  }
187
195
 
188
- if (table.note) {
189
- settingStr += "note: '".concat(table.note, "'").concat(settingSep);
190
- }
191
-
192
196
  if (settingStr.endsWith(', ')) {
193
197
  settingStr = settingStr.replace(/,\s$/, '');
194
198
  }
@@ -215,9 +219,10 @@ var DbmlExporter = /*#__PURE__*/function () {
215
219
  }).join('\n'), "\n}");
216
220
  }
217
221
 
222
+ var tableNote = table.note ? " Note: '".concat(table.note, "'\n") : '';
218
223
  var tableStr = "Table ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(table.name, "\"").concat(tableSettingStr, " {\n").concat(tableContent.fieldContents.map(function (line) {
219
224
  return " ".concat(line);
220
- }).join('\n'), "\n").concat(indexStr ? "".concat(indexStr, "\n") : '', "}\n");
225
+ }).join('\n'), "\n").concat(indexStr ? "".concat(indexStr, "\n") : '').concat(tableNote, "}\n");
221
226
  return tableStr;
222
227
  });
223
228
  return tableStrs.length ? tableStrs.join('\n') : '';
@@ -144,7 +144,7 @@ var MySQLExporter = /*#__PURE__*/function () {
144
144
  }).join(',\n'), "\n);\n");
145
145
  return tableStr;
146
146
  });
147
- return tableStrs.length ? tableStrs.join('\n') : '';
147
+ return tableStrs;
148
148
  }
149
149
  }, {
150
150
  key: "buildFieldName",
@@ -154,16 +154,64 @@ var MySQLExporter = /*#__PURE__*/function () {
154
154
  }).join(', ');
155
155
  return "(".concat(fieldNames, ")");
156
156
  }
157
+ }, {
158
+ key: "buildTableManyToMany",
159
+ value: function buildTableManyToMany(firstTableFieldsMap, secondTableFieldsMap, tableName) {
160
+ var line = "CREATE TABLE `".concat(tableName, "` (\n");
161
+
162
+ var key1s = _toConsumableArray(firstTableFieldsMap.keys()).join('`, `');
163
+
164
+ var key2s = _toConsumableArray(secondTableFieldsMap.keys()).join('`, `');
165
+
166
+ firstTableFieldsMap.forEach(function (fieldType, fieldName) {
167
+ line += " `".concat(fieldName, "` ").concat(fieldType, " NOT NULL,\n");
168
+ });
169
+ secondTableFieldsMap.forEach(function (fieldType, fieldName) {
170
+ line += " `".concat(fieldName, "` ").concat(fieldType, " NOT NULL,\n");
171
+ });
172
+ line += " PRIMARY KEY (`".concat(key1s, "`, `").concat(key2s, "`)\n");
173
+ line += ');\n\n';
174
+ return line;
175
+ }
176
+ }, {
177
+ key: "buildForeignKeyManyToMany",
178
+ value: function buildForeignKeyManyToMany(fieldsMap, foreignEndpointFields, refEndpointTableName, foreignEndpointTableName, schema, model) {
179
+ var refEndpointFields = _toConsumableArray(fieldsMap.keys()).join('`, `');
180
+
181
+ var line = "ALTER TABLE `".concat(refEndpointTableName, "` ADD FOREIGN KEY (`").concat(refEndpointFields, "`) REFERENCES ").concat((0, _utils.shouldPrintSchema)(schema, model) ? "`".concat(schema.name, "`.") : '', "`").concat(foreignEndpointTableName, "` ").concat(foreignEndpointFields, ";\n\n");
182
+ return line;
183
+ }
184
+ }, {
185
+ key: "buildIndexManytoMany",
186
+ value: function buildIndexManytoMany(fieldsMap, newTableName, tableRefName, usedIndexNames) {
187
+ var newIndexName = "".concat(newTableName, "_").concat(tableRefName);
188
+ var count = 1;
189
+
190
+ while (usedIndexNames.has(newIndexName)) {
191
+ newIndexName = "".concat(newTableName, "_").concat(tableRefName, "(").concat(count, ")");
192
+ count += 1;
193
+ }
194
+
195
+ usedIndexNames.add(newIndexName);
196
+
197
+ var indexFields = _toConsumableArray(fieldsMap.keys()).join('`, `');
198
+
199
+ var line = "CREATE INDEX `idx_".concat(newIndexName, "` ON `").concat(newTableName, "` (");
200
+ line += "`".concat(indexFields, "`);\n\n");
201
+ return line;
202
+ }
157
203
  }, {
158
204
  key: "exportRefs",
159
- value: function exportRefs(refIds, model) {
205
+ value: function exportRefs(refIds, model, usedTableNames, usedIndexNames) {
160
206
  var _this = this;
161
207
 
162
208
  var strArr = refIds.map(function (refId) {
209
+ var line = '';
163
210
  var ref = model.refs[refId];
164
- var refEndpointIndex = ref.endpointIds.findIndex(function (endpointId) {
211
+ var refOneIndex = ref.endpointIds.findIndex(function (endpointId) {
165
212
  return model.endpoints[endpointId].relation === '1';
166
213
  });
214
+ var refEndpointIndex = refOneIndex === -1 ? 0 : refOneIndex;
167
215
  var foreignEndpointId = ref.endpointIds[1 - refEndpointIndex];
168
216
  var refEndpointId = ref.endpointIds[refEndpointIndex];
169
217
  var foreignEndpoint = model.endpoints[foreignEndpointId];
@@ -180,26 +228,45 @@ var MySQLExporter = /*#__PURE__*/function () {
180
228
 
181
229
  var foreignEndpointFieldName = _this.buildFieldName(foreignEndpoint.fieldIds, model, 'mysql');
182
230
 
183
- var line = "ALTER TABLE ".concat((0, _utils.shouldPrintSchema)(foreignEndpointSchema, model) ? "`".concat(foreignEndpointSchema.name, "`.") : '', "`").concat(foreignEndpointTable.name, "` ADD ");
231
+ if (refOneIndex === -1) {
232
+ var firstTableFieldsMap = (0, _utils.buildJunctionFields1)(refEndpoint.fieldIds, model);
233
+ var secondTableFieldsMap = (0, _utils.buildJunctionFields2)(foreignEndpoint.fieldIds, model, firstTableFieldsMap);
234
+ var newTableName = (0, _utils.buildNewTableName)(refEndpointTable.name, foreignEndpointTable.name, usedTableNames);
235
+ line += _this.buildTableManyToMany(firstTableFieldsMap, secondTableFieldsMap, newTableName);
184
236
 
185
- if (ref.name) {
186
- line += "CONSTRAINT `".concat(ref.name, "` ");
187
- }
237
+ if (firstTableFieldsMap.size > 1) {
238
+ line += _this.buildIndexManytoMany(firstTableFieldsMap, newTableName, refEndpointTable.name, usedIndexNames);
239
+ }
188
240
 
189
- line += "FOREIGN KEY ".concat(foreignEndpointFieldName, " REFERENCES ").concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "`".concat(refEndpointSchema.name, "`.") : '', "`").concat(refEndpointTable.name, "` ").concat(refEndpointFieldName);
241
+ if (secondTableFieldsMap.size > 1) {
242
+ line += _this.buildIndexManytoMany(secondTableFieldsMap, newTableName, foreignEndpointTable.name, usedIndexNames);
243
+ }
190
244
 
191
- if (ref.onDelete) {
192
- line += " ON DELETE ".concat(ref.onDelete.toUpperCase());
193
- }
245
+ line += _this.buildForeignKeyManyToMany(firstTableFieldsMap, refEndpointFieldName, newTableName, refEndpointTable.name, refEndpointSchema, model);
246
+ line += _this.buildForeignKeyManyToMany(secondTableFieldsMap, foreignEndpointFieldName, newTableName, foreignEndpointTable.name, foreignEndpointSchema, model);
247
+ } else {
248
+ line = "ALTER TABLE ".concat((0, _utils.shouldPrintSchema)(foreignEndpointSchema, model) ? "`".concat(foreignEndpointSchema.name, "`.") : '', "`").concat(foreignEndpointTable.name, "` ADD ");
249
+
250
+ if (ref.name) {
251
+ line += "CONSTRAINT `".concat(ref.name, "` ");
252
+ }
194
253
 
195
- if (ref.onUpdate) {
196
- line += " ON UPDATE ".concat(ref.onUpdate.toUpperCase());
254
+ line += "FOREIGN KEY ".concat(foreignEndpointFieldName, " REFERENCES ").concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "`".concat(refEndpointSchema.name, "`.") : '', "`").concat(refEndpointTable.name, "` ").concat(refEndpointFieldName);
255
+
256
+ if (ref.onDelete) {
257
+ line += " ON DELETE ".concat(ref.onDelete.toUpperCase());
258
+ }
259
+
260
+ if (ref.onUpdate) {
261
+ line += " ON UPDATE ".concat(ref.onUpdate.toUpperCase());
262
+ }
263
+
264
+ line += ';\n';
197
265
  }
198
266
 
199
- line += ';\n';
200
267
  return line;
201
268
  });
202
- return strArr.length ? strArr.join('\n') : '';
269
+ return strArr;
203
270
  }
204
271
  }, {
205
272
  key: "exportIndexes",
@@ -241,7 +308,7 @@ var MySQLExporter = /*#__PURE__*/function () {
241
308
  line += ';\n';
242
309
  return line;
243
310
  });
244
- return indexArr.length ? indexArr.join('\n') : '';
311
+ return indexArr;
245
312
  }
246
313
  }, {
247
314
  key: "exportComments",
@@ -257,62 +324,74 @@ var MySQLExporter = /*#__PURE__*/function () {
257
324
  line += ';\n';
258
325
  return line;
259
326
  });
260
- return commentArr.length ? commentArr.join('\n') : '';
327
+ return commentArr;
261
328
  }
262
329
  }, {
263
330
  key: "export",
264
331
  value: function _export(model) {
265
- var res = '';
266
- var hasBlockAbove = false;
267
332
  var database = model.database['1'];
268
- var indexIds = [];
269
- var comments = [];
270
- database.schemaIds.forEach(function (schemaId) {
333
+ var usedTableNames = new Set(Object.values(model.tables).map(function (table) {
334
+ return table.name;
335
+ }));
336
+ var usedIndexNames = new Set(Object.values(model.indexes).map(function (index) {
337
+ return index.name;
338
+ }));
339
+ var statements = database.schemaIds.reduce(function (prevStatements, schemaId) {
271
340
  var schema = model.schemas[schemaId];
272
341
  var tableIds = schema.tableIds,
273
342
  refIds = schema.refIds;
274
343
 
275
344
  if ((0, _utils.shouldPrintSchema)(schema, model)) {
276
- if (hasBlockAbove) res += '\n';
277
- res += "CREATE DATABASE `".concat(schema.name, "`;\n");
278
- hasBlockAbove = true;
345
+ prevStatements.schemas.push("CREATE SCHEMA `".concat(schema.name, "`;\n"));
279
346
  }
280
347
 
281
348
  if (!_lodash["default"].isEmpty(tableIds)) {
282
- if (hasBlockAbove) res += '\n';
283
- res += MySQLExporter.exportTables(tableIds, model);
284
- hasBlockAbove = true;
285
- }
349
+ var _prevStatements$table;
286
350
 
287
- if (!_lodash["default"].isEmpty(refIds)) {
288
- if (hasBlockAbove) res += '\n';
289
- res += MySQLExporter.exportRefs(refIds, model);
290
- hasBlockAbove = true;
351
+ (_prevStatements$table = prevStatements.tables).push.apply(_prevStatements$table, _toConsumableArray(MySQLExporter.exportTables(tableIds, model)));
291
352
  }
292
353
 
293
- indexIds.push.apply(indexIds, _toConsumableArray(_lodash["default"].flatten(tableIds.map(function (tableId) {
354
+ var indexIds = _lodash["default"].flatten(tableIds.map(function (tableId) {
294
355
  return model.tables[tableId].indexIds;
295
- }))));
296
- comments.push.apply(comments, _toConsumableArray(_lodash["default"].flatten(tableIds.map(function (tableId) {
356
+ }));
357
+
358
+ if (!_lodash["default"].isEmpty(indexIds)) {
359
+ var _prevStatements$index;
360
+
361
+ (_prevStatements$index = prevStatements.indexes).push.apply(_prevStatements$index, _toConsumableArray(MySQLExporter.exportIndexes(indexIds, model)));
362
+ }
363
+
364
+ var commentNodes = _lodash["default"].flatten(tableIds.map(function (tableId) {
297
365
  var note = model.tables[tableId].note;
298
366
  return note ? [{
299
367
  type: 'table',
300
368
  tableId: tableId
301
369
  }] : [];
302
- }))));
303
- });
370
+ }));
304
371
 
305
- if (!_lodash["default"].isEmpty(indexIds)) {
306
- if (hasBlockAbove) res += '\n';
307
- res += MySQLExporter.exportIndexes(indexIds, model);
308
- hasBlockAbove = true;
309
- }
372
+ if (!_lodash["default"].isEmpty(commentNodes)) {
373
+ var _prevStatements$comme;
310
374
 
311
- if (!_lodash["default"].isEmpty(comments)) {
312
- if (hasBlockAbove) res += '\n';
313
- res += MySQLExporter.exportComments(comments, model);
314
- hasBlockAbove = true;
315
- }
375
+ (_prevStatements$comme = prevStatements.comments).push.apply(_prevStatements$comme, _toConsumableArray(MySQLExporter.exportComments(commentNodes, model)));
376
+ }
377
+
378
+ if (!_lodash["default"].isEmpty(refIds)) {
379
+ var _prevStatements$refs;
380
+
381
+ (_prevStatements$refs = prevStatements.refs).push.apply(_prevStatements$refs, _toConsumableArray(MySQLExporter.exportRefs(refIds, model, usedTableNames, usedIndexNames)));
382
+ }
383
+
384
+ return prevStatements;
385
+ }, {
386
+ schemas: [],
387
+ enums: [],
388
+ tables: [],
389
+ indexes: [],
390
+ comments: [],
391
+ refs: []
392
+ });
393
+
394
+ var res = _lodash["default"].concat(statements.schemas, statements.enums, statements.tables, statements.indexes, statements.comments, statements.refs).join('\n');
316
395
 
317
396
  return res;
318
397
  }
@@ -9,6 +9,8 @@ var _lodash = _interopRequireDefault(require("lodash"));
9
9
 
10
10
  var _utils = require("./utils");
11
11
 
12
+ var _config = require("../model_structure/config");
13
+
12
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13
15
 
14
16
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
@@ -50,7 +52,7 @@ var PostgresExporter = /*#__PURE__*/function () {
50
52
  var line = "CREATE TYPE ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(_enum.name, "\" AS ENUM (\n").concat(enumValueStr, "\n);\n");
51
53
  return line;
52
54
  });
53
- return enumArr.length ? enumArr.join('\n') : '';
55
+ return enumArr;
54
56
  }
55
57
  }, {
56
58
  key: "getFieldLines",
@@ -63,10 +65,15 @@ var PostgresExporter = /*#__PURE__*/function () {
63
65
  if (field.increment) {
64
66
  var typeSerial = field.type.type_name === 'bigint' ? 'BIGSERIAL' : 'SERIAL';
65
67
  line = "\"".concat(field.name, "\" ").concat(typeSerial);
66
- } else if ((0, _utils.hasWhiteSpace)(field.type.type_name)) {
67
- line = "\"".concat(field.name, "\" \"").concat(field.type.type_name, "\"");
68
68
  } else {
69
- line = "\"".concat(field.name, "\" ").concat(field.type.type_name);
69
+ var schemaName = '';
70
+
71
+ if (field.type.schemaName && field.type.schemaName !== _config.DEFAULT_SCHEMA_NAME) {
72
+ schemaName = (0, _utils.hasWhiteSpace)(field.type.schemaName) ? "\"".concat(field.type.schemaName, "\".") : "".concat(field.type.schemaName, ".");
73
+ }
74
+
75
+ var typeName = (0, _utils.hasWhiteSpace)(field.type.type_name) ? "\"".concat(field.type.type_name, "\"") : field.type.type_name;
76
+ line = "\"".concat(field.name, "\" ").concat(schemaName).concat(typeName);
70
77
  }
71
78
 
72
79
  if (field.unique) {
@@ -150,7 +157,7 @@ var PostgresExporter = /*#__PURE__*/function () {
150
157
  }).join(',\n'), "\n);\n");
151
158
  return tableStr;
152
159
  });
153
- return tableStrs.length ? tableStrs.join('\n') : '';
160
+ return tableStrs;
154
161
  }
155
162
  }, {
156
163
  key: "buildFieldName",
@@ -160,16 +167,64 @@ var PostgresExporter = /*#__PURE__*/function () {
160
167
  }).join(', ');
161
168
  return "(".concat(fieldNames, ")");
162
169
  }
170
+ }, {
171
+ key: "buildTableManyToMany",
172
+ value: function buildTableManyToMany(firstTableFieldsMap, secondTableFieldsMap, tableName) {
173
+ var line = "CREATE TABLE \"".concat(tableName, "\" (\n");
174
+
175
+ var key1s = _toConsumableArray(firstTableFieldsMap.keys()).join('", "');
176
+
177
+ var key2s = _toConsumableArray(secondTableFieldsMap.keys()).join('", "');
178
+
179
+ firstTableFieldsMap.forEach(function (fieldType, fieldName) {
180
+ line += " \"".concat(fieldName, "\" ").concat(fieldType, " NOT NULL,\n");
181
+ });
182
+ secondTableFieldsMap.forEach(function (fieldType, fieldName) {
183
+ line += " \"".concat(fieldName, "\" ").concat(fieldType, " NOT NULL,\n");
184
+ });
185
+ line += " PRIMARY KEY (\"".concat(key1s, "\", \"").concat(key2s, "\")\n");
186
+ line += ');\n\n';
187
+ return line;
188
+ }
189
+ }, {
190
+ key: "buildForeignKeyManyToMany",
191
+ value: function buildForeignKeyManyToMany(fieldsMap, foreignEndpointFields, refEndpointTableName, foreignEndpointTableName, schema, model) {
192
+ var refEndpointFields = _toConsumableArray(fieldsMap.keys()).join('", "');
193
+
194
+ var line = "ALTER TABLE \"".concat(refEndpointTableName, "\" ADD FOREIGN KEY (\"").concat(refEndpointFields, "\") REFERENCES ").concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(foreignEndpointTableName, "\" ").concat(foreignEndpointFields, ";\n\n");
195
+ return line;
196
+ }
197
+ }, {
198
+ key: "buildIndexManytoMany",
199
+ value: function buildIndexManytoMany(fieldsMap, newTableName, tableRefName, usedIndexNames) {
200
+ var newIndexName = "".concat(newTableName, "_").concat(tableRefName);
201
+ var count = 1;
202
+
203
+ while (usedIndexNames.has(newIndexName)) {
204
+ newIndexName = "".concat(newTableName, "_").concat(tableRefName, "(").concat(count, ")");
205
+ count += 1;
206
+ }
207
+
208
+ usedIndexNames.add(newIndexName);
209
+
210
+ var indexFields = _toConsumableArray(fieldsMap.keys()).join('", "');
211
+
212
+ var line = "CREATE INDEX \"idx_".concat(newIndexName, "\" ON \"").concat(newTableName, "\" (");
213
+ line += "\"".concat(indexFields, "\");\n\n");
214
+ return line;
215
+ }
163
216
  }, {
164
217
  key: "exportRefs",
165
- value: function exportRefs(refIds, model) {
218
+ value: function exportRefs(refIds, model, usedTableNames, usedIndexNames) {
166
219
  var _this = this;
167
220
 
168
221
  var strArr = refIds.map(function (refId) {
222
+ var line = '';
169
223
  var ref = model.refs[refId];
170
- var refEndpointIndex = ref.endpointIds.findIndex(function (endpointId) {
224
+ var refOneIndex = ref.endpointIds.findIndex(function (endpointId) {
171
225
  return model.endpoints[endpointId].relation === '1';
172
226
  });
227
+ var refEndpointIndex = refOneIndex === -1 ? 0 : refOneIndex;
173
228
  var foreignEndpointId = ref.endpointIds[1 - refEndpointIndex];
174
229
  var refEndpointId = ref.endpointIds[refEndpointIndex];
175
230
  var foreignEndpoint = model.endpoints[foreignEndpointId];
@@ -186,26 +241,46 @@ var PostgresExporter = /*#__PURE__*/function () {
186
241
 
187
242
  var foreignEndpointFieldName = _this.buildFieldName(foreignEndpoint.fieldIds, model, 'postgres');
188
243
 
189
- var line = "ALTER TABLE ".concat((0, _utils.shouldPrintSchema)(foreignEndpointSchema, model) ? "\"".concat(foreignEndpointSchema.name, "\".") : '', "\"").concat(foreignEndpointTable.name, "\" ADD ");
244
+ if (refOneIndex === -1) {
245
+ // many to many relationship
246
+ var firstTableFieldsMap = (0, _utils.buildJunctionFields1)(refEndpoint.fieldIds, model);
247
+ var secondTableFieldsMap = (0, _utils.buildJunctionFields2)(foreignEndpoint.fieldIds, model, firstTableFieldsMap);
248
+ var newTableName = (0, _utils.buildNewTableName)(refEndpointTable.name, foreignEndpointTable.name, usedTableNames);
249
+ line += _this.buildTableManyToMany(firstTableFieldsMap, secondTableFieldsMap, newTableName);
190
250
 
191
- if (ref.name) {
192
- line += "CONSTRAINT \"".concat(ref.name, "\" ");
193
- }
251
+ if (firstTableFieldsMap.size > 1) {
252
+ line += _this.buildIndexManytoMany(firstTableFieldsMap, newTableName, refEndpointTable.name, usedIndexNames);
253
+ }
194
254
 
195
- line += "FOREIGN KEY ".concat(foreignEndpointFieldName, " REFERENCES ").concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "\"".concat(refEndpointSchema.name, "\".") : '', "\"").concat(refEndpointTable.name, "\" ").concat(refEndpointFieldName);
255
+ if (secondTableFieldsMap.size > 1) {
256
+ line += _this.buildIndexManytoMany(secondTableFieldsMap, newTableName, foreignEndpointTable.name, usedIndexNames);
257
+ }
196
258
 
197
- if (ref.onDelete) {
198
- line += " ON DELETE ".concat(ref.onDelete.toUpperCase());
199
- }
259
+ line += _this.buildForeignKeyManyToMany(firstTableFieldsMap, refEndpointFieldName, newTableName, refEndpointTable.name, refEndpointSchema, model);
260
+ line += _this.buildForeignKeyManyToMany(secondTableFieldsMap, foreignEndpointFieldName, newTableName, foreignEndpointTable.name, foreignEndpointSchema, model);
261
+ } else {
262
+ line = "ALTER TABLE ".concat((0, _utils.shouldPrintSchema)(foreignEndpointSchema, model) ? "\"".concat(foreignEndpointSchema.name, "\".") : '', "\"").concat(foreignEndpointTable.name, "\" ADD ");
200
263
 
201
- if (ref.onUpdate) {
202
- line += " ON UPDATE ".concat(ref.onUpdate.toUpperCase());
264
+ if (ref.name) {
265
+ line += "CONSTRAINT \"".concat(ref.name, "\" ");
266
+ }
267
+
268
+ line += "FOREIGN KEY ".concat(foreignEndpointFieldName, " REFERENCES ").concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "\"".concat(refEndpointSchema.name, "\".") : '', "\"").concat(refEndpointTable.name, "\" ").concat(refEndpointFieldName);
269
+
270
+ if (ref.onDelete) {
271
+ line += " ON DELETE ".concat(ref.onDelete.toUpperCase());
272
+ }
273
+
274
+ if (ref.onUpdate) {
275
+ line += " ON UPDATE ".concat(ref.onUpdate.toUpperCase());
276
+ }
277
+
278
+ line += ';\n';
203
279
  }
204
280
 
205
- line += ';\n';
206
281
  return line;
207
282
  });
208
- return strArr.length ? strArr.join('\n') : '';
283
+ return strArr;
209
284
  }
210
285
  }, {
211
286
  key: "exportIndexes",
@@ -253,7 +328,7 @@ var PostgresExporter = /*#__PURE__*/function () {
253
328
  line += ';\n';
254
329
  return line;
255
330
  });
256
- return indexArr.length ? indexArr.join('\n') : '';
331
+ return indexArr;
257
332
  }
258
333
  }, {
259
334
  key: "exportComments",
@@ -284,50 +359,51 @@ var PostgresExporter = /*#__PURE__*/function () {
284
359
  line += ';\n';
285
360
  return line;
286
361
  });
287
- return commentArr.length ? commentArr.join('\n') : '';
362
+ return commentArr;
288
363
  }
289
364
  }, {
290
365
  key: "export",
291
366
  value: function _export(model) {
292
- var res = '';
293
- var hasBlockAbove = false;
294
367
  var database = model.database['1'];
295
- var indexIds = [];
296
- var comments = [];
297
- database.schemaIds.forEach(function (schemaId) {
368
+ var usedTableNames = new Set(Object.values(model.tables).map(function (table) {
369
+ return table.name;
370
+ }));
371
+ var usedIndexNames = new Set(Object.values(model.indexes).map(function (index) {
372
+ return index.name;
373
+ }));
374
+ var statements = database.schemaIds.reduce(function (prevStatements, schemaId) {
298
375
  var schema = model.schemas[schemaId];
299
376
  var tableIds = schema.tableIds,
300
377
  enumIds = schema.enumIds,
301
378
  refIds = schema.refIds;
302
379
 
303
380
  if ((0, _utils.shouldPrintSchema)(schema, model)) {
304
- if (hasBlockAbove) res += '\n';
305
- res += "CREATE SCHEMA \"".concat(schema.name, "\";\n");
306
- hasBlockAbove = true;
381
+ prevStatements.schemas.push("CREATE SCHEMA \"".concat(schema.name, "\";\n"));
307
382
  }
308
383
 
309
384
  if (!_lodash["default"].isEmpty(enumIds)) {
310
- if (hasBlockAbove) res += '\n';
311
- res += PostgresExporter.exportEnums(enumIds, model);
312
- hasBlockAbove = true;
385
+ var _prevStatements$enums;
386
+
387
+ (_prevStatements$enums = prevStatements.enums).push.apply(_prevStatements$enums, _toConsumableArray(PostgresExporter.exportEnums(enumIds, model)));
313
388
  }
314
389
 
315
390
  if (!_lodash["default"].isEmpty(tableIds)) {
316
- if (hasBlockAbove) res += '\n';
317
- res += PostgresExporter.exportTables(tableIds, model);
318
- hasBlockAbove = true;
319
- }
391
+ var _prevStatements$table;
320
392
 
321
- if (!_lodash["default"].isEmpty(refIds)) {
322
- if (hasBlockAbove) res += '\n';
323
- res += PostgresExporter.exportRefs(refIds, model);
324
- hasBlockAbove = true;
393
+ (_prevStatements$table = prevStatements.tables).push.apply(_prevStatements$table, _toConsumableArray(PostgresExporter.exportTables(tableIds, model)));
325
394
  }
326
395
 
327
- indexIds.push.apply(indexIds, _toConsumableArray(_lodash["default"].flatten(tableIds.map(function (tableId) {
396
+ var indexIds = _lodash["default"].flatten(tableIds.map(function (tableId) {
328
397
  return model.tables[tableId].indexIds;
329
- }))));
330
- comments.push.apply(comments, _toConsumableArray(_lodash["default"].flatten(tableIds.map(function (tableId) {
398
+ }));
399
+
400
+ if (!_lodash["default"].isEmpty(indexIds)) {
401
+ var _prevStatements$index;
402
+
403
+ (_prevStatements$index = prevStatements.indexes).push.apply(_prevStatements$index, _toConsumableArray(PostgresExporter.exportIndexes(indexIds, model)));
404
+ }
405
+
406
+ var commentNodes = _lodash["default"].flatten(tableIds.map(function (tableId) {
331
407
  var _model$tables$tableId = model.tables[tableId],
332
408
  fieldIds = _model$tables$tableId.fieldIds,
333
409
  note = _model$tables$tableId.note;
@@ -344,20 +420,31 @@ var PostgresExporter = /*#__PURE__*/function () {
344
420
  type: 'table',
345
421
  tableId: tableId
346
422
  }].concat(fieldObjects) : fieldObjects;
347
- }))));
348
- });
423
+ }));
349
424
 
350
- if (!_lodash["default"].isEmpty(indexIds)) {
351
- if (hasBlockAbove) res += '\n';
352
- res += PostgresExporter.exportIndexes(indexIds, model);
353
- hasBlockAbove = true;
354
- }
425
+ if (!_lodash["default"].isEmpty(commentNodes)) {
426
+ var _prevStatements$comme;
355
427
 
356
- if (!_lodash["default"].isEmpty(comments)) {
357
- if (hasBlockAbove) res += '\n';
358
- res += PostgresExporter.exportComments(comments, model);
359
- hasBlockAbove = true;
360
- }
428
+ (_prevStatements$comme = prevStatements.comments).push.apply(_prevStatements$comme, _toConsumableArray(PostgresExporter.exportComments(commentNodes, model)));
429
+ }
430
+
431
+ if (!_lodash["default"].isEmpty(refIds)) {
432
+ var _prevStatements$refs;
433
+
434
+ (_prevStatements$refs = prevStatements.refs).push.apply(_prevStatements$refs, _toConsumableArray(PostgresExporter.exportRefs(refIds, model, usedTableNames, usedIndexNames)));
435
+ }
436
+
437
+ return prevStatements;
438
+ }, {
439
+ schemas: [],
440
+ enums: [],
441
+ tables: [],
442
+ indexes: [],
443
+ comments: [],
444
+ refs: []
445
+ });
446
+
447
+ var res = _lodash["default"].concat(statements.schemas, statements.enums, statements.tables, statements.indexes, statements.comments, statements.refs).join('\n');
361
448
 
362
449
  return res;
363
450
  }