@nocobase/database 2.1.0-alpha.14 → 2.1.0-alpha.16
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/query/builder.js +8 -2
- package/lib/query/formatter.d.ts +1 -1
- package/lib/query/formatter.js +7 -1
- package/lib/query/formatters/mysql.js +6 -4
- package/lib/query/formatters/oracle.js +4 -3
- package/lib/query/formatters/postgres.js +4 -3
- package/lib/query/formatters/sqlite.js +2 -2
- package/lib/view/field-type-map.d.ts +4 -4
- package/lib/view/field-type-map.js +4 -4
- package/package.json +4 -4
package/lib/query/builder.js
CHANGED
|
@@ -49,6 +49,7 @@ var import_postgres = require("./formatters/postgres");
|
|
|
49
49
|
var import_sqlite = require("./formatters/sqlite");
|
|
50
50
|
var import_having = require("./having");
|
|
51
51
|
const ALLOWED_AGG_FUNCS = ["sum", "count", "avg", "min", "max"];
|
|
52
|
+
const ALLOWED_ORDER_DIRECTIONS = ["ASC", "DESC"];
|
|
52
53
|
function createQueryFormatter(database) {
|
|
53
54
|
switch (database.sequelize.getDialect()) {
|
|
54
55
|
case "sqlite":
|
|
@@ -165,6 +166,7 @@ function buildQuery(database, collection, options = {}) {
|
|
|
165
166
|
let hasAgg = false;
|
|
166
167
|
const attributes = [];
|
|
167
168
|
const fieldMap = {};
|
|
169
|
+
const projectedFieldMap = {};
|
|
168
170
|
measures.forEach((measure) => {
|
|
169
171
|
const { field, aggregation, alias, distinct } = measure;
|
|
170
172
|
const col = sequelize.col(field);
|
|
@@ -183,6 +185,7 @@ function buildQuery(database, collection, options = {}) {
|
|
|
183
185
|
}
|
|
184
186
|
attributes.push(attribute.length > 1 ? attribute : attribute[0]);
|
|
185
187
|
fieldMap[alias || field] = measure;
|
|
188
|
+
projectedFieldMap[alias || field] = attribute[0];
|
|
186
189
|
});
|
|
187
190
|
const group = [];
|
|
188
191
|
dimensions.forEach((dimension) => {
|
|
@@ -201,11 +204,14 @@ function buildQuery(database, collection, options = {}) {
|
|
|
201
204
|
group.push(attribute[0]);
|
|
202
205
|
}
|
|
203
206
|
fieldMap[alias || field] = dimension;
|
|
207
|
+
projectedFieldMap[alias || field] = attribute[0];
|
|
204
208
|
});
|
|
205
209
|
const order = orders.map((item) => {
|
|
210
|
+
var _a2;
|
|
206
211
|
const alias = sequelize.getQueryInterface().quoteIdentifier(item.alias);
|
|
207
|
-
const
|
|
208
|
-
|
|
212
|
+
const projectedField = projectedFieldMap[item.alias] || projectedFieldMap[item.name] || projectedFieldMap[item.field];
|
|
213
|
+
const name = hasAgg ? projectedField || sequelize.literal(alias) : sequelize.col(item.field);
|
|
214
|
+
let sort = ALLOWED_ORDER_DIRECTIONS.includes((_a2 = item.order) == null ? void 0 : _a2.toUpperCase()) ? item.order.toUpperCase() : "ASC";
|
|
209
215
|
if (item.nulls === "first") {
|
|
210
216
|
sort += " NULLS FIRST";
|
|
211
217
|
}
|
package/lib/query/formatter.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare abstract class QueryFormatter {
|
|
|
8
8
|
abstract formatDate(field: Col, format: string, timezone?: string): Fn | Col;
|
|
9
9
|
abstract formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): Fn | Literal | Col;
|
|
10
10
|
convertFormat(format: string): string;
|
|
11
|
-
protected getTimezoneByOffset(offset
|
|
11
|
+
protected getTimezoneByOffset(offset?: string): string;
|
|
12
12
|
protected getOffsetExpression(timezone: string): string;
|
|
13
13
|
format(options: {
|
|
14
14
|
type: string;
|
package/lib/query/formatter.js
CHANGED
|
@@ -50,9 +50,15 @@ const _QueryFormatter = class _QueryFormatter {
|
|
|
50
50
|
return format;
|
|
51
51
|
}
|
|
52
52
|
getTimezoneByOffset(offset) {
|
|
53
|
-
if (
|
|
53
|
+
if (!offset) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (import_moment_timezone.default.tz.zone(offset)) {
|
|
54
57
|
return offset;
|
|
55
58
|
}
|
|
59
|
+
if (!/^[+-]\d{1,2}:\d{2}$/.test(offset)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
56
62
|
const offsetMinutes = import_moment_timezone.default.duration(offset).asMinutes();
|
|
57
63
|
return import_moment_timezone.default.tz.names().find((timezone) => {
|
|
58
64
|
return import_moment_timezone.default.tz(timezone).utcOffset() === offsetMinutes;
|
|
@@ -37,10 +37,11 @@ const _MySQLQueryFormatter = class _MySQLQueryFormatter extends import_formatter
|
|
|
37
37
|
}
|
|
38
38
|
formatDate(field, format, timezone) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
|
-
|
|
40
|
+
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
41
|
+
if (resolvedTimezone) {
|
|
41
42
|
return this.sequelize.fn(
|
|
42
43
|
"date_format",
|
|
43
|
-
this.sequelize.fn("convert_tz", field, process.env.TZ || "UTC",
|
|
44
|
+
this.sequelize.fn("convert_tz", field, process.env.TZ || "UTC", resolvedTimezone),
|
|
44
45
|
fmt
|
|
45
46
|
);
|
|
46
47
|
}
|
|
@@ -49,11 +50,12 @@ const _MySQLQueryFormatter = class _MySQLQueryFormatter extends import_formatter
|
|
|
49
50
|
formatUnixTimestamp(field, format, accuracy = "second", timezone) {
|
|
50
51
|
const fmt = this.convertFormat(format);
|
|
51
52
|
const quoted = this.sequelize.getQueryInterface().quoteIdentifiers(field);
|
|
53
|
+
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
52
54
|
const timestamp = accuracy === "millisecond" ? this.sequelize.fn("from_unixtime", this.sequelize.literal(`ROUND(${quoted} / 1000)`)) : this.sequelize.fn("from_unixtime", this.sequelize.col(field));
|
|
53
|
-
if (
|
|
55
|
+
if (resolvedTimezone) {
|
|
54
56
|
return this.sequelize.fn(
|
|
55
57
|
"date_format",
|
|
56
|
-
this.sequelize.fn("convert_tz", timestamp, process.env.TZ || "UTC",
|
|
58
|
+
this.sequelize.fn("convert_tz", timestamp, process.env.TZ || "UTC", resolvedTimezone),
|
|
57
59
|
fmt
|
|
58
60
|
);
|
|
59
61
|
}
|
|
@@ -37,8 +37,8 @@ const _OracleQueryFormatter = class _OracleQueryFormatter extends import_formatt
|
|
|
37
37
|
}
|
|
38
38
|
formatDate(field, format, timezone) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
41
|
+
if (resolvedTimezone) {
|
|
42
42
|
const quoted = this.sequelize.getQueryInterface().quoteIdentifiers(field.col);
|
|
43
43
|
return this.sequelize.fn(
|
|
44
44
|
"to_char",
|
|
@@ -51,7 +51,8 @@ const _OracleQueryFormatter = class _OracleQueryFormatter extends import_formatt
|
|
|
51
51
|
formatUnixTimestamp(field, format, accuracy = "second", timezone) {
|
|
52
52
|
const quoted = this.sequelize.getQueryInterface().quoteIdentifiers(field);
|
|
53
53
|
const timestamp = accuracy === "millisecond" ? `to_timestamp(ROUND(${quoted} / 1000))` : `to_timestamp(${quoted})`;
|
|
54
|
-
const
|
|
54
|
+
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
55
|
+
const literal = resolvedTimezone ? `${timestamp} AT TIME ZONE '${resolvedTimezone}'` : timestamp;
|
|
55
56
|
return this.sequelize.fn("to_char", this.sequelize.literal(literal), this.convertFormat(format));
|
|
56
57
|
}
|
|
57
58
|
};
|
|
@@ -37,8 +37,8 @@ const _PostgresQueryFormatter = class _PostgresQueryFormatter extends import_for
|
|
|
37
37
|
}
|
|
38
38
|
formatDate(field, format, timezone) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
41
|
+
if (resolvedTimezone) {
|
|
42
42
|
const quoted = this.sequelize.getQueryInterface().quoteIdentifiers(field.col);
|
|
43
43
|
return this.sequelize.fn(
|
|
44
44
|
"to_char",
|
|
@@ -51,7 +51,8 @@ const _PostgresQueryFormatter = class _PostgresQueryFormatter extends import_for
|
|
|
51
51
|
formatUnixTimestamp(field, format, accuracy = "second", timezone) {
|
|
52
52
|
const quoted = this.sequelize.getQueryInterface().quoteIdentifiers(field);
|
|
53
53
|
const timestamp = accuracy === "millisecond" ? `to_timestamp(ROUND(${quoted} / 1000))` : `to_timestamp(${quoted})`;
|
|
54
|
-
const
|
|
54
|
+
const resolvedTimezone = this.getTimezoneByOffset(timezone);
|
|
55
|
+
const literal = resolvedTimezone ? `${timestamp} AT TIME ZONE '${resolvedTimezone}'` : timestamp;
|
|
55
56
|
return this.sequelize.fn("to_char", this.sequelize.literal(literal), this.convertFormat(format));
|
|
56
57
|
}
|
|
57
58
|
};
|
|
@@ -37,7 +37,7 @@ const _SQLiteQueryFormatter = class _SQLiteQueryFormatter extends import_formatt
|
|
|
37
37
|
}
|
|
38
38
|
formatDate(field, format, timezone) {
|
|
39
39
|
const fmt = this.convertFormat(format);
|
|
40
|
-
if (timezone) {
|
|
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
43
|
return this.sequelize.fn("strftime", fmt, field);
|
|
@@ -46,7 +46,7 @@ const _SQLiteQueryFormatter = class _SQLiteQueryFormatter extends import_formatt
|
|
|
46
46
|
const quoted = this.sequelize.getQueryInterface().quoteIdentifiers(field);
|
|
47
47
|
const base = accuracy === "millisecond" ? this.sequelize.literal(`ROUND(${quoted} / 1000)`) : this.sequelize.col(field);
|
|
48
48
|
const args = [base, "unixepoch"];
|
|
49
|
-
if (timezone) {
|
|
49
|
+
if (timezone && /^[+-]\d{1,2}:\d{2}$/.test(timezone)) {
|
|
50
50
|
args.push(this.getOffsetExpression(timezone));
|
|
51
51
|
}
|
|
52
52
|
return this.sequelize.fn("strftime", this.convertFormat(format), this.sequelize.fn("DATETIME", ...args));
|
|
@@ -23,7 +23,7 @@ declare const fieldTypeMap: {
|
|
|
23
23
|
real: string;
|
|
24
24
|
'double precision': string;
|
|
25
25
|
'timestamp without time zone': string;
|
|
26
|
-
'timestamp with time zone': string;
|
|
26
|
+
'timestamp with time zone': string[];
|
|
27
27
|
'time without time zone': string;
|
|
28
28
|
date: string;
|
|
29
29
|
boolean: string;
|
|
@@ -63,7 +63,7 @@ declare const fieldTypeMap: {
|
|
|
63
63
|
decimal: string;
|
|
64
64
|
year: string[];
|
|
65
65
|
datetime: string[];
|
|
66
|
-
timestamp: string;
|
|
66
|
+
timestamp: string[];
|
|
67
67
|
json: string[];
|
|
68
68
|
enum: string;
|
|
69
69
|
};
|
|
@@ -72,7 +72,7 @@ declare const fieldTypeMap: {
|
|
|
72
72
|
varchar: string[];
|
|
73
73
|
integer: string;
|
|
74
74
|
real: string;
|
|
75
|
-
datetime: string;
|
|
75
|
+
datetime: string[];
|
|
76
76
|
date: string;
|
|
77
77
|
time: string;
|
|
78
78
|
boolean: string;
|
|
@@ -105,7 +105,7 @@ declare const fieldTypeMap: {
|
|
|
105
105
|
decimal: string;
|
|
106
106
|
year: string[];
|
|
107
107
|
datetime: string[];
|
|
108
|
-
timestamp: string;
|
|
108
|
+
timestamp: string[];
|
|
109
109
|
json: string[];
|
|
110
110
|
enum: string;
|
|
111
111
|
};
|
|
@@ -45,7 +45,7 @@ const postgres = {
|
|
|
45
45
|
real: "float",
|
|
46
46
|
"double precision": "float",
|
|
47
47
|
"timestamp without time zone": "datetimeNoTz",
|
|
48
|
-
"timestamp with time zone": "datetimeTz",
|
|
48
|
+
"timestamp with time zone": ["datetimeTz", "date"],
|
|
49
49
|
"time without time zone": "time",
|
|
50
50
|
date: "dateOnly",
|
|
51
51
|
boolean: "boolean",
|
|
@@ -84,8 +84,8 @@ const mysql = {
|
|
|
84
84
|
boolean: "boolean",
|
|
85
85
|
decimal: "decimal",
|
|
86
86
|
year: ["string", "integer"],
|
|
87
|
-
datetime: ["datetimeNoTz", "datetimeTz"],
|
|
88
|
-
timestamp: "datetimeTz",
|
|
87
|
+
datetime: ["datetimeNoTz", "datetimeTz", "date"],
|
|
88
|
+
timestamp: ["datetimeTz", "date"],
|
|
89
89
|
json: ["json", "array"],
|
|
90
90
|
enum: "string"
|
|
91
91
|
};
|
|
@@ -94,7 +94,7 @@ const sqlite = {
|
|
|
94
94
|
varchar: ["string", "uuid", "nanoid", "encryption"],
|
|
95
95
|
integer: "integer",
|
|
96
96
|
real: "real",
|
|
97
|
-
datetime: "datetimeTz",
|
|
97
|
+
datetime: ["datetimeTz", "date"],
|
|
98
98
|
date: "date",
|
|
99
99
|
time: "time",
|
|
100
100
|
boolean: "boolean",
|
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.16",
|
|
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.16",
|
|
10
|
+
"@nocobase/utils": "2.1.0-alpha.16",
|
|
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": "14cf3dbdb9f0a9669602de4ad21a9464fa27c105"
|
|
42
42
|
}
|