@oino-ts/db 0.21.2 → 1.0.1
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/dist/cjs/OINODb.js +6 -144
- package/dist/cjs/OINODbApi.js +50 -318
- package/dist/cjs/OINODbConfig.js +10 -10
- package/dist/cjs/OINODbConstants.js +10 -0
- package/dist/cjs/OINODbDataField.js +28 -70
- package/dist/cjs/OINODbDataModel.js +30 -144
- package/dist/cjs/OINODbFactory.js +2 -2
- package/dist/cjs/OINODbModelSet.js +23 -23
- package/dist/cjs/OINODbQueryParams.js +201 -0
- package/dist/cjs/index.js +12 -41
- package/dist/esm/OINODb.js +6 -142
- package/dist/esm/OINODbApi.js +49 -314
- package/dist/esm/OINODbConstants.js +7 -0
- package/dist/esm/OINODbDataModel.js +31 -145
- package/dist/esm/OINODbFactory.js +1 -1
- package/dist/esm/OINODbQueryParams.js +194 -0
- package/dist/esm/index.js +4 -14
- package/dist/types/OINODb.d.ts +6 -173
- package/dist/types/OINODbApi.d.ts +18 -104
- package/dist/types/OINODbConstants.d.ts +23 -0
- package/dist/types/OINODbDataModel.d.ts +7 -61
- package/dist/types/OINODbFactory.d.ts +5 -2
- package/dist/types/OINODbQueryParams.d.ts +72 -0
- package/dist/types/index.d.ts +4 -108
- package/package.json +37 -37
- package/src/OINODb.ts +99 -348
- package/src/OINODbApi.test.ts +507 -498
- package/src/OINODbApi.ts +389 -667
- package/src/OINODbConstants.ts +32 -0
- package/src/OINODbDataModel.ts +191 -307
- package/src/OINODbFactory.ts +73 -68
- package/src/OINODbQueryParams.ts +203 -0
- package/src/index.ts +6 -118
- package/src/OINODbConfig.ts +0 -98
- package/src/OINODbDataField.ts +0 -405
- package/src/OINODbModelSet.ts +0 -353
- package/src/OINODbParser.ts +0 -438
- package/src/OINODbSqlParams.ts +0 -593
- package/src/OINODbSwagger.ts +0 -209
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
4
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
import { OINO_ERROR_PREFIX } from "@oino-ts/common";
|
|
7
|
-
import {
|
|
6
|
+
import { OINO_ERROR_PREFIX, OINODataModel, OINOConfig, OINONumberDataField } from "@oino-ts/common";
|
|
7
|
+
import { OINODB_UNDEFINED } from "./OINODbConstants.js";
|
|
8
|
+
import { OINODbQueryOrder, OINODbQueryFilter, OINODbQueryLimit, OINODbQueryAggregate } from "./OINODbQueryParams.js";
|
|
8
9
|
/**
|
|
9
10
|
* OINO Datamodel object for representing one database table and it's columns.
|
|
10
11
|
*
|
|
11
12
|
*/
|
|
12
|
-
export class OINODbDataModel {
|
|
13
|
-
_fieldIndexLookup;
|
|
13
|
+
export class OINODbDataModel extends OINODataModel {
|
|
14
14
|
/** Database refererence of the table */
|
|
15
|
-
|
|
15
|
+
dbApi;
|
|
16
16
|
/** Field refererences of the API */
|
|
17
17
|
fields;
|
|
18
18
|
/**
|
|
@@ -23,26 +23,19 @@ export class OINODbDataModel {
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
constructor(api) {
|
|
26
|
-
|
|
27
|
-
this.
|
|
26
|
+
super(api);
|
|
27
|
+
this.dbApi = api;
|
|
28
28
|
this.fields = [];
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
* Initialize datamodel from SQL schema.
|
|
32
|
-
*
|
|
33
|
-
*/
|
|
34
|
-
async initialize() {
|
|
35
|
-
await this.api.db.initializeApiDatamodel(this.api);
|
|
36
|
-
}
|
|
37
|
-
_printSqlColumnNames(select) {
|
|
30
|
+
_printColumnNames(select) {
|
|
38
31
|
let result = "";
|
|
39
32
|
for (let i = 0; i < this.fields.length; i++) {
|
|
40
33
|
const f = this.fields[i];
|
|
41
|
-
if (select?.isSelected(f) === false) { // if a field is not selected, we include a constant and correct fieldname instead so that dimensions of the data don't change but no unnecessary data is fetched
|
|
42
|
-
result += f.
|
|
34
|
+
if ((select?.isSelected(f.name) === false) && (f.fieldParams.isPrimaryKey == false)) { // if a field is not selected, we include a constant and correct fieldname instead so that dimensions of the data don't change but no unnecessary data is fetched
|
|
35
|
+
result += f.datasource.printStringValue(OINODB_UNDEFINED) + " as " + f.printColumnName() + ",";
|
|
43
36
|
}
|
|
44
37
|
else {
|
|
45
|
-
result += f.
|
|
38
|
+
result += f.printColumnName() + ",";
|
|
46
39
|
}
|
|
47
40
|
}
|
|
48
41
|
return result.substring(0, result.length - 1);
|
|
@@ -59,8 +52,8 @@ export class OINODbDataModel {
|
|
|
59
52
|
columns += ",";
|
|
60
53
|
values += ",";
|
|
61
54
|
}
|
|
62
|
-
columns += f.
|
|
63
|
-
values += f.
|
|
55
|
+
columns += f.printColumnName();
|
|
56
|
+
values += f.printCellAsValue(val);
|
|
64
57
|
}
|
|
65
58
|
}
|
|
66
59
|
// console.log("_printSqlInsertColumnsAndValues: columns=" + columns + ", values=" + values)
|
|
@@ -75,7 +68,7 @@ export class OINODbDataModel {
|
|
|
75
68
|
if (result != "") {
|
|
76
69
|
result += ",";
|
|
77
70
|
}
|
|
78
|
-
result += f.
|
|
71
|
+
result += f.printColumnName() + "=" + f.printCellAsValue(val);
|
|
79
72
|
}
|
|
80
73
|
}
|
|
81
74
|
if (result == "") {
|
|
@@ -86,21 +79,21 @@ export class OINODbDataModel {
|
|
|
86
79
|
_printSqlPrimaryKeyCondition(id_value) {
|
|
87
80
|
let result = "";
|
|
88
81
|
let i = 0;
|
|
89
|
-
const id_parts = id_value.split(
|
|
82
|
+
const id_parts = id_value.split(OINOConfig.OINO_ID_SEPARATOR);
|
|
90
83
|
for (let f of this.fields) {
|
|
91
84
|
if (f.fieldParams.isPrimaryKey) {
|
|
92
85
|
if (result != "") {
|
|
93
86
|
result += " AND ";
|
|
94
87
|
}
|
|
95
88
|
let value = decodeURIComponent(id_parts[i]);
|
|
96
|
-
if ((f instanceof OINONumberDataField) && (this.
|
|
97
|
-
value = this.
|
|
89
|
+
if ((f instanceof OINONumberDataField) && (this.dbApi.hashid)) {
|
|
90
|
+
value = this.dbApi.hashid.decode(value);
|
|
98
91
|
}
|
|
99
|
-
value = f.
|
|
92
|
+
value = f.printCellAsValue(value);
|
|
100
93
|
if (value == "") { // ids are user input and could be specially crafted to be empty
|
|
101
94
|
throw new Error(OINO_ERROR_PREFIX + ": empty condition for id '" + id_value + "' for table " + this.api.params.tableName);
|
|
102
95
|
}
|
|
103
|
-
result += f.
|
|
96
|
+
result += f.printColumnName() + "=" + value;
|
|
104
97
|
i = i + 1;
|
|
105
98
|
}
|
|
106
99
|
}
|
|
@@ -113,118 +106,11 @@ export class OINODbDataModel {
|
|
|
113
106
|
let result = [];
|
|
114
107
|
for (let f of this.fields) {
|
|
115
108
|
if (f.fieldParams.isPrimaryKey) {
|
|
116
|
-
result.push(this.
|
|
109
|
+
result.push(this.dbApi.db.printColumnName(f.name));
|
|
117
110
|
}
|
|
118
111
|
}
|
|
119
112
|
return result;
|
|
120
113
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Add a field to the datamodel.
|
|
123
|
-
*
|
|
124
|
-
* @param field dataset field
|
|
125
|
-
*
|
|
126
|
-
*/
|
|
127
|
-
addField(field) {
|
|
128
|
-
this.fields.push(field);
|
|
129
|
-
this._fieldIndexLookup[field.name] = this.fields.length - 1;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Find a field of a given name if any.
|
|
133
|
-
*
|
|
134
|
-
* @param name name of the field to find
|
|
135
|
-
*
|
|
136
|
-
*/
|
|
137
|
-
findFieldByName(name) {
|
|
138
|
-
const i = this._fieldIndexLookup[name];
|
|
139
|
-
if (i >= 0) {
|
|
140
|
-
return this.fields[i];
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Find index of a field of a given name if any.
|
|
148
|
-
*
|
|
149
|
-
* @param name name of the field to find
|
|
150
|
-
*
|
|
151
|
-
*/
|
|
152
|
-
findFieldIndexByName(name) {
|
|
153
|
-
const i = this._fieldIndexLookup[name];
|
|
154
|
-
if (i >= 0) {
|
|
155
|
-
return i;
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
return -1;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Find all fields based of given filter callback criteria (e.g. fields of certain data type, primary keys etc.)
|
|
163
|
-
*
|
|
164
|
-
* @param filter callback called for each field to include or not
|
|
165
|
-
*
|
|
166
|
-
*/
|
|
167
|
-
filterFields(filter) {
|
|
168
|
-
let result = [];
|
|
169
|
-
for (let f of this.fields) {
|
|
170
|
-
if (filter(f)) {
|
|
171
|
-
result.push(f);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return result;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Return the primary key values of one row in order of the data model
|
|
178
|
-
*
|
|
179
|
-
* @param row data row
|
|
180
|
-
* @param hashidValues apply hashid when applicable
|
|
181
|
-
*
|
|
182
|
-
*/
|
|
183
|
-
getRowPrimarykeyValues(row, hashidValues = false) {
|
|
184
|
-
let values = [];
|
|
185
|
-
for (let i = 0; i < this.fields.length; i++) {
|
|
186
|
-
const f = this.fields[i];
|
|
187
|
-
if (f.fieldParams.isPrimaryKey) {
|
|
188
|
-
const value = row[i]?.toString() || "";
|
|
189
|
-
if (hashidValues && value && (f instanceof OINONumberDataField) && this.api.hashid) {
|
|
190
|
-
values.push(this.api.hashid.encode(value));
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
values.push(value);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return values;
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Print debug information about the fields.
|
|
201
|
-
*
|
|
202
|
-
* @param separator string to separate field prints
|
|
203
|
-
*
|
|
204
|
-
*/
|
|
205
|
-
printDebug(separator = "") {
|
|
206
|
-
let result = this.api.params.tableName + ":" + separator;
|
|
207
|
-
for (let f of this.fields) {
|
|
208
|
-
result += f.printColumnDebug() + separator;
|
|
209
|
-
}
|
|
210
|
-
return result;
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Print all public properties (db, table name, fields) of the datamodel. Used
|
|
214
|
-
* in automated testing validate schema has stayed the same.
|
|
215
|
-
*
|
|
216
|
-
*/
|
|
217
|
-
printFieldPublicPropertiesJson() {
|
|
218
|
-
const result = JSON.stringify(this.fields, (key, value) => {
|
|
219
|
-
if (key.startsWith("_")) {
|
|
220
|
-
return undefined;
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
return value;
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
return result;
|
|
227
|
-
}
|
|
228
114
|
/**
|
|
229
115
|
* Print SQL select statement using optional id and filter.
|
|
230
116
|
*
|
|
@@ -235,15 +121,15 @@ export class OINODbDataModel {
|
|
|
235
121
|
printSqlSelect(id, params) {
|
|
236
122
|
let column_names = "";
|
|
237
123
|
if (params.aggregate) {
|
|
238
|
-
column_names = params.aggregate
|
|
124
|
+
column_names = OINODbQueryAggregate.printColumnNames(params.aggregate, this, params.select);
|
|
239
125
|
}
|
|
240
126
|
else {
|
|
241
|
-
column_names = this.
|
|
127
|
+
column_names = this._printColumnNames(params.select);
|
|
242
128
|
}
|
|
243
|
-
const order_sql = params.order
|
|
244
|
-
const limit_sql = params.limit
|
|
245
|
-
const filter_sql = params.filter
|
|
246
|
-
const groupby_sql = params.aggregate
|
|
129
|
+
const order_sql = params.order ? OINODbQueryOrder.printSql(params.order, this) : "";
|
|
130
|
+
const limit_sql = params.limit ? OINODbQueryLimit.printSql(params.limit, this) : "";
|
|
131
|
+
const filter_sql = params.filter ? OINODbQueryFilter.printSql(params.filter, this) : "";
|
|
132
|
+
const groupby_sql = params.aggregate ? OINODbQueryAggregate.printSql(params.aggregate, this, params.select) : "";
|
|
247
133
|
let where_sql = "";
|
|
248
134
|
if ((id != null) && (id != "") && (filter_sql != "")) {
|
|
249
135
|
where_sql = this._printSqlPrimaryKeyCondition(id) + " AND " + filter_sql;
|
|
@@ -254,7 +140,7 @@ export class OINODbDataModel {
|
|
|
254
140
|
else if (filter_sql != "") {
|
|
255
141
|
where_sql = filter_sql;
|
|
256
142
|
}
|
|
257
|
-
const result = this.
|
|
143
|
+
const result = this.dbApi.db.printSqlSelect(this.api.params.tableName, column_names, where_sql, order_sql, limit_sql, groupby_sql);
|
|
258
144
|
return result;
|
|
259
145
|
}
|
|
260
146
|
/**
|
|
@@ -264,10 +150,10 @@ export class OINODbDataModel {
|
|
|
264
150
|
*
|
|
265
151
|
*/
|
|
266
152
|
printSqlInsert(row) {
|
|
267
|
-
const table_name = this.
|
|
153
|
+
const table_name = this.dbApi.db.printTableName(this.api.params.tableName);
|
|
268
154
|
const [columns, values] = this._printSqlInsertColumnsAndValues(row);
|
|
269
155
|
const return_fields = this.api.params.returnInsertedIds ? this._printSqlPrimaryKeyColumns() : undefined;
|
|
270
|
-
return this.
|
|
156
|
+
return this.dbApi.db.printSqlInsert(table_name, columns, values, return_fields);
|
|
271
157
|
}
|
|
272
158
|
/**
|
|
273
159
|
* Print SQL insert statement from one data row.
|
|
@@ -277,7 +163,7 @@ export class OINODbDataModel {
|
|
|
277
163
|
*
|
|
278
164
|
*/
|
|
279
165
|
printSqlUpdate(id, row) {
|
|
280
|
-
let result = "UPDATE " + this.
|
|
166
|
+
let result = "UPDATE " + this.dbApi.db.printTableName(this.api.params.tableName) + " SET " + this._printSqlUpdateValues(row) + " WHERE " + this._printSqlPrimaryKeyCondition(id) + ";";
|
|
281
167
|
return result;
|
|
282
168
|
}
|
|
283
169
|
/**
|
|
@@ -287,7 +173,7 @@ export class OINODbDataModel {
|
|
|
287
173
|
*
|
|
288
174
|
*/
|
|
289
175
|
printSqlDelete(id) {
|
|
290
|
-
let result = "DELETE FROM " + this.
|
|
176
|
+
let result = "DELETE FROM " + this.dbApi.db.printTableName(this.api.params.tableName) + " WHERE " + this._printSqlPrimaryKeyCondition(id) + ";";
|
|
291
177
|
return result;
|
|
292
178
|
}
|
|
293
179
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
4
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
import { OINODbApi } from "./
|
|
6
|
+
import { OINODbApi } from "./OINODbApi.js";
|
|
7
7
|
/**
|
|
8
8
|
* Static factory class for easily creating things based on data
|
|
9
9
|
*
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
import { OINO_ERROR_PREFIX, OINOLog, OINOQueryNullCheck, OINOQueryFilter, OINOQueryOrder, OINOQueryLimit, OINOQueryAggregate, OINOQueryAggregateFunctions } from "@oino-ts/common";
|
|
7
|
+
/**
|
|
8
|
+
* Class for recursively parsing of filters and printing them as SQL conditions.
|
|
9
|
+
* Supports three types of statements
|
|
10
|
+
* - comparison: (field)-lt|le|eq|ge|gt|like(value)
|
|
11
|
+
* - negation: -not(filter)
|
|
12
|
+
* - conjunction/disjunction: (filter)-and|or(filter)
|
|
13
|
+
* Supported conditions are comparisons (<, <=, =, >=, >) and substring match (LIKE).
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export class OINODbQueryFilter extends OINOQueryFilter {
|
|
17
|
+
static operatorToSql(filter) {
|
|
18
|
+
switch (filter.operator) {
|
|
19
|
+
case "and": return " AND ";
|
|
20
|
+
case "or": return " OR ";
|
|
21
|
+
case "not": return "NOT ";
|
|
22
|
+
case "lt": return " < ";
|
|
23
|
+
case "le": return " <= ";
|
|
24
|
+
case "eq": return " = ";
|
|
25
|
+
case "ne": return " != ";
|
|
26
|
+
case "ge": return " >= ";
|
|
27
|
+
case "gt": return " > ";
|
|
28
|
+
case "like": return " LIKE ";
|
|
29
|
+
case "isnull": return " IS NULL";
|
|
30
|
+
case "isNotNull": return " IS NOT NULL";
|
|
31
|
+
}
|
|
32
|
+
return " ";
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Print filter as SQL condition based on the datamodel of the API.
|
|
36
|
+
*
|
|
37
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
static printSql(filter, dataModel) {
|
|
41
|
+
if (filter.isEmpty()) {
|
|
42
|
+
return "";
|
|
43
|
+
}
|
|
44
|
+
let result = "";
|
|
45
|
+
let field = null;
|
|
46
|
+
if (filter.leftSide instanceof OINOQueryFilter) {
|
|
47
|
+
result += OINODbQueryFilter.printSql(filter.leftSide, dataModel);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
field = dataModel.findFieldByName(filter.leftSide);
|
|
51
|
+
if (!field) {
|
|
52
|
+
OINOLog.error("@oino-ts/db", "OINODbQueryFilter", "toSql", "Invalid field!", { field: filter.leftSide });
|
|
53
|
+
throw new Error(OINO_ERROR_PREFIX + ": OINODbQueryFilter.toSql - Invalid field '" + filter.leftSide + "'"); // invalid field name could be a security risk, stop processing
|
|
54
|
+
}
|
|
55
|
+
result += dataModel.api.datasource.printColumnName(field.name);
|
|
56
|
+
}
|
|
57
|
+
result += OINODbQueryFilter.operatorToSql(filter);
|
|
58
|
+
if (filter.rightSide instanceof OINOQueryFilter) {
|
|
59
|
+
result += OINODbQueryFilter.printSql(filter.rightSide, dataModel);
|
|
60
|
+
}
|
|
61
|
+
else if (filter.operator == OINOQueryNullCheck.isnull || filter.operator == OINOQueryNullCheck.isNotNull) {
|
|
62
|
+
// nothing to do, IS NULL and IS NOT NULL do not have a right side
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const value = field.deserializeCell(filter.rightSide);
|
|
66
|
+
if ((value == null) || (value === "")) {
|
|
67
|
+
OINOLog.error("@oino-ts/db", "OINODbQueryFilter", "toSql", "Invalid value!", { value: value });
|
|
68
|
+
throw new Error(OINO_ERROR_PREFIX + ": OINODbQueryFilter.toSql - Invalid value '" + value + "'"); // invalid value could be a security risk, stop processing
|
|
69
|
+
}
|
|
70
|
+
result += field.printCellAsValue(value);
|
|
71
|
+
}
|
|
72
|
+
result = "(" + result + ")";
|
|
73
|
+
OINOLog.debug("@oino-ts/db", "OINODbQueryFilter", "toSql", "Result", { sql: result });
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Class for ordering select results on a number of columns.
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
export class OINODbQueryOrder extends OINOQueryOrder {
|
|
82
|
+
/**
|
|
83
|
+
* Print order as SQL condition based on the datamodel of the API.
|
|
84
|
+
*
|
|
85
|
+
* @param order order instance
|
|
86
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
87
|
+
*
|
|
88
|
+
*/
|
|
89
|
+
static printSql(order, dataModel) {
|
|
90
|
+
if (order.isEmpty()) {
|
|
91
|
+
return "";
|
|
92
|
+
}
|
|
93
|
+
let result = "";
|
|
94
|
+
for (let i = 0; i < order.columns.length; i++) {
|
|
95
|
+
const field = dataModel.findFieldByName(order.columns[i]);
|
|
96
|
+
if (!field) {
|
|
97
|
+
OINOLog.error("@oino-ts/db", "OINODbQueryOrder", "toSql", "Invalid field!", { field: order.columns[i] });
|
|
98
|
+
throw new Error(OINO_ERROR_PREFIX + ": OINODbQueryOrder.toSql - Invalid field '" + order.columns[i] + "'"); // invalid field name could be a security risk, stop processing
|
|
99
|
+
}
|
|
100
|
+
if (result) {
|
|
101
|
+
result += ",";
|
|
102
|
+
}
|
|
103
|
+
result += dataModel.api.datasource.printColumnName(field.name) + " ";
|
|
104
|
+
if (order.descending[i]) {
|
|
105
|
+
result += "DESC";
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
result += "ASC";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
OINOLog.debug("@oino-ts/db", "OINODbQueryOrder", "toSql", "Result", { sql: result });
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Class for limiting the number of results.
|
|
117
|
+
*
|
|
118
|
+
*/
|
|
119
|
+
export class OINODbQueryLimit extends OINOQueryLimit {
|
|
120
|
+
/**
|
|
121
|
+
* Print order as SQL condition based on the datamodel of the API.
|
|
122
|
+
*
|
|
123
|
+
* @param limit limit instance
|
|
124
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
125
|
+
*
|
|
126
|
+
*/
|
|
127
|
+
static printSql(limit, dataModel) {
|
|
128
|
+
if (limit.isEmpty()) {
|
|
129
|
+
return "";
|
|
130
|
+
}
|
|
131
|
+
let result = limit.limit.toString();
|
|
132
|
+
if (limit.page > 0) {
|
|
133
|
+
result += " OFFSET " + (limit.limit * (limit.page - 1) + 1).toString();
|
|
134
|
+
}
|
|
135
|
+
OINOLog.debug("@oino-ts/db", "OINODbQueryLimit", "toSql", "Result", { sql: result });
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Class for limiting the number of results.
|
|
141
|
+
*
|
|
142
|
+
*/
|
|
143
|
+
export class OINODbQueryAggregate extends OINOQueryAggregate {
|
|
144
|
+
/**
|
|
145
|
+
* Print non-aggregated fields as SQL GROUP BY-condition based on the datamodel of the API.
|
|
146
|
+
*
|
|
147
|
+
* @param aggregate aggregate instance
|
|
148
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
149
|
+
* @param select what fields to select
|
|
150
|
+
*
|
|
151
|
+
*/
|
|
152
|
+
static printSql(aggregate, dataModel, select) {
|
|
153
|
+
if (aggregate.isEmpty()) {
|
|
154
|
+
return "";
|
|
155
|
+
}
|
|
156
|
+
let result = "";
|
|
157
|
+
for (let i = 0; i < dataModel.fields.length; i++) {
|
|
158
|
+
const f = dataModel.fields[i];
|
|
159
|
+
if ((select?.isSelected(f.name) || (f.fieldParams.isPrimaryKey == true)) && (aggregate.fields.includes(f.name) == false)) {
|
|
160
|
+
result += f.printColumnName() + ",";
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
result = result.substring(0, result.length - 1);
|
|
164
|
+
OINOLog.debug("@oino-ts/db", "OINODbQueryAggregate", "toSql", "Result", { sql: result });
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Print non-aggregated fields as SQL GROUP BY-condition based on the datamodel of the API.
|
|
169
|
+
*
|
|
170
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
171
|
+
* @param select what fields to select
|
|
172
|
+
*
|
|
173
|
+
*/
|
|
174
|
+
static printColumnNames(aggregate, dataModel, select) {
|
|
175
|
+
let result = "";
|
|
176
|
+
for (let i = 0; i < dataModel.fields.length; i++) {
|
|
177
|
+
const f = dataModel.fields[i];
|
|
178
|
+
if ((select?.isSelected(f.name) === false) && (f.fieldParams.isPrimaryKey == false)) { // if a field is not selected, we include an aggregated constant (min of const string) and correct fieldname instead so that dimensions of the data don't change, it does not need a group by but no unnecessary data is fetched
|
|
179
|
+
result += OINOQueryAggregateFunctions.min + "(" + f.datasource.printStringValue("") + ") as " + f.printColumnName() + ",";
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const aggregate_index = aggregate.fields.indexOf(f.name);
|
|
183
|
+
const col_name = f.printColumnName();
|
|
184
|
+
if (aggregate_index >= 0) {
|
|
185
|
+
result += aggregate.functions[aggregate_index] + "(" + col_name + ") as " + col_name + ",";
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
result += col_name + ",";
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return result.substring(0, result.length - 1);
|
|
193
|
+
}
|
|
194
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { OINODb } from "./OINODb.js";
|
|
2
2
|
export { OINODbDataModel } from "./OINODbDataModel.js";
|
|
3
|
-
export { OINODbModelSet } from "./OINODbModelSet.js";
|
|
4
|
-
export { OINODbDataField, OINOBooleanDataField, OINONumberDataField, OINOStringDataField, OINOBlobDataField, OINODatetimeDataField } from "./OINODbDataField.js";
|
|
5
|
-
export { OINODbDataSet, OINODbMemoryDataSet, OINODb } from "./OINODb.js";
|
|
6
|
-
export { OINODbSqlFilter, OINODbSqlOrder, OINODbSqlComparison, OINODbSqlLimit, OINODbSqlBooleanOperation, OINODbSqlAggregate, OINODbSqlAggregateFunctions, OINODbSqlSelect, OINODbSqlNullCheck } from "./OINODbSqlParams.js";
|
|
7
|
-
export { OINODbConfig } from "./OINODbConfig.js";
|
|
8
3
|
export { OINODbFactory } from "./OINODbFactory.js";
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
|
|
12
|
-
export const OINODB_EMPTY_ROW = [];
|
|
13
|
-
/** Empty row array instance */
|
|
14
|
-
export const OINODB_EMPTY_ROWS = [];
|
|
15
|
-
/** Constant for undefined values */
|
|
16
|
-
export const OINODB_UNDEFINED = ""; // original idea was to have a defined literal that get's swapped back to undefined, but current implementation just leaves it out at serialization (so value does not matter)
|
|
4
|
+
export { OINODbApi } from "./OINODbApi.js";
|
|
5
|
+
export { OINODbQueryFilter, OINODbQueryOrder, OINODbQueryLimit, OINODbQueryAggregate } from "./OINODbQueryParams.js";
|
|
6
|
+
export { OINODB_UNDEFINED } from "./OINODbConstants.js";
|