@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
@@ -1,8 +1,27 @@
1
1
  // Base rules:
2
2
  // collumn_name, table_name
3
3
  column_name "valid column name" = identifier
4
- table_name "valid table name"
5
- = ((identifier _ "." _)*)? name:identifier { return name }
4
+
5
+ path_name = names:(identifier _ "." _)* {
6
+ let dbName = null;
7
+ let schemaName = null;
8
+ if (names && names.length > 0) {
9
+ if (names.length === 1) schemaName = names[0][0];
10
+ else {
11
+ dbName = names[0][0];
12
+ schemaName = names[1][0];
13
+ }
14
+ }
15
+ return { dbName, schemaName }
16
+ }
17
+
18
+ table_name "valid table name" = pathName:path_name name:identifier {
19
+ return { ...pathName, name }
20
+ }
21
+
22
+ enum_name "valid enum name" = pathName:path_name? name:identifier {
23
+ return { ...pathName, name }
24
+ }
6
25
 
7
26
  // string constant
8
27
  string_constant "string" = "'" c:char_inside_single_quote+ "'" {
@@ -58,6 +77,7 @@ data_type "VALID TYPE" = c1:"CHARACTER"i _ c2:"VARYING"i _ args:("("expression")
58
77
  const args = c.args;
59
78
  return {
60
79
  type_name: c.type_name + (dimensions ? dimensions.map((dimension) => '[' + dimension + ']').join('') : ''),
80
+ schemaName: c.schemaName,
61
81
  args
62
82
  };
63
83
  }
@@ -67,7 +87,7 @@ data_type "VALID TYPE" = c1:"CHARACTER"i _ c2:"VARYING"i _ args:("("expression")
67
87
  args: null
68
88
  }
69
89
  }
70
- type_name = c:(character)+ _ args:("(" expression ")")? {
90
+ type_name = pathName:path_name? c:(character)+ _ args:("(" expression ")")? {
71
91
  let type_name = c.join("");
72
92
  args = args ? args[1] : null;
73
93
  if (type_name.toLowerCase() !== 'enum') {
@@ -75,6 +95,7 @@ type_name = c:(character)+ _ args:("(" expression ")")? {
75
95
  }
76
96
 
77
97
  return {
98
+ ...pathName,
78
99
  type_name,
79
100
  args
80
101
  }
@@ -1,17 +1,57 @@
1
- alter_table = alter_table_action:alter_table_action {
1
+ alter_table = alter_sub_syntax:(
2
+ alter_table_action /
3
+ alter_table_rename /
4
+ alter_table_set_schema /
5
+ alter_table_set_tablespace /
6
+ alter_table_attach /
7
+ alter_table_detach
8
+ ) {
2
9
  return {
3
10
  command_name: "alter_table",
4
- value: alter_table_action
11
+ value: alter_sub_syntax
5
12
  }
6
13
  }
7
14
 
8
- alter_table_action = _ ALTER __ TABLE (__ IF_EXISTS)? (__ ONLY)? __ name:table_name __
15
+ alter_table_rename = _ ALTER __ TABLE (__ IF_EXISTS)? (__ ONLY)? __ table_name (_ "*")? __ RENAME (cmt / !semicolon .)* _ semicolon _ {
16
+ return {
17
+ syntax_name: "alter_table_rename",
18
+ }
19
+ }
20
+
21
+ alter_table_set_schema = _ ALTER __ TABLE (__ IF_EXISTS)? __ table_name __ SET __ SCHEMA (cmt / !semicolon .)* _ semicolon _ {
22
+ return {
23
+ syntax_name: "alter_table_set_schema",
24
+ }
25
+ }
26
+
27
+ alter_table_set_tablespace = _ ALTER __ TABLE __ ALL __ IN __ TABLESPACE __ table_name
28
+ (__ OWNED __ BY __ identifier (_ comma _ identifier)*)? __ SET __ TABLESPACE
29
+ (cmt / !semicolon .)* _ semicolon _ {
30
+ return {
31
+ syntax_name: "alter_set_tablespace",
32
+ }
33
+ }
34
+
35
+ alter_table_attach = _ ALTER __ TABLE (__ IF_EXISTS)? __ table_name __ ATTACH __ PARTITION (cmt / !semicolon .)* _ semicolon _ {
36
+ return {
37
+ syntax_name: "alter_table_attach",
38
+ }
39
+ }
40
+
41
+ alter_table_detach = _ ALTER __ TABLE (__ IF_EXISTS)? __ table_name __ DETACH __ PARTITION (cmt / !semicolon .)* _ semicolon _ {
42
+ return {
43
+ syntax_name: "alter_table_detach",
44
+ }
45
+ }
46
+
47
+ alter_table_action = _ ALTER __ TABLE (__ IF_EXISTS)? (__ ONLY)? __ name:table_name (_ "*")? __
9
48
  actions:actions _ semicolon _ {
10
49
  actions.forEach(({ type, t_value}) => {
11
50
  switch(type.toLowerCase()) {
12
51
  case "fk":
13
52
  t_value.forEach(({ endpoints }) => {
14
- endpoints[0].tableName = name
53
+ endpoints[0].tableName = name.name;
54
+ endpoints[0].schemaName = name.schemaName;
15
55
  })
16
56
  }
17
57
  })
@@ -78,6 +118,11 @@ action = ADD __ table_constraint:table_constraint (__ NOT __ VALID)? { // reuse
78
118
  value: value.toLowerCase()
79
119
  }
80
120
  }
121
+ / (cmt / !semicolon .)* {
122
+ return {
123
+ type: "unknown",
124
+ }
125
+ }
81
126
 
82
127
 
83
128
  set_attribute_options = first:set_attribute_option rest:(_ comma _ set_attribute_option)* {
@@ -2,9 +2,7 @@ comment = _ COMMENT __ ON __ comment_option:comment_option __ IS __ text:(string
2
2
  _ semicolon _ {
3
3
  if (text.toLowerCase() !== "null") {
4
4
  comment_option.value.text = text;
5
- } else {
6
- comment_option.value.syntax_name = "remove_comment";
7
- }
5
+ } else comment_option.value.text = null;
8
6
 
9
7
  return {
10
8
  command_name: "comment",
@@ -13,12 +11,26 @@ comment = _ COMMENT __ ON __ comment_option:comment_option __ IS __ text:(string
13
11
  }
14
12
 
15
13
  comment_option = (
16
- COLUMN __ relation_name:identifier "." column_name:column_name {
14
+ COLUMN __ path:(identifier '.')+ column_name:column_name {
15
+ let dbName = null, schemaName = null, tableName;
16
+ if (path.length === 1) {
17
+ tableName = path[0][0];
18
+ } else if (path.length === 2) {
19
+ schemaName = path[0][0];
20
+ tableName = path[1][0];
21
+ }
22
+ else {
23
+ dbName = path[0][0];
24
+ schemaName = path[1][0];
25
+ tableName = path[2][0];
26
+ }
17
27
  return {
18
28
  syntax_name: "column",
19
29
  value: {
20
- relation_name: relation_name,
21
- column_name
30
+ dbName,
31
+ schemaName,
32
+ tableName,
33
+ columnName: column_name
22
34
  }
23
35
  }
24
36
  }
@@ -7,7 +7,7 @@ create_table_normal =
7
7
  (__ ON __ COMMIT __ (PRESERVE __ ROWS/ DELETE __ ROWS/ DROP))?
8
8
  (__ TABLESPACE __ tablespace_name:identifier)?
9
9
  _ semicolon _ {
10
- const table = { name: table_name, fields: [], indexes: [] }
10
+ const table = { name: table_name.name, schemaName: table_name.schemaName, fields: [], indexes: [] }
11
11
  // process table_properties
12
12
  table_properties.forEach(({ table_property_name, value }) => {
13
13
  switch(table_property_name.toLowerCase()) {
@@ -156,7 +156,8 @@ column_constraint = (CONSTRAINT __ constraint_name:identifier __)?
156
156
  type: "fk",
157
157
  value: {
158
158
  endpoint: {
159
- tableName: reftable,
159
+ tableName: reftable.name,
160
+ schemaName: reftable.schemaName,
160
161
  fieldNames: refcolumn ? [refcolumn] : null,
161
162
  relation: "1"
162
163
  },
@@ -192,7 +193,8 @@ table_constraint = (CONSTRAINT __ constraint_name:identifier __)?
192
193
  relation: "*",
193
194
  },
194
195
  {
195
- tableName: reftable,
196
+ tableName: reftable.name,
197
+ schemaName: reftable.schemaName,
196
198
  fieldNames: refcolumn,// ? refcolumn[key] : null,
197
199
  relation: "1",
198
200
  },
@@ -6,7 +6,7 @@ create_table_of =
6
6
  (__ ON __ COMMIT __ (PRESERVE __ ROWS/ DELETE __ ROWS/ DROP))?
7
7
  (__ TABLESPACE __ tablespace_name:identifier)?
8
8
  _ semicolon _ {
9
- const table = { name: table_name, type: type_name}
9
+ const table = { name: table_name.name, schemaName: table_name.schemaName, type: type_name}
10
10
  return {
11
11
  syntax_name: "create_table_of",
12
12
  value: table
@@ -7,7 +7,7 @@ create_table_partition_of =
7
7
  (__ ON __ COMMIT __ (PRESERVE __ ROWS/ DELETE __ ROWS/ DROP))?
8
8
  (__ TABLESPACE __ tablespace_name:identifier)?
9
9
  _ semicolon _ {
10
- const table = { name: table_name, parent_table: parent_table}
10
+ const table = { name: table_name.name, schemaName: table_name.schemaName, parent_table: parent_table}
11
11
  return {
12
12
  syntax_name: "create_table_partition_of",
13
13
  value: table
@@ -1,12 +1,12 @@
1
1
  create_type_enum =
2
- _ CREATE __ TYPE __ name:identifier __ AS __ ENUM _
2
+ _ CREATE __ TYPE __ enumName:enum_name __ AS __ ENUM _
3
3
  "(" _ labels:labels _ ")"
4
4
  _ semicolon _ {
5
5
  const values = labels.map(name => ({ name }))
6
6
  return {
7
7
  syntax_name: "create_type_enum",
8
8
  value: {
9
- name,
9
+ ...enumName,
10
10
  values,
11
11
  }
12
12
  }
@@ -8,10 +8,19 @@ ignore_syntax = _ value:(
8
8
  / CREATE __ SEQUENCE [^;]* { return { syntax_name: "create_sequence" } }
9
9
  / CREATE __ SCHEMA [^;]* { return { syntax_name: "create_schema" } }
10
10
  / CREATE __ VIEW [^;]* { return { syntax_name: "create_view" } }
11
+ / ALTER __ (cmt / !(semicolon) .)* { return { syntax_name: "alter_not_table" } }
11
12
  / __ { return { syntax_name: "comment_and_space" } }
12
13
  ) semicolon _ {
14
+ const loc = location();
15
+ const t = text();
13
16
  return {
14
17
  command_name: "ignore_syntax",
15
- value
18
+ value,
19
+ warning: {
20
+ type: 'ignore',
21
+ location: loc,
22
+ text: t,
23
+ message: `ignoring "${t}" at line: ${loc.start.line}`,
24
+ },
16
25
  }
17
26
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  // intput:
3
- // `
3
+ // `
4
4
  // 'created'
5
- // ,
5
+ // ,
6
6
  // 'pending', 'done'
7
7
  // `
8
8
  // => `'created', 'pending', 'done'`
@@ -14,4 +14,16 @@
14
14
  });
15
15
  return arrAfterTrim.join(', ');
16
16
  }
17
+
18
+ // TODO: support configurable default schema name other than 'public'
19
+ const findTable = (schemaName, tableName) => {
20
+ const realSchemaName = schemaName || 'public';
21
+ const table = tables.find(table => {
22
+ const targetSchemaName = table.schemaName || 'public';
23
+ return targetSchemaName === realSchemaName && table.name === tableName;
24
+ });
25
+ return table;
26
+ };
27
+
28
+ const findField = (table, fieldName) => table.fields.find(field => field.name === fieldName);
17
29
  }
@@ -110,4 +110,8 @@ SELECT = "SELECT"i
110
110
  USE = "USE"i
111
111
  SEQUENCE = "SEQUENCE"i
112
112
  SCHEMA = "SCHEMA"i
113
- VIEW = "VIEW"i
113
+ VIEW = "VIEW"i
114
+ RENAME = "RENAME"i
115
+ OWNED = "OWNED"i
116
+ ATTACH = "ATTACH"i
117
+ DETACH = "DETACH"i
@@ -2,10 +2,12 @@
2
2
  const tables = [];
3
3
  const refs = [];
4
4
  const enums = [];
5
+ const warnings = [];
5
6
  }
6
7
 
7
8
  parser = commands:command* {
8
- commands.forEach(({ command_name, value: { syntax_name, value } }) => {
9
+ commands.forEach((cmd) => {
10
+ const { command_name, value: { syntax_name, value }, warning } = cmd;
9
11
  switch(command_name.toLowerCase()){
10
12
  case "create_table":
11
13
  const table = value;
@@ -23,6 +25,7 @@ parser = commands:command* {
23
25
  endpoints: [
24
26
  {
25
27
  tableName: table.name,
28
+ schemaName: table.schemaName,
26
29
  fieldNames: [field.name],
27
30
  relation: "*",
28
31
  },
@@ -70,7 +73,7 @@ parser = commands:command* {
70
73
  case "create_index":
71
74
  const { table_name } = value;
72
75
  delete value.table_name; // remove table_name from column
73
- const table_index = tables.find(table => table.name === table_name);
76
+ const table_index = findTable(table_name.schemaName, table_name.name);
74
77
  if (table_index.indexes) {
75
78
  table_index.indexes.push(value);
76
79
  } else {
@@ -103,18 +106,29 @@ parser = commands:command* {
103
106
  break;
104
107
  case "comment":
105
108
  switch(syntax_name.toLowerCase()) {
106
- case "column":
107
- const table_comment = tables.find(table => table.name === value.relation_name);
108
- const field_comment = table_comment.fields.find(field => field.name === value.column_name);
109
- field_comment.note = value.text;
109
+ case "column": {
110
+ const { schemaName, tableName, columnName } = value;
111
+ const foundTable = findTable(schemaName, tableName);
112
+ if (foundTable) {
113
+ const foundField = findField(foundTable, columnName);
114
+ if (foundField) foundField.note = value.text;
115
+ }
116
+ break;
117
+ }
118
+ case "table": {
119
+ const { schemaName, name: tableName } = value.table_name;
120
+ const foundTable = findTable(schemaName, tableName);
121
+ if (foundTable) foundTable.note = value.text;
110
122
  break;
123
+ }
111
124
  }
112
125
  break;
113
- case "ignore_commands":
126
+ case "ignore_syntax":
127
+ // warnings.push(warning);
114
128
  break;
115
129
  }
116
130
  })
117
- // console.log({tables, refs, enums, indexes});
131
+
118
132
  return {tables, refs, enums};
119
133
  }
120
134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbml/core",
3
- "version": "2.3.1",
3
+ "version": "2.4.2",
4
4
  "description": "> TODO: description",
5
5
  "author": "Holistics <dev@holistics.io>",
6
6
  "license": "Apache-2.0",
@@ -56,5 +56,5 @@
56
56
  "\\.(?!json$)[^.]*$": "jest-raw-loader"
57
57
  }
58
58
  },
59
- "gitHead": "ddd4566d6773c3fb7893222a8903833e847a58b7"
59
+ "gitHead": "2d33941ba6f0833254bfc434abed1dc59f8f2b87"
60
60
  }