@oino-ts/db 0.17.1 → 0.17.2

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.
@@ -1,352 +1,352 @@
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
-
7
- import { OINODbDataSet, OINODbDataModel, OINODbDataField, OINODataRow, OINOContentType, OINOBlobDataField, OINOStr, OINODbConfig, OINONumberDataField, OINOBooleanDataField, OINODataCell, OINOLog, OINODbSqlSelect, OINODbSqlParams } from "./index.js";
8
-
9
- /**
10
- * Class for dataset based on a data model that can be serialized to
11
- * a supported format:
12
- * - JSON (application/json)
13
- * - CSV (text/csv)
14
- *
15
- */
16
- export class OINODbModelSet {
17
-
18
- /** Reference to datamodel */
19
- readonly datamodel: OINODbDataModel
20
-
21
- /** Reference to data set */
22
- readonly dataset: OINODbDataSet
23
-
24
- /** SQL parameters */
25
- readonly sqlParams?: OINODbSqlParams
26
-
27
- /** Collection of errors */
28
- errors: string[]
29
-
30
- /**
31
- * Constructor for `OINODbModelSet`.
32
- *
33
- * @param datamodel data model
34
- * @param dataset data set
35
- * @param sqlParams SQL parameters
36
- */
37
- constructor(datamodel: OINODbDataModel, dataset: OINODbDataSet, sqlParams?: OINODbSqlParams) {
38
- this.datamodel = datamodel
39
- this.dataset = dataset
40
- this.sqlParams = sqlParams
41
- this.errors = this.dataset.messages
42
- }
43
-
44
- private _encodeAndHashFieldValue(field:OINODbDataField, value:string|null, contentType:OINOContentType, primaryKeyValues:string[], rowIdSeed:string):string {
45
- let result:string
46
- if (field.fieldParams.isPrimaryKey || field.fieldParams.isForeignKey) {
47
- if (value && (field instanceof OINONumberDataField) && (this.datamodel.api.hashid) && ((this.sqlParams?.aggregate === undefined) || (this.sqlParams.aggregate.isAggregated(field) == false))) {
48
- value = this.datamodel.api.hashid.encode(value, rowIdSeed)
49
- }
50
- if (field.fieldParams.isPrimaryKey) {
51
- primaryKeyValues.push(value || "")
52
- }
53
- }
54
- result = OINOStr.encode(value, contentType)
55
- return result
56
- }
57
-
58
- private _writeRowJson(row:OINODataRow):string {
59
- // console.log("OINODbModelSet._writeRowJson: row=" + row)
60
- const model:OINODbDataModel = this.datamodel
61
- const fields:OINODbDataField[] = model.fields
62
- let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
63
- let primary_key_values:string[] = []
64
- let json_row:string = ""
65
- for (let i=0; i<fields.length; i++) {
66
- const f = fields[i]
67
- if (this.sqlParams?.select?.isSelected(f) === false) {
68
- continue
69
- }
70
- let value:string|null|undefined = f.serializeCell(row[i])
71
- if (value === undefined) {
72
- // skip undefined values
73
-
74
- } else if (value === null) {
75
- json_row += "," + OINOStr.encode(f.name, OINOContentType.json) + ":null"
76
-
77
- } else {
78
-
79
- let is_hashed:boolean = (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) && (f instanceof OINONumberDataField) && (this.datamodel.api.hashid != null)
80
- let is_value = (f instanceof OINOBooleanDataField) || ((f instanceof OINONumberDataField) && !is_hashed)
81
- value = this._encodeAndHashFieldValue(f, value, OINOContentType.json, primary_key_values, f.name + " " + row_id_seed)
82
- if (is_value) {
83
- value = value.substring(1, value.length-1)
84
- }
85
- json_row += "," + OINOStr.encode(f.name, OINOContentType.json) + ":" + value
86
- }
87
- }
88
- json_row = OINOStr.encode(OINODbConfig.OINODB_ID_FIELD, OINOContentType.json) + ":" + OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.json) + json_row
89
- return "{" + json_row + "}"
90
- }
91
-
92
- private async _writeStringJson():Promise<string> {
93
- let result:string = ""
94
- while (!this.dataset.isEof()) {
95
- if (result != "") {
96
- result += ",\r\n"
97
- }
98
- const row:OINODataRow = this.dataset.getRow()
99
- result += this._writeRowJson(row)
100
- await this.dataset.next()
101
- }
102
- result = "[\r\n" + result + "\r\n]"
103
- return result
104
- }
105
-
106
- private _writeHeaderCsv():string {
107
- const model:OINODbDataModel = this.datamodel
108
- const fields:OINODbDataField[] = model.fields
109
- let csv_header:string = "\"" + OINODbConfig.OINODB_ID_FIELD + "\""
110
- for (let i=0; i<fields.length; i++) {
111
- if (this.sqlParams?.select?.isSelected(fields[i]) === false) {
112
- continue
113
- }
114
- csv_header += ",\"" + fields[i].name + "\""
115
- }
116
- return csv_header
117
- }
118
-
119
- private _writeRowCsv(row:OINODataRow):string {
120
- const model:OINODbDataModel = this.datamodel
121
- const fields:OINODbDataField[] = model.fields
122
- let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
123
- let primary_key_values:string[] = []
124
- let csv_row:string = ""
125
- for (let i=0; i<fields.length; i++) {
126
- const f = fields[i]
127
- if (this.sqlParams?.select?.isSelected(f) === false) {
128
- continue
129
- }
130
- let value:string|null|undefined = f.serializeCell(row[i])
131
- if (value == null) {
132
- csv_row += "," + OINOStr.encode(value, OINOContentType.csv) // either null or undefined
133
-
134
- } else {
135
- value = this._encodeAndHashFieldValue(f, value, OINOContentType.csv, primary_key_values, f.name + " " + row_id_seed)
136
- csv_row += "," + value
137
- }
138
- }
139
- csv_row = OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.csv) + csv_row
140
- return csv_row
141
- }
142
-
143
- private async _writeStringCsv():Promise<string> {
144
- let result:string = this._writeHeaderCsv()
145
- while (!this.dataset.isEof()) {
146
- if (result != "") {
147
- result += "\r\n"
148
- }
149
- const row:OINODataRow = this.dataset.getRow()
150
- result += this._writeRowCsv(row)
151
- await this.dataset.next()
152
- }
153
- return result
154
- }
155
-
156
- private _writeRowFormdataParameterBlock(blockName:string, blockValue:string|null, multipartBoundary:string):string {
157
- if (blockValue === null) {
158
- return multipartBoundary + "\r\n" + "Content-Disposition: form-data; name=\"" + blockName + "\"\r\n\r\n"
159
- } else {
160
- return multipartBoundary + "\r\n" + "Content-Disposition: form-data; name=\"" + blockName + "\"\r\n\r\n" + blockValue + "\r\n"
161
- }
162
- }
163
-
164
- private _writeRowFormdataFileBlock(blockName:string, blockValue:string, multipartBoundary:string):string {
165
- 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"
166
- }
167
-
168
- private _writeRowFormdata(row:OINODataRow):string {
169
- const multipart_boundary:string = "---------OINOMultipartBoundary35424568" // this method is just used for test data generation and we want it to be static
170
- const model:OINODbDataModel = this.datamodel
171
- const fields:OINODbDataField[] = model.fields
172
- let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
173
- let primary_key_values:string[] = []
174
- let result:string = ""
175
- for (let i=0; i<fields.length; i++) {
176
- const f = fields[i]
177
- if (this.sqlParams?.select?.isSelected(f) === false) {
178
- continue
179
- }
180
- let value:string|null|undefined = f.serializeCell(row[i])
181
- let formdata_block:string = ""
182
- let is_file = (f instanceof OINOBlobDataField)
183
-
184
- if (value === undefined) {
185
- OINOLog.info("@oino-ts/db", "OINODbModelSet", "_writeRowFormdata", "Undefined value skipped", {field_name:f.name})
186
-
187
- } else if (value === null) {
188
- formdata_block = this._writeRowFormdataParameterBlock(fields[i].name, null, multipart_boundary)
189
-
190
- } else {
191
- value = this._encodeAndHashFieldValue(f, value, OINOContentType.formdata, primary_key_values, f.name + " " + row_id_seed)
192
- if (is_file) {
193
- formdata_block = this._writeRowFormdataFileBlock(f.name, value, multipart_boundary)
194
- } else {
195
- formdata_block = this._writeRowFormdataParameterBlock(fields[i].name, value, multipart_boundary)
196
- }
197
- }
198
-
199
- result += formdata_block
200
- }
201
- result = this._writeRowFormdataParameterBlock(OINODbConfig.OINODB_ID_FIELD, OINODbConfig.printOINOId(primary_key_values), multipart_boundary) + result
202
- return result
203
- }
204
-
205
- private _writeStringFormdata():string {
206
- const row:OINODataRow = this.dataset.getRow()
207
- let result:string = this._writeRowFormdata(row)
208
- return result
209
- }
210
-
211
-
212
- private _writeRowUrlencode(row:OINODataRow):string {
213
- const model:OINODbDataModel = this.datamodel
214
- const fields:OINODbDataField[] = model.fields
215
- let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
216
- let primary_key_values:string[] = []
217
- let urlencode_row:string = ""
218
- for (let i=0; i<fields.length; i++) {
219
- const f = fields[i]
220
- if (this.sqlParams?.select?.isSelected(f) === false) {
221
- continue
222
- }
223
- let value:string|null|undefined = f.serializeCell(row[i])
224
- if ((value === undefined)) { // || (value === null)) {
225
- // console.log("OINODbModelSet._writeRowUrlencode undefined field value:" + fields[i].name)
226
- } else {
227
- value = this._encodeAndHashFieldValue(f, value, OINOContentType.urlencode, primary_key_values, f.name + " " + row_id_seed)
228
- if (urlencode_row != "") {
229
- urlencode_row += "&"
230
- }
231
- urlencode_row += OINOStr.encode(f.name, OINOContentType.urlencode) + "=" + value
232
- }
233
- }
234
- urlencode_row = OINOStr.encode(OINODbConfig.OINODB_ID_FIELD, OINOContentType.urlencode) + "=" + OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.urlencode) + "&" + urlencode_row
235
- return urlencode_row
236
- }
237
-
238
- private async _writeStringUrlencode():Promise<string> {
239
- let result:string = ""
240
- let line_count = 0
241
- while (!this.dataset.isEof()) {
242
- const row:OINODataRow = this.dataset.getRow()
243
- result += this._writeRowUrlencode(row) + "\r\n"
244
- await this.dataset.next()
245
- line_count += 1
246
- }
247
- if (line_count > 1) {
248
- OINOLog.warning("@oino-ts/db", "OINODbModelSet", "_writeStringUrlencode", "Content type " + OINOContentType.urlencode + " does not officially support multiline content!", {})
249
- }
250
- return result
251
- }
252
-
253
- private _exportRow(row:OINODataRow):any {
254
- // console.log("OINODbModelSet._exportRow: row=" + row)
255
- const model:OINODbDataModel = this.datamodel
256
- const fields:OINODbDataField[] = model.fields
257
- let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
258
- let primary_key_values:string[] = []
259
- let result:any = {}
260
- for (let i=0; i<fields.length; i++) {
261
- const f = fields[i]
262
- if (f.fieldParams.isPrimaryKey) {
263
- primary_key_values.push(f.serializeCell(row[i]) || "")
264
- }
265
- if (this.sqlParams?.select?.isSelected(f) === false) {
266
- continue
267
- }
268
- let value:OINODataCell = f.db.parseSqlValueAsCell(row[i], f.sqlType) // retain original value without serialization
269
- if (value === undefined) {
270
- // skip undefined values
271
-
272
- } else if (value === null) { // differentiate null and undefined
273
- result[f.name] = null
274
-
275
- } else {
276
- result[f.name] = value
277
- }
278
- }
279
- result[OINODbConfig.OINODB_ID_FIELD] = OINODbConfig.printOINOId(primary_key_values)
280
- return result
281
- }
282
-
283
-
284
- /**
285
- * Serialize model set in the given format.
286
- *
287
- * @param [contentType=OINOContentType.json] serialization content type
288
- *
289
- */
290
- async writeString(contentType:OINOContentType = OINOContentType.json):Promise<string> {
291
- let result:string = ""
292
- if (contentType == OINOContentType.csv) {
293
- result += await this._writeStringCsv()
294
-
295
- } else if (contentType == OINOContentType.json) {
296
- result += await this._writeStringJson()
297
-
298
- } else if (contentType == OINOContentType.formdata) {
299
- result += await this._writeStringFormdata()
300
-
301
- } else if (contentType == OINOContentType.urlencode) {
302
- result += await this._writeStringUrlencode()
303
-
304
- } else {
305
- OINOLog.error("@oino-ts/db", "OINODbModelSet", "writeString", "Content type is only for input!", {contentType:contentType})
306
- }
307
- return result
308
- }
309
-
310
- /**
311
- * Get value of given field in the current row. Undefined if no rows,
312
- * field not found or value does not exist.
313
- *
314
- * @param fieldName name of the field
315
- * @param serialize serialize the value
316
- *
317
- */
318
- getValueByFieldName(fieldName:string, serialize:boolean = false):OINODataCell {
319
- let result:OINODataCell = undefined
320
- if (!this.dataset.isEof()) {
321
- const current_row:OINODataRow = this.dataset.getRow()
322
- const field_index:number = this.datamodel.findFieldIndexByName(fieldName)
323
- if (field_index >= 0) {
324
- result = current_row[field_index]
325
- if (serialize) {
326
- result = this.datamodel.fields[field_index].serializeCell(result)
327
- }
328
- }
329
- }
330
- return result
331
- }
332
-
333
- /**
334
- * Export all rows as a record with OINOId as key and object with row cells as values.
335
- *
336
- * @param idFieldName optional field name to use as key instead of OINOId
337
- */
338
-
339
- async exportAsRecord(idFieldName?:string):Promise<Record<string, any>> {
340
- const result:Record<string, any> = {}
341
- const row_id_field = idFieldName || OINODbConfig.OINODB_ID_FIELD
342
- while (!this.dataset.isEof()) {
343
- const row_data:OINODataRow = this.dataset.getRow()
344
- const row_export = this._exportRow(row_data)
345
- const row_id = row_export[row_id_field]
346
- result[row_id] = row_export
347
- await this.dataset.next()
348
- }
349
- return result
350
- }
351
-
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
+
7
+ import { OINODbDataSet, OINODbDataModel, OINODbDataField, OINODataRow, OINOContentType, OINOBlobDataField, OINOStr, OINODbConfig, OINONumberDataField, OINOBooleanDataField, OINODataCell, OINOLog, OINODbSqlSelect, OINODbSqlParams } from "./index.js";
8
+
9
+ /**
10
+ * Class for dataset based on a data model that can be serialized to
11
+ * a supported format:
12
+ * - JSON (application/json)
13
+ * - CSV (text/csv)
14
+ *
15
+ */
16
+ export class OINODbModelSet {
17
+
18
+ /** Reference to datamodel */
19
+ readonly datamodel: OINODbDataModel
20
+
21
+ /** Reference to data set */
22
+ readonly dataset: OINODbDataSet
23
+
24
+ /** SQL parameters */
25
+ readonly sqlParams?: OINODbSqlParams
26
+
27
+ /** Collection of errors */
28
+ errors: string[]
29
+
30
+ /**
31
+ * Constructor for `OINODbModelSet`.
32
+ *
33
+ * @param datamodel data model
34
+ * @param dataset data set
35
+ * @param sqlParams SQL parameters
36
+ */
37
+ constructor(datamodel: OINODbDataModel, dataset: OINODbDataSet, sqlParams?: OINODbSqlParams) {
38
+ this.datamodel = datamodel
39
+ this.dataset = dataset
40
+ this.sqlParams = sqlParams
41
+ this.errors = this.dataset.messages
42
+ }
43
+
44
+ private _encodeAndHashFieldValue(field:OINODbDataField, value:string|null, contentType:OINOContentType, primaryKeyValues:string[], rowIdSeed:string):string {
45
+ let result:string
46
+ if (field.fieldParams.isPrimaryKey || field.fieldParams.isForeignKey) {
47
+ if (value && (field instanceof OINONumberDataField) && (this.datamodel.api.hashid) && ((this.sqlParams?.aggregate === undefined) || (this.sqlParams.aggregate.isAggregated(field) == false))) {
48
+ value = this.datamodel.api.hashid.encode(value, rowIdSeed)
49
+ }
50
+ if (field.fieldParams.isPrimaryKey) {
51
+ primaryKeyValues.push(value || "")
52
+ }
53
+ }
54
+ result = OINOStr.encode(value, contentType)
55
+ return result
56
+ }
57
+
58
+ private _writeRowJson(row:OINODataRow):string {
59
+ // console.log("OINODbModelSet._writeRowJson: row=" + row)
60
+ const model:OINODbDataModel = this.datamodel
61
+ const fields:OINODbDataField[] = model.fields
62
+ let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
63
+ let primary_key_values:string[] = []
64
+ let json_row:string = ""
65
+ for (let i=0; i<fields.length; i++) {
66
+ const f = fields[i]
67
+ if (this.sqlParams?.select?.isSelected(f) === false) {
68
+ continue
69
+ }
70
+ let value:string|null|undefined = f.serializeCell(row[i])
71
+ if (value === undefined) {
72
+ // skip undefined values
73
+
74
+ } else if (value === null) {
75
+ json_row += "," + OINOStr.encode(f.name, OINOContentType.json) + ":null"
76
+
77
+ } else {
78
+
79
+ let is_hashed:boolean = (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) && (f instanceof OINONumberDataField) && (this.datamodel.api.hashid != null)
80
+ let is_value = (f instanceof OINOBooleanDataField) || ((f instanceof OINONumberDataField) && !is_hashed)
81
+ value = this._encodeAndHashFieldValue(f, value, OINOContentType.json, primary_key_values, f.name + " " + row_id_seed)
82
+ if (is_value) {
83
+ value = value.substring(1, value.length-1)
84
+ }
85
+ json_row += "," + OINOStr.encode(f.name, OINOContentType.json) + ":" + value
86
+ }
87
+ }
88
+ json_row = OINOStr.encode(OINODbConfig.OINODB_ID_FIELD, OINOContentType.json) + ":" + OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.json) + json_row
89
+ return "{" + json_row + "}"
90
+ }
91
+
92
+ private async _writeStringJson():Promise<string> {
93
+ let result:string = ""
94
+ while (!this.dataset.isEof()) {
95
+ if (result != "") {
96
+ result += ",\r\n"
97
+ }
98
+ const row:OINODataRow = this.dataset.getRow()
99
+ result += this._writeRowJson(row)
100
+ await this.dataset.next()
101
+ }
102
+ result = "[\r\n" + result + "\r\n]"
103
+ return result
104
+ }
105
+
106
+ private _writeHeaderCsv():string {
107
+ const model:OINODbDataModel = this.datamodel
108
+ const fields:OINODbDataField[] = model.fields
109
+ let csv_header:string = "\"" + OINODbConfig.OINODB_ID_FIELD + "\""
110
+ for (let i=0; i<fields.length; i++) {
111
+ if (this.sqlParams?.select?.isSelected(fields[i]) === false) {
112
+ continue
113
+ }
114
+ csv_header += ",\"" + fields[i].name + "\""
115
+ }
116
+ return csv_header
117
+ }
118
+
119
+ private _writeRowCsv(row:OINODataRow):string {
120
+ const model:OINODbDataModel = this.datamodel
121
+ const fields:OINODbDataField[] = model.fields
122
+ let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
123
+ let primary_key_values:string[] = []
124
+ let csv_row:string = ""
125
+ for (let i=0; i<fields.length; i++) {
126
+ const f = fields[i]
127
+ if (this.sqlParams?.select?.isSelected(f) === false) {
128
+ continue
129
+ }
130
+ let value:string|null|undefined = f.serializeCell(row[i])
131
+ if (value == null) {
132
+ csv_row += "," + OINOStr.encode(value, OINOContentType.csv) // either null or undefined
133
+
134
+ } else {
135
+ value = this._encodeAndHashFieldValue(f, value, OINOContentType.csv, primary_key_values, f.name + " " + row_id_seed)
136
+ csv_row += "," + value
137
+ }
138
+ }
139
+ csv_row = OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.csv) + csv_row
140
+ return csv_row
141
+ }
142
+
143
+ private async _writeStringCsv():Promise<string> {
144
+ let result:string = this._writeHeaderCsv()
145
+ while (!this.dataset.isEof()) {
146
+ if (result != "") {
147
+ result += "\r\n"
148
+ }
149
+ const row:OINODataRow = this.dataset.getRow()
150
+ result += this._writeRowCsv(row)
151
+ await this.dataset.next()
152
+ }
153
+ return result
154
+ }
155
+
156
+ private _writeRowFormdataParameterBlock(blockName:string, blockValue:string|null, multipartBoundary:string):string {
157
+ if (blockValue === null) {
158
+ return multipartBoundary + "\r\n" + "Content-Disposition: form-data; name=\"" + blockName + "\"\r\n\r\n"
159
+ } else {
160
+ return multipartBoundary + "\r\n" + "Content-Disposition: form-data; name=\"" + blockName + "\"\r\n\r\n" + blockValue + "\r\n"
161
+ }
162
+ }
163
+
164
+ private _writeRowFormdataFileBlock(blockName:string, blockValue:string, multipartBoundary:string):string {
165
+ 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"
166
+ }
167
+
168
+ private _writeRowFormdata(row:OINODataRow):string {
169
+ const multipart_boundary:string = "---------OINOMultipartBoundary35424568" // this method is just used for test data generation and we want it to be static
170
+ const model:OINODbDataModel = this.datamodel
171
+ const fields:OINODbDataField[] = model.fields
172
+ let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
173
+ let primary_key_values:string[] = []
174
+ let result:string = ""
175
+ for (let i=0; i<fields.length; i++) {
176
+ const f = fields[i]
177
+ if (this.sqlParams?.select?.isSelected(f) === false) {
178
+ continue
179
+ }
180
+ let value:string|null|undefined = f.serializeCell(row[i])
181
+ let formdata_block:string = ""
182
+ let is_file = (f instanceof OINOBlobDataField)
183
+
184
+ if (value === undefined) {
185
+ OINOLog.info("@oino-ts/db", "OINODbModelSet", "_writeRowFormdata", "Undefined value skipped", {field_name:f.name})
186
+
187
+ } else if (value === null) {
188
+ formdata_block = this._writeRowFormdataParameterBlock(fields[i].name, null, multipart_boundary)
189
+
190
+ } else {
191
+ value = this._encodeAndHashFieldValue(f, value, OINOContentType.formdata, primary_key_values, f.name + " " + row_id_seed)
192
+ if (is_file) {
193
+ formdata_block = this._writeRowFormdataFileBlock(f.name, value, multipart_boundary)
194
+ } else {
195
+ formdata_block = this._writeRowFormdataParameterBlock(fields[i].name, value, multipart_boundary)
196
+ }
197
+ }
198
+
199
+ result += formdata_block
200
+ }
201
+ result = this._writeRowFormdataParameterBlock(OINODbConfig.OINODB_ID_FIELD, OINODbConfig.printOINOId(primary_key_values), multipart_boundary) + result
202
+ return result
203
+ }
204
+
205
+ private _writeStringFormdata():string {
206
+ const row:OINODataRow = this.dataset.getRow()
207
+ let result:string = this._writeRowFormdata(row)
208
+ return result
209
+ }
210
+
211
+
212
+ private _writeRowUrlencode(row:OINODataRow):string {
213
+ const model:OINODbDataModel = this.datamodel
214
+ const fields:OINODbDataField[] = model.fields
215
+ let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
216
+ let primary_key_values:string[] = []
217
+ let urlencode_row:string = ""
218
+ for (let i=0; i<fields.length; i++) {
219
+ const f = fields[i]
220
+ if (this.sqlParams?.select?.isSelected(f) === false) {
221
+ continue
222
+ }
223
+ let value:string|null|undefined = f.serializeCell(row[i])
224
+ if ((value === undefined)) { // || (value === null)) {
225
+ // console.log("OINODbModelSet._writeRowUrlencode undefined field value:" + fields[i].name)
226
+ } else {
227
+ value = this._encodeAndHashFieldValue(f, value, OINOContentType.urlencode, primary_key_values, f.name + " " + row_id_seed)
228
+ if (urlencode_row != "") {
229
+ urlencode_row += "&"
230
+ }
231
+ urlencode_row += OINOStr.encode(f.name, OINOContentType.urlencode) + "=" + value
232
+ }
233
+ }
234
+ urlencode_row = OINOStr.encode(OINODbConfig.OINODB_ID_FIELD, OINOContentType.urlencode) + "=" + OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.urlencode) + "&" + urlencode_row
235
+ return urlencode_row
236
+ }
237
+
238
+ private async _writeStringUrlencode():Promise<string> {
239
+ let result:string = ""
240
+ let line_count = 0
241
+ while (!this.dataset.isEof()) {
242
+ const row:OINODataRow = this.dataset.getRow()
243
+ result += this._writeRowUrlencode(row) + "\r\n"
244
+ await this.dataset.next()
245
+ line_count += 1
246
+ }
247
+ if (line_count > 1) {
248
+ OINOLog.warning("@oino-ts/db", "OINODbModelSet", "_writeStringUrlencode", "Content type " + OINOContentType.urlencode + " does not officially support multiline content!", {})
249
+ }
250
+ return result
251
+ }
252
+
253
+ private _exportRow(row:OINODataRow):any {
254
+ // console.log("OINODbModelSet._exportRow: row=" + row)
255
+ const model:OINODbDataModel = this.datamodel
256
+ const fields:OINODbDataField[] = model.fields
257
+ let row_id_seed:string = model.getRowPrimarykeyValues(row).join(' ')
258
+ let primary_key_values:string[] = []
259
+ let result:any = {}
260
+ for (let i=0; i<fields.length; i++) {
261
+ const f = fields[i]
262
+ if (f.fieldParams.isPrimaryKey) {
263
+ primary_key_values.push(f.serializeCell(row[i]) || "")
264
+ }
265
+ if (this.sqlParams?.select?.isSelected(f) === false) {
266
+ continue
267
+ }
268
+ let value:OINODataCell = f.db.parseSqlValueAsCell(row[i], f.sqlType) // retain original value without serialization
269
+ if (value === undefined) {
270
+ // skip undefined values
271
+
272
+ } else if (value === null) { // differentiate null and undefined
273
+ result[f.name] = null
274
+
275
+ } else {
276
+ result[f.name] = value
277
+ }
278
+ }
279
+ result[OINODbConfig.OINODB_ID_FIELD] = OINODbConfig.printOINOId(primary_key_values)
280
+ return result
281
+ }
282
+
283
+
284
+ /**
285
+ * Serialize model set in the given format.
286
+ *
287
+ * @param [contentType=OINOContentType.json] serialization content type
288
+ *
289
+ */
290
+ async writeString(contentType:OINOContentType = OINOContentType.json):Promise<string> {
291
+ let result:string = ""
292
+ if (contentType == OINOContentType.csv) {
293
+ result += await this._writeStringCsv()
294
+
295
+ } else if (contentType == OINOContentType.json) {
296
+ result += await this._writeStringJson()
297
+
298
+ } else if (contentType == OINOContentType.formdata) {
299
+ result += await this._writeStringFormdata()
300
+
301
+ } else if (contentType == OINOContentType.urlencode) {
302
+ result += await this._writeStringUrlencode()
303
+
304
+ } else {
305
+ OINOLog.error("@oino-ts/db", "OINODbModelSet", "writeString", "Content type is only for input!", {contentType:contentType})
306
+ }
307
+ return result
308
+ }
309
+
310
+ /**
311
+ * Get value of given field in the current row. Undefined if no rows,
312
+ * field not found or value does not exist.
313
+ *
314
+ * @param fieldName name of the field
315
+ * @param serialize serialize the value
316
+ *
317
+ */
318
+ getValueByFieldName(fieldName:string, serialize:boolean = false):OINODataCell {
319
+ let result:OINODataCell = undefined
320
+ if (!this.dataset.isEof()) {
321
+ const current_row:OINODataRow = this.dataset.getRow()
322
+ const field_index:number = this.datamodel.findFieldIndexByName(fieldName)
323
+ if (field_index >= 0) {
324
+ result = current_row[field_index]
325
+ if (serialize) {
326
+ result = this.datamodel.fields[field_index].serializeCell(result)
327
+ }
328
+ }
329
+ }
330
+ return result
331
+ }
332
+
333
+ /**
334
+ * Export all rows as a record with OINOId as key and object with row cells as values.
335
+ *
336
+ * @param idFieldName optional field name to use as key instead of OINOId
337
+ */
338
+
339
+ async exportAsRecord(idFieldName?:string):Promise<Record<string, any>> {
340
+ const result:Record<string, any> = {}
341
+ const row_id_field = idFieldName || OINODbConfig.OINODB_ID_FIELD
342
+ while (!this.dataset.isEof()) {
343
+ const row_data:OINODataRow = this.dataset.getRow()
344
+ const row_export = this._exportRow(row_data)
345
+ const row_id = row_export[row_id_field]
346
+ result[row_id] = row_export
347
+ await this.dataset.next()
348
+ }
349
+ return result
350
+ }
351
+
352
352
  }