@egi/smart-db 2.4.10 → 2.5.0
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/assets/oracle/smart-db-core-init.sql +116 -0
- package/drivers/smart-db-better-sqlite3.d.ts +3 -2
- package/drivers/smart-db-better-sqlite3.js +1 -1
- package/drivers/smart-db-mysql.d.ts +3 -1
- package/drivers/smart-db-mysql.js +1 -1
- package/drivers/smart-db-mysql2.d.ts +3 -1
- package/drivers/smart-db-mysql2.js +1 -1
- package/drivers/smart-db-oracle.d.ts +36 -0
- package/drivers/smart-db-oracle.js +1 -0
- package/drivers/smart-db-sqlite3.d.ts +2 -0
- package/drivers/smart-db-sqlite3.js +1 -1
- package/helpers/extract-db-api.js +1 -1
- package/models/abstract-model.js +1 -1
- package/models/oracle-cat-model.d.ts +23 -0
- package/models/oracle-cat-model.js +1 -0
- package/models/oracle-user-tab-columns-model.d.ts +39 -0
- package/models/oracle-user-tab-columns-model.js +1 -0
- package/models/oracle-user-tab-columns-view-model.d.ts +43 -0
- package/models/oracle-user-tab-columns-view-model.js +1 -0
- package/models/smart-db-core-table-model.d.ts +6 -0
- package/models/smart-db-core-table-model.js +1 -1
- package/models/smart-db-dictionary.d.ts +2 -1
- package/models/smart-db-dictionary.js +1 -1
- package/models/smart-db-log-model.d.ts +22 -5
- package/models/smart-db-log-model.js +1 -1
- package/models/smart-db-user-tab-columns-view-model.d.ts +305 -0
- package/models/smart-db-user-tab-columns-view-model.js +1 -0
- package/models/smart-db-version-model.d.ts +22 -5
- package/models/smart-db-version-model.js +1 -1
- package/models/smart-db-version-view-model.d.ts +28 -10
- package/models/smart-db-version-view-model.js +1 -1
- package/models.generated/abstract-model.d.ts +23 -0
- package/models.generated/abstract-model.js +1 -0
- package/models.generated/smart-db-core-table-model.d.ts +41 -0
- package/models.generated/smart-db-core-table-model.js +1 -0
- package/models.generated/smart-db-dictionary.d.ts +14 -0
- package/models.generated/smart-db-dictionary.js +1 -0
- package/models.generated/smart-db-log-model.d.ts +82 -0
- package/models.generated/smart-db-log-model.js +1 -0
- package/models.generated/smart-db-user-tab-columns-view-model.d.ts +305 -0
- package/models.generated/smart-db-user-tab-columns-view-model.js +1 -0
- package/models.generated/smart-db-version-model.d.ts +82 -0
- package/models.generated/smart-db-version-model.js +1 -0
- package/models.generated/smart-db-version-view-model.d.ts +90 -0
- package/models.generated/smart-db-version-view-model.js +1 -0
- package/package.json +6 -2
- package/smart-db-globals.d.ts +3 -1
- package/smart-db-globals.js +1 -1
- package/smart-db-interfaces.d.ts +2 -0
- package/smart-db-log.d.ts +1 -1
- package/smart-db-log.js +1 -1
- package/smart-db-upgrade-manager.js +1 -1
- package/smart-db.d.ts +12 -2
- package/smart-db.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@egi/smart-db",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Unified Smart DB Access",
|
|
5
5
|
"author": "Marcel Egloff",
|
|
6
6
|
"type": "module",
|
|
@@ -59,6 +59,9 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"lodash": "^4.17.21",
|
|
62
|
+
"node-oracledb": "^1.0.2",
|
|
63
|
+
"oracledb": "^5.5.0",
|
|
64
|
+
"rxjs": "^7.8.0",
|
|
62
65
|
"sqlite3": "^5.1.4"
|
|
63
66
|
},
|
|
64
67
|
"devDependencies": {
|
|
@@ -67,12 +70,13 @@
|
|
|
67
70
|
"@types/lodash": "^4.14.191",
|
|
68
71
|
"@types/mysql": "^2.15.18",
|
|
69
72
|
"@types/node": "^18.11.18",
|
|
73
|
+
"@types/oracledb": "^5.2.3",
|
|
70
74
|
"@types/sqlite3": "^3.1.7",
|
|
71
75
|
"@types/uglify-js": "^3.17.1",
|
|
72
76
|
"glob": "^8.1.0",
|
|
73
77
|
"mocha": "^10.2.0",
|
|
74
78
|
"npm-run-all": "^4.1.5",
|
|
75
|
-
"terser": "^5.16.
|
|
79
|
+
"terser": "^5.16.3",
|
|
76
80
|
"uglify-js": "^3.17.4"
|
|
77
81
|
},
|
|
78
82
|
"optionalDependencies": {
|
package/smart-db-globals.d.ts
CHANGED
|
@@ -11,11 +11,13 @@ export declare const GE: (value: SqlValueType) => SqlOperation;
|
|
|
11
11
|
export declare const LT: (value: SqlValueType) => SqlOperation;
|
|
12
12
|
export declare const LE: (value: SqlValueType) => SqlOperation;
|
|
13
13
|
export declare const EQ: (value: SqlValueType) => SqlOperation;
|
|
14
|
-
export declare const NE: (value:
|
|
14
|
+
export declare const NE: (value: SqlValueType) => SqlOperation;
|
|
15
15
|
export declare const IN: (value: SqlValueType[]) => SqlOperation;
|
|
16
16
|
export declare const NOT_IN: (value: SqlValueType[]) => SqlOperation;
|
|
17
17
|
export declare const IS_NULL: () => SqlOperation;
|
|
18
18
|
export declare const IS_NOT_NULL: () => SqlOperation;
|
|
19
|
+
export declare const LIKE: (value: SqlValueType) => SqlOperation;
|
|
20
|
+
export declare const NOT_LIKE: (value: SqlValueType) => SqlOperation;
|
|
19
21
|
export declare const SmartDbDateRegexp: RegExp;
|
|
20
22
|
export declare const SmartDbTimestampRegexp: RegExp;
|
|
21
23
|
export declare function toSmartDbDate(d: Date | number): string;
|
package/smart-db-globals.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import _ from"lodash";import{SqlFieldOperationType,SqlOperationType}from"./smart-db-interfaces";export const OP=(e,t,o,
|
|
1
|
+
import _ from"lodash";import{SqlFieldOperationType,SqlOperationType}from"./smart-db-interfaces";export const OP=(e,t,o,p)=>o?{operation:e,value:t,key:o,literalOperation:p}:{operation:e,value:t};export const VALUE=(e,t,o)=>({operation:SqlFieldOperationType.VALUE,value:e,alias:t,literal:o});export const FIELD=(e,t)=>({operation:SqlFieldOperationType.FIELD,value:e,alias:t});export const COUNT=(e,t)=>({operation:SqlFieldOperationType.COUNT,value:e,alias:t});export const COALESCE=(e,t)=>({operation:SqlFieldOperationType.COALESCE,value:e,alias:t});export const NVL=(e,t)=>COALESCE(e,t);export const LITERAL=(e,t,o)=>OP(SqlOperationType.LITERAL,t,e,o||SqlOperationType.EQ);export const GT=e=>OP(SqlOperationType.GT,e);export const GE=e=>OP(SqlOperationType.GE,e);export const LT=e=>OP(SqlOperationType.LT,e);export const LE=e=>OP(SqlOperationType.LE,e);export const EQ=e=>OP(SqlOperationType.EQ,e);export const NE=e=>OP(SqlOperationType.NE,e);export const IN=e=>OP(SqlOperationType.IN,e);export const NOT_IN=e=>OP(SqlOperationType.NOT_IN,e);export const IS_NULL=()=>OP(SqlOperationType.IS_NULL);export const IS_NOT_NULL=()=>OP(SqlOperationType.IS_NOT_NULL);export const LIKE=e=>OP(SqlOperationType.LIKE,e);export const NOT_LIKE=e=>OP(SqlOperationType.NOT_LIKE,e);export const SmartDbDateRegexp=/^(\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d)(Z| GMT| GMT[-+]\d{1,2})?$/;export const SmartDbTimestampRegexp=/^(\d{4}-[01]\d-[0-3]\d [0-2]\d:[0-5]\d:[0-5]\d\.\d{3})(Z| GMT| GMT[-+]\d{1,2})?$/;export function toSmartDbDate(e){let t;return e&&(_.isNumber(e)&&(e=new Date(e)),t=e.toISOString().substr(0,19).replace("T"," ")),t}export function toSmartDbTimestamp(e){let t;return e&&(_.isNumber(e)&&(e=new Date(e)),t=e.toISOString().substr(0,23).replace("T"," ")),t}export function smartDbToDate(e){let t=null;return _.isDate(e)?t=e:(_.isNumber(e)||_.isString(e)&&(e.match(SmartDbDateRegexp)||e.match(SmartDbTimestampRegexp)))&&(t=new Date(e)),t}
|
package/smart-db-interfaces.d.ts
CHANGED
|
@@ -164,6 +164,8 @@ export interface SmartDbApi {
|
|
|
164
164
|
toDbTimestamp(d: Date | number): string;
|
|
165
165
|
toDbDate(d: Date | number): string;
|
|
166
166
|
hasConcurrentTransactions(): boolean;
|
|
167
|
+
supportSyncCalls(): boolean;
|
|
168
|
+
supportAsyncCalls(): boolean;
|
|
167
169
|
closeSync(): boolean;
|
|
168
170
|
close(): Promise<void>;
|
|
169
171
|
}
|
package/smart-db-log.d.ts
CHANGED
|
@@ -53,6 +53,6 @@ export declare class SmartDbLog {
|
|
|
53
53
|
logWarning(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
|
|
54
54
|
logInfo(type: SmartDbLogLocationValue, location: string, message: string | Error, data?: any): void;
|
|
55
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
|
|
56
|
+
writeLog(type: SmartDbLogLocationValue, location: string, severity: SeverityCodeValue, message: string | Error, data: unknown, timestamp?: Date | string | number): Promise<void>;
|
|
57
57
|
}
|
|
58
58
|
export declare const smartDbLog: SmartDbLog;
|
package/smart-db-log.js
CHANGED
|
@@ -1 +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
|
|
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.dbLogging=!!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)}async writeLog(e,t,o,r,s,i){try{if(this.isLogging)console.error("recursive logging error:",e,t,o,r,s);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(i)){const e=i.match(SmartDbTimestampRegexp),t=e&&i.match(SmartDbDateRegexp);g=e?e[1]:t?t[1]+".000":toSmartDbTimestamp(new Date)}else g=_.isDate(i)?toSmartDbTimestamp(i):_.isNumber(i)?toSmartDbTimestamp(new Date(i)):toSmartDbTimestamp(new Date);if(_.isObjectLike(r))if(r instanceof Error)s||(s=r),r=r.message;else try{r=JSON.stringify(r)}catch(e){r=r.toString()}else"boolean"==typeof r&&(r=r?"<true>":"<false>");if(s){if(s instanceof Error)s=s.stack;else if(_.isObject(s))try{s=JSON.stringify(s)}catch(e){s=s.toString(),this.db&&this.dbLogLevel>=n&&console.error("unable to stringify log data",s)}else s.toString?s=s.toString():(s=null,this.db&&this.dbLogLevel>=n&&console.error("unable to store log data",s));s&&(r+=` (${s})`)}if(this.consoleLogLevel>=n){const i=e.substring(0,1).toUpperCase();if(e==SmartDbLogLocation.Database&&this.db&&a(`${o}-${i}-${g}: last statement:`,this.db.getLastBuildData()),a(`${o}-${i}-${g}: ${r}`),this.dbLogging)try{e==SmartDbLogLocation.Database&&(s||(s=JSON.stringify(this.db.getLastBuildData()))),this.db.supportAsyncCalls()?await this.db.insert(SmartDbLogModel,{severity:o,type:e,location:t,info:r||"<empty>",data:s,user:this.userId,timestamp:new Date(g)}).then((()=>{this.db.exec("commit")})).catch((e=>{console.error(`F-B-${g}: unable to write the log statement below to database`,e,e.code,e.name,e.message)})):this.db.insertSync(SmartDbLogModel,{severity:o,type:e,location:t,info:r||"<empty>",data:s,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;
|
|
@@ -1 +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"
|
|
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
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Observable, Subject } from "rxjs";
|
|
1
2
|
import { AbstractModel } from "./models/abstract-model";
|
|
2
3
|
import { SmartDbVersionViewModel } from "./models/smart-db-version-view-model";
|
|
3
4
|
import { GenericModelData, IndexedGenericModelData, SmartDbApi, SmartDbConnector, SmartDbDatabase, SmartDbOptions, SmartDbRunResult, SmartDbSqlOptions, SmartDbTableInfo, SqlFieldDescriptor, SqlLimit, SqlOrderBy, SqlUpdateValues, SqlValueType, SqlWhere } from "./smart-db-interfaces";
|
|
@@ -6,6 +7,8 @@ import { SmartDbSqlBuildData } from "./smart-db-sql-build-data";
|
|
|
6
7
|
export declare abstract class SmartDb implements SmartDbApi {
|
|
7
8
|
abstract getDatabaseType(): string;
|
|
8
9
|
abstract hasConcurrentTransactions(): boolean;
|
|
10
|
+
abstract supportSyncCalls(): boolean;
|
|
11
|
+
abstract supportAsyncCalls(): boolean;
|
|
9
12
|
abstract exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
|
|
10
13
|
abstract existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): boolean;
|
|
11
14
|
abstract exec(script: string): Promise<void>;
|
|
@@ -21,14 +24,19 @@ export declare abstract class SmartDb implements SmartDbApi {
|
|
|
21
24
|
protected abstract statementGetSync(buildData: SmartDbSqlBuildData): any;
|
|
22
25
|
protected abstract statementGetAll(buildData: SmartDbSqlBuildData): Promise<any[]>;
|
|
23
26
|
protected abstract statementGetAllSync(buildData: SmartDbSqlBuildData): any[];
|
|
24
|
-
protected
|
|
27
|
+
protected: any;
|
|
25
28
|
protected dbConnector: SmartDbConnector;
|
|
26
29
|
protected lastError: Error;
|
|
27
30
|
protected lastBuildData: SmartDbSqlBuildData;
|
|
28
31
|
protected smartDbLog: SmartDbLog;
|
|
32
|
+
protected _onReady: Subject<boolean>;
|
|
33
|
+
protected db: SmartDbDatabase;
|
|
29
34
|
private dictionaries;
|
|
30
|
-
|
|
35
|
+
private _isReady;
|
|
36
|
+
private dbLogging;
|
|
37
|
+
protected constructor(dbConnector: SmartDbConnector, noDbLogging?: boolean);
|
|
31
38
|
initDb(appOptions: SmartDbOptions): Promise<SmartDbVersionViewModel[]>;
|
|
39
|
+
onReady(): Observable<boolean>;
|
|
32
40
|
getLogger(): SmartDbLog;
|
|
33
41
|
getDb(): SmartDbDatabase;
|
|
34
42
|
getLastBuildData(): SmartDbSqlBuildData;
|
|
@@ -64,4 +72,6 @@ export declare abstract class SmartDb implements SmartDbApi {
|
|
|
64
72
|
private prepareResultRow;
|
|
65
73
|
private prepareResultRows;
|
|
66
74
|
private getTableName;
|
|
75
|
+
get isReady(): boolean;
|
|
76
|
+
set isReady(ready: boolean);
|
|
67
77
|
}
|
package/smart-db.js
CHANGED
|
@@ -1 +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:case SqlOperationType.NOT_IN:const t=new Array(e.value.length);t.fill("?"),a=e.operation+" ("+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||s==SqlOperationType.NOT_IN){const t=new Array(e.value.length);t.fill("?"),a=s+" ("+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=[],l=t instanceof AbstractModel?t.getPlainObject(FieldNamingStyle.Database):t;return _.forOwn(l,(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.replace(/'/,"''").replace(/\\/,"\\\\")}'`),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{const i=e.from(t);r=a.style==FieldNamingStyle.TypeScript?i.getPlainObject():i}return r}prepareResultRows(e,t,a){let r;if(!t||!a.indexedBy&&!a.collapseRow&&_.isString(e))r=t;else{const i=e;r=a.indexedBy?{}:new Array(t.length),_.forEach(t,(e,t)=>{let s=i.from?i.from(e):null,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 s&&a.style==FieldNamingStyle.TypeScript&&(s=s.getPlainObject()),l?r[l]=s||e:r[t]=s||e})}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}}
|
|
1
|
+
import _ from"lodash";import{Subject}from"rxjs";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,t){this.dictionaries=[],this.dbConnector=e,this.smartDbLog=new SmartDbLog(t?null:this),this.dbLogging=!t,this.db=null,this._onReady=new Subject}initDb(e){return new Promise(((t,a)=>{this.dictionaries.push(SmartDbDictionary);const s=new SmartDbUpgradeManager(this);let r;r=import.meta&&import.meta.url?import.meta.url.replace(/file:\/\//,"").replace(/\/[^/]*$/,""):__dirname;const i={module:"smart-db-core",sqlFilesDirectory:r+"/assets/"+this.getDatabaseType()};s.prepareDatabase(i).then((r=>{this.exists(SmartDbLogModel).then((i=>{this.smartDbLog.setDbLogging(this.dbLogging&&i),s.prepareDatabase(e).then((e=>{t([r,e])}),(e=>{a(e)}))}))})).catch((e=>{a(e)}))}))}onReady(){return this._onReady.asObservable()}getLogger(){return this.smartDbLog}getDb(){return this.db}getLastBuildData(){return this.lastBuildData}get(e,t){return new Promise(((a,s)=>{if(this.supportAsyncCalls()){t||(t={});const r=this.buildSelectStatement(e,t);t.firstOnly||t.count?this.statementGet(r).then((s=>{a(this.prepareResultRow(e,s,t))})).catch((e=>{s(e)})):this.statementGetAll(r).then((s=>{a(this.prepareResultRows(e,s,t))})).catch((e=>{s(e)}))}else s("get: this database driver doesn't support async calls")}))}getSync(e,t){if(this.supportSyncCalls())return this.saveExecute((()=>{t||(t={});const a=this.buildSelectStatement(e,t);let s;if(t.firstOnly||t.count){const r=this.statementGetSync(a);s=this.prepareResultRow(e,r,t)}else{const r=this.statementGetAllSync(a);s=this.prepareResultRows(e,r,t)}return s}));throw"getSync: this database driver doesn't support sync calls"}getFirst(e,t,a,s){return this.get(e,{firstOnly:!0,where:t,fields:a,orderBy:s})}getFirstSync(e,t,a,s){return this.getSync(e,{firstOnly:!0,where:t,fields:a,orderBy:s})}getAll(e,t,a,s,r){return this.get(e,{where:t,fields:a,orderBy:s,limit:r})}getAllSync(e,t,a,s,r){return this.getSync(e,{where:t,fields:a,orderBy:s,limit:r})}delete(e,t){return new Promise(((a,s)=>{if(this.supportAsyncCalls()){const r=this.buildDeleteStatement(e,t);this.statementRun(r).then((e=>{e?a(e.changes):s(this.getLastError())})).catch((e=>{s(e)}))}else s("delete: this database driver doesn't support sync calls")}))}deleteSync(e,t){if(this.supportSyncCalls())return this.saveExecute((()=>{const a=this.buildDeleteStatement(e,t);return this.statementRunSync(a).changes}));throw"deleteSync: this database driver doesn't support sync calls"}update(e,t,a){return new Promise(((s,r)=>{if(this.supportAsyncCalls()){const i=this.buildUpdateStatement(e,t,a);this.statementRun(i).then((e=>{e?s(e.changes):r(this.getLastError())})).catch((e=>{r(e)}))}else r("update: this database driver doesn't support sync calls")}))}updateSync(e,t,a){if(this.supportSyncCalls())return this.saveExecute((()=>{const s=this.buildUpdateStatement(e,t,a);return this.statementRunSync(s).changes}));throw"updateSync: this database driver doesn't support sync calls"}insert(e,t){return new Promise(((a,s)=>{if(this.supportAsyncCalls()){const r=this.buildInsertStatement(e,t);this.statementRun(r).then((e=>{e?a(e.lastId):s(this.getLastError())})).catch((e=>{s(e)}))}else s("insert: this database driver doesn't support sync calls")}))}insertSync(e,t){if(this.supportSyncCalls())return this.saveExecute((()=>{const a=this.buildInsertStatement(e,t);return this.statementRunSync(a).lastId}));throw"insertSync: this database driver doesn't support sync calls"}getLastError(){return this.lastError}buildSelectStatement(e,t){t||(t={});const a=this.buildSelectSectionStatement(e,t);if(_.forEach(["union","minus","intersect"],(e=>{let s=_.get(t,e);s&&(_.isArray(s)||(s=[s]),_.forEach(s,(t=>{const s=this.buildSelectSectionStatement(t.model,t);a.sql+=" "+e.toUpperCase()+" ",a.append(s)})))})),t.orderBy){a.sql+=" ORDER BY ";const s=_.isString(t.orderBy)?t.orderBy.split(/ *, */):t.orderBy;a.sql+=s.map((t=>{let a="";const s=t.match(/^(\w*) (asc|desc)$/i);return s&&(t=s[1],a=s[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 s=new SmartDbSqlBuildData;return t&&_.keys(t).length>0&&(a||(a="AND",s.sql+=" WHERE "),s.sql+=_.map(t,((t,r)=>{const i=r.toUpperCase();if("AND"==i||"OR"==i){let a="";return(_.isArray(t)?t:[t]).forEach(((t,r)=>{const l=this.buildWhere(e,t,i);r>0&&(a+=" "+i+" "),a+=l.sql,s.values=_.concat(s.values,l.values)})),a="("+a+")",a}if("EXPRESSION"==i){let r=[];return _.forEach(t,(t=>{const a=this.prepareField(e,t.compare,s.values),i=this.prepareField(e,t.with,s.values);let l;l=_.isString(t.operation)&&SqlOperationType[t.operation]?SqlOperationType[t.operation]:t.operation||SqlOperationType.EQ,r.push(`${a} ${l} ${i}`)})),r.join(" "+a+" ")}{let a,i,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:case SqlOperationType.NOT_IN:const t=new Array(e.value.length);t.fill("?"),a=e.operation+" ("+t.join(", ")+")",s.values=_.concat(s.values,e.value);break;case SqlOperationType.IS_NULL:case SqlOperationType.IS_NOT_NULL:a=e.operation;break;case SqlOperationType.LITERAL:r=e.key;const i=e.literalOperation||SqlOperationType.EQ;if(i==SqlOperationType.IN||i==SqlOperationType.NOT_IN){const t=new Array(e.value.length);t.fill("?"),a=i+" ("+t.join(", ")+")",s.values=_.concat(s.values,e.value)}else _.isUndefined(e.value)?a=i:(a=i+" ?",s.values.push(this.makeDbValue(e.value)));l=!1;break;default:a=e.operation+" ?",s.values.push(this.makeDbValue(e.value))}}else null===t?a=SqlOperationType.IS_NULL:void 0===t?(r="1",a="= 1",l=!1):(a=_.isString(t)&&t.match(/[%_]/)?SqlOperationType.LIKE+" ?":SqlOperationType.EQ+" ?",s.values.push(this.makeDbValue(t)));return i=l?this.translateFieldName(e,r)+" "+a:r+" "+a,i}})).join(" "+a+" ")),s}buildDeleteStatement(e,t){const a=this.getTableName(e),s=new SmartDbSqlBuildData("DELETE FROM");return s.sql+=" "+a,t&&s.append(this.buildWhere(e,t)),this.lastBuildData=s,s}buildUpdateStatement(e,t,a){const s=this.getTableName(e),r=new SmartDbSqlBuildData("UPDATE");r.sql+=" "+s+" SET ";const i=[],l=t instanceof AbstractModel?t.getPlainObject(FieldNamingStyle.Database):t;return _.forOwn(l,((t,a)=>{i.push(this.translateFieldName(e,a)+" = ?"),r.values.push(this.makeDbValue(t))})),r.sql+=i.join(", "),a&&r.append(this.buildWhere(e,a)),this.lastBuildData=r,r}buildInsertStatement(e,t){const a=this.getTableName(e),s=new SmartDbSqlBuildData("INSERT");s.sql+=" INTO "+a;const r=[];t instanceof AbstractModel&&(t=t.getPlainObject(FieldNamingStyle.Database)),_.forOwn(t,((t,a)=>{a=this.translateFieldName(e,a),r.push(a),s.values.push(this.makeDbValue(t))}));const i=new Array(r.length);return i.fill("?"),s.sql+=" ("+r.join(", ")+") VALUES ("+i.join(", ")+")",this.lastBuildData=s,s}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 s=_.isArray(t.value)?t.value:[t.value];a="COALESCE("+this.buildFieldList(e,s).join(",")+")"}if(t.alias){const e=this.getDbQuote();a+=` as ${e}${t.alias}${e}`}return a}prepareField(e,t,a){let s;if(null===t)s="NULL";else if(_.isString(t)){const r=t.match(/^'(.*)'$/);r?a?(s="?",a.push(r[1])):s=t:s=this.translateFieldName(e,t)}else t.operation?s=this.prepareFieldValue(e,t):a?(s="?",a.push(t)):s=this.makeArgumentDbValue(t).toString();return s}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 s,r;if(_.isArray(t.fields))s=t.fields;else if(_.isString(t.fields)){const e=t.fields.trim();s=""===e||"*"==e?[]:e.split(/,/)}else s=t.fields&&t.fields.operation?[t.fields]:[];if(s.length>0){r=this.buildFieldList(e,s).join(", ")}else r="*";t.distinct&&(r="DISTINCT "+r),t.count&&(r=`COUNT(${r})`);const i=new SmartDbSqlBuildData(`SELECT ${r} FROM ${a}`);if(t.where&&i.append(this.buildWhere(e,t.where)),t.groupBy){i.sql+=" GROUP BY ";const a=_.isArray(t.groupBy)?t.groupBy:[t.groupBy];i.sql+=a.map((t=>this.translateFieldName(e,t))).join(", ")}return i}translateFieldName(e,t){if(_.isString(e)){const t=e;let a=!1;_.forEach(this.dictionaries,(s=>(s.models&&s.models[t]&&(e=s.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.replace(/'/,"''").replace(/\\/,"\\\\")}'`),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 s;if(a.indexedBy&&this.smartDbLog.logWarning(SmartDbLogLocation.Database,"AbstractModel.get","option 'indexedBy' not supported without 'all'"),t)if(a.count)s=parseInt(_.values(t)[0],10);else if(a.collapseRow)s=_.values(t).join(",");else{const r=e.from(t);s=a.style==FieldNamingStyle.TypeScript?r.getPlainObject():r}return s}prepareResultRows(e,t,a){let s;if(!t||!a.indexedBy&&!a.collapseRow&&_.isString(e))s=t;else{const r=e;s=a.indexedBy?{}:new Array(t.length),_.forEach(t,((e,t)=>{let i=r.from?r.from(e):null,l=null;if(a.indexedBy&&(l=i?i.getValue(a.indexedBy):e[a.indexedBy]),a.collapseRow){const a=_.values(e).join(",");l?s[l]=a:s[t]=a}else i&&a.style==FieldNamingStyle.TypeScript&&(i=i.getPlainObject()),l?s[l]=i||e:s[t]=i||e}))}return s}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}get isReady(){return this._isReady}set isReady(e){this._isReady=e,this._onReady.next(e)}}
|