@nocobase/database 2.1.0-alpha.15 → 2.1.0-alpha.17
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/database.d.ts +1 -0
- package/lib/query/builder.js +21 -9
- package/lib/query/formatter.d.ts +11 -2
- package/lib/query/formatter.js +4 -1
- package/lib/query/formatters/mysql.d.ts +1 -1
- package/lib/query/formatters/mysql.js +1 -1
- package/lib/query/formatters/oracle.d.ts +1 -1
- package/lib/query/formatters/oracle.js +1 -1
- package/lib/query/formatters/postgres.d.ts +1 -1
- package/lib/query/formatters/postgres.js +1 -1
- package/lib/query/formatters/sqlite.d.ts +1 -1
- package/lib/query/formatters/sqlite.js +4 -1
- package/lib/repository.js +4 -3
- package/package.json +4 -4
package/lib/database.d.ts
CHANGED
package/lib/query/builder.js
CHANGED
|
@@ -53,23 +53,23 @@ const ALLOWED_ORDER_DIRECTIONS = ["ASC", "DESC"];
|
|
|
53
53
|
function createQueryFormatter(database) {
|
|
54
54
|
switch (database.sequelize.getDialect()) {
|
|
55
55
|
case "sqlite":
|
|
56
|
-
return new import_sqlite.SQLiteQueryFormatter(database.sequelize);
|
|
56
|
+
return new import_sqlite.SQLiteQueryFormatter(database.sequelize, database.options.rawTimezone);
|
|
57
57
|
case "postgres":
|
|
58
|
-
return new import_postgres.PostgresQueryFormatter(database.sequelize);
|
|
58
|
+
return new import_postgres.PostgresQueryFormatter(database.sequelize, database.options.rawTimezone);
|
|
59
59
|
case "mysql":
|
|
60
60
|
case "mariadb":
|
|
61
|
-
return new import_mysql.MySQLQueryFormatter(database.sequelize);
|
|
61
|
+
return new import_mysql.MySQLQueryFormatter(database.sequelize, database.options.rawTimezone);
|
|
62
62
|
case "oracle":
|
|
63
|
-
return new import_oracle.OracleQueryFormatter(database.sequelize);
|
|
63
|
+
return new import_oracle.OracleQueryFormatter(database.sequelize, database.options.rawTimezone);
|
|
64
64
|
default:
|
|
65
65
|
return new class extends import_formatter.QueryFormatter {
|
|
66
|
-
formatDate(field, _format, _timezone) {
|
|
66
|
+
formatDate(field, _format, _timezone, _preserveLocalTime) {
|
|
67
67
|
return field;
|
|
68
68
|
}
|
|
69
69
|
formatUnixTimestamp(field, _format, _accuracy, _timezone) {
|
|
70
70
|
return this.sequelize.col(field);
|
|
71
71
|
}
|
|
72
|
-
}(database.sequelize);
|
|
72
|
+
}(database.sequelize, database.options.rawTimezone);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
__name(createQueryFormatter, "createQueryFormatter");
|
|
@@ -166,6 +166,7 @@ function buildQuery(database, collection, options = {}) {
|
|
|
166
166
|
let hasAgg = false;
|
|
167
167
|
const attributes = [];
|
|
168
168
|
const fieldMap = {};
|
|
169
|
+
const projectedFieldMap = {};
|
|
169
170
|
measures.forEach((measure) => {
|
|
170
171
|
const { field, aggregation, alias, distinct } = measure;
|
|
171
172
|
const col = sequelize.col(field);
|
|
@@ -184,6 +185,7 @@ function buildQuery(database, collection, options = {}) {
|
|
|
184
185
|
}
|
|
185
186
|
attributes.push(attribute.length > 1 ? attribute : attribute[0]);
|
|
186
187
|
fieldMap[alias || field] = measure;
|
|
188
|
+
projectedFieldMap[alias || field] = attribute[0];
|
|
187
189
|
});
|
|
188
190
|
const group = [];
|
|
189
191
|
dimensions.forEach((dimension) => {
|
|
@@ -202,11 +204,13 @@ function buildQuery(database, collection, options = {}) {
|
|
|
202
204
|
group.push(attribute[0]);
|
|
203
205
|
}
|
|
204
206
|
fieldMap[alias || field] = dimension;
|
|
207
|
+
projectedFieldMap[alias || field] = attribute[0];
|
|
205
208
|
});
|
|
206
209
|
const order = orders.map((item) => {
|
|
207
210
|
var _a2;
|
|
208
211
|
const alias = sequelize.getQueryInterface().quoteIdentifier(item.alias);
|
|
209
|
-
const
|
|
212
|
+
const projectedField = projectedFieldMap[item.alias] || projectedFieldMap[item.name] || projectedFieldMap[item.field];
|
|
213
|
+
const name = hasAgg ? projectedField || sequelize.literal(alias) : sequelize.col(item.field);
|
|
210
214
|
let sort = ALLOWED_ORDER_DIRECTIONS.includes((_a2 = item.order) == null ? void 0 : _a2.toUpperCase()) ? item.order.toUpperCase() : "ASC";
|
|
211
215
|
if (item.nulls === "first") {
|
|
212
216
|
sort += " NULLS FIRST";
|
|
@@ -234,15 +238,23 @@ function buildQuery(database, collection, options = {}) {
|
|
|
234
238
|
}
|
|
235
239
|
__name(buildQuery, "buildQuery");
|
|
236
240
|
function normalizeQueryResult(data, fieldMap) {
|
|
241
|
+
const dateTimeTypes = ["date", "datetime", "datetimeTz", "datetimeNoTz"];
|
|
237
242
|
return data.map((record) => {
|
|
238
243
|
Object.entries(record).forEach(([key, value]) => {
|
|
239
|
-
var _a;
|
|
240
244
|
if (value === null || value === void 0) {
|
|
241
245
|
return;
|
|
242
246
|
}
|
|
243
|
-
const
|
|
247
|
+
const field = fieldMap[key];
|
|
248
|
+
const type = field == null ? void 0 : field.type;
|
|
244
249
|
if (["bigInt", "integer", "float", "double", "decimal"].includes(type)) {
|
|
245
250
|
record[key] = Number(value);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (!(field == null ? void 0 : field.format) && dateTimeTypes.includes(type) && !(value instanceof Date)) {
|
|
254
|
+
const dateValue = new Date(value);
|
|
255
|
+
if (!Number.isNaN(dateValue.getTime())) {
|
|
256
|
+
record[key] = dateValue;
|
|
257
|
+
}
|
|
246
258
|
}
|
|
247
259
|
});
|
|
248
260
|
return record;
|
package/lib/query/formatter.d.ts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import { Sequelize } from 'sequelize';
|
|
2
10
|
export type Col = ReturnType<typeof Sequelize.col>;
|
|
3
11
|
export type Literal = ReturnType<typeof Sequelize.literal>;
|
|
4
12
|
export type Fn = ReturnType<typeof Sequelize.fn>;
|
|
5
13
|
export declare abstract class QueryFormatter {
|
|
6
14
|
sequelize: Sequelize;
|
|
7
|
-
|
|
8
|
-
|
|
15
|
+
rawTimezone?: string;
|
|
16
|
+
constructor(sequelize: Sequelize, rawTimezone?: string);
|
|
17
|
+
abstract formatDate(field: Col, format: string, timezone?: string, preserveLocalTime?: boolean): Fn | Col;
|
|
9
18
|
abstract formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): Fn | Literal | Col;
|
|
10
19
|
convertFormat(format: string): string;
|
|
11
20
|
protected getTimezoneByOffset(offset?: string): string;
|
package/lib/query/formatter.js
CHANGED
|
@@ -43,8 +43,10 @@ module.exports = __toCommonJS(formatter_exports);
|
|
|
43
43
|
var import_moment_timezone = __toESM(require("moment-timezone"));
|
|
44
44
|
const _QueryFormatter = class _QueryFormatter {
|
|
45
45
|
sequelize;
|
|
46
|
-
|
|
46
|
+
rawTimezone;
|
|
47
|
+
constructor(sequelize, rawTimezone) {
|
|
47
48
|
this.sequelize = sequelize;
|
|
49
|
+
this.rawTimezone = rawTimezone;
|
|
48
50
|
}
|
|
49
51
|
convertFormat(format) {
|
|
50
52
|
return format;
|
|
@@ -80,6 +82,7 @@ const _QueryFormatter = class _QueryFormatter {
|
|
|
80
82
|
case "datetimeTz":
|
|
81
83
|
return this.formatDate(col, format, timezone);
|
|
82
84
|
case "datetimeNoTz":
|
|
85
|
+
return this.formatDate(col, format, void 0, true);
|
|
83
86
|
case "dateOnly":
|
|
84
87
|
case "time":
|
|
85
88
|
return this.formatDate(col, format);
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
import { QueryFormatter, Col } from '../formatter';
|
|
10
10
|
export declare class MySQLQueryFormatter extends QueryFormatter {
|
|
11
11
|
convertFormat(format: string): string;
|
|
12
|
-
formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
|
|
12
|
+
formatDate(field: Col, format: string, timezone?: string, _preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
|
|
13
13
|
formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
|
|
14
14
|
}
|
|
@@ -35,7 +35,7 @@ const _MySQLQueryFormatter = class _MySQLQueryFormatter extends import_formatter
|
|
|
35
35
|
convertFormat(format) {
|
|
36
36
|
return format.replace(/YYYY/g, "%Y").replace(/MM/g, "%m").replace(/DD/g, "%d").replace(/hh/g, "%H").replace(/mm/g, "%i").replace(/ss/g, "%S");
|
|
37
37
|
}
|
|
38
|
-
formatDate(field, format, timezone) {
|
|
38
|
+
formatDate(field, format, timezone, _preserveLocalTime) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
40
|
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
41
41
|
if (resolvedTimezone) {
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
import { QueryFormatter, Col } from '../formatter';
|
|
10
10
|
export declare class OracleQueryFormatter extends QueryFormatter {
|
|
11
11
|
convertFormat(format: string): string;
|
|
12
|
-
formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
|
|
12
|
+
formatDate(field: Col, format: string, timezone?: string, _preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
|
|
13
13
|
formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
|
|
14
14
|
}
|
|
@@ -35,7 +35,7 @@ const _OracleQueryFormatter = class _OracleQueryFormatter extends import_formatt
|
|
|
35
35
|
convertFormat(format) {
|
|
36
36
|
return format.replace(/hh/g, "HH24").replace(/mm/g, "MI").replace(/ss/g, "SS");
|
|
37
37
|
}
|
|
38
|
-
formatDate(field, format, timezone) {
|
|
38
|
+
formatDate(field, format, timezone, _preserveLocalTime) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
40
|
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
41
41
|
if (resolvedTimezone) {
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
import { QueryFormatter, Col } from '../formatter';
|
|
10
10
|
export declare class PostgresQueryFormatter extends QueryFormatter {
|
|
11
11
|
convertFormat(format: string): string;
|
|
12
|
-
formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
|
|
12
|
+
formatDate(field: Col, format: string, timezone?: string, _preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
|
|
13
13
|
formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
|
|
14
14
|
}
|
|
@@ -35,7 +35,7 @@ const _PostgresQueryFormatter = class _PostgresQueryFormatter extends import_for
|
|
|
35
35
|
convertFormat(format) {
|
|
36
36
|
return format.replace(/hh/g, "HH24").replace(/mm/g, "MI").replace(/ss/g, "SS");
|
|
37
37
|
}
|
|
38
|
-
formatDate(field, format, timezone) {
|
|
38
|
+
formatDate(field, format, timezone, _preserveLocalTime) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
40
|
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
41
41
|
if (resolvedTimezone) {
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
import { QueryFormatter, Col } from '../formatter';
|
|
10
10
|
export declare class SQLiteQueryFormatter extends QueryFormatter {
|
|
11
11
|
convertFormat(format: string): string;
|
|
12
|
-
formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
|
|
12
|
+
formatDate(field: Col, format: string, timezone?: string, preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
|
|
13
13
|
formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
|
|
14
14
|
}
|
|
@@ -35,11 +35,14 @@ const _SQLiteQueryFormatter = class _SQLiteQueryFormatter extends import_formatt
|
|
|
35
35
|
convertFormat(format) {
|
|
36
36
|
return format.replace(/YYYY/g, "%Y").replace(/MM/g, "%m").replace(/DD/g, "%d").replace(/hh/g, "%H").replace(/mm/g, "%M").replace(/ss/g, "%S");
|
|
37
37
|
}
|
|
38
|
-
formatDate(field, format, timezone) {
|
|
38
|
+
formatDate(field, format, timezone, preserveLocalTime) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
40
|
if (timezone && /^[+-]\d{1,2}:\d{2}$/.test(timezone)) {
|
|
41
41
|
return this.sequelize.fn("strftime", fmt, field, this.getOffsetExpression(timezone));
|
|
42
42
|
}
|
|
43
|
+
if (preserveLocalTime && this.rawTimezone && /^[+-]\d{1,2}:\d{2}$/.test(this.rawTimezone)) {
|
|
44
|
+
return this.sequelize.fn("strftime", fmt, field, this.getOffsetExpression(this.rawTimezone));
|
|
45
|
+
}
|
|
43
46
|
return this.sequelize.fn("strftime", fmt, field);
|
|
44
47
|
}
|
|
45
48
|
formatUnixTimestamp(field, format, accuracy = "second", timezone) {
|
package/lib/repository.js
CHANGED
|
@@ -152,12 +152,13 @@ const _Repository = class _Repository {
|
|
|
152
152
|
[import_sequelize.Op.and]: [options["where"] || {}, optionParser.filterByTkToWhereOption()]
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
|
+
const hasInclude = Array.isArray(options["include"]) && options["include"].length > 0;
|
|
155
156
|
const queryOptions = {
|
|
156
|
-
...options
|
|
157
|
-
distinct: Boolean(this.collection.model.primaryKeyAttribute) && !this.collection.isMultiFilterTargetKey()
|
|
157
|
+
...options
|
|
158
158
|
};
|
|
159
|
-
if (
|
|
159
|
+
if (hasInclude) {
|
|
160
160
|
queryOptions.include = (0, import_utils2.processIncludes)(queryOptions.include, this.collection.model);
|
|
161
|
+
queryOptions.distinct = Boolean(this.collection.model.primaryKeyAttribute) && !this.collection.isMultiFilterTargetKey();
|
|
161
162
|
} else {
|
|
162
163
|
delete queryOptions.include;
|
|
163
164
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "2.1.0-alpha.
|
|
3
|
+
"version": "2.1.0-alpha.17",
|
|
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": "2.1.0-alpha.
|
|
10
|
-
"@nocobase/utils": "2.1.0-alpha.
|
|
9
|
+
"@nocobase/logger": "2.1.0-alpha.17",
|
|
10
|
+
"@nocobase/utils": "2.1.0-alpha.17",
|
|
11
11
|
"async-mutex": "^0.3.2",
|
|
12
12
|
"chalk": "^4.1.1",
|
|
13
13
|
"cron-parser": "4.4.0",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
39
39
|
"directory": "packages/database"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "586cb00f56557e66168b9720d0e0193a1b752067"
|
|
42
42
|
}
|