xansql 1.0.8 → 1.0.9
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/core/Xansql.cjs +7 -8
- package/core/Xansql.cjs.map +1 -1
- package/core/Xansql.d.ts +2 -3
- package/core/Xansql.mjs +7 -8
- package/core/Xansql.mjs.map +1 -1
- package/core/classes/ForeignInfo.cjs +3 -2
- package/core/classes/ForeignInfo.cjs.map +1 -1
- package/core/classes/ForeignInfo.d.ts +1 -2
- package/core/classes/ForeignInfo.mjs +3 -2
- package/core/classes/ForeignInfo.mjs.map +1 -1
- package/core/classes/Migration/TableMigration.cjs +24 -15
- package/core/classes/Migration/TableMigration.cjs.map +1 -1
- package/core/classes/Migration/TableMigration.mjs +25 -16
- package/core/classes/Migration/TableMigration.mjs.map +1 -1
- package/core/classes/Migration/index.cjs +13 -10
- package/core/classes/Migration/index.cjs.map +1 -1
- package/core/classes/Migration/index.mjs +14 -11
- package/core/classes/Migration/index.mjs.map +1 -1
- package/core/classes/{ModelFormatter.cjs → ModelFactory.cjs} +82 -56
- package/core/classes/ModelFactory.cjs.map +1 -0
- package/core/classes/{ModelFormatter.d.ts → ModelFactory.d.ts} +7 -2
- package/core/classes/{ModelFormatter.mjs → ModelFactory.mjs} +82 -56
- package/core/classes/ModelFactory.mjs.map +1 -0
- package/core/types.d.ts +1 -1
- package/dialect/MysqlDialect.cjs +7 -4
- package/dialect/MysqlDialect.cjs.map +1 -1
- package/dialect/MysqlDialect.d.ts +7 -4
- package/dialect/MysqlDialect.mjs +7 -4
- package/dialect/MysqlDialect.mjs.map +1 -1
- package/dialect/PostgresDialect.cjs +5 -2
- package/dialect/PostgresDialect.cjs.map +1 -1
- package/dialect/PostgresDialect.d.ts +5 -2
- package/dialect/PostgresDialect.mjs +5 -2
- package/dialect/PostgresDialect.mjs.map +1 -1
- package/dialect/SqliteDialect.cjs +3 -2
- package/dialect/SqliteDialect.cjs.map +1 -1
- package/dialect/SqliteDialect.d.ts +3 -2
- package/dialect/SqliteDialect.mjs +3 -2
- package/dialect/SqliteDialect.mjs.map +1 -1
- package/dialect/XansqlBridge/XansqlBridgeServer.cjs.map +1 -1
- package/dialect/XansqlBridge/XansqlBridgeServer.mjs.map +1 -1
- package/dialect/XansqlBridge/base.cjs +10 -5
- package/dialect/XansqlBridge/base.cjs.map +1 -1
- package/dialect/XansqlBridge/base.mjs +10 -5
- package/dialect/XansqlBridge/base.mjs.map +1 -1
- package/model/Args/WhereArgs.cjs +5 -8
- package/model/Args/WhereArgs.cjs.map +1 -1
- package/model/Args/WhereArgs.mjs +6 -9
- package/model/Args/WhereArgs.mjs.map +1 -1
- package/model/Base.cjs +2 -1
- package/model/Base.cjs.map +1 -1
- package/model/Base.mjs +2 -1
- package/model/Base.mjs.map +1 -1
- package/model/Executer/Aggregate/SelectArgs.cjs +2 -1
- package/model/Executer/Aggregate/SelectArgs.cjs.map +1 -1
- package/model/Executer/Aggregate/SelectArgs.mjs +2 -1
- package/model/Executer/Aggregate/SelectArgs.mjs.map +1 -1
- package/model/Executer/Aggregate/index.cjs +4 -4
- package/model/Executer/Aggregate/index.cjs.map +1 -1
- package/model/Executer/Aggregate/index.mjs +4 -4
- package/model/Executer/Aggregate/index.mjs.map +1 -1
- package/model/Executer/Create/CreateDataArgs.cjs +9 -5
- package/model/Executer/Create/CreateDataArgs.cjs.map +1 -1
- package/model/Executer/Create/CreateDataArgs.mjs +10 -6
- package/model/Executer/Create/CreateDataArgs.mjs.map +1 -1
- package/model/Executer/Create/index.cjs +1 -1
- package/model/Executer/Create/index.cjs.map +1 -1
- package/model/Executer/Create/index.mjs +1 -1
- package/model/Executer/Create/index.mjs.map +1 -1
- package/model/Executer/Delete/index.cjs +2 -1
- package/model/Executer/Delete/index.cjs.map +1 -1
- package/model/Executer/Delete/index.mjs +2 -1
- package/model/Executer/Delete/index.mjs.map +1 -1
- package/model/Executer/Find/SelectArgs.cjs +3 -3
- package/model/Executer/Find/SelectArgs.cjs.map +1 -1
- package/model/Executer/Find/SelectArgs.mjs +3 -3
- package/model/Executer/Find/SelectArgs.mjs.map +1 -1
- package/model/Executer/Update/UpdateDataArgs.cjs +4 -4
- package/model/Executer/Update/UpdateDataArgs.cjs.map +1 -1
- package/model/Executer/Update/UpdateDataArgs.mjs +5 -5
- package/model/Executer/Update/UpdateDataArgs.mjs.map +1 -1
- package/model/Executer/Update/index.cjs +1 -1
- package/model/Executer/Update/index.cjs.map +1 -1
- package/model/Executer/Update/index.mjs +1 -1
- package/model/Executer/Update/index.mjs.map +1 -1
- package/model/include/ValueFormatter.cjs +72 -17
- package/model/include/ValueFormatter.cjs.map +1 -1
- package/model/include/ValueFormatter.d.ts +1 -1
- package/model/include/ValueFormatter.mjs +72 -17
- package/model/include/ValueFormatter.mjs.map +1 -1
- package/model/index.cjs +8 -7
- package/model/index.cjs.map +1 -1
- package/model/index.mjs +8 -7
- package/model/index.mjs.map +1 -1
- package/package.json +12 -7
- package/utils/index.cjs +5 -2
- package/utils/index.cjs.map +1 -1
- package/utils/index.d.ts +2 -1
- package/utils/index.mjs +5 -3
- package/utils/index.mjs.map +1 -1
- package/xt/additional/IP.cjs +22 -0
- package/xt/additional/IP.cjs.map +1 -0
- package/xt/additional/IP.d.ts +6 -0
- package/xt/additional/IP.mjs +20 -0
- package/xt/additional/IP.mjs.map +1 -0
- package/xt/additional/Name.cjs +21 -0
- package/xt/additional/Name.cjs.map +1 -0
- package/xt/additional/Name.d.ts +6 -0
- package/xt/additional/Name.mjs +19 -0
- package/xt/additional/Name.mjs.map +1 -0
- package/xt/additional/Password.cjs +25 -0
- package/xt/additional/Password.cjs.map +1 -0
- package/xt/additional/Password.d.ts +6 -0
- package/xt/additional/Password.mjs +23 -0
- package/xt/additional/Password.mjs.map +1 -0
- package/xt/additional/Phone.cjs +21 -0
- package/xt/additional/Phone.cjs.map +1 -0
- package/xt/additional/Phone.d.ts +6 -0
- package/xt/additional/Phone.mjs +19 -0
- package/xt/additional/Phone.mjs.map +1 -0
- package/xt/additional/Photo.cjs +21 -0
- package/xt/additional/Photo.cjs.map +1 -0
- package/xt/additional/Photo.d.ts +6 -0
- package/xt/additional/Photo.mjs +19 -0
- package/xt/additional/Photo.mjs.map +1 -0
- package/xt/additional/Slug.cjs +21 -0
- package/xt/additional/Slug.cjs.map +1 -0
- package/xt/additional/Slug.d.ts +6 -0
- package/xt/additional/Slug.mjs +19 -0
- package/xt/additional/Slug.mjs.map +1 -0
- package/xt/additional/Url.cjs +26 -0
- package/xt/additional/Url.cjs.map +1 -0
- package/xt/additional/Url.d.ts +6 -0
- package/xt/additional/Url.mjs +24 -0
- package/xt/additional/Url.mjs.map +1 -0
- package/xt/additional/Username.cjs +21 -0
- package/xt/additional/Username.cjs.map +1 -0
- package/xt/additional/Username.d.ts +6 -0
- package/xt/additional/Username.mjs +19 -0
- package/xt/additional/Username.mjs.map +1 -0
- package/xt/fields/Array.cjs +9 -2
- package/xt/fields/Array.cjs.map +1 -1
- package/xt/fields/Array.d.ts +2 -0
- package/xt/fields/Array.mjs +9 -2
- package/xt/fields/Array.mjs.map +1 -1
- package/xt/fields/Boolean.cjs +10 -5
- package/xt/fields/Boolean.cjs.map +1 -1
- package/xt/fields/Boolean.d.ts +2 -0
- package/xt/fields/Boolean.mjs +10 -5
- package/xt/fields/Boolean.mjs.map +1 -1
- package/xt/fields/Date.cjs +12 -12
- package/xt/fields/Date.cjs.map +1 -1
- package/xt/fields/Date.d.ts +2 -0
- package/xt/fields/Date.mjs +12 -12
- package/xt/fields/Date.mjs.map +1 -1
- package/xt/fields/Enum.cjs +10 -4
- package/xt/fields/Enum.cjs.map +1 -1
- package/xt/fields/Enum.d.ts +2 -0
- package/xt/fields/Enum.mjs +10 -4
- package/xt/fields/Enum.mjs.map +1 -1
- package/xt/fields/File.cjs +9 -2
- package/xt/fields/File.cjs.map +1 -1
- package/xt/fields/File.d.ts +2 -0
- package/xt/fields/File.mjs +9 -2
- package/xt/fields/File.mjs.map +1 -1
- package/xt/fields/IDField.cjs +8 -0
- package/xt/fields/IDField.cjs.map +1 -1
- package/xt/fields/IDField.d.ts +2 -0
- package/xt/fields/IDField.mjs +8 -0
- package/xt/fields/IDField.mjs.map +1 -1
- package/xt/fields/Number.cjs +10 -5
- package/xt/fields/Number.cjs.map +1 -1
- package/xt/fields/Number.d.ts +2 -0
- package/xt/fields/Number.mjs +10 -5
- package/xt/fields/Number.mjs.map +1 -1
- package/xt/fields/Object.cjs +10 -5
- package/xt/fields/Object.cjs.map +1 -1
- package/xt/fields/Object.d.ts +2 -0
- package/xt/fields/Object.mjs +10 -5
- package/xt/fields/Object.mjs.map +1 -1
- package/xt/fields/Record.cjs +10 -5
- package/xt/fields/Record.cjs.map +1 -1
- package/xt/fields/Record.d.ts +2 -0
- package/xt/fields/Record.mjs +10 -5
- package/xt/fields/Record.mjs.map +1 -1
- package/xt/fields/Schema.cjs +12 -1
- package/xt/fields/Schema.cjs.map +1 -1
- package/xt/fields/Schema.d.ts +4 -1
- package/xt/fields/Schema.mjs +12 -1
- package/xt/fields/Schema.mjs.map +1 -1
- package/xt/fields/String.cjs +12 -9
- package/xt/fields/String.cjs.map +1 -1
- package/xt/fields/String.d.ts +2 -0
- package/xt/fields/String.mjs +12 -9
- package/xt/fields/String.mjs.map +1 -1
- package/xt/fields/Tuple.cjs +10 -5
- package/xt/fields/Tuple.cjs.map +1 -1
- package/xt/fields/Tuple.d.ts +2 -0
- package/xt/fields/Tuple.mjs +10 -5
- package/xt/fields/Tuple.mjs.map +1 -1
- package/xt/fields/Union.cjs +10 -5
- package/xt/fields/Union.cjs.map +1 -1
- package/xt/fields/Union.d.ts +2 -0
- package/xt/fields/Union.mjs +10 -5
- package/xt/fields/Union.mjs.map +1 -1
- package/xt/index.cjs +16 -100
- package/xt/index.cjs.map +1 -1
- package/xt/index.d.ts +16 -9
- package/xt/index.mjs +16 -100
- package/xt/index.mjs.map +1 -1
- package/core/classes/ModelFormatter.cjs.map +0 -1
- package/core/classes/ModelFormatter.mjs.map +0 -1
|
@@ -7,65 +7,86 @@ var core_XansqlError = require('../XansqlError.cjs');
|
|
|
7
7
|
/**
|
|
8
8
|
* this class will format the models and assign relationships
|
|
9
9
|
*/
|
|
10
|
-
class
|
|
10
|
+
class ModelFactgory {
|
|
11
11
|
constructor(xansql) {
|
|
12
12
|
this.isFormated = false;
|
|
13
|
-
this.restricted_columns = [
|
|
14
|
-
|
|
15
|
-
// "OPTIONAL", "NULLABLE", "META", "METAARRAY", "SCHEMA", "ARRAY",
|
|
16
|
-
// "EQUALS", "NOT", "LT", "LTE", "GT", "GTE", "IN", "NOTIN", "BETWEEN", "NOTBETWEEN", "CONTAINS", "NOTCONTAINS", "STARTSWITH", "ENDSWITH", "ISNULL", "ISNOTNULL", "ISEMPTY", "ISNOTEMPTY", "ISTRUE", "ISFALSE",
|
|
17
|
-
// "AGGREGATE",
|
|
18
|
-
];
|
|
13
|
+
this.restricted_columns = [];
|
|
14
|
+
this.models = new Map();
|
|
19
15
|
this.xansql = xansql;
|
|
20
16
|
}
|
|
21
17
|
restrictedColumn(column) {
|
|
22
18
|
return this.restricted_columns.includes(column.toUpperCase());
|
|
23
19
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Topological sort with cycle detection
|
|
22
|
+
*/
|
|
23
|
+
sortModelsByDependencies(models) {
|
|
24
|
+
const graph = new Map();
|
|
25
|
+
const visiting = new Set();
|
|
26
|
+
const visited = new Set();
|
|
27
|
+
const result = [];
|
|
28
|
+
// build dependency graph
|
|
29
|
+
for (const [table, model] of models) {
|
|
30
|
+
const deps = new Set();
|
|
31
|
+
for (const column in model.schema) {
|
|
32
|
+
const field = model.schema[column];
|
|
36
33
|
if (core_classes_ForeignInfo.isSchema(field)) {
|
|
37
|
-
|
|
38
|
-
const foreignTable = foreignInfo.table;
|
|
39
|
-
const indexOfMainTable = sortedTables.indexOf(table);
|
|
40
|
-
const indexOfForeignTable = sortedTables.indexOf(foreignTable);
|
|
41
|
-
if (indexOfForeignTable === -1) {
|
|
42
|
-
// foreign table not in sorted list, add it before main table
|
|
43
|
-
sortedTables.splice(indexOfMainTable, 0, foreignTable);
|
|
44
|
-
}
|
|
45
|
-
else if (indexOfForeignTable > indexOfMainTable) {
|
|
46
|
-
// foreign table is after main table, move it before
|
|
47
|
-
sortedTables.splice(indexOfForeignTable, 1);
|
|
48
|
-
sortedTables.splice(indexOfMainTable, 0, foreignTable);
|
|
49
|
-
}
|
|
34
|
+
deps.add(field.table);
|
|
50
35
|
}
|
|
51
36
|
}
|
|
52
|
-
|
|
53
|
-
|
|
37
|
+
graph.set(table, deps);
|
|
38
|
+
}
|
|
39
|
+
const visit = (table) => {
|
|
40
|
+
if (visiting.has(table)) {
|
|
41
|
+
throw new core_XansqlError({
|
|
42
|
+
message: `Circular foreign key detected involving "${table}"`,
|
|
43
|
+
model: table
|
|
44
|
+
});
|
|
54
45
|
}
|
|
46
|
+
if (visited.has(table))
|
|
47
|
+
return;
|
|
48
|
+
visiting.add(table);
|
|
49
|
+
const deps = graph.get(table);
|
|
50
|
+
if (deps) {
|
|
51
|
+
for (const dep of deps) {
|
|
52
|
+
if (!models.has(dep)) {
|
|
53
|
+
throw new core_XansqlError({
|
|
54
|
+
message: `Foreign model "${dep}" not found while sorting "${table}"`,
|
|
55
|
+
model: table
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
visit(dep);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
visiting.delete(table);
|
|
62
|
+
visited.add(table);
|
|
63
|
+
result.push(table);
|
|
64
|
+
};
|
|
65
|
+
for (const table of models.keys()) {
|
|
66
|
+
visit(table);
|
|
55
67
|
}
|
|
56
|
-
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
format() {
|
|
71
|
+
if (this.isFormated) {
|
|
72
|
+
return this.models;
|
|
73
|
+
}
|
|
74
|
+
const models = this.models;
|
|
75
|
+
// Proper, safe table sorting
|
|
76
|
+
const sortedTables = this.sortModelsByDependencies(models);
|
|
77
|
+
// rebuild model map in correct order
|
|
57
78
|
const sortedModels = new Map();
|
|
58
|
-
for (
|
|
79
|
+
for (const table of sortedTables) {
|
|
59
80
|
const model = models.get(table);
|
|
60
81
|
sortedModels.set(table, model);
|
|
61
82
|
}
|
|
62
|
-
// assign relationships
|
|
63
83
|
models.clear();
|
|
64
|
-
for (
|
|
84
|
+
for (const [table, model] of sortedModels) {
|
|
65
85
|
models.set(table, model);
|
|
66
86
|
}
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
// relationship wiring
|
|
88
|
+
for (const model of models.values()) {
|
|
89
|
+
for (const column in model.schema) {
|
|
69
90
|
if (this.restrictedColumn(column)) {
|
|
70
91
|
throw new core_XansqlError({
|
|
71
92
|
message: `Column name "${column}" in model "${model.table}" is restricted and cannot be used.`,
|
|
@@ -73,7 +94,7 @@ class ModelFormatter {
|
|
|
73
94
|
column,
|
|
74
95
|
});
|
|
75
96
|
}
|
|
76
|
-
|
|
97
|
+
const field = model.schema[column];
|
|
77
98
|
if (core_classes_ForeignInfo.isSchema(field)) {
|
|
78
99
|
this.formatIsSchema(model, column);
|
|
79
100
|
}
|
|
@@ -82,19 +103,21 @@ class ModelFormatter {
|
|
|
82
103
|
}
|
|
83
104
|
}
|
|
84
105
|
}
|
|
106
|
+
this.isFormated = true;
|
|
85
107
|
return models;
|
|
86
108
|
}
|
|
87
109
|
formatIsSchema(model, column) {
|
|
88
|
-
const models = this.
|
|
89
|
-
|
|
110
|
+
const models = this.models;
|
|
111
|
+
const field = model.schema[column];
|
|
90
112
|
const FModel = models.get(field.table);
|
|
91
113
|
if (!FModel) {
|
|
92
114
|
throw new core_XansqlError({
|
|
93
|
-
message: `Foreign model ${field.table} not found for ${model.table}.${column}`,
|
|
115
|
+
message: `Foreign model "${field.table}" not found for ${model.table}.${column}`,
|
|
94
116
|
model: model.table,
|
|
95
117
|
column
|
|
96
118
|
});
|
|
97
119
|
}
|
|
120
|
+
// ensure reciprocal field exists
|
|
98
121
|
if (field.column in FModel.schema) {
|
|
99
122
|
const foreignCol = FModel.schema[field.column];
|
|
100
123
|
if (core_classes_ForeignInfo.isArray(foreignCol)) {
|
|
@@ -117,26 +140,29 @@ class ModelFormatter {
|
|
|
117
140
|
}
|
|
118
141
|
else {
|
|
119
142
|
const n = xt_index.schema(model.table, column).nullable();
|
|
120
|
-
n.dynamic = true;
|
|
143
|
+
n.dynamic = true;
|
|
121
144
|
FModel.schema[field.column] = xt_index.array(n);
|
|
122
145
|
models.set(FModel.table, FModel);
|
|
123
146
|
}
|
|
124
147
|
}
|
|
125
148
|
formatIsArray(model, column) {
|
|
126
|
-
|
|
127
|
-
|
|
149
|
+
var _a, _b, _c, _d;
|
|
150
|
+
const models = this.models;
|
|
151
|
+
const field = model.schema[column];
|
|
128
152
|
const FSchemaField = field.type;
|
|
129
153
|
const FModel = models.get(FSchemaField.table);
|
|
130
154
|
if (!FModel) {
|
|
131
155
|
throw new core_XansqlError({
|
|
132
|
-
message: `Foreign model ${FSchemaField.table} not found for ${model.table}.${column}`,
|
|
156
|
+
message: `Foreign model "${FSchemaField.table}" not found for ${model.table}.${column}`,
|
|
133
157
|
model: model.table,
|
|
134
158
|
column
|
|
135
159
|
});
|
|
136
160
|
}
|
|
137
161
|
if (FSchemaField.column in FModel.schema) {
|
|
138
162
|
const foreignCol = FModel.schema[FSchemaField.column];
|
|
139
|
-
if (!core_classes_ForeignInfo.isSchema(foreignCol) ||
|
|
163
|
+
if (!core_classes_ForeignInfo.isSchema(foreignCol) ||
|
|
164
|
+
foreignCol.table !== model.table ||
|
|
165
|
+
foreignCol.column !== column) {
|
|
140
166
|
throw new core_XansqlError({
|
|
141
167
|
message: `Foreign column ${FSchemaField.table}.${FSchemaField.column} does not reference back to ${model.table}.${column}`,
|
|
142
168
|
model: model.table,
|
|
@@ -146,20 +172,20 @@ class ModelFormatter {
|
|
|
146
172
|
}
|
|
147
173
|
else {
|
|
148
174
|
const n = xt_index.schema(model.table, column);
|
|
149
|
-
if (FSchemaField.meta.nullable)
|
|
175
|
+
if ((_a = FSchemaField.meta) === null || _a === void 0 ? void 0 : _a.nullable)
|
|
150
176
|
n.nullable();
|
|
151
|
-
if (FSchemaField.meta.optional)
|
|
177
|
+
if ((_b = FSchemaField.meta) === null || _b === void 0 ? void 0 : _b.optional)
|
|
152
178
|
n.optional();
|
|
153
|
-
if (FSchemaField.meta.default !== undefined)
|
|
179
|
+
if (((_c = FSchemaField.meta) === null || _c === void 0 ? void 0 : _c.default) !== undefined)
|
|
154
180
|
n.default(FSchemaField.meta.default);
|
|
155
|
-
if (FSchemaField.meta.transform)
|
|
181
|
+
if ((_d = FSchemaField.meta) === null || _d === void 0 ? void 0 : _d.transform)
|
|
156
182
|
n.transform(FSchemaField.meta.transform);
|
|
157
|
-
n.dynamic = true;
|
|
183
|
+
n.dynamic = true;
|
|
158
184
|
FModel.schema[FSchemaField.column] = n;
|
|
159
185
|
models.set(FModel.table, FModel);
|
|
160
186
|
}
|
|
161
187
|
}
|
|
162
188
|
}
|
|
163
189
|
|
|
164
|
-
module.exports =
|
|
165
|
-
//# sourceMappingURL=
|
|
190
|
+
module.exports = ModelFactgory;
|
|
191
|
+
//# sourceMappingURL=ModelFactory.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModelFactory.cjs","sources":["../../../src/core/classes/ModelFactory.ts"],"sourcesContent":["import xt from \"../../xt\";\nimport Model from \"../../model\";\nimport XqlSchema from \"../../xt/fields/Schema\";\nimport Xansql from \"../Xansql\";\nimport Foreign from \"./ForeignInfo\";\nimport XansqlError from \"../XansqlError\";\n\n/**\n * this class will format the models and assign relationships\n */\nclass ModelFactgory {\n private xansql: Xansql;\n private isFormated: boolean = false;\n private restricted_columns: string[] = [];\n readonly models: Map<string, Model> = new Map();\n\n constructor(xansql: Xansql) {\n this.xansql = xansql;\n }\n\n private restrictedColumn(column: string): boolean {\n return this.restricted_columns.includes(column.toUpperCase());\n }\n\n /**\n * Topological sort with cycle detection\n */\n private sortModelsByDependencies(models: Map<string, Model>): string[] {\n const graph = new Map<string, Set<string>>();\n const visiting = new Set<string>();\n const visited = new Set<string>();\n const result: string[] = [];\n\n // build dependency graph\n for (const [table, model] of models) {\n const deps = new Set<string>();\n for (const column in model.schema) {\n const field: any = model.schema[column];\n if (Foreign.isSchema(field)) {\n deps.add(field.table);\n }\n }\n graph.set(table, deps);\n }\n\n const visit = (table: string) => {\n if (visiting.has(table)) {\n throw new XansqlError({\n message: `Circular foreign key detected involving \"${table}\"`,\n model: table\n });\n }\n\n if (visited.has(table)) return;\n\n visiting.add(table);\n\n const deps = graph.get(table);\n if (deps) {\n for (const dep of deps) {\n if (!models.has(dep)) {\n throw new XansqlError({\n message: `Foreign model \"${dep}\" not found while sorting \"${table}\"`,\n model: table\n });\n }\n visit(dep);\n }\n }\n\n visiting.delete(table);\n visited.add(table);\n result.push(table);\n };\n\n for (const table of models.keys()) {\n visit(table);\n }\n\n return result;\n }\n\n format() {\n if (this.isFormated) {\n return this.models;\n }\n const models = this.models;\n\n // Proper, safe table sorting\n const sortedTables = this.sortModelsByDependencies(models);\n\n // rebuild model map in correct order\n const sortedModels = new Map<string, Model>();\n for (const table of sortedTables) {\n const model = models.get(table) as Model;\n sortedModels.set(table, model);\n }\n\n models.clear();\n for (const [table, model] of sortedModels) {\n models.set(table, model);\n }\n\n // relationship wiring\n for (const model of models.values()) {\n for (const column in model.schema) {\n if (this.restrictedColumn(column)) {\n throw new XansqlError({\n message: `Column name \"${column}\" in model \"${model.table}\" is restricted and cannot be used.`,\n model: model.table,\n column,\n });\n }\n\n const field: any = model.schema[column];\n\n if (Foreign.isSchema(field)) {\n this.formatIsSchema(model, column);\n } else if (Foreign.isArray(field)) {\n this.formatIsArray(model, column);\n }\n }\n }\n\n this.isFormated = true;\n return models;\n }\n\n private formatIsSchema(model: Model, column: string) {\n const models = this.models;\n const field: any = model.schema[column];\n\n const FModel = models.get(field.table);\n if (!FModel) {\n throw new XansqlError({\n message: `Foreign model \"${field.table}\" not found for ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n\n // ensure reciprocal field exists\n if (field.column in FModel.schema) {\n const foreignCol = FModel.schema[field.column];\n\n if (Foreign.isArray(foreignCol)) {\n const foreignType = (foreignCol as any).type as XqlSchema;\n if (foreignType.table !== model.table || foreignType.column !== column) {\n throw new XansqlError({\n message: `Foreign column ${field.table}.${field.column} does not reference back to ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n } else {\n throw new XansqlError({\n message: `Foreign column ${field.table}.${field.column} is not an array referencing back to ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n } else {\n const n = xt.schema(model.table, column).nullable();\n (n as any).dynamic = true;\n FModel.schema[field.column] = xt.array(n);\n models.set(FModel.table, FModel);\n }\n }\n\n private formatIsArray(model: Model, column: string) {\n const models = this.models;\n const field: any = model.schema[column];\n const FSchemaField = (field as any).type as XqlSchema;\n\n const FModel = models.get(FSchemaField.table);\n if (!FModel) {\n throw new XansqlError({\n message: `Foreign model \"${FSchemaField.table}\" not found for ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n\n if (FSchemaField.column in FModel.schema) {\n const foreignCol = FModel.schema[FSchemaField.column] as any;\n\n if (\n !Foreign.isSchema(foreignCol) ||\n foreignCol.table !== model.table ||\n foreignCol.column !== column\n ) {\n throw new XansqlError({\n message: `Foreign column ${FSchemaField.table}.${FSchemaField.column} does not reference back to ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n } else {\n const n = xt.schema(model.table, column);\n\n if (FSchemaField.meta?.nullable) n.nullable();\n if (FSchemaField.meta?.optional) n.optional();\n if (FSchemaField.meta?.default !== undefined) n.default(FSchemaField.meta.default);\n if (FSchemaField.meta?.transform) n.transform(FSchemaField.meta.transform);\n\n (n as any).dynamic = true;\n FModel.schema[FSchemaField.column] = n;\n models.set(FModel.table, FModel);\n }\n }\n}\n\nexport default ModelFactgory;\n"],"names":["Foreign","XansqlError","xt"],"mappings":"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"}
|
|
@@ -3,14 +3,19 @@ import Xansql from "../Xansql";
|
|
|
3
3
|
/**
|
|
4
4
|
* this class will format the models and assign relationships
|
|
5
5
|
*/
|
|
6
|
-
declare class
|
|
6
|
+
declare class ModelFactgory {
|
|
7
7
|
private xansql;
|
|
8
8
|
private isFormated;
|
|
9
9
|
private restricted_columns;
|
|
10
|
+
readonly models: Map<string, Model>;
|
|
10
11
|
constructor(xansql: Xansql);
|
|
11
12
|
private restrictedColumn;
|
|
13
|
+
/**
|
|
14
|
+
* Topological sort with cycle detection
|
|
15
|
+
*/
|
|
16
|
+
private sortModelsByDependencies;
|
|
12
17
|
format(): Map<string, Model>;
|
|
13
18
|
private formatIsSchema;
|
|
14
19
|
private formatIsArray;
|
|
15
20
|
}
|
|
16
|
-
export default
|
|
21
|
+
export default ModelFactgory;
|
|
@@ -5,65 +5,86 @@ import XansqlError from '../XansqlError.mjs';
|
|
|
5
5
|
/**
|
|
6
6
|
* this class will format the models and assign relationships
|
|
7
7
|
*/
|
|
8
|
-
class
|
|
8
|
+
class ModelFactgory {
|
|
9
9
|
constructor(xansql) {
|
|
10
10
|
this.isFormated = false;
|
|
11
|
-
this.restricted_columns = [
|
|
12
|
-
|
|
13
|
-
// "OPTIONAL", "NULLABLE", "META", "METAARRAY", "SCHEMA", "ARRAY",
|
|
14
|
-
// "EQUALS", "NOT", "LT", "LTE", "GT", "GTE", "IN", "NOTIN", "BETWEEN", "NOTBETWEEN", "CONTAINS", "NOTCONTAINS", "STARTSWITH", "ENDSWITH", "ISNULL", "ISNOTNULL", "ISEMPTY", "ISNOTEMPTY", "ISTRUE", "ISFALSE",
|
|
15
|
-
// "AGGREGATE",
|
|
16
|
-
];
|
|
11
|
+
this.restricted_columns = [];
|
|
12
|
+
this.models = new Map();
|
|
17
13
|
this.xansql = xansql;
|
|
18
14
|
}
|
|
19
15
|
restrictedColumn(column) {
|
|
20
16
|
return this.restricted_columns.includes(column.toUpperCase());
|
|
21
17
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Topological sort with cycle detection
|
|
20
|
+
*/
|
|
21
|
+
sortModelsByDependencies(models) {
|
|
22
|
+
const graph = new Map();
|
|
23
|
+
const visiting = new Set();
|
|
24
|
+
const visited = new Set();
|
|
25
|
+
const result = [];
|
|
26
|
+
// build dependency graph
|
|
27
|
+
for (const [table, model] of models) {
|
|
28
|
+
const deps = new Set();
|
|
29
|
+
for (const column in model.schema) {
|
|
30
|
+
const field = model.schema[column];
|
|
34
31
|
if (Foreign.isSchema(field)) {
|
|
35
|
-
|
|
36
|
-
const foreignTable = foreignInfo.table;
|
|
37
|
-
const indexOfMainTable = sortedTables.indexOf(table);
|
|
38
|
-
const indexOfForeignTable = sortedTables.indexOf(foreignTable);
|
|
39
|
-
if (indexOfForeignTable === -1) {
|
|
40
|
-
// foreign table not in sorted list, add it before main table
|
|
41
|
-
sortedTables.splice(indexOfMainTable, 0, foreignTable);
|
|
42
|
-
}
|
|
43
|
-
else if (indexOfForeignTable > indexOfMainTable) {
|
|
44
|
-
// foreign table is after main table, move it before
|
|
45
|
-
sortedTables.splice(indexOfForeignTable, 1);
|
|
46
|
-
sortedTables.splice(indexOfMainTable, 0, foreignTable);
|
|
47
|
-
}
|
|
32
|
+
deps.add(field.table);
|
|
48
33
|
}
|
|
49
34
|
}
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
graph.set(table, deps);
|
|
36
|
+
}
|
|
37
|
+
const visit = (table) => {
|
|
38
|
+
if (visiting.has(table)) {
|
|
39
|
+
throw new XansqlError({
|
|
40
|
+
message: `Circular foreign key detected involving "${table}"`,
|
|
41
|
+
model: table
|
|
42
|
+
});
|
|
52
43
|
}
|
|
44
|
+
if (visited.has(table))
|
|
45
|
+
return;
|
|
46
|
+
visiting.add(table);
|
|
47
|
+
const deps = graph.get(table);
|
|
48
|
+
if (deps) {
|
|
49
|
+
for (const dep of deps) {
|
|
50
|
+
if (!models.has(dep)) {
|
|
51
|
+
throw new XansqlError({
|
|
52
|
+
message: `Foreign model "${dep}" not found while sorting "${table}"`,
|
|
53
|
+
model: table
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
visit(dep);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
visiting.delete(table);
|
|
60
|
+
visited.add(table);
|
|
61
|
+
result.push(table);
|
|
62
|
+
};
|
|
63
|
+
for (const table of models.keys()) {
|
|
64
|
+
visit(table);
|
|
53
65
|
}
|
|
54
|
-
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
format() {
|
|
69
|
+
if (this.isFormated) {
|
|
70
|
+
return this.models;
|
|
71
|
+
}
|
|
72
|
+
const models = this.models;
|
|
73
|
+
// Proper, safe table sorting
|
|
74
|
+
const sortedTables = this.sortModelsByDependencies(models);
|
|
75
|
+
// rebuild model map in correct order
|
|
55
76
|
const sortedModels = new Map();
|
|
56
|
-
for (
|
|
77
|
+
for (const table of sortedTables) {
|
|
57
78
|
const model = models.get(table);
|
|
58
79
|
sortedModels.set(table, model);
|
|
59
80
|
}
|
|
60
|
-
// assign relationships
|
|
61
81
|
models.clear();
|
|
62
|
-
for (
|
|
82
|
+
for (const [table, model] of sortedModels) {
|
|
63
83
|
models.set(table, model);
|
|
64
84
|
}
|
|
65
|
-
|
|
66
|
-
|
|
85
|
+
// relationship wiring
|
|
86
|
+
for (const model of models.values()) {
|
|
87
|
+
for (const column in model.schema) {
|
|
67
88
|
if (this.restrictedColumn(column)) {
|
|
68
89
|
throw new XansqlError({
|
|
69
90
|
message: `Column name "${column}" in model "${model.table}" is restricted and cannot be used.`,
|
|
@@ -71,7 +92,7 @@ class ModelFormatter {
|
|
|
71
92
|
column,
|
|
72
93
|
});
|
|
73
94
|
}
|
|
74
|
-
|
|
95
|
+
const field = model.schema[column];
|
|
75
96
|
if (Foreign.isSchema(field)) {
|
|
76
97
|
this.formatIsSchema(model, column);
|
|
77
98
|
}
|
|
@@ -80,19 +101,21 @@ class ModelFormatter {
|
|
|
80
101
|
}
|
|
81
102
|
}
|
|
82
103
|
}
|
|
104
|
+
this.isFormated = true;
|
|
83
105
|
return models;
|
|
84
106
|
}
|
|
85
107
|
formatIsSchema(model, column) {
|
|
86
|
-
const models = this.
|
|
87
|
-
|
|
108
|
+
const models = this.models;
|
|
109
|
+
const field = model.schema[column];
|
|
88
110
|
const FModel = models.get(field.table);
|
|
89
111
|
if (!FModel) {
|
|
90
112
|
throw new XansqlError({
|
|
91
|
-
message: `Foreign model ${field.table} not found for ${model.table}.${column}`,
|
|
113
|
+
message: `Foreign model "${field.table}" not found for ${model.table}.${column}`,
|
|
92
114
|
model: model.table,
|
|
93
115
|
column
|
|
94
116
|
});
|
|
95
117
|
}
|
|
118
|
+
// ensure reciprocal field exists
|
|
96
119
|
if (field.column in FModel.schema) {
|
|
97
120
|
const foreignCol = FModel.schema[field.column];
|
|
98
121
|
if (Foreign.isArray(foreignCol)) {
|
|
@@ -115,26 +138,29 @@ class ModelFormatter {
|
|
|
115
138
|
}
|
|
116
139
|
else {
|
|
117
140
|
const n = xt.schema(model.table, column).nullable();
|
|
118
|
-
n.dynamic = true;
|
|
141
|
+
n.dynamic = true;
|
|
119
142
|
FModel.schema[field.column] = xt.array(n);
|
|
120
143
|
models.set(FModel.table, FModel);
|
|
121
144
|
}
|
|
122
145
|
}
|
|
123
146
|
formatIsArray(model, column) {
|
|
124
|
-
|
|
125
|
-
|
|
147
|
+
var _a, _b, _c, _d;
|
|
148
|
+
const models = this.models;
|
|
149
|
+
const field = model.schema[column];
|
|
126
150
|
const FSchemaField = field.type;
|
|
127
151
|
const FModel = models.get(FSchemaField.table);
|
|
128
152
|
if (!FModel) {
|
|
129
153
|
throw new XansqlError({
|
|
130
|
-
message: `Foreign model ${FSchemaField.table} not found for ${model.table}.${column}`,
|
|
154
|
+
message: `Foreign model "${FSchemaField.table}" not found for ${model.table}.${column}`,
|
|
131
155
|
model: model.table,
|
|
132
156
|
column
|
|
133
157
|
});
|
|
134
158
|
}
|
|
135
159
|
if (FSchemaField.column in FModel.schema) {
|
|
136
160
|
const foreignCol = FModel.schema[FSchemaField.column];
|
|
137
|
-
if (!Foreign.isSchema(foreignCol) ||
|
|
161
|
+
if (!Foreign.isSchema(foreignCol) ||
|
|
162
|
+
foreignCol.table !== model.table ||
|
|
163
|
+
foreignCol.column !== column) {
|
|
138
164
|
throw new XansqlError({
|
|
139
165
|
message: `Foreign column ${FSchemaField.table}.${FSchemaField.column} does not reference back to ${model.table}.${column}`,
|
|
140
166
|
model: model.table,
|
|
@@ -144,20 +170,20 @@ class ModelFormatter {
|
|
|
144
170
|
}
|
|
145
171
|
else {
|
|
146
172
|
const n = xt.schema(model.table, column);
|
|
147
|
-
if (FSchemaField.meta.nullable)
|
|
173
|
+
if ((_a = FSchemaField.meta) === null || _a === void 0 ? void 0 : _a.nullable)
|
|
148
174
|
n.nullable();
|
|
149
|
-
if (FSchemaField.meta.optional)
|
|
175
|
+
if ((_b = FSchemaField.meta) === null || _b === void 0 ? void 0 : _b.optional)
|
|
150
176
|
n.optional();
|
|
151
|
-
if (FSchemaField.meta.default !== undefined)
|
|
177
|
+
if (((_c = FSchemaField.meta) === null || _c === void 0 ? void 0 : _c.default) !== undefined)
|
|
152
178
|
n.default(FSchemaField.meta.default);
|
|
153
|
-
if (FSchemaField.meta.transform)
|
|
179
|
+
if ((_d = FSchemaField.meta) === null || _d === void 0 ? void 0 : _d.transform)
|
|
154
180
|
n.transform(FSchemaField.meta.transform);
|
|
155
|
-
n.dynamic = true;
|
|
181
|
+
n.dynamic = true;
|
|
156
182
|
FModel.schema[FSchemaField.column] = n;
|
|
157
183
|
models.set(FModel.table, FModel);
|
|
158
184
|
}
|
|
159
185
|
}
|
|
160
186
|
}
|
|
161
187
|
|
|
162
|
-
export {
|
|
163
|
-
//# sourceMappingURL=
|
|
188
|
+
export { ModelFactgory as default };
|
|
189
|
+
//# sourceMappingURL=ModelFactory.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModelFactory.mjs","sources":["../../../src/core/classes/ModelFactory.ts"],"sourcesContent":["import xt from \"../../xt\";\nimport Model from \"../../model\";\nimport XqlSchema from \"../../xt/fields/Schema\";\nimport Xansql from \"../Xansql\";\nimport Foreign from \"./ForeignInfo\";\nimport XansqlError from \"../XansqlError\";\n\n/**\n * this class will format the models and assign relationships\n */\nclass ModelFactgory {\n private xansql: Xansql;\n private isFormated: boolean = false;\n private restricted_columns: string[] = [];\n readonly models: Map<string, Model> = new Map();\n\n constructor(xansql: Xansql) {\n this.xansql = xansql;\n }\n\n private restrictedColumn(column: string): boolean {\n return this.restricted_columns.includes(column.toUpperCase());\n }\n\n /**\n * Topological sort with cycle detection\n */\n private sortModelsByDependencies(models: Map<string, Model>): string[] {\n const graph = new Map<string, Set<string>>();\n const visiting = new Set<string>();\n const visited = new Set<string>();\n const result: string[] = [];\n\n // build dependency graph\n for (const [table, model] of models) {\n const deps = new Set<string>();\n for (const column in model.schema) {\n const field: any = model.schema[column];\n if (Foreign.isSchema(field)) {\n deps.add(field.table);\n }\n }\n graph.set(table, deps);\n }\n\n const visit = (table: string) => {\n if (visiting.has(table)) {\n throw new XansqlError({\n message: `Circular foreign key detected involving \"${table}\"`,\n model: table\n });\n }\n\n if (visited.has(table)) return;\n\n visiting.add(table);\n\n const deps = graph.get(table);\n if (deps) {\n for (const dep of deps) {\n if (!models.has(dep)) {\n throw new XansqlError({\n message: `Foreign model \"${dep}\" not found while sorting \"${table}\"`,\n model: table\n });\n }\n visit(dep);\n }\n }\n\n visiting.delete(table);\n visited.add(table);\n result.push(table);\n };\n\n for (const table of models.keys()) {\n visit(table);\n }\n\n return result;\n }\n\n format() {\n if (this.isFormated) {\n return this.models;\n }\n const models = this.models;\n\n // Proper, safe table sorting\n const sortedTables = this.sortModelsByDependencies(models);\n\n // rebuild model map in correct order\n const sortedModels = new Map<string, Model>();\n for (const table of sortedTables) {\n const model = models.get(table) as Model;\n sortedModels.set(table, model);\n }\n\n models.clear();\n for (const [table, model] of sortedModels) {\n models.set(table, model);\n }\n\n // relationship wiring\n for (const model of models.values()) {\n for (const column in model.schema) {\n if (this.restrictedColumn(column)) {\n throw new XansqlError({\n message: `Column name \"${column}\" in model \"${model.table}\" is restricted and cannot be used.`,\n model: model.table,\n column,\n });\n }\n\n const field: any = model.schema[column];\n\n if (Foreign.isSchema(field)) {\n this.formatIsSchema(model, column);\n } else if (Foreign.isArray(field)) {\n this.formatIsArray(model, column);\n }\n }\n }\n\n this.isFormated = true;\n return models;\n }\n\n private formatIsSchema(model: Model, column: string) {\n const models = this.models;\n const field: any = model.schema[column];\n\n const FModel = models.get(field.table);\n if (!FModel) {\n throw new XansqlError({\n message: `Foreign model \"${field.table}\" not found for ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n\n // ensure reciprocal field exists\n if (field.column in FModel.schema) {\n const foreignCol = FModel.schema[field.column];\n\n if (Foreign.isArray(foreignCol)) {\n const foreignType = (foreignCol as any).type as XqlSchema;\n if (foreignType.table !== model.table || foreignType.column !== column) {\n throw new XansqlError({\n message: `Foreign column ${field.table}.${field.column} does not reference back to ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n } else {\n throw new XansqlError({\n message: `Foreign column ${field.table}.${field.column} is not an array referencing back to ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n } else {\n const n = xt.schema(model.table, column).nullable();\n (n as any).dynamic = true;\n FModel.schema[field.column] = xt.array(n);\n models.set(FModel.table, FModel);\n }\n }\n\n private formatIsArray(model: Model, column: string) {\n const models = this.models;\n const field: any = model.schema[column];\n const FSchemaField = (field as any).type as XqlSchema;\n\n const FModel = models.get(FSchemaField.table);\n if (!FModel) {\n throw new XansqlError({\n message: `Foreign model \"${FSchemaField.table}\" not found for ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n\n if (FSchemaField.column in FModel.schema) {\n const foreignCol = FModel.schema[FSchemaField.column] as any;\n\n if (\n !Foreign.isSchema(foreignCol) ||\n foreignCol.table !== model.table ||\n foreignCol.column !== column\n ) {\n throw new XansqlError({\n message: `Foreign column ${FSchemaField.table}.${FSchemaField.column} does not reference back to ${model.table}.${column}`,\n model: model.table,\n column\n });\n }\n } else {\n const n = xt.schema(model.table, column);\n\n if (FSchemaField.meta?.nullable) n.nullable();\n if (FSchemaField.meta?.optional) n.optional();\n if (FSchemaField.meta?.default !== undefined) n.default(FSchemaField.meta.default);\n if (FSchemaField.meta?.transform) n.transform(FSchemaField.meta.transform);\n\n (n as any).dynamic = true;\n FModel.schema[FSchemaField.column] = n;\n models.set(FModel.table, FModel);\n }\n }\n}\n\nexport default ModelFactgory;\n"],"names":[],"mappings":"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"}
|
package/core/types.d.ts
CHANGED
|
@@ -48,9 +48,9 @@ export type XansqlFileConfig = {
|
|
|
48
48
|
};
|
|
49
49
|
export type XansqlDialect = {
|
|
50
50
|
engine: XansqlDialectEngine;
|
|
51
|
+
file?: XansqlFileConfig;
|
|
51
52
|
execute: (sql: string, xansql: Xansql) => Promise<ExecuterResult | null>;
|
|
52
53
|
getSchema: (xansql: Xansql) => Promise<XansqlDialectSchemaType | void>;
|
|
53
|
-
file?: XansqlFileConfig;
|
|
54
54
|
};
|
|
55
55
|
export type XansqlSocket = {
|
|
56
56
|
open: (socket: WebSocket) => Promise<void>;
|
package/dialect/MysqlDialect.cjs
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var tslib = require('tslib');
|
|
3
4
|
var mysql = require('mysql2/promise');
|
|
4
5
|
|
|
5
|
-
const MysqlDialect = (
|
|
6
|
+
const MysqlDialect = (_a) => {
|
|
7
|
+
var { file } = _a, config = tslib.__rest(_a, ["file"]);
|
|
6
8
|
const pool = mysql.createPool(typeof config === 'string' ? { uri: config } : config);
|
|
7
|
-
const execute = async (sql
|
|
9
|
+
const execute = async (sql) => {
|
|
8
10
|
var _a, _b;
|
|
9
11
|
const conn = await pool.getConnection();
|
|
10
12
|
try {
|
|
11
|
-
const [rows] = await conn.query(sql
|
|
13
|
+
const [rows] = await conn.query(sql);
|
|
12
14
|
const result = rows;
|
|
13
15
|
return {
|
|
14
16
|
results: result,
|
|
@@ -66,7 +68,8 @@ const MysqlDialect = (config) => {
|
|
|
66
68
|
return {
|
|
67
69
|
engine: 'mysql',
|
|
68
70
|
execute,
|
|
69
|
-
getSchema
|
|
71
|
+
getSchema,
|
|
72
|
+
file
|
|
70
73
|
};
|
|
71
74
|
};
|
|
72
75
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MysqlDialect.cjs","sources":["../../src/dialect/MysqlDialect.ts"],"sourcesContent":["import { PoolOptions } from 'mysql2';\nimport mysql from 'mysql2/promise';\nimport { ExecuterResult } from '../core/types';\n\nconst MysqlDialect = (config:
|
|
1
|
+
{"version":3,"file":"MysqlDialect.cjs","sources":["../../src/dialect/MysqlDialect.ts"],"sourcesContent":["import { PoolOptions } from 'mysql2';\nimport mysql from 'mysql2/promise';\nimport { ExecuterResult, XansqlDialectEngine, XansqlFileConfig } from '../core/types';\n\nconst MysqlDialect = ({ file, ...config }: PoolOptions & { file?: XansqlFileConfig }) => {\n const pool = mysql.createPool(typeof config === 'string' ? { uri: config } : config);\n\n const execute = async (sql: string): Promise<ExecuterResult> => {\n const conn = await pool.getConnection();\n try {\n const [rows] = await conn.query(sql);\n const result: any = rows;\n\n return {\n results: result,\n insertId: result?.insertId ?? 0,\n affectedRows: result?.affectedRows ?? 0\n };\n } finally {\n conn.release();\n }\n };\n\n const getSchema = async () => {\n const conn = await pool.getConnection();\n\n try {\n const [tables] = await conn.query<any[]>(\n `SELECT table_name as name\n FROM information_schema.tables \n WHERE table_schema = DATABASE();`\n );\n\n const schema: Record<string, any[]> = {};\n\n for (const t of tables) {\n const table = t.name;\n schema[table] = [];\n\n // Columns\n const [columns] = await conn.query<any[]>(\n `SELECT \n COLUMN_NAME as name,\n COLUMN_TYPE as type,\n IS_NULLABLE,\n COLUMN_DEFAULT,\n COLUMN_KEY\n FROM information_schema.columns\n WHERE table_schema = DATABASE()\n AND table_name = ?`,\n [table]\n );\n\n // Indexes\n const [indexes] = await conn.query<any[]>(\n `SHOW INDEX FROM \\`${table}\\``\n );\n\n for (const col of columns) {\n const colName = col.name;\n\n const isIndexed = indexes.some(i => i.Column_name === colName);\n const isUnique = indexes.some(i => i.Column_name === colName && i.Non_unique === 0);\n\n schema[table].push({\n name: colName,\n type: col.type,\n notnull: col.IS_NULLABLE === \"NO\",\n default_value: col.COLUMN_DEFAULT,\n pk: col.COLUMN_KEY === \"PRI\",\n index: isIndexed,\n unique: isUnique,\n });\n }\n }\n\n return schema;\n } finally {\n conn.release();\n }\n };\n\n return {\n engine: 'mysql' as XansqlDialectEngine,\n execute,\n getSchema,\n file\n };\n};\n\nexport default MysqlDialect;\n"],"names":["__rest"],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { PoolOptions } from 'mysql2';
|
|
2
|
-
import { ExecuterResult } from '../core/types';
|
|
3
|
-
declare const MysqlDialect: (config:
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { ExecuterResult, XansqlDialectEngine, XansqlFileConfig } from '../core/types';
|
|
3
|
+
declare const MysqlDialect: ({ file, ...config }: PoolOptions & {
|
|
4
|
+
file?: XansqlFileConfig;
|
|
5
|
+
}) => {
|
|
6
|
+
engine: XansqlDialectEngine;
|
|
7
|
+
execute: (sql: string) => Promise<ExecuterResult>;
|
|
6
8
|
getSchema: () => Promise<Record<string, any[]>>;
|
|
9
|
+
file: XansqlFileConfig;
|
|
7
10
|
};
|
|
8
11
|
export default MysqlDialect;
|
package/dialect/MysqlDialect.mjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { __rest } from 'tslib';
|
|
1
2
|
import mysql from 'mysql2/promise';
|
|
2
3
|
|
|
3
|
-
const MysqlDialect = (
|
|
4
|
+
const MysqlDialect = (_a) => {
|
|
5
|
+
var { file } = _a, config = __rest(_a, ["file"]);
|
|
4
6
|
const pool = mysql.createPool(typeof config === 'string' ? { uri: config } : config);
|
|
5
|
-
const execute = async (sql
|
|
7
|
+
const execute = async (sql) => {
|
|
6
8
|
var _a, _b;
|
|
7
9
|
const conn = await pool.getConnection();
|
|
8
10
|
try {
|
|
9
|
-
const [rows] = await conn.query(sql
|
|
11
|
+
const [rows] = await conn.query(sql);
|
|
10
12
|
const result = rows;
|
|
11
13
|
return {
|
|
12
14
|
results: result,
|
|
@@ -64,7 +66,8 @@ const MysqlDialect = (config) => {
|
|
|
64
66
|
return {
|
|
65
67
|
engine: 'mysql',
|
|
66
68
|
execute,
|
|
67
|
-
getSchema
|
|
69
|
+
getSchema,
|
|
70
|
+
file
|
|
68
71
|
};
|
|
69
72
|
};
|
|
70
73
|
|