@egi/smart-db 2.3.2 → 2.3.4
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/drivers/smart-db-better-sqlite3.d.ts +36 -0
- package/drivers/smart-db-better-sqlite3.js +1 -0
- package/drivers/smart-db-mysql.d.ts +26 -0
- package/drivers/smart-db-mysql.js +1 -0
- package/drivers/smart-db-mysql2.d.ts +26 -0
- package/drivers/smart-db-mysql2.js +1 -0
- package/drivers/smart-db-sqlite3.d.ts +30 -0
- package/drivers/smart-db-sqlite3.js +1 -0
- package/helpers/extract-db-api.d.ts +1 -0
- package/helpers/extract-db-api.js +1 -0
- package/models/abstract-model.d.ts +22 -0
- package/models/abstract-model.js +1 -0
- package/models/smart-db-core-table-model.d.ts +35 -0
- package/models/smart-db-core-table-model.js +1 -0
- package/models/smart-db-dictionary.d.ts +13 -0
- package/models/smart-db-dictionary.js +1 -0
- package/models/smart-db-log-model.d.ts +65 -0
- package/models/smart-db-log-model.js +1 -0
- package/models/smart-db-version-model.d.ts +65 -0
- package/models/smart-db-version-model.js +1 -0
- package/models/smart-db-version-view-model.d.ts +71 -0
- package/models/smart-db-version-view-model.js +1 -0
- package/models/sqlite-master-model.d.ts +36 -0
- package/models/sqlite-master-model.js +1 -0
- package/models/sqlite-sequence-model.d.ts +24 -0
- package/models/sqlite-sequence-model.js +1 -0
- package/package.json +1 -1
- package/{src/smart-db-api.ts → smart-db-api.d.ts} +0 -3
- package/smart-db-api.js +1 -0
- package/smart-db-globals.d.ts +22 -0
- package/smart-db-globals.js +1 -0
- package/{src/smart-db-interfaces.ts → smart-db-interfaces.d.ts} +34 -82
- package/smart-db-interfaces.js +1 -0
- package/smart-db-log.d.ts +58 -0
- package/smart-db-log.js +1 -0
- package/smart-db-sql-build-data.d.ts +9 -0
- package/smart-db-sql-build-data.js +1 -0
- package/smart-db-upgrade-manager.d.ts +13 -0
- package/smart-db-upgrade-manager.js +1 -0
- package/smart-db.d.ts +67 -0
- package/smart-db.js +1 -0
- package/.eslintrc.json +0 -212
- package/README.md +0 -2
- package/bin/copy-assets +0 -6
- package/src/drivers/smart-db-better-sqlite3.ts +0 -284
- package/src/drivers/smart-db-mysql.ts +0 -159
- package/src/drivers/smart-db-mysql2.ts +0 -159
- package/src/drivers/smart-db-sqlite3.ts +0 -198
- package/src/helpers/extract-db-api.ts +0 -465
- package/src/helpers/terser-tree.ts +0 -39
- package/src/models/abstract-model.ts +0 -209
- package/src/models/smart-db-core-table-model.ts +0 -161
- package/src/models/smart-db-dictionary.ts +0 -28
- package/src/models/smart-db-log-model.ts +0 -316
- package/src/models/smart-db-version-model.ts +0 -316
- package/src/models/smart-db-version-view-model.ts +0 -347
- package/src/models/sqlite-master-model.ts +0 -140
- package/src/models/sqlite-sequence-model.ts +0 -91
- package/src/smart-db-globals.ts +0 -136
- package/src/smart-db-log.ts +0 -262
- package/src/smart-db-sql-build-data.ts +0 -28
- package/src/smart-db-upgrade-manager.ts +0 -171
- package/src/smart-db.ts +0 -854
- package/test/data/sql-engine-tests.json +0 -232
- package/test/db/mysql/database-init.sql +0 -11
- package/test/db/sqlite3/database-init.sql +0 -11
- package/test/exer.js +0 -28
- package/test/model/smart-db-dictionary.ts +0 -19
- package/test/model/test-table-model.ts +0 -214
- package/test/test.js +0 -273
- package/test/test2.js +0 -252
- package/tsconfig.json +0 -32
- package/tsconfig.pro.json +0 -32
- package/tsconfig.test-model.json +0 -23
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
import {AbstractModel} from "./models/abstract-model";
|
|
2
|
-
import {SmartDbDictionary} from "./models/smart-db-dictionary";
|
|
3
|
-
import {SmartDbVersionViewModel} from "./models/smart-db-version-view-model";
|
|
4
|
-
import {SmartDbSqlBuildData} from "./smart-db-sql-build-data";
|
|
5
|
-
|
|
1
|
+
import { AbstractModel } from "./models/abstract-model";
|
|
2
|
+
import { SmartDbDictionary } from "./models/smart-db-dictionary";
|
|
3
|
+
import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
|
|
4
|
+
import { SmartDbSqlBuildData } from "./smart-db-sql-build-data";
|
|
6
5
|
export interface SmartDbOptions {
|
|
7
6
|
module: string;
|
|
8
7
|
sqlFilesDirectory: string;
|
|
9
8
|
smartDbDictionary?: typeof SmartDbDictionary | any[];
|
|
10
9
|
skipAutoUpgrade?: boolean;
|
|
11
10
|
}
|
|
12
|
-
|
|
13
11
|
export interface SmartDbRunResult {
|
|
14
12
|
lastId: number;
|
|
15
13
|
changes: number;
|
|
16
14
|
affected: number;
|
|
17
15
|
}
|
|
18
|
-
|
|
19
16
|
export interface SmartDbTableInfo {
|
|
20
17
|
name: string;
|
|
21
18
|
fields: SmartDbFieldDescription[];
|
|
22
19
|
}
|
|
23
|
-
|
|
24
20
|
export interface SmartDbFieldDescription {
|
|
25
21
|
cid?: string | number;
|
|
26
22
|
name: string;
|
|
@@ -30,19 +26,18 @@ export interface SmartDbFieldDescription {
|
|
|
30
26
|
defaultValue?: number | string | boolean;
|
|
31
27
|
isPk?: boolean;
|
|
32
28
|
}
|
|
33
|
-
|
|
34
29
|
export interface SmartDbSqlComparison {
|
|
35
|
-
compare: string | SqlFieldDescriptor
|
|
30
|
+
compare: string | SqlFieldDescriptor;
|
|
36
31
|
with: string | SqlFieldDescriptor;
|
|
37
32
|
operation?: SqlOperationType;
|
|
38
33
|
}
|
|
39
|
-
|
|
40
|
-
export
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
export declare type SqlValueType = string | number | boolean | Date;
|
|
35
|
+
export declare enum FieldNamingStyle {
|
|
36
|
+
Database = 0,
|
|
37
|
+
TypeScript = 1,
|
|
38
|
+
All = 2
|
|
39
|
+
}
|
|
40
|
+
export declare type GenericModelData = Record<string, SqlValueType>;
|
|
46
41
|
export interface AttributeInfo {
|
|
47
42
|
attribute: string;
|
|
48
43
|
type: string;
|
|
@@ -52,42 +47,34 @@ export interface AttributeInfo {
|
|
|
52
47
|
alternative?: boolean;
|
|
53
48
|
typeScriptStyle?: boolean;
|
|
54
49
|
}
|
|
55
|
-
|
|
56
50
|
export interface ModelAttributeMap {
|
|
57
51
|
[key: string]: AttributeInfo;
|
|
58
52
|
}
|
|
59
|
-
|
|
60
53
|
export interface AbstractModelGlobals<T extends AbstractModel<T, D>, D extends GenericModelData> {
|
|
61
54
|
attributeMap: ModelAttributeMap;
|
|
62
55
|
getTableName: () => string;
|
|
63
56
|
from: (other: T | D) => T;
|
|
64
57
|
}
|
|
65
|
-
|
|
66
58
|
export interface SqlWhere {
|
|
67
59
|
or?: SqlWhere | SqlWhere[];
|
|
68
60
|
and?: SqlWhere | SqlWhere[];
|
|
69
61
|
expression?: SmartDbSqlComparison[];
|
|
70
|
-
|
|
71
62
|
[key: string]: SqlValueType | SqlValueType[] | SqlOperation | SqlWhere | SqlWhere[] | SmartDbSqlComparison[];
|
|
72
63
|
}
|
|
73
|
-
|
|
74
|
-
export type
|
|
75
|
-
|
|
76
|
-
type SqlGroupBy = string | string[];
|
|
77
|
-
|
|
64
|
+
export declare type SqlUpdateValues = Record<string, SqlValueType>;
|
|
65
|
+
export declare type SqlOrderBy = string | string[];
|
|
66
|
+
declare type SqlGroupBy = string | string[];
|
|
78
67
|
export interface SqlLimit {
|
|
79
68
|
offset?: number;
|
|
80
69
|
limit?: number;
|
|
81
70
|
}
|
|
82
|
-
|
|
83
71
|
export interface SectionDescription<T extends AbstractModel<T, D>, D extends GenericModelData> {
|
|
84
|
-
model: (new() => T) | string;
|
|
72
|
+
model: (new () => T) | string;
|
|
85
73
|
where?: SqlWhere;
|
|
86
74
|
fields?: string | SqlFieldDescriptor | (string | SqlFieldDescriptor)[] | null;
|
|
87
75
|
groupBy?: SqlGroupBy;
|
|
88
76
|
limit?: SqlLimit;
|
|
89
77
|
}
|
|
90
|
-
|
|
91
78
|
export interface SmartDbSqlOptions<T extends AbstractModel<T, D>, D extends GenericModelData> {
|
|
92
79
|
firstOnly?: boolean;
|
|
93
80
|
where?: SqlWhere;
|
|
@@ -103,116 +90,81 @@ export interface SmartDbSqlOptions<T extends AbstractModel<T, D>, D extends Gene
|
|
|
103
90
|
minus?: SectionDescription<T, D> | SectionDescription<T, D>[];
|
|
104
91
|
intersect?: SectionDescription<T, D> | SectionDescription<T, D>[];
|
|
105
92
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
93
|
+
export declare enum SqlOperationType {
|
|
94
|
+
GT = ">",
|
|
95
|
+
GE = ">=",
|
|
96
|
+
LT = "<",
|
|
97
|
+
LE = "<=",
|
|
98
|
+
EQ = "=",
|
|
99
|
+
NE = "!=",
|
|
100
|
+
IN = "IN",
|
|
101
|
+
LIKE = "LIKE",
|
|
102
|
+
NOT_LIKE = "NOT LIKE",
|
|
103
|
+
IS_NULL = "IS NULL",
|
|
104
|
+
IS_NOT_NULL = "IS NOT NULL",
|
|
116
105
|
LITERAL = "LITERAL",
|
|
117
106
|
VALUE = "VALUE"
|
|
118
107
|
}
|
|
119
|
-
|
|
120
|
-
export enum SqlFieldOperationType {
|
|
108
|
+
export declare enum SqlFieldOperationType {
|
|
121
109
|
VALUE = "VALUE",
|
|
122
110
|
FIELD = "FIELD",
|
|
123
111
|
COUNT = "COUNT",
|
|
124
112
|
COALESCE = "COALESCE"
|
|
125
113
|
}
|
|
126
|
-
|
|
127
114
|
export interface SqlFieldDescriptor {
|
|
128
|
-
operation: SqlFieldOperationType
|
|
129
|
-
value: SqlFieldDescriptor | SqlValueType | (SqlFieldDescriptor | SqlValueType)[]
|
|
130
|
-
alias?: string
|
|
115
|
+
operation: SqlFieldOperationType;
|
|
116
|
+
value: SqlFieldDescriptor | SqlValueType | (SqlFieldDescriptor | SqlValueType)[];
|
|
117
|
+
alias?: string;
|
|
131
118
|
literal?: boolean;
|
|
132
119
|
}
|
|
133
|
-
|
|
134
120
|
export interface SqlOperation {
|
|
135
121
|
operation: SqlOperationType;
|
|
136
122
|
value: SqlValueType | SqlValueType[];
|
|
137
123
|
key?: string;
|
|
138
124
|
literalOperation?: SqlOperationType;
|
|
139
125
|
}
|
|
140
|
-
|
|
141
126
|
export interface KeyValueList {
|
|
142
127
|
[key: string]: SqlValueType;
|
|
143
128
|
}
|
|
144
|
-
|
|
145
129
|
export interface IndexedGenericModelData<T extends AbstractModel<T, D>, D extends GenericModelData> {
|
|
146
130
|
[key: string]: T | GenericModelData;
|
|
147
131
|
}
|
|
148
|
-
|
|
149
132
|
export interface SmartDbSqlBuildDataResults {
|
|
150
133
|
sql: string;
|
|
151
134
|
values: SqlValueType[];
|
|
152
135
|
}
|
|
153
|
-
|
|
154
136
|
export interface SmartDbApi {
|
|
155
137
|
initDb(appOptions: SmartDbOptions): Promise<SmartDbVersionViewModel[]>;
|
|
156
|
-
|
|
157
138
|
exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
|
|
158
|
-
|
|
159
139
|
existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): boolean;
|
|
160
|
-
|
|
161
140
|
get<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): Promise<(T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[]>;
|
|
162
|
-
|
|
163
141
|
getSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): (T | D)[] | T | D | IndexedGenericModelData<T, D> | SqlValueType | string[] | false;
|
|
164
|
-
|
|
165
142
|
getFirst<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): Promise<T>;
|
|
166
|
-
|
|
167
143
|
getFirstSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): T | false;
|
|
168
|
-
|
|
169
144
|
getAll<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): Promise<T[]>;
|
|
170
|
-
|
|
171
145
|
getAllSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): T[] | false;
|
|
172
|
-
|
|
173
146
|
delete<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): Promise<number>;
|
|
174
|
-
|
|
175
147
|
deleteSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): number | false;
|
|
176
|
-
|
|
177
148
|
update<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): Promise<number>;
|
|
178
|
-
|
|
179
149
|
updateSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): number | false;
|
|
180
|
-
|
|
181
150
|
insert<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): Promise<number>;
|
|
182
|
-
|
|
183
151
|
insertSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): number | false;
|
|
184
|
-
|
|
185
152
|
exec(script: string): Promise<void>;
|
|
186
|
-
|
|
187
153
|
execSync(script: string): SmartDbDatabase | false;
|
|
188
|
-
|
|
189
154
|
getLastError(): any;
|
|
190
|
-
|
|
191
155
|
getLastBuildData(): SmartDbSqlBuildData;
|
|
192
|
-
|
|
193
156
|
getDbQuote(): string;
|
|
194
|
-
|
|
195
157
|
getTableInfo(table: string): Promise<SmartDbTableInfo>;
|
|
196
|
-
|
|
197
158
|
toDate(d: Date | number | string): Date | null;
|
|
198
|
-
|
|
199
159
|
getDbConnector(): string | SmartDbConnector;
|
|
200
|
-
|
|
201
160
|
toDbTimestamp(d: Date | number): string;
|
|
202
|
-
|
|
203
161
|
toDbDate(d: Date | number): string;
|
|
204
|
-
|
|
205
162
|
hasConcurrentTransactions(): boolean;
|
|
206
|
-
|
|
207
163
|
closeSync(): boolean;
|
|
208
|
-
|
|
209
164
|
close(): Promise<void>;
|
|
210
165
|
}
|
|
211
|
-
|
|
212
166
|
export interface SmartDbDatabase {
|
|
213
|
-
// empty placeholder interface
|
|
214
167
|
}
|
|
215
|
-
|
|
216
168
|
export interface SmartDbConnector {
|
|
217
|
-
|
|
218
|
-
}
|
|
169
|
+
}
|
|
170
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export var FieldNamingStyle;!function(e){e[e.Database=0]="Database",e[e.TypeScript=1]="TypeScript",e[e.All=2]="All"}(FieldNamingStyle||(FieldNamingStyle={}));export var SqlOperationType;!function(e){e.GT=">",e.GE=">=",e.LT="<",e.LE="<=",e.EQ="=",e.NE="!=",e.IN="IN",e.LIKE="LIKE",e.NOT_LIKE="NOT LIKE",e.IS_NULL="IS NULL",e.IS_NOT_NULL="IS NOT NULL",e.LITERAL="LITERAL",e.VALUE="VALUE"}(SqlOperationType||(SqlOperationType={}));export var SqlFieldOperationType;!function(e){e.VALUE="VALUE",e.FIELD="FIELD",e.COUNT="COUNT",e.COALESCE="COALESCE"}(SqlFieldOperationType||(SqlFieldOperationType={}));
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SmartDbApi } from "./smart-db-interfaces";
|
|
2
|
+
export declare const SmartDbLogLocation: {
|
|
3
|
+
Frontend: string;
|
|
4
|
+
Backend: string;
|
|
5
|
+
Database: string;
|
|
6
|
+
UpgradeManager: string;
|
|
7
|
+
Other: string;
|
|
8
|
+
};
|
|
9
|
+
export declare type SmartDbLogLocationType = typeof SmartDbLogLocation;
|
|
10
|
+
export declare type SmartDbLogLocationKey = keyof SmartDbLogLocationType;
|
|
11
|
+
export declare type SmartDbLogLocationValue = SmartDbLogLocationType[keyof SmartDbLogLocationType];
|
|
12
|
+
export declare const SeverityCode: {
|
|
13
|
+
readonly Fatal: "F";
|
|
14
|
+
readonly Error: "E";
|
|
15
|
+
readonly Warning: "W";
|
|
16
|
+
readonly Info: "I";
|
|
17
|
+
readonly Debug: "D";
|
|
18
|
+
readonly Local: "L";
|
|
19
|
+
};
|
|
20
|
+
export declare type SeverityCodeType = typeof SeverityCode;
|
|
21
|
+
export declare type SeverityCodeKey = keyof SeverityCodeType;
|
|
22
|
+
export declare type SeverityCodeValue = SeverityCodeType[keyof SeverityCodeType];
|
|
23
|
+
export declare const SeverityLevel: {
|
|
24
|
+
readonly None: 0;
|
|
25
|
+
readonly Fatal: 1;
|
|
26
|
+
readonly Error: 2;
|
|
27
|
+
readonly Warning: 3;
|
|
28
|
+
readonly Info: 4;
|
|
29
|
+
readonly Debug: 5;
|
|
30
|
+
readonly All: 9;
|
|
31
|
+
};
|
|
32
|
+
export declare type SeverityLevelType = typeof SeverityLevel;
|
|
33
|
+
export declare type SeverityLevelKey = keyof SeverityLevelType;
|
|
34
|
+
export declare type SeverityLevelValue = SeverityLevelType[keyof SeverityLevelType];
|
|
35
|
+
export declare class SmartDbLog {
|
|
36
|
+
private db;
|
|
37
|
+
private dbLogLevel;
|
|
38
|
+
private consoleLogLevel;
|
|
39
|
+
private userId;
|
|
40
|
+
private dbLogging;
|
|
41
|
+
private isLogging;
|
|
42
|
+
constructor(db?: SmartDbApi);
|
|
43
|
+
getConsoleLogLevel(): SeverityLevelValue;
|
|
44
|
+
setConsoleLogLevel(consoleLogLevel: SeverityLevelValue): void;
|
|
45
|
+
getDbLogLevel(): SeverityLevelValue;
|
|
46
|
+
setDbLogLevel(dbLogLevel: SeverityLevelValue): void;
|
|
47
|
+
setDb(db: SmartDbApi): void;
|
|
48
|
+
setUserId(userId: string | number): void;
|
|
49
|
+
setDbLogging(dbLogging: boolean): void;
|
|
50
|
+
getDbLogging(): boolean;
|
|
51
|
+
logFatal(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
|
|
52
|
+
logError(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
|
|
53
|
+
logWarning(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
|
|
54
|
+
logInfo(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
|
|
55
|
+
logDebug(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
|
|
56
|
+
writeLog(type: SmartDbLogLocationValue, location: string, severity: SeverityCodeValue, message: string | Error, data: unknown, timestamp?: Date | string | number): void;
|
|
57
|
+
}
|
|
58
|
+
export declare const smartDbLog: SmartDbLog;
|
package/smart-db-log.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import _ from"lodash";import{SmartDbLogModel}from"./models/smart-db-log-model";import{SmartDbDateRegexp,SmartDbTimestampRegexp,toSmartDbTimestamp}from"./smart-db-globals";export const SmartDbLogLocation={Frontend:"frontend",Backend:"backend",Database:"database",UpgradeManager:"upgrade-manager",Other:"other"};export const SeverityCode={Fatal:"F",Error:"E",Warning:"W",Info:"I",Debug:"D",Local:"L"};export const SeverityLevel={None:0,Fatal:1,Error:2,Warning:3,Info:4,Debug:5,All:9};export class SmartDbLog{constructor(e){this.userId=null,this.dbLogging=!0,this.isLogging=!1,this.db=e,this.dbLogLevel=SeverityLevel.Info,this.consoleLogLevel=SeverityLevel.Info}getConsoleLogLevel(){return this.consoleLogLevel}setConsoleLogLevel(e){this.consoleLogLevel=e}getDbLogLevel(){return this.dbLogLevel}setDbLogLevel(e){this.dbLogLevel=e}setDb(e){this.db=e,this.db?this.db.exists(SmartDbLogModel).then(e=>{this.dbLogging=e}).catch(e=>{throw e}):this.dbLogging=!1}setUserId(e){this.userId=e}setDbLogging(e){this.dbLogging=e}getDbLogging(){return this.dbLogging}logFatal(e,t,o,r){this.writeLog(e,t,SeverityCode.Fatal,o,r)}logError(e,t,o,r){this.writeLog(e,t,SeverityCode.Error,o,r)}logWarning(e,t,o,r){this.writeLog(e,t,SeverityCode.Warning,o,r)}logInfo(e,t,o,r){this.writeLog(e,t,SeverityCode.Info,o,r)}logDebug(e,t,o,r){this.writeLog(e,t,SeverityCode.Debug,o,r)}writeLog(e,t,o,r,i,s){try{if(this.isLogging)console.error("recursive logging error:",e,t,o,r,i);else{this.isLogging=!0;let a,g,n=SeverityLevel.None;switch(o){case SeverityCode.Fatal:a=console.error,n=SeverityLevel.Fatal;break;case SeverityCode.Error:a=console.error,n=SeverityLevel.Error;break;case SeverityCode.Warning:a=console.warn,n=SeverityLevel.Warning;break;case SeverityCode.Info:a=console.info,n=SeverityLevel.Info;break;case SeverityCode.Debug:a=console.debug,n=SeverityLevel.Debug}if(_.isString(s)){const e=s.match(SmartDbTimestampRegexp),t=e&&s.match(SmartDbDateRegexp);g=e?e[1]:t?t[1]+".000":toSmartDbTimestamp(new Date)}else g=_.isDate(s)?toSmartDbTimestamp(s):_.isNumber(s)?toSmartDbTimestamp(new Date(s)):toSmartDbTimestamp(new Date);if(_.isObjectLike(r))if(r instanceof Error)i||(i=r),r=r.message;else try{r=JSON.stringify(r)}catch(e){r=r.toString()}else"boolean"==typeof r&&(r=r?"<true>":"<false>");if(i){if(i instanceof Error)i=i.stack;else if(_.isObject(i))try{i=JSON.stringify(i)}catch(e){i=i.toString(),this.db&&this.dbLogLevel>=n&&console.error("unable to stringify log data",i)}else i.toString?i=i.toString():(i=null,this.db&&this.dbLogLevel>=n&&console.error("unable to store log data",i));i&&(r+=` (${i})`)}if(this.consoleLogLevel>=n){const s=e.substr(0,1).toUpperCase();if(e==SmartDbLogLocation.Database&&this.db&&a(`${o}-${s}-${g}: last statement:`,this.db.getLastBuildData()),a(`${o}-${s}-${g}: ${r}`),this.dbLogging)try{e==SmartDbLogLocation.Database&&(i||(i=JSON.stringify(this.db.getLastBuildData()))),this.db.insertSync(SmartDbLogModel,{severity:o,type:e,location:t,info:r||"<empty>",data:i,user:this.userId,timestamp:new Date(g)})}catch(e){console.error(`F-B-${g}: unable to write the log statement below to database`,e,e.code,e.name,e.message);try{a(`F-B-${g}: last statement:`,this.db.getLastBuildData())}catch{a(`F-B-${g}: last statement not available`)}}}}this.isLogging=!1}catch(e){this.isLogging=!1,console.error("fatal logging error",e)}}}export const smartDbLog=new SmartDbLog;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SmartDbSqlBuildDataResults, SqlValueType } from "./smart-db-interfaces";
|
|
2
|
+
export declare class SmartDbSqlBuildData {
|
|
3
|
+
sql: string;
|
|
4
|
+
values: SqlValueType[];
|
|
5
|
+
constructor(sql?: string, values?: SqlValueType[]);
|
|
6
|
+
append(data: SmartDbSqlBuildData): void;
|
|
7
|
+
toString(): string;
|
|
8
|
+
results(): SmartDbSqlBuildDataResults;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import _ from"lodash";export class SmartDbSqlBuildData{constructor(s,t){this.sql=s||"",this.values=t||[]}append(s){this.sql=this.sql.trim()+" "+s.sql.trim(),this.values=_.concat(this.values,s.values)}toString(){return this.sql+" <= ("+this.values.join(", ")+")"}results(){return{sql:this.sql,values:this.values}}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
|
|
2
|
+
import { SmartDb } from "./smart-db";
|
|
3
|
+
import { SmartDbOptions } from "./smart-db-interfaces";
|
|
4
|
+
export declare class SmartDbUpgradeManager {
|
|
5
|
+
private db;
|
|
6
|
+
private log;
|
|
7
|
+
constructor(db: SmartDb);
|
|
8
|
+
hasDatabaseModule(module: string): Promise<boolean>;
|
|
9
|
+
prepareDatabase(options: SmartDbOptions): Promise<SmartDbVersionViewModel>;
|
|
10
|
+
private executeSqlScript;
|
|
11
|
+
private upgradeDatabase;
|
|
12
|
+
private executeScriptSequentially;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as fs from"fs";import _ from"lodash";import{SmartDbVersionViewModel}from"./models/smart-db-version-view-model";import{SmartDbLogLocation}from"./smart-db-log";export class SmartDbUpgradeManager{constructor(e){this.db=e,this.log=e.getLogger()}hasDatabaseModule(e){return new Promise((t,a)=>{this.db.exists(SmartDbVersionViewModel).then(o=>{o?this.db.getFirst(SmartDbVersionViewModel,{module:e}).then(e=>{t(!!e)}).catch(e=>{a(e)}):t(!1)}).catch(e=>{a(e)})})}prepareDatabase(e){return new Promise((t,a)=>{try{const o=fs.existsSync(e.sqlFilesDirectory)&&fs.statSync(e.sqlFilesDirectory);if(o&&o.isDirectory()){const o=e.sqlFilesDirectory+`/${e.module}-init.sql`;fs.existsSync(o)?this.hasDatabaseModule(e.module).then(r=>{r?(this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`database module '${e.module}' exists`),this.upgradeDatabase(e).then(a=>{this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`connected to module '${e.module}' version ${a.versionString}`),t(a)}).catch(e=>{a(e)})):(this.log.setDbLogging(!1),this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`database '${e.module}' doesn't exists - begin creation`),this.executeSqlScript(o).then(()=>{this.log.setDbLogging(!0),this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase","database module creation complete"),this.hasDatabaseModule(e.module).then(o=>{o?(this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase","successfully initialized database for new module "+e.module),this.upgradeDatabase(e).then(a=>{this.log.logInfo(SmartDbLogLocation.UpgradeManager,"prepareDatabase",`connected to module '${e.module}' version ${a.versionString}`),t(a)}).catch(e=>{a(e)})):a("error running database initialization script")}).catch(e=>{a(e)})}).catch(e=>{a(e)}))}).catch(e=>{a(e)}):a(`missing mandatory '${e.module}-init.sql' file in ${o}`)}else a(`option 'sqlFilesDirectory' (${e.sqlFilesDirectory}) must point to an existing directory (absolute or relative to ${fs.realpathSync(".")})`)}catch(e){a(e)}})}executeSqlScript(e){const t=fs.readFileSync(e,"utf8");return this.db.exec(t)}upgradeDatabase(e){return new Promise((t,a)=>{this.db.getFirst(SmartDbVersionViewModel,{module:e.module}).then(o=>{o?fs.readdir(e.sqlFilesDirectory,(r,s)=>{if(r)a("unable to read database files from "+e.sqlFilesDirectory);else{let r=[];s.forEach(t=>{const a=new RegExp(`^${e.module}-update.([0-9]{3})\\..*\\.sql$`),s=t.match(a);if(s){parseInt(s[1],10)>o.sequence&&r.push(t)}}),r=_.sortBy(r),this.executeScriptSequentially(r,e).then(()=>{this.db.getFirst(SmartDbVersionViewModel,{module:e.module},"*","sequence DESC").then(e=>{e?t(SmartDbVersionViewModel.from(e)):a("unable to determine final smart db version")}).catch(e=>{a(e)})}).catch(e=>{a(e)})}}):a(`missing version entry for module ${e.module} - add the mandatory insert into smart_db_version statement to your database creation script!`)}).catch(e=>{a(e)})})}executeScriptSequentially(e,t){return new Promise(async(a,o)=>{e&&e.length>0?(this.log.logInfo(SmartDbLogLocation.UpgradeManager,"upgradeDatabase",`execute update script '${e[0]}' for module ${t.module}`),await this.executeSqlScript(`${t.sqlFilesDirectory}/${e[0]}`).then(()=>{this.log.logInfo(SmartDbLogLocation.UpgradeManager,"upgradeDatabase",`successfully executed update script '${e[0]}' for module ${t.module}`),1==e.length&&a(!0)}).catch(e=>{o(e)}),e.length>1&&this.executeScriptSequentially(e.splice(1),t).then(e=>{a(e)}).catch(e=>{o(e)})):a(!0)})}}
|
package/smart-db.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { AbstractModel } from "./models/abstract-model";
|
|
2
|
+
import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
|
|
3
|
+
import { GenericModelData, IndexedGenericModelData, SmartDbApi, SmartDbConnector, SmartDbDatabase, SmartDbOptions, SmartDbRunResult, SmartDbSqlOptions, SmartDbTableInfo, SqlFieldDescriptor, SqlLimit, SqlOrderBy, SqlUpdateValues, SqlValueType, SqlWhere } from "./smart-db-interfaces";
|
|
4
|
+
import { SmartDbLog } from "./smart-db-log";
|
|
5
|
+
import { SmartDbSqlBuildData } from "./smart-db-sql-build-data";
|
|
6
|
+
export declare abstract class SmartDb implements SmartDbApi {
|
|
7
|
+
abstract getDatabaseType(): string;
|
|
8
|
+
abstract hasConcurrentTransactions(): boolean;
|
|
9
|
+
abstract exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
|
|
10
|
+
abstract existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): boolean;
|
|
11
|
+
abstract exec(script: string): Promise<void>;
|
|
12
|
+
abstract execSync(script: string): SmartDbDatabase | false;
|
|
13
|
+
abstract close(): Promise<void>;
|
|
14
|
+
abstract closeSync(): boolean;
|
|
15
|
+
abstract getDbQuote(): string;
|
|
16
|
+
abstract getTableInfo(table: string): Promise<SmartDbTableInfo>;
|
|
17
|
+
abstract getDbConnector(): string | SmartDbConnector;
|
|
18
|
+
protected abstract statementRun(buildData: SmartDbSqlBuildData): Promise<SmartDbRunResult>;
|
|
19
|
+
protected abstract statementRunSync(buildData: SmartDbSqlBuildData): SmartDbRunResult;
|
|
20
|
+
protected abstract statementGet(buildData: SmartDbSqlBuildData): Promise<any>;
|
|
21
|
+
protected abstract statementGetSync(buildData: SmartDbSqlBuildData): any;
|
|
22
|
+
protected abstract statementGetAll(buildData: SmartDbSqlBuildData): Promise<any[]>;
|
|
23
|
+
protected abstract statementGetAllSync(buildData: SmartDbSqlBuildData): any[];
|
|
24
|
+
protected db: SmartDbDatabase;
|
|
25
|
+
protected dbConnector: SmartDbConnector;
|
|
26
|
+
protected lastError: Error;
|
|
27
|
+
protected lastBuildData: SmartDbSqlBuildData;
|
|
28
|
+
protected smartDbLog: SmartDbLog;
|
|
29
|
+
private dictionaries;
|
|
30
|
+
protected constructor(dbConnector: SmartDbConnector);
|
|
31
|
+
initDb(appOptions: SmartDbOptions): Promise<SmartDbVersionViewModel[]>;
|
|
32
|
+
getLogger(): SmartDbLog;
|
|
33
|
+
getDb(): SmartDbDatabase;
|
|
34
|
+
getLastBuildData(): SmartDbSqlBuildData;
|
|
35
|
+
get<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): Promise<(T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[]>;
|
|
36
|
+
getSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): (T | D)[] | T | D | SqlValueType | IndexedGenericModelData<T, D> | string | string[] | false;
|
|
37
|
+
getFirst<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): Promise<T>;
|
|
38
|
+
getFirstSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy): T | false;
|
|
39
|
+
getAll<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): Promise<T[]>;
|
|
40
|
+
getAllSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere, fields?: string | string[] | null, orderBy?: SqlOrderBy, limit?: SqlLimit): T[] | false;
|
|
41
|
+
delete<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): Promise<number>;
|
|
42
|
+
deleteSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): number | false;
|
|
43
|
+
update<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): Promise<number>;
|
|
44
|
+
updateSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): number | false;
|
|
45
|
+
insert<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): Promise<number>;
|
|
46
|
+
insertSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): number | false;
|
|
47
|
+
getLastError(): Error;
|
|
48
|
+
buildSelectStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): SmartDbSqlBuildData;
|
|
49
|
+
toDate(d: Date | number | string): Date | null;
|
|
50
|
+
toDbTimestamp(d: Date | number): string;
|
|
51
|
+
toDbDate(d: Date | number): string;
|
|
52
|
+
protected buildWhere<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where: SqlWhere, op?: string): SmartDbSqlBuildData;
|
|
53
|
+
protected buildDeleteStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), where?: SqlWhere): SmartDbSqlBuildData;
|
|
54
|
+
protected buildUpdateStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T, where?: SqlWhere): SmartDbSqlBuildData;
|
|
55
|
+
protected buildInsertStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), values: SqlUpdateValues | T): SmartDbSqlBuildData;
|
|
56
|
+
protected prepareFieldValue<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), fieldOperation: SqlFieldDescriptor): string;
|
|
57
|
+
protected prepareField<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), field: SqlValueType | SqlFieldDescriptor, values?: SqlValueType[]): string;
|
|
58
|
+
protected buildFieldList<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), fields: (SqlValueType | SqlFieldDescriptor)[]): string[];
|
|
59
|
+
protected buildSelectSectionStatement<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), options: SmartDbSqlOptions<T, D>): SmartDbSqlBuildData;
|
|
60
|
+
protected translateFieldName<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), field: string): string;
|
|
61
|
+
protected makeDbValue(value: SqlValueType): SqlValueType;
|
|
62
|
+
protected makeArgumentDbValue(value: SqlValueType): SqlValueType;
|
|
63
|
+
protected saveExecute<T>(fn: () => T): T | false;
|
|
64
|
+
private prepareResultRow;
|
|
65
|
+
private prepareResultRows;
|
|
66
|
+
private getTableName;
|
|
67
|
+
}
|
package/smart-db.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import _ from"lodash";import{AbstractModel}from"./models/abstract-model";import{SmartDbDictionary}from"./models/smart-db-dictionary";import{SmartDbLogModel}from"./models/smart-db-log-model";import{IN,smartDbToDate,toSmartDbDate,toSmartDbTimestamp}from"./smart-db-globals";import{FieldNamingStyle,SqlFieldOperationType,SqlOperationType}from"./smart-db-interfaces";import{SmartDbLog,SmartDbLogLocation}from"./smart-db-log";import{SmartDbSqlBuildData}from"./smart-db-sql-build-data";import{SmartDbUpgradeManager}from"./smart-db-upgrade-manager";export class SmartDb{constructor(e){this.dictionaries=[],this.dbConnector=e,this.smartDbLog=new SmartDbLog(this)}initDb(e){return new Promise((t,a)=>{this.dictionaries.push(SmartDbDictionary);const r=new SmartDbUpgradeManager(this);let i;i=import.meta&&import.meta.url?import.meta.url.replace(/file:\/\//,"").replace(/\/[^/]*$/,""):__dirname;const s={module:"smart-db-core",sqlFilesDirectory:i+"/assets/"+this.getDatabaseType()};r.prepareDatabase(s).then(i=>{this.exists(SmartDbLogModel).then(s=>{this.smartDbLog.setDbLogging(s),r.prepareDatabase(e).then(e=>{t([i,e])},e=>{a(e)})})}).catch(e=>{a(e)})})}getLogger(){return this.smartDbLog}getDb(){return this.db}getLastBuildData(){return this.lastBuildData}get(e,t){return new Promise((a,r)=>{t||(t={});const i=this.buildSelectStatement(e,t);t.firstOnly||t.count?this.statementGet(i).then(r=>{a(this.prepareResultRow(e,r,t))}).catch(e=>{r(e)}):this.statementGetAll(i).then(r=>{a(this.prepareResultRows(e,r,t))}).catch(e=>{r(e)})})}getSync(e,t){return this.saveExecute(()=>{t||(t={});const a=this.buildSelectStatement(e,t);let r;if(t.firstOnly||t.count){const i=this.statementGetSync(a);r=this.prepareResultRow(e,i,t)}else{const i=this.statementGetAllSync(a);r=this.prepareResultRows(e,i,t)}return r})}getFirst(e,t,a,r){return this.get(e,{firstOnly:!0,where:t,fields:a,orderBy:r})}getFirstSync(e,t,a,r){return this.getSync(e,{firstOnly:!0,where:t,fields:a,orderBy:r})}getAll(e,t,a,r,i){return this.get(e,{where:t,fields:a,orderBy:r,limit:i})}getAllSync(e,t,a,r,i){return this.getSync(e,{where:t,fields:a,orderBy:r,limit:i})}delete(e,t){return new Promise((a,r)=>{const i=this.buildDeleteStatement(e,t);this.statementRun(i).then(e=>{e?a(e.changes):r(this.getLastError())}).catch(e=>{r(e)})})}deleteSync(e,t){return this.saveExecute(()=>{const a=this.buildDeleteStatement(e,t);return this.statementRunSync(a).changes})}update(e,t,a){return new Promise((r,i)=>{const s=this.buildUpdateStatement(e,t,a);this.statementRun(s).then(e=>{e?r(e.changes):i(this.getLastError())}).catch(e=>{i(e)})})}updateSync(e,t,a){return this.saveExecute(()=>{const r=this.buildUpdateStatement(e,t,a);return this.statementRunSync(r).changes})}insert(e,t){return new Promise((a,r)=>{const i=this.buildInsertStatement(e,t);this.statementRun(i).then(e=>{e?a(e.lastId):r(this.getLastError())}).catch(e=>{r(e)})})}insertSync(e,t){return this.saveExecute(()=>{const a=this.buildInsertStatement(e,t);return this.statementRunSync(a).lastId})}getLastError(){return this.lastError}buildSelectStatement(e,t){t||(t={});const a=this.buildSelectSectionStatement(e,t);if(_.forEach(["union","minus","intersect"],e=>{let r=_.get(t,e);r&&(_.isArray(r)||(r=[r]),_.forEach(r,t=>{const r=this.buildSelectSectionStatement(t.model,t);a.sql+=" "+e.toUpperCase()+" ",a.append(r)}))}),t.orderBy){a.sql+=" ORDER BY ";const r=_.isString(t.orderBy)?t.orderBy.split(/ *, */):t.orderBy;a.sql+=r.map(t=>{let a="";const r=t.match(/^(\w*) (asc|desc)$/i);return r&&(t=r[1],a=r[2].toUpperCase()),t=this.translateFieldName(e,t),a&&(t+=" "+a),t}).join(", ")}return t.limit&&(t.limit.limit&&(a.sql+=" LIMIT "+t.limit.limit.toString()),t.limit.offset&&(a.sql+=" OFFSET "+t.limit.offset.toString())),this.lastBuildData=a,a}toDate(e){return smartDbToDate(e)}toDbTimestamp(e){return toSmartDbTimestamp(e)}toDbDate(e){return toSmartDbDate(e)}buildWhere(e,t,a){const r=new SmartDbSqlBuildData;return t&&_.keys(t).length>0&&(a||(a="AND",r.sql+=" WHERE "),r.sql+=_.map(t,(t,i)=>{const s=i.toUpperCase();if("AND"==s||"OR"==s){let a="";return(_.isArray(t)?t:[t]).forEach((t,i)=>{const l=this.buildWhere(e,t,s);i>0&&(a+=" "+s+" "),a+=l.sql,r.values=_.concat(r.values,l.values)}),a="("+a+")",a}if("EXPRESSION"==s){let i=[];return _.forEach(t,t=>{const a=this.prepareField(e,t.compare,r.values),s=this.prepareField(e,t.with,r.values);let l;l=_.isString(t.operation)&&SqlOperationType[t.operation]?SqlOperationType[t.operation]:t.operation||SqlOperationType.EQ,i.push(`${a} ${l} ${s}`)}),i.join(" "+a+" ")}{let a,s,l=!0;if(_.isArray(t)&&(t=IN(t)),_.isObject(t)){const e=t;switch(_.isString(e.operation)&&SqlOperationType[e.operation]&&(e.operation=SqlOperationType[e.operation]),e.operation){case SqlOperationType.IN:const t=new Array(e.value.length);t.fill("?"),a=SqlOperationType.IN+" ("+t.join(", ")+")",r.values=_.concat(r.values,e.value);break;case SqlOperationType.IS_NULL:case SqlOperationType.IS_NOT_NULL:a=e.operation;break;case SqlOperationType.LITERAL:i=e.key;const s=e.literalOperation||SqlOperationType.EQ;if(s==SqlOperationType.IN){const t=new Array(e.value.length);t.fill("?"),a=SqlOperationType.IN+" ("+t.join(", ")+")",r.values=_.concat(r.values,e.value)}else _.isUndefined(e.value)?a=s:(a=s+" ?",r.values.push(this.makeDbValue(e.value)));l=!1;break;default:a=e.operation+" ?",r.values.push(this.makeDbValue(e.value))}}else null===t?a=SqlOperationType.IS_NULL:void 0===t?(i="1",a="= 1",l=!1):(a=_.isString(t)&&t.match(/[%_]/)?SqlOperationType.LIKE+" ?":SqlOperationType.EQ+" ?",r.values.push(this.makeDbValue(t)));return s=l?this.translateFieldName(e,i)+" "+a:i+" "+a,s}}).join(" "+a+" ")),r}buildDeleteStatement(e,t){const a=this.getTableName(e),r=new SmartDbSqlBuildData("DELETE FROM");return r.sql+=" "+a,t&&r.append(this.buildWhere(e,t)),this.lastBuildData=r,r}buildUpdateStatement(e,t,a){const r=this.getTableName(e),i=new SmartDbSqlBuildData("UPDATE");i.sql+=" "+r+" SET ";const s=[];return t instanceof AbstractModel&&(t=t.getPlainObject(FieldNamingStyle.Database)),_.forOwn(t,(t,a)=>{s.push(this.translateFieldName(e,a)+" = ?"),i.values.push(this.makeDbValue(t))}),i.sql+=s.join(", "),a&&i.append(this.buildWhere(e,a)),this.lastBuildData=i,i}buildInsertStatement(e,t){const a=this.getTableName(e),r=new SmartDbSqlBuildData("INSERT");r.sql+=" INTO "+a;const i=[];t instanceof AbstractModel&&(t=t.getPlainObject(FieldNamingStyle.Database)),_.forOwn(t,(t,a)=>{a=this.translateFieldName(e,a),i.push(a),r.values.push(this.makeDbValue(t))});const s=new Array(i.length);return s.fill("?"),r.sql+=" ("+i.join(", ")+") VALUES ("+s.join(", ")+")",this.lastBuildData=r,r}prepareFieldValue(e,t){let a="<undefined>";switch(t.operation){case SqlFieldOperationType.FIELD:a=this.translateFieldName(e,t.value);break;case SqlFieldOperationType.VALUE:null===t.value?a="NULL":t.literal?a=t.value:_.isString(t.value)?!isNaN(parseFloat(t.value))&&isFinite(t.value)||(a="'"+t.value+"'"):_.isNumber(t.value)?a=t.value.toString():_.isBoolean(t.value)?a=t.value?"1":"0":_.isDate(t.value)?a="'"+t.value.toISOString().substr(0,23).replace("T"," ")+"'":console.error("unhandled field data type",typeof t.value,t.value);break;case SqlFieldOperationType.COUNT:a=_.isArray(t.value)?"COUNT("+t.value.join(",")+")":"COUNT("+(t.value||"")+")";break;case SqlFieldOperationType.COALESCE:const r=_.isArray(t.value)?t.value:[t.value];a="COALESCE("+this.buildFieldList(e,r).join(",")+")"}if(t.alias){const e=this.getDbQuote();a+=` as ${e}${t.alias}${e}`}return a}prepareField(e,t,a){let r;if(null===t)r="NULL";else if(_.isString(t)){const i=t.match(/^'(.*)'$/);i?a?(r="?",a.push(i[1])):r=t:r=this.translateFieldName(e,t)}else t.operation?r=this.prepareFieldValue(e,t):a?(r="?",a.push(t)):r=this.makeArgumentDbValue(t).toString();return r}buildFieldList(e,t){const a=[];return _.forEach(t,t=>{a.push(this.prepareField(e,t))}),a}buildSelectSectionStatement(e,t){const a=this.getTableName(e);let r,i;if(_.isArray(t.fields))r=t.fields;else if(_.isString(t.fields)){const e=t.fields.trim();r=""===e||"*"==e?[]:e.split(/,/)}else r=t.fields&&t.fields.operation?[t.fields]:[];if(r.length>0){i=this.buildFieldList(e,r).join(", ")}else i="*";t.distinct&&(i="DISTINCT "+i),t.count&&(i=`COUNT(${i})`);const s=new SmartDbSqlBuildData(`SELECT ${i} FROM ${a}`);if(t.where&&s.append(this.buildWhere(e,t.where)),t.groupBy){s.sql+=" GROUP BY ";const a=_.isArray(t.groupBy)?t.groupBy:[t.groupBy];s.sql+=a.map(t=>this.translateFieldName(e,t)).join(", ")}return s}translateFieldName(e,t){if(_.isString(e)){const t=e;let a=!1;_.forEach(this.dictionaries,r=>(r.models&&r.models[t]&&(e=r.models[t].cls,a=!0),!a))}if(!_.isString(e)){const a=e.attributeMap[t];if(a)a.alias&&(t=a.alias);else{const a=e.getTableName();this.lastError=new Error(`unknown field '${t}' in table '${a}'`),this.smartDbLog.logError(SmartDbLogLocation.Database,"translateFieldName",this.lastError)}}return t}makeDbValue(e){return _.isBoolean(e)?e=e?1:0:_.isDate(e)&&(e=toSmartDbDate(e)),e}makeArgumentDbValue(e){return _.isBoolean(e)?e=e?1:0:_.isDate(e)?e=`'${toSmartDbDate(e)}'`:_.isString(e)&&(e=`'${e}'`),e}saveExecute(e){let t;try{t=e()}catch(e){this.lastError=e instanceof Error?e:new Error(e||"Unknown error"),this.smartDbLog.logFatal(SmartDbLogLocation.Database,"saveExecute-catch",this.lastError),t=!1}return t}prepareResultRow(e,t,a){let r;if(a.indexedBy&&this.smartDbLog.logWarning(SmartDbLogLocation.Database,"AbstractModel.get","option 'indexedBy' not supported without 'all'"),t)if(a.count)r=parseInt(_.values(t)[0],10);else if(a.collapseRow)r=_.values(t).join(",");else{r=e.from(t)}return r}prepareResultRows(e,t,a){let r;if(a.indexedBy||a.collapseRow||!_.isString(e)){const i=e;r=a.indexedBy?{}:new Array(t.length),_.forEach(t,(e,t)=>{const s=i.from?i.from(e):null;let l=null;if(a.indexedBy&&(l=s?s.getValue(a.indexedBy):e[a.indexedBy]),a.collapseRow){const a=_.values(e).join(",");l?r[l]=a:r[t]=a}else l?r[l]=s||e:r[t]=s||e})}else r=t;return r}getTableName(e){let t;if(_.isString(e)){let a=e;_.forEach(this.dictionaries,e=>(e.models&&e.models[a]&&(t=e.models[a].cls.getTableName()),!t)),t||(t=a)}else{if(!e||!e.getTableName)throw new Error("unknown model: "+e);t=e.getTableName()}return t}}
|