@oino-ts/db 0.0.11
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/README.md +222 -0
- package/dist/cjs/OINODb.js +27 -0
- package/dist/cjs/OINODbApi.js +270 -0
- package/dist/cjs/OINODbConfig.js +86 -0
- package/dist/cjs/OINODbDataField.js +354 -0
- package/dist/cjs/OINODbDataModel.js +279 -0
- package/dist/cjs/OINODbDataSet.js +139 -0
- package/dist/cjs/OINODbFactory.js +563 -0
- package/dist/cjs/OINODbModelSet.js +267 -0
- package/dist/cjs/OINODbParams.js +280 -0
- package/dist/cjs/OINODbRequestParams.js +280 -0
- package/dist/cjs/OINODbSwagger.js +201 -0
- package/dist/cjs/index.js +51 -0
- package/dist/esm/OINODb.js +23 -0
- package/dist/esm/OINODbApi.js +265 -0
- package/dist/esm/OINODbConfig.js +82 -0
- package/dist/esm/OINODbDataField.js +345 -0
- package/dist/esm/OINODbDataModel.js +275 -0
- package/dist/esm/OINODbDataSet.js +134 -0
- package/dist/esm/OINODbFactory.js +559 -0
- package/dist/esm/OINODbModelSet.js +263 -0
- package/dist/esm/OINODbRequestParams.js +274 -0
- package/dist/esm/OINODbSwagger.js +197 -0
- package/dist/esm/index.js +17 -0
- package/dist/types/OINODb.d.ts +75 -0
- package/dist/types/OINODbApi.d.ts +57 -0
- package/dist/types/OINODbConfig.d.ts +52 -0
- package/dist/types/OINODbDataField.d.ts +202 -0
- package/dist/types/OINODbDataModel.d.ts +108 -0
- package/dist/types/OINODbDataSet.d.ts +95 -0
- package/dist/types/OINODbFactory.d.ts +99 -0
- package/dist/types/OINODbModelSet.d.ts +50 -0
- package/dist/types/OINODbRequestParams.d.ts +130 -0
- package/dist/types/OINODbSwagger.d.ts +25 -0
- package/dist/types/index.d.ts +103 -0
- package/package.json +35 -0
- package/src/OINODb.ts +98 -0
- package/src/OINODbApi.test.ts +243 -0
- package/src/OINODbApi.ts +270 -0
- package/src/OINODbConfig.ts +92 -0
- package/src/OINODbDataField.ts +372 -0
- package/src/OINODbDataModel.ts +290 -0
- package/src/OINODbDataSet.ts +170 -0
- package/src/OINODbFactory.ts +570 -0
- package/src/OINODbModelSet.ts +286 -0
- package/src/OINODbRequestParams.ts +281 -0
- package/src/OINODbSwagger.ts +209 -0
- package/src/index.ts +116 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.OINODbModelSet = void 0;
|
|
9
|
+
const index_js_1 = require("./index.js");
|
|
10
|
+
/**
|
|
11
|
+
* Class for dataset based on a data model that can be serialized to
|
|
12
|
+
* a supported format:
|
|
13
|
+
* - JSON (application/json)
|
|
14
|
+
* - CSV (text/csv)
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
class OINODbModelSet {
|
|
18
|
+
/** Reference to datamodel */
|
|
19
|
+
datamodel;
|
|
20
|
+
/** Reference to data set */
|
|
21
|
+
dataset;
|
|
22
|
+
/** Collection of errors */
|
|
23
|
+
errors;
|
|
24
|
+
/**
|
|
25
|
+
* Constructor for `OINODbModelSet`.
|
|
26
|
+
*
|
|
27
|
+
* @param datamodel data model
|
|
28
|
+
* @param dataset data set
|
|
29
|
+
*/
|
|
30
|
+
constructor(datamodel, dataset) {
|
|
31
|
+
this.datamodel = datamodel;
|
|
32
|
+
this.dataset = dataset;
|
|
33
|
+
this.errors = this.dataset.messages;
|
|
34
|
+
}
|
|
35
|
+
_encodeAndHashFieldValue(field, value, contentType, primaryKeyValues, rowIdSeed) {
|
|
36
|
+
if (field.fieldParams.isPrimaryKey) {
|
|
37
|
+
if (value && (field instanceof index_js_1.OINONumberDataField) && (this.datamodel.api.hashid)) {
|
|
38
|
+
value = this.datamodel.api.hashid.encode(value, rowIdSeed);
|
|
39
|
+
}
|
|
40
|
+
primaryKeyValues.push(value || "");
|
|
41
|
+
}
|
|
42
|
+
value = index_js_1.OINOStr.encode(value, contentType);
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
_writeRowJson(row) {
|
|
46
|
+
// console.log("OINODbModelSet._writeRowJson: row=" + row)
|
|
47
|
+
const model = this.datamodel;
|
|
48
|
+
const fields = model.fields;
|
|
49
|
+
let row_id_seed = model.getRowPrimarykeyValues(row).join(' ');
|
|
50
|
+
let primary_key_values = [];
|
|
51
|
+
let json_row = "";
|
|
52
|
+
for (let i = 0; i < fields.length; i++) {
|
|
53
|
+
const f = fields[i];
|
|
54
|
+
let value = f.serializeCell(row[i]);
|
|
55
|
+
if (value === undefined) {
|
|
56
|
+
index_js_1.OINOLog.info("OINODbModelSet._writeRowJson: undefined value skipped", { field_name: f.name });
|
|
57
|
+
}
|
|
58
|
+
else if (value === null) {
|
|
59
|
+
json_row += "," + index_js_1.OINOStr.encode(f.name, index_js_1.OINOContentType.json) + ":null";
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
let is_hashed = f.fieldParams.isPrimaryKey && (f instanceof index_js_1.OINONumberDataField) && (this.datamodel.api.hashid != null);
|
|
63
|
+
let is_value = (f instanceof index_js_1.OINOBooleanDataField) || ((f instanceof index_js_1.OINONumberDataField) && !is_hashed);
|
|
64
|
+
value = this._encodeAndHashFieldValue(f, value, index_js_1.OINOContentType.json, primary_key_values, f.name + " " + row_id_seed);
|
|
65
|
+
if (is_value) {
|
|
66
|
+
value = value.substring(1, value.length - 1);
|
|
67
|
+
}
|
|
68
|
+
json_row += "," + index_js_1.OINOStr.encode(f.name, index_js_1.OINOContentType.json) + ":" + value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
json_row = index_js_1.OINOStr.encode(index_js_1.OINODbConfig.OINODB_ID_FIELD, index_js_1.OINOContentType.json) + ":" + index_js_1.OINOStr.encode(index_js_1.OINODbConfig.printOINOId(primary_key_values), index_js_1.OINOContentType.json) + json_row;
|
|
72
|
+
// OINOLog_debug("OINODbModelSet._writeRowJson="+json_row)
|
|
73
|
+
return "{" + json_row + "}";
|
|
74
|
+
}
|
|
75
|
+
_writeStringJson() {
|
|
76
|
+
let result = "";
|
|
77
|
+
while (!this.dataset.isEof()) {
|
|
78
|
+
if (result != "") {
|
|
79
|
+
result += ",\r\n";
|
|
80
|
+
}
|
|
81
|
+
result += this._writeRowJson(this.dataset.getRow());
|
|
82
|
+
this.dataset.next();
|
|
83
|
+
}
|
|
84
|
+
result = "[\r\n" + result + "\r\n]";
|
|
85
|
+
// OINOLog_debug("OINODbModelSet._writeStringJson="+result)
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
_writeHeaderCsv() {
|
|
89
|
+
const model = this.datamodel;
|
|
90
|
+
const fields = model.fields;
|
|
91
|
+
let csv_header = "\"" + index_js_1.OINODbConfig.OINODB_ID_FIELD + "\"";
|
|
92
|
+
for (let i = 0; i < fields.length; i++) {
|
|
93
|
+
csv_header += ",\"" + fields[i].name + "\"";
|
|
94
|
+
}
|
|
95
|
+
// OINOLog_debug("OINODbModelSet._writeHeaderCsv="+csv_header)
|
|
96
|
+
return csv_header;
|
|
97
|
+
}
|
|
98
|
+
_writeRowCsv(row) {
|
|
99
|
+
// OINOLog_debug("OINODbModelSet._writeRowCsv", {row:row})
|
|
100
|
+
const model = this.datamodel;
|
|
101
|
+
const fields = model.fields;
|
|
102
|
+
let row_id_seed = model.getRowPrimarykeyValues(row).join(' ');
|
|
103
|
+
let primary_key_values = [];
|
|
104
|
+
let csv_row = "";
|
|
105
|
+
for (let i = 0; i < fields.length; i++) {
|
|
106
|
+
const f = fields[i];
|
|
107
|
+
let value = f.serializeCell(row[i]);
|
|
108
|
+
if (value == null) {
|
|
109
|
+
csv_row += "," + index_js_1.OINOStr.encode(value, index_js_1.OINOContentType.csv); // either null or undefined
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
value = this._encodeAndHashFieldValue(f, value, index_js_1.OINOContentType.csv, primary_key_values, f.name + " " + row_id_seed);
|
|
113
|
+
csv_row += "," + value;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
csv_row = index_js_1.OINOStr.encode(index_js_1.OINODbConfig.printOINOId(primary_key_values), index_js_1.OINOContentType.csv) + csv_row;
|
|
117
|
+
// OINOLog_debug("OINODbModelSet._writeRowCsv="+csv_row)
|
|
118
|
+
return csv_row;
|
|
119
|
+
}
|
|
120
|
+
_writeStringCsv() {
|
|
121
|
+
let result = this._writeHeaderCsv();
|
|
122
|
+
while (!this.dataset.isEof()) {
|
|
123
|
+
if (result != "") {
|
|
124
|
+
result += "\r\n";
|
|
125
|
+
}
|
|
126
|
+
result += this._writeRowCsv(this.dataset.getRow());
|
|
127
|
+
this.dataset.next();
|
|
128
|
+
}
|
|
129
|
+
// OINOLog_debug("OINODbModelSet._writeStringCsv="+result)
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
_writeRowFormdataParameterBlock(blockName, blockValue, multipartBoundary) {
|
|
133
|
+
if (blockValue === null) {
|
|
134
|
+
return multipartBoundary + "\r\n" + "Content-Disposition: form-data; name=\"" + blockName + "\"\r\n\r\n";
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
return multipartBoundary + "\r\n" + "Content-Disposition: form-data; name=\"" + blockName + "\"\r\n\r\n" + blockValue + "\r\n";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
_writeRowFormdataFileBlock(blockName, blockValue, multipartBoundary) {
|
|
141
|
+
return multipartBoundary + "\r\n" + "Content-Disposition: form-data; name=\"" + blockName + "\"; filename=" + blockName + "\"\r\nContent-Type: application/octet-stream\r\nContent-Transfer-Encoding: BASE64\r\n\r\n" + blockValue + "\r\n";
|
|
142
|
+
}
|
|
143
|
+
_writeRowFormdata(row) {
|
|
144
|
+
const multipart_boundary = "---------OINOMultipartBoundary35424568"; // this method is just used for test data generation and we want it to be static
|
|
145
|
+
const model = this.datamodel;
|
|
146
|
+
const fields = model.fields;
|
|
147
|
+
let row_id_seed = model.getRowPrimarykeyValues(row).join(' ');
|
|
148
|
+
let primary_key_values = [];
|
|
149
|
+
let result = "";
|
|
150
|
+
for (let i = 0; i < fields.length; i++) {
|
|
151
|
+
const f = fields[i];
|
|
152
|
+
let value = f.serializeCell(row[i]);
|
|
153
|
+
let formdata_block = "";
|
|
154
|
+
let is_file = (f instanceof index_js_1.OINOBlobDataField);
|
|
155
|
+
if (value === undefined) {
|
|
156
|
+
index_js_1.OINOLog.info("OINODbModelSet._writeRowFormdata: undefined value skipped.", { field: f.name });
|
|
157
|
+
}
|
|
158
|
+
else if (value === null) {
|
|
159
|
+
formdata_block = this._writeRowFormdataParameterBlock(fields[i].name, null, multipart_boundary);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
value = this._encodeAndHashFieldValue(f, value, index_js_1.OINOContentType.formdata, primary_key_values, f.name + " " + row_id_seed);
|
|
163
|
+
if (is_file) {
|
|
164
|
+
formdata_block = this._writeRowFormdataFileBlock(f.name, value, multipart_boundary);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
formdata_block = this._writeRowFormdataParameterBlock(fields[i].name, value, multipart_boundary);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// OINOLog.debug("OINODbModelSet._writeRowFormdata next block", {formdata_block:formdata_block})
|
|
171
|
+
result += formdata_block;
|
|
172
|
+
}
|
|
173
|
+
result = this._writeRowFormdataParameterBlock(index_js_1.OINODbConfig.OINODB_ID_FIELD, index_js_1.OINODbConfig.printOINOId(primary_key_values), multipart_boundary) + result;
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
_writeStringFormdata() {
|
|
177
|
+
let result = this._writeRowFormdata(this.dataset.getRow());
|
|
178
|
+
this.dataset.next();
|
|
179
|
+
if (!this.dataset.isEof()) {
|
|
180
|
+
index_js_1.OINOLog.warning("OINODbModelSet._writeStringUrlencode: content type " + index_js_1.OINOContentType.formdata + " does not mixed part content and only first row has been written!");
|
|
181
|
+
}
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
_writeRowUrlencode(row) {
|
|
185
|
+
// console.log("OINODbModelSet._writeRowCsv row=" + row)
|
|
186
|
+
const model = this.datamodel;
|
|
187
|
+
const fields = model.fields;
|
|
188
|
+
let row_id_seed = model.getRowPrimarykeyValues(row).join(' ');
|
|
189
|
+
let primary_key_values = [];
|
|
190
|
+
let urlencode_row = "";
|
|
191
|
+
for (let i = 0; i < fields.length; i++) {
|
|
192
|
+
const f = fields[i];
|
|
193
|
+
let value = f.serializeCell(row[i]);
|
|
194
|
+
if ((value === undefined)) { // || (value === null)) {
|
|
195
|
+
// console.log("OINODbModelSet._writeRowUrlencode undefined field value:" + fields[i].name)
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
value = this._encodeAndHashFieldValue(f, value, index_js_1.OINOContentType.urlencode, primary_key_values, f.name + " " + row_id_seed);
|
|
199
|
+
if (urlencode_row != "") {
|
|
200
|
+
urlencode_row += "&";
|
|
201
|
+
}
|
|
202
|
+
urlencode_row += index_js_1.OINOStr.encode(f.name, index_js_1.OINOContentType.urlencode) + "=" + value;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
urlencode_row = index_js_1.OINOStr.encode(index_js_1.OINODbConfig.OINODB_ID_FIELD, index_js_1.OINOContentType.urlencode) + "=" + index_js_1.OINOStr.encode(index_js_1.OINODbConfig.printOINOId(primary_key_values), index_js_1.OINOContentType.urlencode) + "&" + urlencode_row;
|
|
206
|
+
// OINOLog_debug("OINODbModelSet._writeRowCsv="+csv_row)
|
|
207
|
+
return urlencode_row;
|
|
208
|
+
}
|
|
209
|
+
_writeStringUrlencode() {
|
|
210
|
+
let result = "";
|
|
211
|
+
let line_count = 0;
|
|
212
|
+
while (!this.dataset.isEof()) {
|
|
213
|
+
result += this._writeRowUrlencode(this.dataset.getRow()) + "\r\n";
|
|
214
|
+
this.dataset.next();
|
|
215
|
+
line_count += 1;
|
|
216
|
+
}
|
|
217
|
+
// OINOLog_debug("OINODbModelSet._writeStringCsv="+result)
|
|
218
|
+
if (line_count > 1) {
|
|
219
|
+
index_js_1.OINOLog.warning("OINODbModelSet._writeStringUrlencode: content type " + index_js_1.OINOContentType.urlencode + " does not officially support multiline content!");
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Serialize model set in the given format.
|
|
225
|
+
*
|
|
226
|
+
* @param [contentType=OINOContentType.json] serialization content type
|
|
227
|
+
*
|
|
228
|
+
*/
|
|
229
|
+
writeString(contentType = index_js_1.OINOContentType.json) {
|
|
230
|
+
let result = "";
|
|
231
|
+
if (contentType == index_js_1.OINOContentType.csv) {
|
|
232
|
+
result += this._writeStringCsv();
|
|
233
|
+
}
|
|
234
|
+
else if (contentType == index_js_1.OINOContentType.json) {
|
|
235
|
+
result += this._writeStringJson();
|
|
236
|
+
}
|
|
237
|
+
else if (contentType == index_js_1.OINOContentType.formdata) {
|
|
238
|
+
result += this._writeStringFormdata();
|
|
239
|
+
}
|
|
240
|
+
else if (contentType == index_js_1.OINOContentType.urlencode) {
|
|
241
|
+
result += this._writeStringUrlencode();
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
index_js_1.OINOLog.error("OINODbModelSet.writeString: content type is only for input!", { contentType: contentType });
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get value of given field in the current row. Undefined if no rows,
|
|
250
|
+
* field not found or value does not exist.
|
|
251
|
+
*
|
|
252
|
+
* @param fieldName name of the field
|
|
253
|
+
*
|
|
254
|
+
*/
|
|
255
|
+
getValueByFieldName(fieldName) {
|
|
256
|
+
let result = undefined;
|
|
257
|
+
if (!this.dataset.isEof()) {
|
|
258
|
+
const current_row = this.dataset.getRow();
|
|
259
|
+
const field_index = this.datamodel.findFieldIndexByName(fieldName);
|
|
260
|
+
if (field_index >= 0) {
|
|
261
|
+
result = current_row[field_index];
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
exports.OINODbModelSet = OINODbModelSet;
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.OINODbLimit = exports.OINODbOrder = exports.OINODbFilter = exports.OINODbComparison = exports.OINODbBooleanOperation = void 0;
|
|
9
|
+
const index_js_1 = require("./index.js");
|
|
10
|
+
/**
|
|
11
|
+
* Supported logical conjunctions in filter predicates.
|
|
12
|
+
* @enum
|
|
13
|
+
*/
|
|
14
|
+
var OINODbBooleanOperation;
|
|
15
|
+
(function (OINODbBooleanOperation) {
|
|
16
|
+
OINODbBooleanOperation["and"] = "and";
|
|
17
|
+
OINODbBooleanOperation["or"] = "or";
|
|
18
|
+
OINODbBooleanOperation["not"] = "not";
|
|
19
|
+
})(OINODbBooleanOperation || (exports.OINODbBooleanOperation = OINODbBooleanOperation = {}));
|
|
20
|
+
/**
|
|
21
|
+
* Supported logical conjunctions in filter predicates.
|
|
22
|
+
* @enum
|
|
23
|
+
*/
|
|
24
|
+
var OINODbComparison;
|
|
25
|
+
(function (OINODbComparison) {
|
|
26
|
+
OINODbComparison["lt"] = "lt";
|
|
27
|
+
OINODbComparison["le"] = "le";
|
|
28
|
+
OINODbComparison["eq"] = "eq";
|
|
29
|
+
OINODbComparison["ge"] = "ge";
|
|
30
|
+
OINODbComparison["gt"] = "gt";
|
|
31
|
+
OINODbComparison["like"] = "like";
|
|
32
|
+
})(OINODbComparison || (exports.OINODbComparison = OINODbComparison = {}));
|
|
33
|
+
/**
|
|
34
|
+
* Class for recursively parsing of filters and printing them as SQL conditions.
|
|
35
|
+
* Supports three types of statements
|
|
36
|
+
* - comparison: (field)-lt|le|eq|ge|gt|like(value)
|
|
37
|
+
* - negation: -not(filter)
|
|
38
|
+
* - conjunction/disjunction: (filter)-and|or(filter)
|
|
39
|
+
* Supported conditions are comparisons (<, <=, =, >=, >) and substring match (LIKE).
|
|
40
|
+
*
|
|
41
|
+
*/
|
|
42
|
+
class OINODbFilter {
|
|
43
|
+
static _booleanOperationRegex = /^\s?\-(and|or)\s?$/i;
|
|
44
|
+
static _negationRegex = /^-(not|)\((.+)\)$/i;
|
|
45
|
+
static _filterComparisonRegex = /^\(([^'"\(\)]+)\)\s?\-(lt|le|eq|ge|gt|like)\s?\(([^'"\(\)]+)\)$/i;
|
|
46
|
+
_leftSide;
|
|
47
|
+
_rightSide;
|
|
48
|
+
_operator;
|
|
49
|
+
/**
|
|
50
|
+
* Constructor of `OINODbFilter`
|
|
51
|
+
* @param leftSide left side of the filter, either another filter or a column name
|
|
52
|
+
* @param operation operation of the filter, either `OINODbComparison` or `OINODbBooleanOperation`
|
|
53
|
+
* @param rightSide right side of the filter, either another filter or a value
|
|
54
|
+
*/
|
|
55
|
+
constructor(leftSide, operation, rightSide) {
|
|
56
|
+
if (!(((operation === null) && (leftSide == "") && (rightSide == "")) ||
|
|
57
|
+
((operation !== null) && (Object.values(OINODbComparison).includes(operation)) && (typeof (leftSide) == "string") && (leftSide != "") && (typeof (rightSide) == "string") && (rightSide != "")) ||
|
|
58
|
+
((operation == OINODbBooleanOperation.not) && (leftSide == "") && (rightSide instanceof OINODbFilter)) ||
|
|
59
|
+
(((operation == OINODbBooleanOperation.and) || (operation == OINODbBooleanOperation.or)) && (leftSide instanceof OINODbFilter) && (rightSide instanceof OINODbFilter)))) {
|
|
60
|
+
index_js_1.OINOLog.debug("Unsupported OINODbFilter format!", { leftSide: leftSide, operation: operation, rightSide: rightSide });
|
|
61
|
+
throw new Error(index_js_1.OINODB_ERROR_PREFIX + ": Unsupported OINODbFilter format!");
|
|
62
|
+
}
|
|
63
|
+
this._leftSide = leftSide;
|
|
64
|
+
this._operator = operation;
|
|
65
|
+
this._rightSide = rightSide;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Constructor for `OINOFilter` as parser of http parameter.
|
|
69
|
+
*
|
|
70
|
+
* @param filterString string representation of filter from HTTP-request
|
|
71
|
+
*
|
|
72
|
+
*/
|
|
73
|
+
static parse(filterString) {
|
|
74
|
+
// OINOLog_debug("OINOFilter.constructor", {filterString:filterString})
|
|
75
|
+
if (!filterString) {
|
|
76
|
+
return new OINODbFilter("", null, "");
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
let match = OINODbFilter._filterComparisonRegex.exec(filterString);
|
|
80
|
+
if (match != null) {
|
|
81
|
+
return new OINODbFilter(match[1], match[2].toLowerCase(), match[3]);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
let match = OINODbFilter._negationRegex.exec(filterString);
|
|
85
|
+
if (match != null) {
|
|
86
|
+
return new OINODbFilter("", OINODbBooleanOperation.not, OINODbFilter.parse(match[3]));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
let boolean_parts = index_js_1.OINOStr.splitByBrackets(filterString, true, false, '(', ')');
|
|
90
|
+
// OINOLog_debug("OINOFilter.constructor", {boolean_parts:boolean_parts})
|
|
91
|
+
if (boolean_parts.length == 3 && (boolean_parts[1].match(OINODbFilter._booleanOperationRegex))) {
|
|
92
|
+
return new OINODbFilter(OINODbFilter.parse(boolean_parts[0]), boolean_parts[1].trim().toLowerCase().substring(1), OINODbFilter.parse(boolean_parts[2]));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
throw new Error(index_js_1.OINODB_ERROR_PREFIX + ": Invalid filter '" + filterString + "'");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Construct a new `OINOFilter` as combination of (boolean and/or) of two filters.
|
|
103
|
+
*
|
|
104
|
+
* @param leftSide left side to combine
|
|
105
|
+
* @param operation boolean operation to use in combination
|
|
106
|
+
* @param rightSide right side to combine
|
|
107
|
+
*
|
|
108
|
+
*/
|
|
109
|
+
static combine(leftSide, operation, rightSide) {
|
|
110
|
+
if ((leftSide) && (!leftSide.isEmpty()) && (rightSide) && (!rightSide.isEmpty())) {
|
|
111
|
+
return new OINODbFilter(leftSide, operation, rightSide);
|
|
112
|
+
}
|
|
113
|
+
else if ((leftSide) && (!leftSide.isEmpty())) {
|
|
114
|
+
return leftSide;
|
|
115
|
+
}
|
|
116
|
+
else if ((rightSide) && (!rightSide.isEmpty())) {
|
|
117
|
+
return rightSide;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
_operatorToSql() {
|
|
124
|
+
switch (this._operator) {
|
|
125
|
+
case "and": return " AND ";
|
|
126
|
+
case "or": return " OR ";
|
|
127
|
+
case "not": return "NOT ";
|
|
128
|
+
case "lt": return " < ";
|
|
129
|
+
case "le": return " <= ";
|
|
130
|
+
case "eq": return " = ";
|
|
131
|
+
case "ge": return " >= ";
|
|
132
|
+
case "gt": return " > ";
|
|
133
|
+
case "like": return " LIKE ";
|
|
134
|
+
}
|
|
135
|
+
return " ";
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Does filter contain any valid conditions.
|
|
139
|
+
*
|
|
140
|
+
*/
|
|
141
|
+
isEmpty() {
|
|
142
|
+
return (this._leftSide == "") && (this._operator == null) && (this._rightSide == "");
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Print filter as SQL condition based on the datamodel of the API.
|
|
146
|
+
*
|
|
147
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
148
|
+
*
|
|
149
|
+
*/
|
|
150
|
+
toSql(dataModel) {
|
|
151
|
+
// OINOLog.debug("OINOFilter.toSql", {_leftSide:this._leftSide, _operator:this._operator, _rightSide:this._rightSide})
|
|
152
|
+
if (this.isEmpty()) {
|
|
153
|
+
return "";
|
|
154
|
+
}
|
|
155
|
+
let result = "";
|
|
156
|
+
let field = null;
|
|
157
|
+
if (this._leftSide instanceof OINODbFilter) {
|
|
158
|
+
result += this._leftSide.toSql(dataModel);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
result += dataModel.api.db.printSqlColumnname(this._leftSide);
|
|
162
|
+
field = dataModel.findFieldByName(this._leftSide);
|
|
163
|
+
}
|
|
164
|
+
result += this._operatorToSql();
|
|
165
|
+
if (this._rightSide instanceof OINODbFilter) {
|
|
166
|
+
result += this._rightSide.toSql(dataModel);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
if (field) {
|
|
170
|
+
result += field.printCellAsSqlValue(this._rightSide);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
result += this._rightSide;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
index_js_1.OINOLog.debug("OINOFilter.toSql", { result: result });
|
|
177
|
+
return "(" + result + ")";
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.OINODbFilter = OINODbFilter;
|
|
181
|
+
/**
|
|
182
|
+
* Class for ordering select results on a number of columns.
|
|
183
|
+
*
|
|
184
|
+
*/
|
|
185
|
+
class OINODbOrder {
|
|
186
|
+
static _orderColumnRegex = /^\s*(\w+)\s?(ASC|DESC)?\s*?$/i;
|
|
187
|
+
_columns;
|
|
188
|
+
_directions;
|
|
189
|
+
/**
|
|
190
|
+
* Constructor for `OINODbOrder`.
|
|
191
|
+
*
|
|
192
|
+
* @param orderString string representation of filter from HTTP-request
|
|
193
|
+
*
|
|
194
|
+
*/
|
|
195
|
+
constructor(orderString) {
|
|
196
|
+
// OINOLog.debug("OINODbOrder.constructor", {orderString:orderString})
|
|
197
|
+
this._columns = [];
|
|
198
|
+
this._directions = [];
|
|
199
|
+
const column_strings = orderString.split(',');
|
|
200
|
+
for (let i = 0; i < column_strings.length; i++) {
|
|
201
|
+
let match = OINODbOrder._orderColumnRegex.exec(column_strings[i]);
|
|
202
|
+
if (match != null) {
|
|
203
|
+
this._columns.push(match[1]);
|
|
204
|
+
this._directions.push((match[2] || "ASC").toUpperCase());
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// OINOLog.debug("OINODbOrder.constructor", {columns:this._columns, directions:this._directions})
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Does filter contain any valid conditions.
|
|
211
|
+
*
|
|
212
|
+
*/
|
|
213
|
+
isEmpty() {
|
|
214
|
+
return (this._columns.length == 0);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Print order as SQL condition based on the datamodel of the API.
|
|
218
|
+
*
|
|
219
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
220
|
+
*
|
|
221
|
+
*/
|
|
222
|
+
toSql(dataModel) {
|
|
223
|
+
if (this.isEmpty()) {
|
|
224
|
+
return "";
|
|
225
|
+
}
|
|
226
|
+
// OINOLog.debug("OINODbOrder.toSql", {columns:this._columns, directions:this._directions})
|
|
227
|
+
let result = "";
|
|
228
|
+
for (let i = 0; i < this._columns.length; i++) {
|
|
229
|
+
const field = dataModel.findFieldByName(this._columns[i]);
|
|
230
|
+
if (field) {
|
|
231
|
+
if (result) {
|
|
232
|
+
result += ",";
|
|
233
|
+
}
|
|
234
|
+
result += dataModel.api.db.printSqlColumnname(field.name) + " " + this._directions[i];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// OINOLog.debug("OINODbOrder.toSql", {result:result})
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
exports.OINODbOrder = OINODbOrder;
|
|
242
|
+
/**
|
|
243
|
+
* Class for limiting the number of results.
|
|
244
|
+
*
|
|
245
|
+
*/
|
|
246
|
+
class OINODbLimit {
|
|
247
|
+
static _orderColumnRegex = /^(\d+)?$/i;
|
|
248
|
+
_limit;
|
|
249
|
+
/**
|
|
250
|
+
* Constructor for `OINODbLimit`.
|
|
251
|
+
*
|
|
252
|
+
* @param limitString string representation of filter from HTTP-request
|
|
253
|
+
*
|
|
254
|
+
*/
|
|
255
|
+
constructor(limitString) {
|
|
256
|
+
this._limit = 0;
|
|
257
|
+
this._limit = Number.parseInt(limitString);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Does filter contain any valid conditions.
|
|
261
|
+
*
|
|
262
|
+
*/
|
|
263
|
+
isEmpty() {
|
|
264
|
+
return (this._limit <= 0);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Print order as SQL condition based on the datamodel of the API.
|
|
268
|
+
*
|
|
269
|
+
* @param dataModel data model (and database) to use for formatting of values
|
|
270
|
+
*
|
|
271
|
+
*/
|
|
272
|
+
toSql(dataModel) {
|
|
273
|
+
if (this.isEmpty()) {
|
|
274
|
+
return "";
|
|
275
|
+
}
|
|
276
|
+
let result = this._limit.toString();
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.OINODbLimit = OINODbLimit;
|