@nocobase/database 0.15.0-alpha.3 → 0.15.0-alpha.5
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/lib/collection-factory.d.ts +10 -3
- package/lib/collection-factory.js +8 -7
- package/lib/collection.js +0 -4
- package/lib/database.d.ts +6 -0
- package/lib/database.js +42 -11
- package/lib/fields/field.js +1 -1
- package/lib/fields/has-many-field.js +10 -0
- package/lib/fields/sort-field.js +42 -31
- package/lib/helpers.d.ts +2 -1
- package/lib/helpers.js +52 -0
- package/lib/model.d.ts +1 -1
- package/lib/model.js +48 -42
- package/lib/operators/utils.js +1 -1
- package/lib/options-parser.js +1 -1
- package/lib/query-interface/mysql-query-interface.d.ts +4 -0
- package/lib/query-interface/mysql-query-interface.js +6 -0
- package/lib/query-interface/postgres-query-interface.d.ts +4 -0
- package/lib/query-interface/postgres-query-interface.js +27 -0
- package/lib/query-interface/query-interface-builder.js +1 -0
- package/lib/query-interface/query-interface.d.ts +4 -0
- package/lib/query-interface/sqlite-query-interface.d.ts +4 -0
- package/lib/query-interface/sqlite-query-interface.js +3 -0
- package/lib/view/field-type-map.d.ts +14 -0
- package/lib/view/field-type-map.js +1 -1
- package/lib/view/view-inference.d.ts +1 -1
- package/lib/view/view-inference.js +9 -3
- package/package.json +4 -4
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { Collection, CollectionOptions } from './collection';
|
|
2
2
|
import Database from './database';
|
|
3
|
+
import { Model } from './model';
|
|
4
|
+
type CollectionTypeOptions = {
|
|
5
|
+
condition: (options: CollectionOptions) => boolean;
|
|
6
|
+
onSync?: (model: typeof Model, options: any) => Promise<void>;
|
|
7
|
+
};
|
|
3
8
|
export declare class CollectionFactory {
|
|
4
9
|
private database;
|
|
5
|
-
|
|
10
|
+
collectionTypes: Map<typeof Collection, CollectionTypeOptions>;
|
|
6
11
|
constructor(database: Database);
|
|
7
|
-
registerCollectionType(collectionClass: typeof Collection,
|
|
8
|
-
|
|
12
|
+
registerCollectionType(collectionClass: typeof Collection, // Using the collection class as the key
|
|
13
|
+
options: CollectionTypeOptions): void;
|
|
14
|
+
createCollection<T extends Collection>(collectionOptions: CollectionOptions): T;
|
|
9
15
|
}
|
|
16
|
+
export {};
|
|
@@ -26,19 +26,20 @@ const _CollectionFactory = class _CollectionFactory {
|
|
|
26
26
|
constructor(database) {
|
|
27
27
|
this.database = database;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
// Using a Map with the collection subclass as the key and options as the value
|
|
30
|
+
collectionTypes = /* @__PURE__ */ new Map();
|
|
31
|
+
registerCollectionType(collectionClass, options) {
|
|
32
|
+
this.collectionTypes.set(collectionClass, options);
|
|
32
33
|
}
|
|
33
|
-
createCollection(
|
|
34
|
+
createCollection(collectionOptions) {
|
|
34
35
|
let klass = import_collection.Collection;
|
|
35
|
-
for (const
|
|
36
|
-
if (condition(
|
|
36
|
+
for (const [ctor, options] of this.collectionTypes) {
|
|
37
|
+
if (options.condition(collectionOptions)) {
|
|
37
38
|
klass = ctor;
|
|
38
39
|
break;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
|
-
return new klass(
|
|
42
|
+
return new klass(collectionOptions, {
|
|
42
43
|
database: this.database
|
|
43
44
|
});
|
|
44
45
|
}
|
package/lib/collection.js
CHANGED
|
@@ -64,10 +64,6 @@ function EnsureAtomicity(target, propertyKey, descriptor) {
|
|
|
64
64
|
}
|
|
65
65
|
const afterRawAttributes = Object.keys(model.rawAttributes);
|
|
66
66
|
const createdRawAttributes = import_lodash.default.difference(afterRawAttributes, beforeRawAttributes);
|
|
67
|
-
console.log({
|
|
68
|
-
beforeRawAttributes,
|
|
69
|
-
afterRawAttributes
|
|
70
|
-
});
|
|
71
67
|
for (const key of createdRawAttributes) {
|
|
72
68
|
delete this.model.rawAttributes[key];
|
|
73
69
|
}
|
package/lib/database.d.ts
CHANGED
|
@@ -65,6 +65,10 @@ export declare const DialectVersionAccessors: {
|
|
|
65
65
|
sql: string;
|
|
66
66
|
get: (v: string) => string;
|
|
67
67
|
};
|
|
68
|
+
mariadb: {
|
|
69
|
+
sql: string;
|
|
70
|
+
get: (v: string) => string;
|
|
71
|
+
};
|
|
68
72
|
postgres: {
|
|
69
73
|
sql: string;
|
|
70
74
|
get: (v: string) => string;
|
|
@@ -116,6 +120,7 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
|
|
|
116
120
|
addMigration(item: MigrationItem): void;
|
|
117
121
|
addMigrations(options: AddMigrationsOptions): void;
|
|
118
122
|
inDialect(...dialect: string[]): boolean;
|
|
123
|
+
isMySQLCompatibleDialect(): boolean;
|
|
119
124
|
/**
|
|
120
125
|
* Add collection to database
|
|
121
126
|
* @param options
|
|
@@ -151,6 +156,7 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
|
|
|
151
156
|
auth(options?: Omit<QueryOptions, 'retry'> & {
|
|
152
157
|
retry?: number | Pick<QueryOptions, 'retry'>;
|
|
153
158
|
}): Promise<void>;
|
|
159
|
+
checkVersion(): Promise<boolean>;
|
|
154
160
|
prepare(): Promise<void>;
|
|
155
161
|
reconnect(): Promise<void>;
|
|
156
162
|
closed(): any;
|
package/lib/database.js
CHANGED
|
@@ -64,6 +64,8 @@ var import_utils2 = require("./utils");
|
|
|
64
64
|
var import_value_parsers = require("./value-parsers");
|
|
65
65
|
var import_view_collection = require("./view-collection");
|
|
66
66
|
var import_collection_factory = require("./collection-factory");
|
|
67
|
+
var import_chalk = __toESM(require("chalk"));
|
|
68
|
+
var import_helpers = require("./helpers");
|
|
67
69
|
const DialectVersionAccessors = {
|
|
68
70
|
sqlite: {
|
|
69
71
|
sql: "select sqlite_version() as version",
|
|
@@ -72,9 +74,13 @@ const DialectVersionAccessors = {
|
|
|
72
74
|
mysql: {
|
|
73
75
|
sql: "select version() as version",
|
|
74
76
|
get: (v) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
const m = /([\d+.]+)/.exec(v);
|
|
78
|
+
return m[0];
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
mariadb: {
|
|
82
|
+
sql: "select version() as version",
|
|
83
|
+
get: (v) => {
|
|
78
84
|
const m = /([\d+.]+)/.exec(v);
|
|
79
85
|
return m[0];
|
|
80
86
|
}
|
|
@@ -101,7 +107,11 @@ const _DatabaseVersion = class _DatabaseVersion {
|
|
|
101
107
|
return false;
|
|
102
108
|
}
|
|
103
109
|
const [result] = await this.db.sequelize.query(accessors[dialect].sql);
|
|
104
|
-
|
|
110
|
+
const versionResult = accessors[dialect].get((_a = result == null ? void 0 : result[0]) == null ? void 0 : _a.version);
|
|
111
|
+
if (import_lodash.default.isPlainObject(versionResult) && versionResult.dialect) {
|
|
112
|
+
return import_semver.default.satisfies(versionResult.version, versions[versionResult.dialect]);
|
|
113
|
+
}
|
|
114
|
+
return import_semver.default.satisfies(versionResult, versions[dialect]);
|
|
105
115
|
}
|
|
106
116
|
}
|
|
107
117
|
return false;
|
|
@@ -231,14 +241,20 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
231
241
|
return this._instanceId;
|
|
232
242
|
}
|
|
233
243
|
registerCollectionType() {
|
|
234
|
-
this.collectionFactory.registerCollectionType(import_inherited_collection.InheritedCollection,
|
|
235
|
-
|
|
244
|
+
this.collectionFactory.registerCollectionType(import_inherited_collection.InheritedCollection, {
|
|
245
|
+
condition: (options) => {
|
|
246
|
+
return options.inherits && import_lodash.default.castArray(options.inherits).length > 0;
|
|
247
|
+
}
|
|
236
248
|
});
|
|
237
|
-
this.collectionFactory.registerCollectionType(import_view_collection.ViewCollection,
|
|
238
|
-
|
|
249
|
+
this.collectionFactory.registerCollectionType(import_view_collection.ViewCollection, {
|
|
250
|
+
condition: (options) => {
|
|
251
|
+
return options.viewName || options.view;
|
|
252
|
+
}
|
|
239
253
|
});
|
|
240
|
-
this.collectionFactory.registerCollectionType(import_sql_collection.SqlCollection,
|
|
241
|
-
|
|
254
|
+
this.collectionFactory.registerCollectionType(import_sql_collection.SqlCollection, {
|
|
255
|
+
condition: (options) => {
|
|
256
|
+
return options.sql;
|
|
257
|
+
}
|
|
242
258
|
});
|
|
243
259
|
}
|
|
244
260
|
setContext(context) {
|
|
@@ -354,6 +370,9 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
354
370
|
inDialect(...dialect) {
|
|
355
371
|
return dialect.includes(this.sequelize.getDialect());
|
|
356
372
|
}
|
|
373
|
+
isMySQLCompatibleDialect() {
|
|
374
|
+
return this.inDialect("mysql", "mariadb");
|
|
375
|
+
}
|
|
357
376
|
/**
|
|
358
377
|
* Add collection to database
|
|
359
378
|
* @param options
|
|
@@ -502,7 +521,7 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
502
521
|
return new Field2(options, context);
|
|
503
522
|
}
|
|
504
523
|
async sync(options) {
|
|
505
|
-
const isMySQL = this.
|
|
524
|
+
const isMySQL = this.isMySQLCompatibleDialect();
|
|
506
525
|
if (isMySQL) {
|
|
507
526
|
await this.sequelize.query("SET FOREIGN_KEY_CHECKS = 0", null);
|
|
508
527
|
}
|
|
@@ -572,7 +591,19 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
572
591
|
throw new Error("Connection failed, please check your database connection credentials and try again.");
|
|
573
592
|
}
|
|
574
593
|
}
|
|
594
|
+
async checkVersion() {
|
|
595
|
+
return await (0, import_helpers.checkDatabaseVersion)(this);
|
|
596
|
+
}
|
|
575
597
|
async prepare() {
|
|
598
|
+
if (this.isMySQLCompatibleDialect()) {
|
|
599
|
+
const result = await this.sequelize.query(`SHOW VARIABLES LIKE 'lower_case_table_names'`, { plain: true });
|
|
600
|
+
if ((result == null ? void 0 : result.Value) === "1" && !this.options.underscored) {
|
|
601
|
+
console.log(
|
|
602
|
+
`Your database lower_case_table_names=1, please add ${import_chalk.default.yellow("DB_UNDERSCORED=true")} to the .env file`
|
|
603
|
+
);
|
|
604
|
+
process.exit();
|
|
605
|
+
}
|
|
606
|
+
}
|
|
576
607
|
if (this.inDialect("postgres") && this.options.schema && this.options.schema != "public") {
|
|
577
608
|
await this.sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${this.options.schema}"`, null);
|
|
578
609
|
}
|
package/lib/fields/field.js
CHANGED
|
@@ -151,7 +151,7 @@ const _Field = class _Field {
|
|
|
151
151
|
sql = `SELECT *
|
|
152
152
|
from pragma_table_info('${this.collection.model.tableName}')
|
|
153
153
|
WHERE name = '${this.columnName()}'`;
|
|
154
|
-
} else if (this.database.inDialect("mysql")) {
|
|
154
|
+
} else if (this.database.inDialect("mysql", "mariadb")) {
|
|
155
155
|
sql = `
|
|
156
156
|
select column_name
|
|
157
157
|
from INFORMATION_SCHEMA.COLUMNS
|
|
@@ -85,6 +85,16 @@ const _HasManyField = class _HasManyField extends import_relation_field.Relation
|
|
|
85
85
|
tcoll.addIndex([this.options.foreignKey]);
|
|
86
86
|
}
|
|
87
87
|
this.database.referenceMap.addReference(this.reference(association));
|
|
88
|
+
if (this.options.sortable) {
|
|
89
|
+
const targetCollection = database.modelCollection.get(this.TargetModel);
|
|
90
|
+
const sortFieldName = `${this.options.foreignKey}Sort`;
|
|
91
|
+
targetCollection.setField(sortFieldName, {
|
|
92
|
+
type: "sort",
|
|
93
|
+
hidden: true,
|
|
94
|
+
scopeKey: this.options.foreignKey
|
|
95
|
+
});
|
|
96
|
+
this.options.sortBy = sortFieldName;
|
|
97
|
+
}
|
|
88
98
|
return true;
|
|
89
99
|
}
|
|
90
100
|
unbind() {
|
package/lib/fields/sort-field.js
CHANGED
|
@@ -87,41 +87,52 @@ const _SortField = class _SortField extends import_field.Field {
|
|
|
87
87
|
const doInit = /* @__PURE__ */ __name(async (scopeKey2 = null, scopeValue = null) => {
|
|
88
88
|
const queryInterface = this.collection.db.sequelize.getQueryInterface();
|
|
89
89
|
if (scopeKey2) {
|
|
90
|
-
const
|
|
91
|
-
if (!
|
|
90
|
+
const scopeAttribute = this.collection.model.rawAttributes[scopeKey2];
|
|
91
|
+
if (!scopeAttribute) {
|
|
92
92
|
throw new Error(`can not find scope field ${scopeKey2} for collection ${this.collection.name}`);
|
|
93
93
|
}
|
|
94
|
-
scopeKey2 =
|
|
94
|
+
scopeKey2 = scopeAttribute.field;
|
|
95
95
|
}
|
|
96
96
|
const quotedOrderField = queryInterface.quoteIdentifier(orderField);
|
|
97
|
-
const sortColumnName = this.collection.model.rawAttributes[this.name].field;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
97
|
+
const sortColumnName = queryInterface.quoteIdentifier(this.collection.model.rawAttributes[this.name].field);
|
|
98
|
+
let sql;
|
|
99
|
+
const whereClause = scopeKey2 && scopeValue ? `
|
|
100
|
+
WHERE ${queryInterface.quoteIdentifier(scopeKey2)} IN (${scopeValue.filter((v) => v !== null).map((v) => `'${v}'`).join(", ")})${scopeValue.includes(null) ? ` OR ${queryInterface.quoteIdentifier(scopeKey2)} IS NULL` : ""}` : "";
|
|
101
|
+
if (this.collection.db.inDialect("postgres")) {
|
|
102
|
+
sql = `
|
|
103
|
+
UPDATE ${this.collection.quotedTableName()}
|
|
104
|
+
SET ${sortColumnName} = ordered_table.new_sequence_number
|
|
105
|
+
FROM (
|
|
106
|
+
SELECT *, ROW_NUMBER() OVER (${scopeKey2 ? `PARTITION BY ${queryInterface.quoteIdentifier(scopeKey2)}` : ""} ORDER BY ${quotedOrderField}) AS new_sequence_number
|
|
107
|
+
FROM ${this.collection.quotedTableName()}
|
|
108
|
+
${whereClause}
|
|
109
|
+
) AS ordered_table
|
|
110
|
+
WHERE ${this.collection.quotedTableName()}.${quotedOrderField} = ordered_table.${quotedOrderField};
|
|
111
|
+
`;
|
|
112
|
+
} else if (this.collection.db.inDialect("sqlite")) {
|
|
113
|
+
sql = `
|
|
114
|
+
UPDATE ${this.collection.quotedTableName()}
|
|
115
|
+
SET ${sortColumnName} = (
|
|
116
|
+
SELECT new_sequence_number
|
|
117
|
+
FROM (
|
|
118
|
+
SELECT *, ROW_NUMBER() OVER (${scopeKey2 ? `PARTITION BY ${queryInterface.quoteIdentifier(scopeKey2)}` : ""} ORDER BY ${quotedOrderField}) AS new_sequence_number
|
|
119
|
+
FROM ${this.collection.quotedTableName()}
|
|
120
|
+
${whereClause}
|
|
121
|
+
) AS ordered_table
|
|
122
|
+
WHERE ${this.collection.quotedTableName()}.${quotedOrderField} = ordered_table.${quotedOrderField}
|
|
123
|
+
);
|
|
124
|
+
`;
|
|
125
|
+
} else if (this.collection.db.inDialect("mysql") || this.collection.db.inDialect("mariadb")) {
|
|
126
|
+
sql = `
|
|
127
|
+
UPDATE ${this.collection.quotedTableName()}
|
|
128
|
+
JOIN (
|
|
129
|
+
SELECT *, ROW_NUMBER() OVER (${scopeKey2 ? `PARTITION BY ${queryInterface.quoteIdentifier(scopeKey2)}` : ""} ORDER BY ${quotedOrderField}) AS new_sequence_number
|
|
130
|
+
FROM ${this.collection.quotedTableName()}
|
|
131
|
+
${whereClause}
|
|
132
|
+
) AS ordered_table ON ${this.collection.quotedTableName()}.${quotedOrderField} = ordered_table.${quotedOrderField}
|
|
133
|
+
SET ${this.collection.quotedTableName()}.${sortColumnName} = ordered_table.new_sequence_number;
|
|
134
|
+
`;
|
|
135
|
+
}
|
|
125
136
|
await this.collection.db.sequelize.query(sql, {
|
|
126
137
|
transaction
|
|
127
138
|
});
|
package/lib/helpers.d.ts
CHANGED
package/lib/helpers.js
CHANGED
|
@@ -28,10 +28,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
var helpers_exports = {};
|
|
30
30
|
__export(helpers_exports, {
|
|
31
|
+
checkDatabaseVersion: () => checkDatabaseVersion,
|
|
31
32
|
parseDatabaseOptionsFromEnv: () => parseDatabaseOptionsFromEnv
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(helpers_exports);
|
|
34
35
|
var import_fs = __toESM(require("fs"));
|
|
36
|
+
var import_semver = __toESM(require("semver"));
|
|
35
37
|
function getEnvValue(key, defaultValue) {
|
|
36
38
|
return process.env[key] || defaultValue;
|
|
37
39
|
}
|
|
@@ -114,7 +116,57 @@ function customLogger(queryString, queryObject) {
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
__name(customLogger, "customLogger");
|
|
119
|
+
const dialectVersionAccessors = {
|
|
120
|
+
sqlite: {
|
|
121
|
+
sql: "select sqlite_version() as version",
|
|
122
|
+
get: (v) => v,
|
|
123
|
+
version: "3.x"
|
|
124
|
+
},
|
|
125
|
+
mysql: {
|
|
126
|
+
sql: "select version() as version",
|
|
127
|
+
get: (v) => {
|
|
128
|
+
const m = /([\d+.]+)/.exec(v);
|
|
129
|
+
return m[0];
|
|
130
|
+
},
|
|
131
|
+
version: ">=8.0.17"
|
|
132
|
+
},
|
|
133
|
+
mariadb: {
|
|
134
|
+
sql: "select version() as version",
|
|
135
|
+
get: (v) => {
|
|
136
|
+
const m = /([\d+.]+)/.exec(v);
|
|
137
|
+
return m[0];
|
|
138
|
+
},
|
|
139
|
+
version: ">=10.9"
|
|
140
|
+
},
|
|
141
|
+
postgres: {
|
|
142
|
+
sql: "select version() as version",
|
|
143
|
+
get: (v) => {
|
|
144
|
+
const m = /([\d+.]+)/.exec(v);
|
|
145
|
+
return import_semver.default.minVersion(m[0]).version;
|
|
146
|
+
},
|
|
147
|
+
version: ">=10"
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
async function checkDatabaseVersion(db) {
|
|
151
|
+
var _a;
|
|
152
|
+
const dialect = db.sequelize.getDialect();
|
|
153
|
+
const accessor = dialectVersionAccessors[dialect];
|
|
154
|
+
if (!accessor) {
|
|
155
|
+
throw new Error(`unsupported dialect ${dialect}`);
|
|
156
|
+
}
|
|
157
|
+
const result = await db.sequelize.query(accessor.sql, {
|
|
158
|
+
type: "SELECT"
|
|
159
|
+
});
|
|
160
|
+
const version = accessor.get((_a = result == null ? void 0 : result[0]) == null ? void 0 : _a.version);
|
|
161
|
+
const versionResult = import_semver.default.satisfies(version, accessor.version);
|
|
162
|
+
if (!versionResult) {
|
|
163
|
+
throw new Error(`to use ${dialect}, please ensure the version is ${accessor.version}`);
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
__name(checkDatabaseVersion, "checkDatabaseVersion");
|
|
117
168
|
// Annotate the CommonJS export names for ESM import in node:
|
|
118
169
|
0 && (module.exports = {
|
|
170
|
+
checkDatabaseVersion,
|
|
119
171
|
parseDatabaseOptionsFromEnv
|
|
120
172
|
});
|
package/lib/model.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare class Model<TModelAttributes extends {} = any, TCreationAttribute
|
|
|
10
10
|
[key: string]: any;
|
|
11
11
|
protected _changedWithAssociations: Set<unknown>;
|
|
12
12
|
protected _previousDataValuesWithAssociations: {};
|
|
13
|
+
static sync(options: any): Promise<any>;
|
|
13
14
|
toChangedWithAssociations(): void;
|
|
14
15
|
changedWithAssociations(key?: string, value?: any): boolean | unknown[] | this;
|
|
15
16
|
clearChangedWithAssociations(): void;
|
|
@@ -17,6 +18,5 @@ export declare class Model<TModelAttributes extends {} = any, TCreationAttribute
|
|
|
17
18
|
private hiddenObjKey;
|
|
18
19
|
private sortAssociations;
|
|
19
20
|
private sortArray;
|
|
20
|
-
static sync(options: any): Promise<any>;
|
|
21
21
|
}
|
|
22
22
|
export {};
|
package/lib/model.js
CHANGED
|
@@ -43,6 +43,54 @@ const _ = import_lodash.default;
|
|
|
43
43
|
const _Model = class _Model extends import_sequelize.Model {
|
|
44
44
|
_changedWithAssociations = /* @__PURE__ */ new Set();
|
|
45
45
|
_previousDataValuesWithAssociations = {};
|
|
46
|
+
static async sync(options) {
|
|
47
|
+
var _a;
|
|
48
|
+
if (this.collection.isView()) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (this.collection.options.sync === false) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const collectionSyncOptions = (_a = this.database.collectionFactory.collectionTypes.get(this.collection.constructor)) == null ? void 0 : _a.onSync;
|
|
55
|
+
if (collectionSyncOptions) {
|
|
56
|
+
await collectionSyncOptions(this, options);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const model = this;
|
|
60
|
+
const _schema = model._schema;
|
|
61
|
+
if (_schema && _schema != "public") {
|
|
62
|
+
await this.sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${_schema}";`, {
|
|
63
|
+
raw: true,
|
|
64
|
+
transaction: options == null ? void 0 : options.transaction
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (Object.keys(model.tableAttributes).length === 0) {
|
|
68
|
+
if (this.database.inDialect("sqlite", "mysql", "mariadb")) {
|
|
69
|
+
console.error(`Zero-column tables aren't supported in ${this.database.sequelize.getDialect()}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const queryInterface = this.sequelize.queryInterface;
|
|
73
|
+
if (!queryInterface.patched) {
|
|
74
|
+
const oldDescribeTable = queryInterface.describeTable;
|
|
75
|
+
queryInterface.describeTable = async function(...args) {
|
|
76
|
+
try {
|
|
77
|
+
return await oldDescribeTable.call(this, ...args);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
if (err.message.includes("No description found for")) {
|
|
80
|
+
return [];
|
|
81
|
+
} else {
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
queryInterface.patched = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (this.collection.isInherited()) {
|
|
90
|
+
return import_sync_runner.SyncRunner.syncInheritModel(model, options);
|
|
91
|
+
}
|
|
92
|
+
return import_sequelize.Model.sync.call(this, options);
|
|
93
|
+
}
|
|
46
94
|
// TODO
|
|
47
95
|
toChangedWithAssociations() {
|
|
48
96
|
this._changedWithAssociations = /* @__PURE__ */ new Set([...this._changedWithAssociations, ...this._changed]);
|
|
@@ -137,48 +185,6 @@ const _Model = class _Model extends import_sequelize.Model {
|
|
|
137
185
|
});
|
|
138
186
|
return import_lodash.default.orderBy(data, orderItems, orderDirections);
|
|
139
187
|
}
|
|
140
|
-
static async sync(options) {
|
|
141
|
-
if (this.collection.isView()) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
if (this.collection.options.sync === false) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
const model = this;
|
|
148
|
-
const _schema = model._schema;
|
|
149
|
-
if (_schema && _schema != "public") {
|
|
150
|
-
await this.sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${_schema}";`, {
|
|
151
|
-
raw: true,
|
|
152
|
-
transaction: options == null ? void 0 : options.transaction
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
if (Object.keys(model.tableAttributes).length === 0) {
|
|
156
|
-
if (this.database.inDialect("sqlite", "mysql")) {
|
|
157
|
-
console.error(`Zero-column tables aren't supported in ${this.database.sequelize.getDialect()}`);
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
const queryInterface = this.sequelize.queryInterface;
|
|
161
|
-
if (!queryInterface.patched) {
|
|
162
|
-
const oldDescribeTable = queryInterface.describeTable;
|
|
163
|
-
queryInterface.describeTable = async function(...args) {
|
|
164
|
-
try {
|
|
165
|
-
return await oldDescribeTable.call(this, ...args);
|
|
166
|
-
} catch (err) {
|
|
167
|
-
if (err.message.includes("No description found for")) {
|
|
168
|
-
return [];
|
|
169
|
-
} else {
|
|
170
|
-
throw err;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
queryInterface.patched = true;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (this.collection.isInherited()) {
|
|
178
|
-
return import_sync_runner.SyncRunner.syncInheritModel(model, options);
|
|
179
|
-
}
|
|
180
|
-
return import_sequelize.Model.sync.call(this, options);
|
|
181
|
-
}
|
|
182
188
|
};
|
|
183
189
|
__name(_Model, "Model");
|
|
184
190
|
__publicField(_Model, "database");
|
package/lib/operators/utils.js
CHANGED
|
@@ -30,7 +30,7 @@ const isPg = /* @__PURE__ */ __name((ctx) => {
|
|
|
30
30
|
return getDialect(ctx) === "postgres";
|
|
31
31
|
}, "isPg");
|
|
32
32
|
const isMySQL = /* @__PURE__ */ __name((ctx) => {
|
|
33
|
-
return getDialect(ctx) === "mysql";
|
|
33
|
+
return getDialect(ctx) === "mysql" || getDialect(ctx) === "mariadb";
|
|
34
34
|
}, "isMySQL");
|
|
35
35
|
// Annotate the CommonJS export names for ESM import in node:
|
|
36
36
|
0 && (module.exports = {
|
package/lib/options-parser.js
CHANGED
|
@@ -132,7 +132,7 @@ const _OptionsParser = class _OptionsParser {
|
|
|
132
132
|
sortField[0] = (rawField == null ? void 0 : rawField.field) || sortField[0];
|
|
133
133
|
}
|
|
134
134
|
sortField.push(direction);
|
|
135
|
-
if (this.database.
|
|
135
|
+
if (this.database.isMySQLCompatibleDialect()) {
|
|
136
136
|
orderParams.push([import_sequelize.Sequelize.fn("ISNULL", import_sequelize.Sequelize.col(`${this.model.name}.${sortField[0]}`))]);
|
|
137
137
|
}
|
|
138
138
|
orderParams.push(sortField);
|
|
@@ -88,6 +88,12 @@ const _MysqlQueryInterface = class _MysqlQueryInterface extends import_query_int
|
|
|
88
88
|
const sql = match[0];
|
|
89
89
|
return sql;
|
|
90
90
|
}
|
|
91
|
+
async showTableDefinition(tableInfo) {
|
|
92
|
+
const { name } = tableInfo;
|
|
93
|
+
const sql = `SHOW CREATE TABLE ${name}`;
|
|
94
|
+
const results = await this.db.sequelize.query(sql, { type: "SELECT" });
|
|
95
|
+
return results[0]["Create Table"];
|
|
96
|
+
}
|
|
91
97
|
};
|
|
92
98
|
__name(_MysqlQueryInterface, "MysqlQueryInterface");
|
|
93
99
|
let MysqlQueryInterface = _MysqlQueryInterface;
|
|
@@ -108,6 +108,33 @@ const _PostgresQueryInterface = class _PostgresQueryInterface extends import_que
|
|
|
108
108
|
return {};
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
+
async showTableDefinition(tableInfo) {
|
|
112
|
+
const showFunc = `
|
|
113
|
+
CREATE OR REPLACE FUNCTION show_create_table(p_schema text, p_table_name text)
|
|
114
|
+
RETURNS text AS
|
|
115
|
+
$BODY$
|
|
116
|
+
SELECT 'CREATE TABLE ' || p_schema || '.' || p_table_name || ' (' || E'\\n' || '' ||
|
|
117
|
+
string_agg(column_list.column_expr, ', ' || E'\\n' || '') ||
|
|
118
|
+
'' || E'\\n' || ');'
|
|
119
|
+
FROM (
|
|
120
|
+
SELECT ' ' || column_name || ' ' || data_type ||
|
|
121
|
+
coalesce('(' || character_maximum_length || ')', '') ||
|
|
122
|
+
case when is_nullable = 'YES' then '' else ' NOT NULL' end as column_expr
|
|
123
|
+
FROM information_schema.columns
|
|
124
|
+
WHERE table_schema = p_schema AND table_name = p_table_name
|
|
125
|
+
ORDER BY ordinal_position) column_list;
|
|
126
|
+
$BODY$
|
|
127
|
+
LANGUAGE SQL STABLE;
|
|
128
|
+
`;
|
|
129
|
+
await this.db.sequelize.query(showFunc, { type: "RAW" });
|
|
130
|
+
const res = await this.db.sequelize.query(
|
|
131
|
+
`SELECT show_create_table('${tableInfo.schema}', '${tableInfo.name || "public"}')`,
|
|
132
|
+
{
|
|
133
|
+
type: "SELECT"
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
return res[0]["show_create_table"];
|
|
137
|
+
}
|
|
111
138
|
};
|
|
112
139
|
__name(_PostgresQueryInterface, "PostgresQueryInterface");
|
|
113
140
|
let PostgresQueryInterface = _PostgresQueryInterface;
|
|
@@ -37,6 +37,7 @@ var import_sqlite_query_interface = __toESM(require("./sqlite-query-interface"))
|
|
|
37
37
|
function buildQueryInterface(db) {
|
|
38
38
|
const map = {
|
|
39
39
|
mysql: import_mysql_query_interface.default,
|
|
40
|
+
mariadb: import_mysql_query_interface.default,
|
|
40
41
|
postgres: import_postgres_query_interface.default,
|
|
41
42
|
sqlite: import_sqlite_query_interface.default
|
|
42
43
|
};
|
|
@@ -98,6 +98,9 @@ const _SqliteQueryInterface = class _SqliteQueryInterface extends import_query_i
|
|
|
98
98
|
const sql = match[0];
|
|
99
99
|
return sql;
|
|
100
100
|
}
|
|
101
|
+
showTableDefinition(tableInfo) {
|
|
102
|
+
return Promise.resolve(void 0);
|
|
103
|
+
}
|
|
101
104
|
};
|
|
102
105
|
__name(_SqliteQueryInterface, "SqliteQueryInterface");
|
|
103
106
|
let SqliteQueryInterface = _SqliteQueryInterface;
|
|
@@ -45,5 +45,19 @@ declare const _default: {
|
|
|
45
45
|
numeric: string;
|
|
46
46
|
json: string[];
|
|
47
47
|
};
|
|
48
|
+
mariadb: {
|
|
49
|
+
varchar: string;
|
|
50
|
+
text: string;
|
|
51
|
+
int: string;
|
|
52
|
+
integer: string;
|
|
53
|
+
bigint: string;
|
|
54
|
+
float: string;
|
|
55
|
+
double: string;
|
|
56
|
+
boolean: string;
|
|
57
|
+
tinyint: string;
|
|
58
|
+
datetime: string;
|
|
59
|
+
timestamp: string;
|
|
60
|
+
json: string[];
|
|
61
|
+
};
|
|
48
62
|
};
|
|
49
63
|
export default _default;
|
|
@@ -14,9 +14,9 @@ export declare class ViewFieldInference {
|
|
|
14
14
|
viewSchema?: string;
|
|
15
15
|
}): Promise<InferredFieldResult>;
|
|
16
16
|
static inferToFieldType(options: {
|
|
17
|
-
db: Database;
|
|
18
17
|
name: string;
|
|
19
18
|
type: string;
|
|
19
|
+
dialect: string;
|
|
20
20
|
}): {
|
|
21
21
|
possibleTypes: string[];
|
|
22
22
|
type?: undefined;
|
|
@@ -99,15 +99,21 @@ const _ViewFieldInference = class _ViewFieldInference {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
if (!inferResult.type) {
|
|
102
|
-
Object.assign(
|
|
102
|
+
Object.assign(
|
|
103
|
+
inferResult,
|
|
104
|
+
this.inferToFieldType({
|
|
105
|
+
dialect: db.sequelize.getDialect(),
|
|
106
|
+
name,
|
|
107
|
+
type: column.type
|
|
108
|
+
})
|
|
109
|
+
);
|
|
103
110
|
}
|
|
104
111
|
rawFields.push([name, inferResult]);
|
|
105
112
|
}
|
|
106
113
|
return Object.fromEntries(rawFields);
|
|
107
114
|
}
|
|
108
115
|
static inferToFieldType(options) {
|
|
109
|
-
const {
|
|
110
|
-
const dialect = db.sequelize.getDialect();
|
|
116
|
+
const { dialect } = options;
|
|
111
117
|
const fieldTypeMap = import_field_type_map.default[dialect];
|
|
112
118
|
if (!options.type) {
|
|
113
119
|
return {
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "0.15.0-alpha.
|
|
3
|
+
"version": "0.15.0-alpha.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@nocobase/logger": "0.15.0-alpha.
|
|
10
|
-
"@nocobase/utils": "0.15.0-alpha.
|
|
9
|
+
"@nocobase/logger": "0.15.0-alpha.5",
|
|
10
|
+
"@nocobase/utils": "0.15.0-alpha.5",
|
|
11
11
|
"async-mutex": "^0.3.2",
|
|
12
12
|
"cron-parser": "4.4.0",
|
|
13
13
|
"dayjs": "^1.11.8",
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
34
34
|
"directory": "packages/database"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "4713b1a887dad4dadf27b65e3b3e2a46c6986cbf"
|
|
37
37
|
}
|