@dbml/core 6.1.0 → 6.2.0-alpha.0
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.
- package/README.md +2 -2
- package/lib/export/DbmlExporter.js +53 -1
- package/lib/export/MysqlExporter.js +47 -1
- package/lib/export/OracleExporter.js +52 -3
- package/lib/export/PostgresExporter.js +53 -1
- package/lib/export/SqlServerExporter.js +48 -1
- package/lib/index.js +103 -0
- package/lib/parse/ANTLR/ASTGeneration/mssql/MssqlASTGen.js +21 -7
- package/lib/parse/ANTLR/ASTGeneration/mysql/MySQLASTGen.js +5 -2
- package/lib/parse/ANTLR/ASTGeneration/oraclesql/OracleSQLASTGen.js +85 -4
- package/lib/parse/ANTLR/ASTGeneration/oraclesql/README.md +5 -5
- package/lib/parse/ANTLR/ASTGeneration/postgres/PostgresASTGen.js +10 -0
- package/lib/parse/ANTLR/ASTGeneration/snowflake/SnowflakeASTGen.js +90 -5
- package/lib/parse/ANTLR/parsers/mysql/MySqlLexerBase.js +1 -1
- package/package.json +3 -3
- package/types/export/index.d.ts +1 -0
- package/types/index.d.ts +30 -2
- package/types/model_structure/database.d.ts +9 -2
- package/types/model_structure/endpoint.d.ts +10 -0
- package/types/model_structure/stickyNote.d.ts +3 -1
package/README.md
CHANGED
|
@@ -160,13 +160,13 @@ For more detailed documentation on each SQL parser, see the individual parser RE
|
|
|
160
160
|
| Feature | PostgreSQL | MySQL | MSSQL | Oracle | Snowflake |
|
|
161
161
|
|---------|------------|-------|-------|--------|-----------|
|
|
162
162
|
| Basic `INSERT` ... VALUES | ✓ | ✓ | ✓ | ✓ | ✗ |
|
|
163
|
-
| Multi-row `INSERT` | ✓ | ✓ | ✓ |
|
|
163
|
+
| Multi-row `INSERT` | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
164
164
|
| `INSERT` ... SELECT | ✗ | ✗ | ✗ | ✗ | ✗ |
|
|
165
165
|
| `INSERT` ... with returned rows (`RETURNING`, `OUTPUT`) | ◐ | — | ◐ | ◐ | — |
|
|
166
166
|
| `INSERT` ... ON CONFLICT/DUPLICATE KEY | ◐ | ◐ | — | — | — |
|
|
167
167
|
|
|
168
168
|
**Notes:**
|
|
169
|
-
- **Oracle**:
|
|
169
|
+
- **Oracle**: Multi-row inserts use `INSERT ALL ... SELECT * FROM dual` syntax, which is fully supported.
|
|
170
170
|
|
|
171
171
|
---
|
|
172
172
|
|
|
@@ -227,7 +227,7 @@ var DbmlExporter = /*#__PURE__*/function () {
|
|
|
227
227
|
if ((0, _utils.shouldPrintSchema)(schema, model)) tableName = "\"".concat(schema.name, "\".\"").concat(table.name, "\"");
|
|
228
228
|
|
|
229
229
|
// Include alias if present
|
|
230
|
-
var aliasStr = table.alias ? " as ".concat((0, _parse.
|
|
230
|
+
var aliasStr = table.alias ? " as ".concat((0, _parse.addDoubleQuoteIfNeeded)(table.alias)) : '';
|
|
231
231
|
var fieldStr = tableContent.fieldContents.map(function (field) {
|
|
232
232
|
return " ".concat(field, "\n");
|
|
233
233
|
}).join('');
|
|
@@ -342,6 +342,57 @@ var DbmlExporter = /*#__PURE__*/function () {
|
|
|
342
342
|
return result ? "".concat(result, "\n").concat(stickyNote) : stickyNote;
|
|
343
343
|
}, '');
|
|
344
344
|
}
|
|
345
|
+
}, {
|
|
346
|
+
key: "exportRecords",
|
|
347
|
+
value: function exportRecords(model) {
|
|
348
|
+
var records = model.records;
|
|
349
|
+
if (!records || (0, _lodash.isEmpty)(records)) {
|
|
350
|
+
return '';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Group records by schemaName and tableName
|
|
354
|
+
var recordGroups = (0, _lodash.groupBy)(Object.values(records), function (record) {
|
|
355
|
+
return "".concat(record.schemaName || '', ".").concat(record.tableName);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Process each group
|
|
359
|
+
var recordStrs = Object.values(recordGroups).map(function (groupRecords) {
|
|
360
|
+
var _groupRecords$ = groupRecords[0],
|
|
361
|
+
schemaName = _groupRecords$.schemaName,
|
|
362
|
+
tableName = _groupRecords$.tableName;
|
|
363
|
+
|
|
364
|
+
// Build table reference
|
|
365
|
+
var tableRef = schemaName ? "".concat((0, _parse.addDoubleQuoteIfNeeded)(schemaName), ".").concat((0, _parse.addDoubleQuoteIfNeeded)(tableName)) : (0, _parse.addDoubleQuoteIfNeeded)(tableName);
|
|
366
|
+
|
|
367
|
+
// Collect all unique columns in order
|
|
368
|
+
var allColumns = _toConsumableArray(new Set(groupRecords.flatMap(function (r) {
|
|
369
|
+
return r.columns;
|
|
370
|
+
})));
|
|
371
|
+
var columnList = allColumns.map(_parse.addDoubleQuoteIfNeeded).join(', ');
|
|
372
|
+
|
|
373
|
+
// Merge all rows
|
|
374
|
+
var allRows = groupRecords.flatMap(function (record) {
|
|
375
|
+
var allColumnIndexes = allColumns.map(function (col) {
|
|
376
|
+
return record.columns.indexOf(col);
|
|
377
|
+
});
|
|
378
|
+
return record.values.map(function (row) {
|
|
379
|
+
return allColumnIndexes.map(function (colIdx) {
|
|
380
|
+
return colIdx === -1 ? {
|
|
381
|
+
value: null,
|
|
382
|
+
type: 'expression'
|
|
383
|
+
} : row[colIdx];
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// Build data rows
|
|
389
|
+
var rowStrs = allRows.map(function (row) {
|
|
390
|
+
return " ".concat(row.map(_parse.formatRecordValue).join(', '));
|
|
391
|
+
});
|
|
392
|
+
return "Records ".concat(tableRef, "(").concat(columnList, ") {\n").concat(rowStrs.join('\n'), "\n}\n");
|
|
393
|
+
});
|
|
394
|
+
return recordStrs.join('\n');
|
|
395
|
+
}
|
|
345
396
|
}, {
|
|
346
397
|
key: "export",
|
|
347
398
|
value: function _export(model) {
|
|
@@ -359,6 +410,7 @@ var DbmlExporter = /*#__PURE__*/function () {
|
|
|
359
410
|
if (!(0, _lodash.isEmpty)(refIds)) elementStrs.push(DbmlExporter.exportRefs(refIds, model));
|
|
360
411
|
});
|
|
361
412
|
if (!(0, _lodash.isEmpty)(model.notes)) elementStrs.push(DbmlExporter.exportStickyNotes(model));
|
|
413
|
+
if (!(0, _lodash.isEmpty)(model.records)) elementStrs.push(DbmlExporter.exportRecords(model));
|
|
362
414
|
|
|
363
415
|
// all elements already end with 1 '\n', so join('\n') to separate them with 1 blank line
|
|
364
416
|
return elementStrs.join('\n');
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports["default"] = void 0;
|
|
7
7
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
8
|
var _utils = require("./utils");
|
|
9
|
+
var _parse = require("@dbml/parse");
|
|
9
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
10
11
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
11
12
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
@@ -24,6 +25,46 @@ var MySQLExporter = /*#__PURE__*/function () {
|
|
|
24
25
|
_classCallCheck(this, MySQLExporter);
|
|
25
26
|
}
|
|
26
27
|
return _createClass(MySQLExporter, null, [{
|
|
28
|
+
key: "exportRecords",
|
|
29
|
+
value: function exportRecords(model) {
|
|
30
|
+
var records = Object.values(model.records || {});
|
|
31
|
+
if (_lodash["default"].isEmpty(records)) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
var insertStatements = records.map(function (record) {
|
|
35
|
+
var schemaName = record.schemaName,
|
|
36
|
+
tableName = record.tableName,
|
|
37
|
+
columns = record.columns,
|
|
38
|
+
values = record.values;
|
|
39
|
+
|
|
40
|
+
// Build the table reference with schema if present
|
|
41
|
+
var tableRef = schemaName ? "`".concat(schemaName, "`.`").concat(tableName, "`") : "`".concat(tableName, "`");
|
|
42
|
+
|
|
43
|
+
// Build the column list
|
|
44
|
+
var columnList = columns.length > 0 ? "(`".concat(columns.join('`, `'), "`)") : '';
|
|
45
|
+
|
|
46
|
+
// Value formatter for MySQL
|
|
47
|
+
var formatValue = function formatValue(val) {
|
|
48
|
+
if (val.value === null) return 'NULL';
|
|
49
|
+
if (val.type === 'expression') return val.value;
|
|
50
|
+
if ((0, _parse.isNumericType)(val.type)) return val.value;
|
|
51
|
+
if ((0, _parse.isBooleanType)(val.type)) return String(val.value).toUpperCase() === 'TRUE' ? 'TRUE' : 'FALSE';
|
|
52
|
+
if ((0, _parse.isStringType)(val.type) || (0, _parse.isBinaryType)(val.type) || (0, _parse.isDateTimeType)(val.type)) return "'".concat(val.value.replace(/'/g, "''").replace(/\\/g, '\\\\'), "'");
|
|
53
|
+
// Unknown type - use CAST
|
|
54
|
+
return "CAST('".concat(val.value.replace(/'/g, "''").replace(/\\/g, '\\\\'), "' AS ").concat(val.type, ")");
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Build the VALUES clause
|
|
58
|
+
var valueRows = values.map(function (row) {
|
|
59
|
+
var valueStrs = row.map(formatValue);
|
|
60
|
+
return "(".concat(valueStrs.join(', '), ")");
|
|
61
|
+
});
|
|
62
|
+
var valuesClause = valueRows.join(',\n ');
|
|
63
|
+
return "INSERT INTO ".concat(tableRef, " ").concat(columnList, "\nVALUES\n ").concat(valuesClause, ";");
|
|
64
|
+
});
|
|
65
|
+
return insertStatements;
|
|
66
|
+
}
|
|
67
|
+
}, {
|
|
27
68
|
key: "getFieldLines",
|
|
28
69
|
value: function getFieldLines(tableId, model) {
|
|
29
70
|
var table = model.tables[tableId];
|
|
@@ -337,7 +378,12 @@ var MySQLExporter = /*#__PURE__*/function () {
|
|
|
337
378
|
comments: [],
|
|
338
379
|
refs: []
|
|
339
380
|
});
|
|
340
|
-
|
|
381
|
+
|
|
382
|
+
// Export INSERT statements
|
|
383
|
+
// Note: MySQL does not support DEFERRED constraints, so foreign key checks are disabled
|
|
384
|
+
var insertStatements = MySQLExporter.exportRecords(model);
|
|
385
|
+
var recordsSection = !_lodash["default"].isEmpty(insertStatements) ? ['-- Disable foreign key checks for INSERT', 'SET FOREIGN_KEY_CHECKS = 0;', ''].concat(_toConsumableArray(insertStatements), ['', '-- Re-enable foreign key checks', 'SET FOREIGN_KEY_CHECKS = 1;']) : [];
|
|
386
|
+
var res = _lodash["default"].concat(statements.schemas, statements.enums, statements.tables, statements.indexes, statements.comments, statements.refs, recordsSection).join('\n');
|
|
341
387
|
return res;
|
|
342
388
|
}
|
|
343
389
|
}]);
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports["default"] = void 0;
|
|
7
7
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
8
|
var _utils = require("./utils");
|
|
9
|
+
var _parse = require("@dbml/parse");
|
|
9
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
10
11
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
11
12
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
@@ -27,6 +28,50 @@ var OracleExporter = /*#__PURE__*/function () {
|
|
|
27
28
|
_classCallCheck(this, OracleExporter);
|
|
28
29
|
}
|
|
29
30
|
return _createClass(OracleExporter, null, [{
|
|
31
|
+
key: "exportRecords",
|
|
32
|
+
value: function exportRecords(model) {
|
|
33
|
+
var records = Object.values(model.records || {});
|
|
34
|
+
if (_lodash["default"].isEmpty(records)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
var insertStatements = records.map(function (record) {
|
|
38
|
+
var schemaName = record.schemaName,
|
|
39
|
+
tableName = record.tableName,
|
|
40
|
+
columns = record.columns,
|
|
41
|
+
values = record.values;
|
|
42
|
+
|
|
43
|
+
// Build the table reference with schema if present
|
|
44
|
+
var tableRef = schemaName ? "\"".concat(schemaName, "\".\"").concat(tableName, "\"") : "\"".concat(tableName, "\"");
|
|
45
|
+
|
|
46
|
+
// Build the column list
|
|
47
|
+
var columnList = columns.length > 0 ? "(\"".concat(columns.join('", "'), "\")") : '';
|
|
48
|
+
var formatValue = function formatValue(val) {
|
|
49
|
+
if (val.value === null) return 'NULL';
|
|
50
|
+
if (val.type === 'expression') return val.value;
|
|
51
|
+
if ((0, _parse.isNumericType)(val.type)) return val.value;
|
|
52
|
+
if ((0, _parse.isBooleanType)(val.type)) return String(val.value).toUpperCase() === 'TRUE' ? '1' : '0';
|
|
53
|
+
if ((0, _parse.isStringType)(val.type) || (0, _parse.isDateTimeType)(val.type)) return "'".concat(val.value.replace(/'/g, "''"), "'");
|
|
54
|
+
if ((0, _parse.isBinaryType)(val.type)) return "HEXTORAW('".concat(val.value, "')");
|
|
55
|
+
// Unknown type - use CAST
|
|
56
|
+
return "CAST('".concat(val.value.replace(/'/g, "''"), "' AS ").concat(val.type, ")");
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Build the INSERT ALL statement for multiple rows
|
|
60
|
+
if (values.length > 1) {
|
|
61
|
+
var intoStatements = values.map(function (row) {
|
|
62
|
+
var valueStrs = row.map(formatValue);
|
|
63
|
+
return " INTO ".concat(tableRef, " ").concat(columnList, " VALUES (").concat(valueStrs.join(', '), ")");
|
|
64
|
+
});
|
|
65
|
+
return "INSERT ALL\n".concat(intoStatements.join('\n'), "\nSELECT * FROM dual;");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Single row INSERT
|
|
69
|
+
var valueStrs = values[0].map(formatValue);
|
|
70
|
+
return "INSERT INTO ".concat(tableRef, " ").concat(columnList, "\nVALUES (").concat(valueStrs.join(', '), ");");
|
|
71
|
+
});
|
|
72
|
+
return insertStatements;
|
|
73
|
+
}
|
|
74
|
+
}, {
|
|
30
75
|
key: "buildSchemaToTableNameSetMap",
|
|
31
76
|
value: function buildSchemaToTableNameSetMap(model) {
|
|
32
77
|
var schemaToTableNameSetMap = new Map();
|
|
@@ -225,7 +270,7 @@ var OracleExporter = /*#__PURE__*/function () {
|
|
|
225
270
|
key: "buildForeignKeyManyToMany",
|
|
226
271
|
value: function buildForeignKeyManyToMany(foreignEndpointTableName, foreignEndpointFields, refEndpointTableName, refEndpointFieldsString) {
|
|
227
272
|
var foreignEndpointFieldsString = _toConsumableArray(foreignEndpointFields.keys()).join('`, `');
|
|
228
|
-
var line = "ALTER TABLE ".concat(foreignEndpointTableName, " ADD FOREIGN KEY (\"").concat(foreignEndpointFieldsString, "\") REFERENCES ").concat(refEndpointTableName, " ").concat(refEndpointFieldsString, ";\n");
|
|
273
|
+
var line = "ALTER TABLE ".concat(foreignEndpointTableName, " ADD FOREIGN KEY (\"").concat(foreignEndpointFieldsString, "\") REFERENCES ").concat(refEndpointTableName, " ").concat(refEndpointFieldsString, " DEFERRABLE INITIALLY IMMEDIATE;\n");
|
|
229
274
|
return line;
|
|
230
275
|
}
|
|
231
276
|
}, {
|
|
@@ -269,7 +314,7 @@ var OracleExporter = /*#__PURE__*/function () {
|
|
|
269
314
|
if (ref.onDelete) {
|
|
270
315
|
line += " ON DELETE ".concat(ref.onDelete.toUpperCase());
|
|
271
316
|
}
|
|
272
|
-
line += ';\n';
|
|
317
|
+
line += ' DEFERRABLE INITIALLY IMMEDIATE;\n';
|
|
273
318
|
result.refs.push(line);
|
|
274
319
|
return;
|
|
275
320
|
}
|
|
@@ -482,7 +527,11 @@ var OracleExporter = /*#__PURE__*/function () {
|
|
|
482
527
|
referenceGrants: [],
|
|
483
528
|
refs: []
|
|
484
529
|
});
|
|
485
|
-
|
|
530
|
+
|
|
531
|
+
// Export INSERT statements with constraint checking disabled
|
|
532
|
+
var insertStatements = this.exportRecords(model);
|
|
533
|
+
var recordsSection = !_lodash["default"].isEmpty(insertStatements) ? ['-- Disable constraint checking for INSERT', 'SET CONSTRAINTS ALL DEFERRED;', ''].concat(_toConsumableArray(insertStatements), ['', 'COMMIT;']) : [];
|
|
534
|
+
var res = _lodash["default"].concat(statements.schemas, statements.tables, statements.indexes, statements.comments, statements.referenceGrants, statements.refs, recordsSection).join('\n');
|
|
486
535
|
return res;
|
|
487
536
|
}
|
|
488
537
|
}]);
|
|
@@ -7,6 +7,7 @@ exports["default"] = void 0;
|
|
|
7
7
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
8
|
var _utils = require("./utils");
|
|
9
9
|
var _utils2 = require("../model_structure/utils");
|
|
10
|
+
var _parse = require("@dbml/parse");
|
|
10
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
11
12
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
12
13
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
@@ -66,6 +67,53 @@ var PostgresExporter = /*#__PURE__*/function () {
|
|
|
66
67
|
_classCallCheck(this, PostgresExporter);
|
|
67
68
|
}
|
|
68
69
|
return _createClass(PostgresExporter, null, [{
|
|
70
|
+
key: "exportRecords",
|
|
71
|
+
value: function exportRecords(model) {
|
|
72
|
+
var records = Object.values(model.records || {});
|
|
73
|
+
if (_lodash["default"].isEmpty(records)) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
var insertStatements = records.map(function (record) {
|
|
77
|
+
var schemaName = record.schemaName,
|
|
78
|
+
tableName = record.tableName,
|
|
79
|
+
columns = record.columns,
|
|
80
|
+
values = record.values;
|
|
81
|
+
|
|
82
|
+
// Skip if no values
|
|
83
|
+
if (!values || values.length === 0) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Build the table reference with schema if present
|
|
88
|
+
var tableRef = schemaName ? "\"".concat(schemaName, "\".\"").concat(tableName, "\"") : "\"".concat(tableName, "\"");
|
|
89
|
+
|
|
90
|
+
// Build the column list
|
|
91
|
+
var columnList = columns.length > 0 ? "(".concat(columns.map(function (col) {
|
|
92
|
+
return "\"".concat(col, "\"");
|
|
93
|
+
}).join(', '), ")") : '';
|
|
94
|
+
|
|
95
|
+
// Value formatter for PostgreSQL
|
|
96
|
+
var formatValue = function formatValue(val) {
|
|
97
|
+
if (val.value === null) return 'NULL';
|
|
98
|
+
if (val.type === 'expression') return val.value;
|
|
99
|
+
if ((0, _parse.isNumericType)(val.type)) return val.value;
|
|
100
|
+
if ((0, _parse.isBooleanType)(val.type)) return String(val.value).toUpperCase() === 'TRUE' ? 'TRUE' : 'FALSE';
|
|
101
|
+
if ((0, _parse.isStringType)(val.type) || (0, _parse.isDateTimeType)(val.type) || (0, _parse.isBinaryType)(val.type)) return "'".concat(String(val.value).replace(/'/g, "''"), "'");
|
|
102
|
+
// Unknown type - use CAST
|
|
103
|
+
return "CAST('".concat(String(val.value).replace(/'/g, "''"), "' AS ").concat(val.type, ")");
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Build the VALUES clause
|
|
107
|
+
var valueRows = values.map(function (row) {
|
|
108
|
+
var valueStrs = row.map(formatValue);
|
|
109
|
+
return "(".concat(valueStrs.join(', '), ")");
|
|
110
|
+
});
|
|
111
|
+
var valuesClause = valueRows.join(',\n ');
|
|
112
|
+
return "INSERT INTO ".concat(tableRef, " ").concat(columnList, "\nVALUES\n ").concat(valuesClause, ";");
|
|
113
|
+
}).filter(Boolean);
|
|
114
|
+
return insertStatements;
|
|
115
|
+
}
|
|
116
|
+
}, {
|
|
69
117
|
key: "exportEnums",
|
|
70
118
|
value: function exportEnums(enumIds, model) {
|
|
71
119
|
return enumIds.map(function (enumId) {
|
|
@@ -451,7 +499,11 @@ var PostgresExporter = /*#__PURE__*/function () {
|
|
|
451
499
|
}
|
|
452
500
|
return prevStatements;
|
|
453
501
|
}, schemaEnumStatements);
|
|
454
|
-
|
|
502
|
+
|
|
503
|
+
// Export INSERT statements with constraint checking disabled
|
|
504
|
+
var insertStatements = PostgresExporter.exportRecords(model);
|
|
505
|
+
var recordsSection = !_lodash["default"].isEmpty(insertStatements) ? ['-- Disable constraint checking for INSERT', 'BEGIN;', 'SET session_replication_role = replica;', ''].concat(_toConsumableArray(insertStatements), ['', 'SET session_replication_role = DEFAULT;', 'COMMIT;']) : [];
|
|
506
|
+
var res = _lodash["default"].concat(statements.schemas, statements.enums, statements.tables, statements.indexes, statements.comments, statements.refs, recordsSection).join('\n');
|
|
455
507
|
return res;
|
|
456
508
|
}
|
|
457
509
|
}]);
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports["default"] = void 0;
|
|
7
7
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
8
|
var _utils = require("./utils");
|
|
9
|
+
var _parse = require("@dbml/parse");
|
|
9
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
10
11
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
11
12
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
@@ -24,6 +25,47 @@ var SqlServerExporter = /*#__PURE__*/function () {
|
|
|
24
25
|
_classCallCheck(this, SqlServerExporter);
|
|
25
26
|
}
|
|
26
27
|
return _createClass(SqlServerExporter, null, [{
|
|
28
|
+
key: "exportRecords",
|
|
29
|
+
value: function exportRecords(model) {
|
|
30
|
+
var records = Object.values(model.records || {});
|
|
31
|
+
if (_lodash["default"].isEmpty(records)) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
var insertStatements = records.map(function (record) {
|
|
35
|
+
var schemaName = record.schemaName,
|
|
36
|
+
tableName = record.tableName,
|
|
37
|
+
columns = record.columns,
|
|
38
|
+
values = record.values;
|
|
39
|
+
|
|
40
|
+
// Build the table reference with schema if present
|
|
41
|
+
var tableRef = schemaName ? "[".concat(schemaName, "].[").concat(tableName, "]") : "[".concat(tableName, "]");
|
|
42
|
+
|
|
43
|
+
// Build the column list
|
|
44
|
+
var columnList = columns.length > 0 ? "([".concat(columns.join('], ['), "])") : '';
|
|
45
|
+
|
|
46
|
+
// Value formatter for SQL Server
|
|
47
|
+
var formatValue = function formatValue(val) {
|
|
48
|
+
if (val.value === null) return 'NULL';
|
|
49
|
+
if (val.type === 'expression') return val.value;
|
|
50
|
+
if ((0, _parse.isNumericType)(val.type)) return val.value;
|
|
51
|
+
if ((0, _parse.isBooleanType)(val.type)) return String(val.value).toUpperCase() === 'TRUE' ? '1' : '0';
|
|
52
|
+
if ((0, _parse.isStringType)(val.type) || (0, _parse.isDateTimeType)(val.type)) return "'".concat(val.value.replace(/'/g, "''"), "'");
|
|
53
|
+
if ((0, _parse.isBinaryType)(val.type)) return "0x".concat(val.value); // SQL Server binary as hex
|
|
54
|
+
// Unknown type - use CAST
|
|
55
|
+
return "CAST('".concat(val.value.replace(/'/g, "''"), "' AS ").concat(val.type, ")");
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Build the VALUES clause
|
|
59
|
+
var valueRows = values.map(function (row) {
|
|
60
|
+
var valueStrs = row.map(formatValue);
|
|
61
|
+
return "(".concat(valueStrs.join(', '), ")");
|
|
62
|
+
});
|
|
63
|
+
var valuesClause = valueRows.join(',\n ');
|
|
64
|
+
return "INSERT INTO ".concat(tableRef, " ").concat(columnList, "\nVALUES\n ").concat(valuesClause, ";\nGO");
|
|
65
|
+
});
|
|
66
|
+
return insertStatements;
|
|
67
|
+
}
|
|
68
|
+
}, {
|
|
27
69
|
key: "getFieldLines",
|
|
28
70
|
value: function getFieldLines(tableId, model) {
|
|
29
71
|
var table = model.tables[tableId];
|
|
@@ -364,7 +406,12 @@ var SqlServerExporter = /*#__PURE__*/function () {
|
|
|
364
406
|
comments: [],
|
|
365
407
|
refs: []
|
|
366
408
|
});
|
|
367
|
-
|
|
409
|
+
|
|
410
|
+
// Export INSERT statements
|
|
411
|
+
// Note: SQL Server does not support DEFERRED constraints, so constraint checks are disabled
|
|
412
|
+
var insertStatements = SqlServerExporter.exportRecords(model);
|
|
413
|
+
var recordsSection = !_lodash["default"].isEmpty(insertStatements) ? ['-- Disable constraint checks for INSERT', 'EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";', 'GO', ''].concat(_toConsumableArray(insertStatements), ['', '-- Re-enable constraint checks', 'EXEC sp_MSforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all";', 'GO']) : [];
|
|
414
|
+
var res = _lodash["default"].concat(statements.schemas, statements.enums, statements.tables, statements.indexes, statements.comments, statements.refs, recordsSection).join('\n');
|
|
368
415
|
return res;
|
|
369
416
|
}
|
|
370
417
|
}]);
|
package/lib/index.js
CHANGED
|
@@ -21,30 +21,132 @@ Object.defineProperty(exports, "Parser", {
|
|
|
21
21
|
return _Parser["default"];
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
+
Object.defineProperty(exports, "SqlDialect", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function get() {
|
|
27
|
+
return _parse.SqlDialect;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
24
30
|
Object.defineProperty(exports, "VERSION", {
|
|
25
31
|
enumerable: true,
|
|
26
32
|
get: function get() {
|
|
27
33
|
return _version.VERSION;
|
|
28
34
|
}
|
|
29
35
|
});
|
|
36
|
+
Object.defineProperty(exports, "addDoubleQuoteIfNeeded", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function get() {
|
|
39
|
+
return _parse.addDoubleQuoteIfNeeded;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
30
42
|
Object.defineProperty(exports, "exporter", {
|
|
31
43
|
enumerable: true,
|
|
32
44
|
get: function get() {
|
|
33
45
|
return _export["default"];
|
|
34
46
|
}
|
|
35
47
|
});
|
|
48
|
+
Object.defineProperty(exports, "formatRecordValue", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function get() {
|
|
51
|
+
return _parse.formatRecordValue;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
36
54
|
Object.defineProperty(exports, "importer", {
|
|
37
55
|
enumerable: true,
|
|
38
56
|
get: function get() {
|
|
39
57
|
return _import["default"];
|
|
40
58
|
}
|
|
41
59
|
});
|
|
60
|
+
Object.defineProperty(exports, "isBinaryType", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function get() {
|
|
63
|
+
return _parse.isBinaryType;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, "isBooleanType", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function get() {
|
|
69
|
+
return _parse.isBooleanType;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "isDateTimeType", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function get() {
|
|
75
|
+
return _parse.isDateTimeType;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "isFloatType", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function get() {
|
|
81
|
+
return _parse.isFloatType;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(exports, "isIntegerType", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function get() {
|
|
87
|
+
return _parse.isIntegerType;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
Object.defineProperty(exports, "isNumericType", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function get() {
|
|
93
|
+
return _parse.isNumericType;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
Object.defineProperty(exports, "isSerialType", {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
get: function get() {
|
|
99
|
+
return _parse.isSerialType;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
Object.defineProperty(exports, "isStringType", {
|
|
103
|
+
enumerable: true,
|
|
104
|
+
get: function get() {
|
|
105
|
+
return _parse.isStringType;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
42
108
|
Object.defineProperty(exports, "renameTable", {
|
|
43
109
|
enumerable: true,
|
|
44
110
|
get: function get() {
|
|
45
111
|
return _transform.renameTable;
|
|
46
112
|
}
|
|
47
113
|
});
|
|
114
|
+
Object.defineProperty(exports, "tryExtractBoolean", {
|
|
115
|
+
enumerable: true,
|
|
116
|
+
get: function get() {
|
|
117
|
+
return _parse.tryExtractBoolean;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
Object.defineProperty(exports, "tryExtractDateTime", {
|
|
121
|
+
enumerable: true,
|
|
122
|
+
get: function get() {
|
|
123
|
+
return _parse.tryExtractDateTime;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
Object.defineProperty(exports, "tryExtractEnum", {
|
|
127
|
+
enumerable: true,
|
|
128
|
+
get: function get() {
|
|
129
|
+
return _parse.tryExtractEnum;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
Object.defineProperty(exports, "tryExtractInteger", {
|
|
133
|
+
enumerable: true,
|
|
134
|
+
get: function get() {
|
|
135
|
+
return _parse.tryExtractInteger;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
Object.defineProperty(exports, "tryExtractNumeric", {
|
|
139
|
+
enumerable: true,
|
|
140
|
+
get: function get() {
|
|
141
|
+
return _parse.tryExtractNumeric;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
Object.defineProperty(exports, "tryExtractString", {
|
|
145
|
+
enumerable: true,
|
|
146
|
+
get: function get() {
|
|
147
|
+
return _parse.tryExtractString;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
48
150
|
var _ModelExporter = _interopRequireDefault(require("./export/ModelExporter"));
|
|
49
151
|
var _Parser = _interopRequireDefault(require("./parse/Parser"));
|
|
50
152
|
var _error = require("./parse/error");
|
|
@@ -52,4 +154,5 @@ var _import = _interopRequireDefault(require("./import"));
|
|
|
52
154
|
var _export = _interopRequireDefault(require("./export"));
|
|
53
155
|
var _transform = require("./transform");
|
|
54
156
|
var _version = require("./utils/version");
|
|
157
|
+
var _parse = require("@dbml/parse");
|
|
55
158
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
@@ -37,6 +37,7 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
37
37
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
38
38
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
39
39
|
var ADD_DESCRIPTION_FUNCTION_NAME = 'sp_addextendedproperty';
|
|
40
|
+
var DEFAULT_SCHEMA = 'dbo';
|
|
40
41
|
var getSchemaAndTableName = function getSchemaAndTableName(names) {
|
|
41
42
|
var tableName = (0, _lodash.last)(names);
|
|
42
43
|
var schemaName = names.length > 1 ? (0, _lodash.nth)(names, -2) : undefined;
|
|
@@ -138,13 +139,23 @@ var MssqlASTGen = exports["default"] = /*#__PURE__*/function (_TSqlParserVisitor
|
|
|
138
139
|
};
|
|
139
140
|
return _this;
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
-
// tsql_file
|
|
143
|
-
// : batch* EOF
|
|
144
|
-
// | execute_body_batch go_statement* EOF
|
|
145
|
-
// ;
|
|
146
142
|
_inherits(MssqlASTGen, _TSqlParserVisitor);
|
|
147
143
|
return _createClass(MssqlASTGen, [{
|
|
144
|
+
key: "findTable",
|
|
145
|
+
value: function findTable(schemaName, tableName) {
|
|
146
|
+
var realSchemaName = schemaName || DEFAULT_SCHEMA;
|
|
147
|
+
var table = this.data.tables.find(function (t) {
|
|
148
|
+
var targetSchemaName = t.schemaName || DEFAULT_SCHEMA;
|
|
149
|
+
return targetSchemaName === realSchemaName && t.name === tableName;
|
|
150
|
+
});
|
|
151
|
+
return table;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// tsql_file
|
|
155
|
+
// : batch* EOF
|
|
156
|
+
// | execute_body_batch go_statement* EOF
|
|
157
|
+
// ;
|
|
158
|
+
}, {
|
|
148
159
|
key: "visitTsql_file",
|
|
149
160
|
value: function visitTsql_file(ctx) {
|
|
150
161
|
var _this2 = this;
|
|
@@ -219,6 +230,7 @@ var MssqlASTGen = exports["default"] = /*#__PURE__*/function (_TSqlParserVisitor
|
|
|
219
230
|
}, {
|
|
220
231
|
key: "visitInsert_statement",
|
|
221
232
|
value: function visitInsert_statement(ctx) {
|
|
233
|
+
var _this$findTable;
|
|
222
234
|
// [ 'users' ]
|
|
223
235
|
// [ 'test', 'users' ]
|
|
224
236
|
// [ 'db', 'test', 'users' ]
|
|
@@ -228,7 +240,9 @@ var MssqlASTGen = exports["default"] = /*#__PURE__*/function (_TSqlParserVisitor
|
|
|
228
240
|
var names = ctx.ddl_object().accept(this);
|
|
229
241
|
var tableName = (0, _lodash.last)(names);
|
|
230
242
|
var schemaName = names.length > 1 ? (0, _lodash.nth)(names, -2) : undefined;
|
|
231
|
-
var columns = ctx.insert_column_name_list() ? ctx.insert_column_name_list().accept(this) :
|
|
243
|
+
var columns = ctx.insert_column_name_list() ? ctx.insert_column_name_list().accept(this) : ((_this$findTable = this.findTable(schemaName, tableName)) === null || _this$findTable === void 0 ? void 0 : _this$findTable.fields.map(function (field) {
|
|
244
|
+
return field.name;
|
|
245
|
+
})) || [];
|
|
232
246
|
var values = ctx.insert_statement_value().accept(this);
|
|
233
247
|
var record = new _AST.TableRecord({
|
|
234
248
|
tableName: tableName,
|
|
@@ -1335,7 +1349,7 @@ var MssqlASTGen = exports["default"] = /*#__PURE__*/function (_TSqlParserVisitor
|
|
|
1335
1349
|
// https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver16#----level0type
|
|
1336
1350
|
var level0Type = argsObj.level0type.toLowerCase();
|
|
1337
1351
|
if (!level0Type.includes('schema')) return;
|
|
1338
|
-
var schemaName = argsObj.level0name !==
|
|
1352
|
+
var schemaName = argsObj.level0name !== DEFAULT_SCHEMA ? argsObj.level0name : undefined;
|
|
1339
1353
|
var level1Type = argsObj.level1type.toLowerCase();
|
|
1340
1354
|
var tableName = level1Type.includes('table') ? argsObj.level1name : null;
|
|
1341
1355
|
var table = this.data.tables.find(function (t) {
|
|
@@ -1226,12 +1226,15 @@ var MySQLASTGen = exports["default"] = /*#__PURE__*/function (_MySQLParserVisito
|
|
|
1226
1226
|
}, {
|
|
1227
1227
|
key: "visitInsertStatement",
|
|
1228
1228
|
value: function visitInsertStatement(ctx) {
|
|
1229
|
+
var _this$findTable;
|
|
1229
1230
|
var names = ctx.tableName().accept(this);
|
|
1230
1231
|
var tableName = (0, _lodash.last)(names);
|
|
1231
1232
|
var schemaName = names.length > 1 ? names[names.length - 2] : undefined;
|
|
1232
1233
|
|
|
1233
|
-
//
|
|
1234
|
-
var columns = ctx.fullColumnNameList() ? ctx.fullColumnNameList().accept(this) :
|
|
1234
|
+
// Get explicit columns if specified, otherwise lookup table definition
|
|
1235
|
+
var columns = ctx.fullColumnNameList() ? ctx.fullColumnNameList().accept(this) : ((_this$findTable = this.findTable(schemaName, tableName)) === null || _this$findTable === void 0 ? void 0 : _this$findTable.fields.map(function (field) {
|
|
1236
|
+
return field.name;
|
|
1237
|
+
})) || [];
|
|
1235
1238
|
var values = ctx.insertStatementValue().accept(this);
|
|
1236
1239
|
var record = new _AST.TableRecord({
|
|
1237
1240
|
schemaName: schemaName,
|
|
@@ -989,13 +989,15 @@ var OracleSqlASTGen = exports["default"] = /*#__PURE__*/function (_OracleSqlPars
|
|
|
989
989
|
}
|
|
990
990
|
|
|
991
991
|
// insert_statement
|
|
992
|
-
// : INSERT (single_table_insert |
|
|
992
|
+
// : INSERT (single_table_insert | multi_table_insert)
|
|
993
993
|
// ;
|
|
994
994
|
}, {
|
|
995
995
|
key: "visitInsert_statement",
|
|
996
996
|
value: function visitInsert_statement(ctx) {
|
|
997
997
|
if (ctx.single_table_insert()) {
|
|
998
998
|
ctx.single_table_insert().accept(this);
|
|
999
|
+
} else if (ctx.multi_table_insert()) {
|
|
1000
|
+
ctx.multi_table_insert().accept(this);
|
|
999
1001
|
}
|
|
1000
1002
|
}
|
|
1001
1003
|
|
|
@@ -1022,18 +1024,97 @@ var OracleSqlASTGen = exports["default"] = /*#__PURE__*/function (_OracleSqlPars
|
|
|
1022
1024
|
}
|
|
1023
1025
|
}
|
|
1024
1026
|
|
|
1027
|
+
// multi_table_insert
|
|
1028
|
+
// : (ALL multi_table_element+ | conditional_insert_clause) select_statement
|
|
1029
|
+
// ;
|
|
1030
|
+
}, {
|
|
1031
|
+
key: "visitMulti_table_insert",
|
|
1032
|
+
value: function visitMulti_table_insert(ctx) {
|
|
1033
|
+
var _this14 = this;
|
|
1034
|
+
if (!ctx.multi_table_element()) {
|
|
1035
|
+
// conditional_insert_clause is not supported yet
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// Collect all insert elements from INSERT ALL statement
|
|
1040
|
+
var elements = ctx.multi_table_element().map(function (element) {
|
|
1041
|
+
return element.accept(_this14);
|
|
1042
|
+
}).filter(Boolean);
|
|
1043
|
+
|
|
1044
|
+
// Group elements by table, schema, and columns to combine multiple rows into single records
|
|
1045
|
+
var recordsMap = new Map();
|
|
1046
|
+
elements.forEach(function (element) {
|
|
1047
|
+
var tableName = element.tableName,
|
|
1048
|
+
schemaName = element.schemaName,
|
|
1049
|
+
columns = element.columns,
|
|
1050
|
+
values = element.values;
|
|
1051
|
+
var key = "".concat(schemaName || '', ".").concat(tableName, ".").concat(columns.join(','));
|
|
1052
|
+
if (recordsMap.has(key)) {
|
|
1053
|
+
var _recordsMap$get$value;
|
|
1054
|
+
// Same table and columns - append values to existing record
|
|
1055
|
+
(_recordsMap$get$value = recordsMap.get(key).values).push.apply(_recordsMap$get$value, _toConsumableArray(values));
|
|
1056
|
+
} else {
|
|
1057
|
+
// New combination - create new record entry
|
|
1058
|
+
recordsMap.set(key, {
|
|
1059
|
+
tableName: tableName,
|
|
1060
|
+
schemaName: schemaName,
|
|
1061
|
+
columns: columns,
|
|
1062
|
+
values: values
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
// Create TableRecord objects for each unique table/column combination
|
|
1068
|
+
recordsMap.forEach(function (recordData) {
|
|
1069
|
+
var record = new _AST.TableRecord({
|
|
1070
|
+
schemaName: recordData.schemaName,
|
|
1071
|
+
tableName: recordData.tableName,
|
|
1072
|
+
columns: recordData.columns,
|
|
1073
|
+
values: recordData.values
|
|
1074
|
+
});
|
|
1075
|
+
_this14.data.records.push(record);
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// multi_table_element
|
|
1080
|
+
// : insert_into_clause values_clause? error_logging_clause?
|
|
1081
|
+
// ;
|
|
1082
|
+
}, {
|
|
1083
|
+
key: "visitMulti_table_element",
|
|
1084
|
+
value: function visitMulti_table_element(ctx) {
|
|
1085
|
+
var _ctx$values_clause;
|
|
1086
|
+
var intoClause = ctx.insert_into_clause().accept(this);
|
|
1087
|
+
var valuesClause = (_ctx$values_clause = ctx.values_clause()) === null || _ctx$values_clause === void 0 ? void 0 : _ctx$values_clause.accept(this);
|
|
1088
|
+
if (intoClause && valuesClause) {
|
|
1089
|
+
var tableName = intoClause.tableName,
|
|
1090
|
+
schemaName = intoClause.schemaName,
|
|
1091
|
+
columns = intoClause.columns;
|
|
1092
|
+
var values = valuesClause.values;
|
|
1093
|
+
return {
|
|
1094
|
+
tableName: tableName,
|
|
1095
|
+
schemaName: schemaName,
|
|
1096
|
+
columns: columns,
|
|
1097
|
+
values: values
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
return null;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1025
1103
|
// insert_into_clause
|
|
1026
1104
|
// : INTO general_table_ref paren_column_list?
|
|
1027
1105
|
// ;
|
|
1028
1106
|
}, {
|
|
1029
1107
|
key: "visitInsert_into_clause",
|
|
1030
1108
|
value: function visitInsert_into_clause(ctx) {
|
|
1109
|
+
var _findTable;
|
|
1031
1110
|
var names = ctx.general_table_ref().accept(this);
|
|
1032
1111
|
var tableName = (0, _lodash.last)(names);
|
|
1033
1112
|
var schemaName = names.length > 1 ? names[names.length - 2] : undefined;
|
|
1034
1113
|
var columns = ctx.paren_column_list() ? ctx.paren_column_list().accept(this).map(function (c) {
|
|
1035
1114
|
return (0, _lodash.last)(c);
|
|
1036
|
-
}) :
|
|
1115
|
+
}) : (_findTable = findTable(this.data.tables, schemaName, tableName)) === null || _findTable === void 0 ? void 0 : _findTable.fields.map(function (field) {
|
|
1116
|
+
return field.name;
|
|
1117
|
+
});
|
|
1037
1118
|
return {
|
|
1038
1119
|
tableName: tableName,
|
|
1039
1120
|
schemaName: schemaName,
|
|
@@ -1078,9 +1159,9 @@ var OracleSqlASTGen = exports["default"] = /*#__PURE__*/function (_OracleSqlPars
|
|
|
1078
1159
|
}, {
|
|
1079
1160
|
key: "visitExpressions_",
|
|
1080
1161
|
value: function visitExpressions_(ctx) {
|
|
1081
|
-
var
|
|
1162
|
+
var _this15 = this;
|
|
1082
1163
|
return ctx.expression().map(function (e) {
|
|
1083
|
-
return e.accept(
|
|
1164
|
+
return e.accept(_this15);
|
|
1084
1165
|
});
|
|
1085
1166
|
}
|
|
1086
1167
|
}, {
|
|
@@ -177,13 +177,13 @@ This module provides SQL parsing capabilities for Oracle databases, enabling con
|
|
|
177
177
|
| Feature | Status | Notes |
|
|
178
178
|
|---------|---------|-------|
|
|
179
179
|
| Basic `INSERT` ... VALUES | ✓ | `INSERT INTO t (col) VALUES (1)` |
|
|
180
|
-
| Multi-row `INSERT` |
|
|
180
|
+
| Multi-row `INSERT` | ✓ | Supported via `INSERT ALL` syntax |
|
|
181
181
|
| `INSERT` ... SELECT | ✗ | Subquery as data source |
|
|
182
182
|
| WITH clause (CTE) | ✗ | CTE before `INSERT` |
|
|
183
183
|
| Target table alias | ✗ | `INSERT INTO t alias ...` |
|
|
184
184
|
| `INSERT` ... RETURNING | ◐ | Returns inserted rows - clause is ignored |
|
|
185
|
-
| `INSERT ALL` (multi-table insert) |
|
|
186
|
-
| Conditional `INSERT` (WHEN/FIRST/ALL) |
|
|
185
|
+
| `INSERT ALL` (multi-table insert) | ✓ | Oracle-specific multi-table insert - fully supported |
|
|
186
|
+
| Conditional `INSERT` (WHEN/FIRST/ALL) | ◐ | Conditional inserts with WHEN clauses not yet supported |
|
|
187
187
|
| `INSERT` OVERWRITE | — | Snowflake/Hive syntax - not valid in Oracle |
|
|
188
188
|
|
|
189
189
|
---
|
|
@@ -243,7 +243,7 @@ This module provides SQL parsing capabilities for Oracle databases, enabling con
|
|
|
243
243
|
## Known Limitations
|
|
244
244
|
|
|
245
245
|
- **`ON UPDATE` for `FOREIGN KEY`**: Oracle does not support `ON UPDATE` actions for foreign keys; only `ON DELETE` is available
|
|
246
|
-
- **
|
|
246
|
+
- **Conditional `INSERT ALL`**: Basic `INSERT ALL` is fully supported, but conditional inserts with WHEN/FIRST clauses are not yet supported
|
|
247
247
|
- **DDL modification statements**: `DROP TABLE`, `DROP INDEX`, `ALTER INDEX` not supported
|
|
248
248
|
- **`INSERT` ... SELECT**: Subqueries in `INSERT` statements not supported
|
|
249
249
|
- **`CREATE VIEW`**: View definitions are not parsed
|
|
@@ -257,5 +257,5 @@ This module provides SQL parsing capabilities for Oracle databases, enabling con
|
|
|
257
257
|
3. **Function-based Indexes**: Oracle's function-based indexes (e.g., `CREATE INDEX ON t (UPPER(col))`) are fully supported
|
|
258
258
|
4. **`ON DELETE` Only**: Oracle foreign keys only support `ON DELETE` actions (`CASCADE`, `SET NULL`, `NO ACTION`). There is no `ON UPDATE` support
|
|
259
259
|
5. **Comments**: Use `COMMENT ON TABLE/COLUMN` statements. These are separate DDL statements, not inline with `CREATE TABLE`
|
|
260
|
-
6.
|
|
260
|
+
6. **`INSERT ALL` Support**: Oracle's `INSERT ALL ... SELECT * FROM dual` syntax for multi-row and multi-table inserts is fully supported. Rows with the same table and columns are automatically grouped together. Conditional inserts with WHEN clauses are not yet supported
|
|
261
261
|
7. **`VARCHAR2`**: Oracle uses `VARCHAR2` (not `VARCHAR`) as the standard variable-length string type
|
|
@@ -1230,6 +1230,16 @@ var PostgresASTGen = exports["default"] = /*#__PURE__*/function (_PostgreSQLPars
|
|
|
1230
1230
|
var _ctx$insert_rest$acce = ctx.insert_rest().accept(this),
|
|
1231
1231
|
columns = _ctx$insert_rest$acce.columns,
|
|
1232
1232
|
values = _ctx$insert_rest$acce.values;
|
|
1233
|
+
|
|
1234
|
+
// When no columns are specified, lookup table and use all its columns
|
|
1235
|
+
if (columns.length === 0) {
|
|
1236
|
+
var table = findTable(this.data.tables, schemaName, tableName);
|
|
1237
|
+
if (table && table.fields) {
|
|
1238
|
+
columns = table.fields.map(function (field) {
|
|
1239
|
+
return field.name;
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1233
1243
|
var record = new _AST.TableRecord({
|
|
1234
1244
|
schemaName: schemaName,
|
|
1235
1245
|
tableName: tableName,
|
|
@@ -33,6 +33,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
|
|
|
33
33
|
function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
|
|
34
34
|
function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
|
|
35
35
|
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
|
|
36
|
+
var DEFAULT_SCHEMA = 'public';
|
|
36
37
|
var sanitizeComment = function sanitizeComment(stringContext) {
|
|
37
38
|
return (0, _helpers.getOriginalText)(stringContext).replace(/''/g, "'").slice(1, -1);
|
|
38
39
|
};
|
|
@@ -48,14 +49,25 @@ var SnowflakeASTGen = exports["default"] = /*#__PURE__*/function (_SnowflakePars
|
|
|
48
49
|
enums: [],
|
|
49
50
|
tableGroups: [],
|
|
50
51
|
aliases: [],
|
|
51
|
-
project: {}
|
|
52
|
+
project: {},
|
|
53
|
+
records: []
|
|
52
54
|
};
|
|
53
55
|
return _this;
|
|
54
56
|
}
|
|
55
|
-
|
|
56
|
-
// batch? EOF
|
|
57
57
|
_inherits(SnowflakeASTGen, _SnowflakeParserVisit);
|
|
58
58
|
return _createClass(SnowflakeASTGen, [{
|
|
59
|
+
key: "findTable",
|
|
60
|
+
value: function findTable(schemaName, tableName) {
|
|
61
|
+
var realSchemaName = schemaName || DEFAULT_SCHEMA;
|
|
62
|
+
var table = this.data.tables.find(function (t) {
|
|
63
|
+
var targetSchemaName = t.schemaName || DEFAULT_SCHEMA;
|
|
64
|
+
return targetSchemaName === realSchemaName && t.name === tableName;
|
|
65
|
+
});
|
|
66
|
+
return table;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// batch? EOF
|
|
70
|
+
}, {
|
|
59
71
|
key: "visitSnowflake_file",
|
|
60
72
|
value: function visitSnowflake_file(ctx) {
|
|
61
73
|
var _ctx$batch;
|
|
@@ -79,6 +91,8 @@ var SnowflakeASTGen = exports["default"] = /*#__PURE__*/function (_SnowflakePars
|
|
|
79
91
|
value: function visitSql_command(ctx) {
|
|
80
92
|
if (ctx.ddl_command()) {
|
|
81
93
|
ctx.ddl_command().accept(this);
|
|
94
|
+
} else if (ctx.dml_command()) {
|
|
95
|
+
ctx.dml_command().accept(this);
|
|
82
96
|
}
|
|
83
97
|
}
|
|
84
98
|
|
|
@@ -93,6 +107,22 @@ var SnowflakeASTGen = exports["default"] = /*#__PURE__*/function (_SnowflakePars
|
|
|
93
107
|
}
|
|
94
108
|
}
|
|
95
109
|
|
|
110
|
+
// dml_command
|
|
111
|
+
// : query_statement
|
|
112
|
+
// | insert_statement
|
|
113
|
+
// | insert_multi_table_statement
|
|
114
|
+
// | update_statement
|
|
115
|
+
// | delete_statement
|
|
116
|
+
// | merge_statement
|
|
117
|
+
// ;
|
|
118
|
+
}, {
|
|
119
|
+
key: "visitDml_command",
|
|
120
|
+
value: function visitDml_command(ctx) {
|
|
121
|
+
if (ctx.insert_statement()) {
|
|
122
|
+
ctx.insert_statement().accept(this);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
96
126
|
// check SnowflakeParser.g4 line 1442
|
|
97
127
|
}, {
|
|
98
128
|
key: "visitCreate_command",
|
|
@@ -171,7 +201,7 @@ var SnowflakeASTGen = exports["default"] = /*#__PURE__*/function (_SnowflakePars
|
|
|
171
201
|
var field = fieldData.field,
|
|
172
202
|
inlineRefs = fieldData.inlineRefs;
|
|
173
203
|
if (((_field$type$type_name = field.type.type_name) === null || _field$type$type_name === void 0 ? void 0 : _field$type$type_name.toLowerCase()) === 'enum') {
|
|
174
|
-
var
|
|
204
|
+
var values = field.type.args.map(function (arg) {
|
|
175
205
|
var newValue = arg.replace(/'|"|`/g, '').trim();
|
|
176
206
|
return {
|
|
177
207
|
name: newValue
|
|
@@ -180,7 +210,7 @@ var SnowflakeASTGen = exports["default"] = /*#__PURE__*/function (_SnowflakePars
|
|
|
180
210
|
var _enum = new _AST.Enum({
|
|
181
211
|
name: "".concat(tableName, "_").concat(field.name, "_enum"),
|
|
182
212
|
schemaName: schemaName,
|
|
183
|
-
values:
|
|
213
|
+
values: values
|
|
184
214
|
});
|
|
185
215
|
field.type.type_name = _enum.name;
|
|
186
216
|
field.type.schemaName = _enum.schemaName;
|
|
@@ -743,5 +773,60 @@ var SnowflakeASTGen = exports["default"] = /*#__PURE__*/function (_SnowflakePars
|
|
|
743
773
|
}
|
|
744
774
|
return null;
|
|
745
775
|
}
|
|
776
|
+
|
|
777
|
+
// insert_statement
|
|
778
|
+
// : INSERT OVERWRITE? INTO object_name column_list_in_parentheses? (
|
|
779
|
+
// values_builder
|
|
780
|
+
// | query_statement
|
|
781
|
+
// )
|
|
782
|
+
// ;
|
|
783
|
+
}, {
|
|
784
|
+
key: "visitInsert_statement",
|
|
785
|
+
value: function visitInsert_statement(ctx) {
|
|
786
|
+
var _this$findTable;
|
|
787
|
+
var _ctx$object_name$acce7 = ctx.object_name().accept(this),
|
|
788
|
+
_ctx$object_name$acce8 = _slicedToArray(_ctx$object_name$acce7, 3),
|
|
789
|
+
databaseName = _ctx$object_name$acce8[0],
|
|
790
|
+
schemaName = _ctx$object_name$acce8[1],
|
|
791
|
+
tableName = _ctx$object_name$acce8[2];
|
|
792
|
+
var columns = ctx.column_list_in_parentheses() ? ctx.column_list_in_parentheses().accept(this) : ((_this$findTable = this.findTable(schemaName, tableName)) === null || _this$findTable === void 0 ? void 0 : _this$findTable.fields.map(function (field) {
|
|
793
|
+
return field.name;
|
|
794
|
+
})) || [];
|
|
795
|
+
|
|
796
|
+
// Only handle values_builder, not query_statement
|
|
797
|
+
var values = ctx.values_builder() ? ctx.values_builder().accept(this) : [];
|
|
798
|
+
var record = new _AST.TableRecord({
|
|
799
|
+
schemaName: schemaName,
|
|
800
|
+
tableName: tableName,
|
|
801
|
+
columns: columns,
|
|
802
|
+
values: values
|
|
803
|
+
});
|
|
804
|
+
this.data.records.push(record);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// values_builder
|
|
808
|
+
// : VALUES '(' expr_list ')' (COMMA '(' expr_list ')')?
|
|
809
|
+
// ;
|
|
810
|
+
}, {
|
|
811
|
+
key: "visitValues_builder",
|
|
812
|
+
value: function visitValues_builder(ctx) {
|
|
813
|
+
var _this0 = this;
|
|
814
|
+
return ctx.expr_list().map(function (exprList) {
|
|
815
|
+
var rowValues = exprList.accept(_this0);
|
|
816
|
+
return (0, _lodash.flattenDepth)(rowValues, 1);
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// expr_list
|
|
821
|
+
// : expr (COMMA expr)*
|
|
822
|
+
// ;
|
|
823
|
+
}, {
|
|
824
|
+
key: "visitExpr_list",
|
|
825
|
+
value: function visitExpr_list(ctx) {
|
|
826
|
+
var _this1 = this;
|
|
827
|
+
return ctx.expr().map(function (expr) {
|
|
828
|
+
return expr.accept(_this1);
|
|
829
|
+
});
|
|
830
|
+
}
|
|
746
831
|
}]);
|
|
747
832
|
}(_SnowflakeParserVisitor["default"]);
|
|
@@ -45,7 +45,7 @@ var MySqlLexerBase = exports["default"] = /*#__PURE__*/function (_antlr4$Lexer)
|
|
|
45
45
|
key: "nextToken",
|
|
46
46
|
value: function nextToken() {
|
|
47
47
|
// See the comment above HIGH_PRIORITY_MODE in the Lexer grammar G4 file
|
|
48
|
-
this.
|
|
48
|
+
this.setMode(MySqlLexerBase.DEFAULT_MODE); // always start in DEFAULT_MODE, which will automatically switch to high priority mode
|
|
49
49
|
return _superPropGet(MySqlLexerBase, "nextToken", this, 3)([]);
|
|
50
50
|
}
|
|
51
51
|
}]);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@dbml/core",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.2.0-alpha.0",
|
|
5
5
|
"description": "> TODO: description",
|
|
6
6
|
"author": "Holistics <dev@holistics.io>",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"lint:fix": "eslint --fix ."
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@dbml/parse": "^6.
|
|
39
|
+
"@dbml/parse": "^6.2.0-alpha.0",
|
|
40
40
|
"antlr4": "^4.13.1",
|
|
41
41
|
"lodash": "^4.17.15",
|
|
42
42
|
"parsimmon": "^1.13.0",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"typescript": "^5.9.3",
|
|
64
64
|
"typescript-eslint": "^8.46.3"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "00865dc46e1cbab39233ad010c6b5e120131476c",
|
|
67
67
|
"engines": {
|
|
68
68
|
"node": ">=16"
|
|
69
69
|
}
|
package/types/export/index.d.ts
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -2,8 +2,16 @@ import ModelExporter from './export/ModelExporter';
|
|
|
2
2
|
import Parser from './parse/Parser';
|
|
3
3
|
import importer from './import';
|
|
4
4
|
import exporter from './export';
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
renameTable,
|
|
7
|
+
} from './transform';
|
|
8
|
+
export {
|
|
9
|
+
renameTable,
|
|
10
|
+
importer,
|
|
11
|
+
exporter,
|
|
12
|
+
ModelExporter,
|
|
13
|
+
Parser,
|
|
14
|
+
};
|
|
7
15
|
export { CompilerDiagnostic, CompilerError as CompilerDiagnostics, EditorPosition, ErrorCode, WarningLevel, } from './parse/error';
|
|
8
16
|
|
|
9
17
|
// Export normalized types
|
|
@@ -43,3 +51,23 @@ export type {
|
|
|
43
51
|
NormalizedRecords,
|
|
44
52
|
RawSchema,
|
|
45
53
|
} from './model_structure';
|
|
54
|
+
export { RecordValueType, RecordValue } from './model_structure/database';
|
|
55
|
+
export {
|
|
56
|
+
SqlDialect,
|
|
57
|
+
isIntegerType,
|
|
58
|
+
isFloatType,
|
|
59
|
+
isNumericType,
|
|
60
|
+
isBooleanType,
|
|
61
|
+
isStringType,
|
|
62
|
+
isBinaryType,
|
|
63
|
+
isDateTimeType,
|
|
64
|
+
isSerialType,
|
|
65
|
+
tryExtractBoolean,
|
|
66
|
+
tryExtractNumeric,
|
|
67
|
+
tryExtractInteger,
|
|
68
|
+
tryExtractString,
|
|
69
|
+
tryExtractDateTime,
|
|
70
|
+
tryExtractEnum,
|
|
71
|
+
addDoubleQuoteIfNeeded,
|
|
72
|
+
formatRecordValue,
|
|
73
|
+
} from '@dbml/parse';
|
|
@@ -19,13 +19,20 @@ export interface Project {
|
|
|
19
19
|
name: string;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
export type RecordValueType = 'string' | 'bool' | 'integer' | 'real' | 'date' | 'time' | 'datetime' | string;
|
|
23
|
+
|
|
24
|
+
export interface RecordValue {
|
|
25
|
+
value: any;
|
|
26
|
+
type: RecordValueType;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface RawTableRecord {
|
|
23
30
|
schemaName: string | undefined;
|
|
24
31
|
tableName: string;
|
|
25
32
|
columns: string[];
|
|
26
33
|
values: {
|
|
27
34
|
value: any;
|
|
28
|
-
type:
|
|
35
|
+
type: RecordValueType;
|
|
29
36
|
}[][];
|
|
30
37
|
}
|
|
31
38
|
|
|
@@ -3,6 +3,16 @@ import Field from './field';
|
|
|
3
3
|
import Ref from './ref';
|
|
4
4
|
import DbState from './dbState';
|
|
5
5
|
import { NormalizedModel } from './database';
|
|
6
|
+
import { Token } from 'antlr4';
|
|
7
|
+
|
|
8
|
+
export interface RawEndpoint {
|
|
9
|
+
schemaName: string | null;
|
|
10
|
+
tableName: string;
|
|
11
|
+
fieldNames: string[];
|
|
12
|
+
relation: '1' | '*';
|
|
13
|
+
token: Token;
|
|
14
|
+
}
|
|
15
|
+
|
|
6
16
|
declare class Endpoint extends Element {
|
|
7
17
|
relation: any;
|
|
8
18
|
schemaName: string;
|
|
@@ -2,13 +2,15 @@ import Element, { Token } from './element';
|
|
|
2
2
|
import Database from './database';
|
|
3
3
|
import DbState from './dbState';
|
|
4
4
|
import { NormalizedModel } from './database';
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
export interface RawStickyNote {
|
|
6
7
|
name: string;
|
|
7
8
|
content: string;
|
|
8
9
|
database: Database;
|
|
9
10
|
token: Token;
|
|
10
11
|
headerColor: string;
|
|
11
12
|
}
|
|
13
|
+
|
|
12
14
|
declare class StickyNote extends Element {
|
|
13
15
|
name: string;
|
|
14
16
|
content: string;
|