@oino-ts/db-bunsqlite 0.0.15 → 0.0.17
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 +18 -47
- package/dist/cjs/OINODbBunSqlite.js +15 -3
- package/dist/esm/OINODbBunSqlite.js +15 -3
- package/dist/types/OINODbBunSqlite.d.ts +1 -0
- package/package.json +2 -2
- package/src/OINODbBunSqlite.ts +15 -3
package/README.md
CHANGED
|
@@ -10,15 +10,15 @@
|
|
|
10
10
|
# GETTING STARTED
|
|
11
11
|
|
|
12
12
|
### Setup
|
|
13
|
-
Install the `@oino-ts/
|
|
13
|
+
Install the `@oino-ts/db` npm package and necessary database packages and import them in your code.
|
|
14
14
|
```
|
|
15
|
-
bun install @oino-ts/
|
|
16
|
-
bun install @oino-ts/bunsqlite
|
|
15
|
+
bun install @oino-ts/db
|
|
16
|
+
bun install @oino-ts/db-bunsqlite
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
```
|
|
20
|
-
import { OINODb, OINOApi, OINOFactory } from "@oino-ts/
|
|
21
|
-
import { OINODbBunSqlite } from "@oino-ts/bunsqlite"
|
|
20
|
+
import { OINODb, OINOApi, OINOFactory } from "@oino-ts/db";
|
|
21
|
+
import { OINODbBunSqlite } from "@oino-ts/db-bunsqlite"
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
### Register database and logger
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
### Write results back to HTTP Response
|
|
52
52
|
The results for a GET request will contain [`OINOModelSet`](https://pragmatta.github.io/oino-ts/classes/db_src.OINODbModelSet.html) data that can be written out as JSON or CSV as needed. For other requests result is just success or error with messages.
|
|
53
53
|
```
|
|
54
|
-
return new Response(result.
|
|
54
|
+
return new Response(result.data.writeString(OINOContentType.json))
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
|
|
@@ -59,20 +59,8 @@
|
|
|
59
59
|
|
|
60
60
|
## RESTfull
|
|
61
61
|
OINO maps HTTP methods GET/POST/PUT/DELETE to SQL operations SELECT/INSERT/UPDATE/DELETE. The GET/POST requests can be made without URL ID to get all rows or insert new ones and others target a single row using URL ID.
|
|
62
|
-
|
|
63
|
-
### HTTP GET
|
|
64
|
-
```
|
|
65
|
-
Request and response:
|
|
66
|
-
> curl.exe -X GET http://localhost:3001/orderdetails/11077:77
|
|
67
|
-
[
|
|
68
|
-
{"_OINOID_":"11077:77","OrderID":11077,"ProductID":77,"UnitPrice":13,"Quantity":2,"Discount":0}
|
|
69
|
-
]
|
|
70
|
-
|
|
71
|
-
SQL:
|
|
72
|
-
SELECT "OrderID","ProductID","UnitPrice","Quantity","Discount" FROM [OrderDetails] WHERE ("OrderID"=11077 AND "ProductID"=77);
|
|
73
|
-
```
|
|
74
62
|
|
|
75
|
-
|
|
63
|
+
For example HTTP POST
|
|
76
64
|
```
|
|
77
65
|
Request and response:
|
|
78
66
|
> curl.exe -X POST http://localhost:3001/orderdetails -H "Content-Type: application/json" --data '[{\"OrderID\":11077,\"ProductID\":99,\"UnitPrice\":19,\"Quantity\":1,\"Discount\":0}]'
|
|
@@ -82,31 +70,12 @@
|
|
|
82
70
|
INSERT INTO [OrderDetails] ("OrderID","ProductID","UnitPrice","Quantity","Discount") VALUES (11077,99,19,1,0);
|
|
83
71
|
```
|
|
84
72
|
|
|
85
|
-
### HTTP PUT
|
|
86
|
-
```
|
|
87
|
-
Request and response:
|
|
88
|
-
> curl.exe -X PUT http://localhost:3001/orderdetails/11077:99 -H "Content-Type: application/json" --data '[{\"UnitPrice\":20}]'
|
|
89
|
-
{"success":true,"statusCode":200,"statusMessage":"OK","messages":[]}
|
|
90
73
|
|
|
91
|
-
SQL:
|
|
92
|
-
UPDATE [OrderDetails] SET "UnitPrice"=20 WHERE ("OrderID"=11077 AND "ProductID"=99);
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### HTTP DELETE
|
|
96
|
-
```
|
|
97
|
-
Request and response:
|
|
98
|
-
> curl.exe -X DELETE http://localhost:3001/orderdetails/11077:99
|
|
99
|
-
{"success":true,"statusCode":200,"statusMessage":"OK","messages":[]}
|
|
100
|
-
|
|
101
|
-
SQL:
|
|
102
|
-
DELETE FROM [OrderDetails] WHERE ("OrderID"=11077 AND "ProductID"=99);
|
|
103
|
-
```
|
|
104
|
-
|
|
105
74
|
## Universal Serialization
|
|
106
75
|
OINO handles serialization of data to JSON/CSV/etc. and back based on the data model. It knows what columns exist, what is their data type and how to convert each to JSON/CSV and back. This allows also partial data to be sent, i.e. you can send only columns that need updating or even send extra columns and have them ignored.
|
|
107
76
|
|
|
108
77
|
### Features
|
|
109
|
-
- Files can be sent to BLOB fields using BASE64 encoding.
|
|
78
|
+
- Files can be sent to BLOB fields using BASE64 or MIME multipart encoding.
|
|
110
79
|
- Datetimes are (optionally) normalized to ISO 8601 format.
|
|
111
80
|
- Extended JSON-encoding
|
|
112
81
|
- Unquoted literal `undefined` can be used to represent non-existent values (leaving property out works too but preserving structure might be easier e.g. when translating data).
|
|
@@ -129,12 +98,13 @@
|
|
|
129
98
|
- Bun Sqlite through Bun native implementation
|
|
130
99
|
- Postgresql through [pg](https://www.npmjs.com/package/pg)-package
|
|
131
100
|
- Mariadb / Mysql-support through [mariadb](https://www.npmjs.com/package/mariadb)-package
|
|
101
|
+
- Sql Server through [mssql](https://www.npmjs.com/package/mssql)-package
|
|
132
102
|
|
|
133
103
|
## Complex Keys
|
|
134
104
|
To support tables with multipart primary keys OINO generates a composite key `_OINOID_` that is included in the result and can be used as the REST ID. For example in the example above table `OrderDetails` has two primary keys `OrderID` and `ProductID` making the `_OINOID_` of form `11077:99`.
|
|
135
105
|
|
|
136
106
|
## Power Of SQL
|
|
137
|
-
Since OINO
|
|
107
|
+
Since OINO is just generating SQL, WHERE-conditions can be defined with [`OINOSqlFilter`](https://pragmatta.github.io/oino-ts/classes/db_src.OINODbSqlFilter.html), order with [`OINOSqlOrder`](https://pragmatta.github.io/oino-ts/classes/db_src.OINODbSqlOrder.html) and limits/paging with [`OINOSqlOrder`](https://pragmatta.github.io/oino-ts/classes/db_src.OINODbSqlLimit.html) that are passed as HTTP request parameters. No more API development where you make unique API endpoints for each filter that fetch all data with original API and filter in backend code. Every API can be filtered when and as needed without unnessecary data tranfer and utilizing SQL indexing when available.
|
|
138
108
|
|
|
139
109
|
## Swagger Support
|
|
140
110
|
Swagger is great as long as the definitions are updated and with OINO you can automatically get a Swagger definition including a data model schema.
|
|
@@ -158,7 +128,7 @@
|
|
|
158
128
|
# STATUS
|
|
159
129
|
OINO is currently a hobby project which should and should considered in alpha status. That also means compatibility breaking changes can be made without prior notice when architectual issues are discovered.
|
|
160
130
|
|
|
161
|
-
## Beta
|
|
131
|
+
## Beta
|
|
162
132
|
For a beta status following milestones are planned:
|
|
163
133
|
|
|
164
134
|
### Realistic app
|
|
@@ -178,8 +148,8 @@
|
|
|
178
148
|
### Batch updates
|
|
179
149
|
Supporting batch updates similar to batch inserts is slightly bending the RESTfull principles but would still be a useful optional feature.
|
|
180
150
|
|
|
181
|
-
### Aggregation
|
|
182
|
-
Similar to filtering and
|
|
151
|
+
### Aggregation
|
|
152
|
+
Similar to filtering, ordering and limits, aggregation could be implemented as HTTP request parameters telling what column is aggregated or used for ordering or how many results to return.
|
|
183
153
|
|
|
184
154
|
### Streaming
|
|
185
155
|
One core idea is to be efficient in not making unnecessary copies of the data and minimizing garbage collection debt. This can be taken further by implementing streaming, allowing large dataset to be written to HTTP response as SQL result rows are received.
|
|
@@ -205,18 +175,19 @@
|
|
|
205
175
|
# LINKS
|
|
206
176
|
- [Github repository](https://github.com/pragmatta/oino-ts)
|
|
207
177
|
- [NPM repository](https://www.npmjs.com/org/oino-ts)
|
|
208
|
-
|
|
178
|
+
|
|
209
179
|
|
|
210
180
|
# ACKNOWLEDGEMENTS
|
|
211
181
|
|
|
212
182
|
## Libraries
|
|
213
183
|
OINO uses the following open source libraries and npm packages and I would like to thank everyone for their contributions:
|
|
214
|
-
- Postgresql
|
|
215
|
-
- Mariadb / Mysql
|
|
184
|
+
- Postgresql [node-postgres package](https://www.npmjs.com/package/pg)
|
|
185
|
+
- Mariadb / Mysql [mariadb package](https://www.npmjs.com/package/mariadb)
|
|
186
|
+
- Sql Server [mssql package](https://www.npmjs.com/package/mssql)
|
|
187
|
+
- Custom base encoding [base-x package](https://www.npmjs.com/package/base-x)
|
|
216
188
|
|
|
217
189
|
## Bun
|
|
218
190
|
OINO has been developed using the Bun runtime, not because of the speed improvements but for the first class Typescript support and integrated developper experience. Kudos on the bun team for making Typescript work more exiting again.
|
|
219
191
|
|
|
220
192
|
## SQL Scripts
|
|
221
193
|
The SQL scripts for creating the sample Northwind database are based on [Google Code archive](https://code.google.com/archive/p/northwindextended/downloads) and have been further customized to ensure they would have identical data (in the scope of the automated testing).
|
|
222
|
-
|
|
@@ -24,6 +24,7 @@ class OINOBunSqliteDataset extends db_1.OINODbMemoryDataSet {
|
|
|
24
24
|
class OINODbBunSqlite extends db_1.OINODb {
|
|
25
25
|
static _tableDescriptionRegex = /^CREATE TABLE\s*[\"\[]?\w+[\"\]]?\s*\(\s*(.*)\s*\)\s*(WITHOUT ROWID)?$/msi;
|
|
26
26
|
static _tablePrimarykeyRegex = /PRIMARY KEY \(([^\)]+)\)/i;
|
|
27
|
+
static _tableForeignkeyRegex = /FOREIGN KEY \(\[([^\)]+)\]\)/i;
|
|
27
28
|
static _tableFieldTypeRegex = /[\"\[\s]?(\w+)[\"\]\s]\s?(INTEGER|REAL|DOUBLE|NUMERIC|DECIMAL|TEXT|BLOB|VARCHAR|DATETIME|DATE|BOOLEAN)(\s?\((\d+)\s?\,?\s?(\d*)?\))?/i;
|
|
28
29
|
_db;
|
|
29
30
|
/**
|
|
@@ -36,7 +37,7 @@ class OINODbBunSqlite extends db_1.OINODb {
|
|
|
36
37
|
if (!this._params.url.startsWith("file://")) {
|
|
37
38
|
throw new Error(db_1.OINO_ERROR_PREFIX + ": OINODbBunSqlite url must be a file://-url!");
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
+
// OINOLog.debug("OINODbBunSqlite.constructor", {params:params})
|
|
40
41
|
if (this._params.type !== "OINODbBunSqlite") {
|
|
41
42
|
throw new Error(db_1.OINO_ERROR_PREFIX + ": Not OINODbBunSqlite-type: " + this._params.type);
|
|
42
43
|
}
|
|
@@ -44,6 +45,7 @@ class OINODbBunSqlite extends db_1.OINODb {
|
|
|
44
45
|
_parseDbFieldParams(fieldStr) {
|
|
45
46
|
const result = {
|
|
46
47
|
isPrimaryKey: fieldStr.indexOf("PRIMARY KEY") >= 0,
|
|
48
|
+
isForeignKey: false,
|
|
47
49
|
isAutoInc: fieldStr.indexOf("AUTOINCREMENT") >= 0,
|
|
48
50
|
isNotNull: fieldStr.indexOf("NOT NULL") >= 0
|
|
49
51
|
};
|
|
@@ -134,7 +136,7 @@ class OINODbBunSqlite extends db_1.OINODb {
|
|
|
134
136
|
connect() {
|
|
135
137
|
const filepath = this._params.url.substring(7);
|
|
136
138
|
try {
|
|
137
|
-
|
|
139
|
+
// OINOLog.debug("OINODbBunSqlite.connect", {params:this._params})
|
|
138
140
|
this._db = bun_sqlite_1.Database.open(filepath, { create: true, readonly: false, readwrite: true });
|
|
139
141
|
// OINOLog.debug("OINODbBunSqlite.connect done")
|
|
140
142
|
return Promise.resolve(true);
|
|
@@ -191,6 +193,7 @@ class OINODbBunSqlite extends db_1.OINODb {
|
|
|
191
193
|
async initializeApiDatamodel(api) {
|
|
192
194
|
const res = await this.sqlSelect("select sql from sqlite_schema WHERE name='" + api.params.tableName + "'");
|
|
193
195
|
const sql_desc = (res?.getRow()[0]);
|
|
196
|
+
const foreign_keys = [];
|
|
194
197
|
// OINOLog.debug("OINODbBunSqlite.initDatamodel.sql_desc=" + sql_desc)
|
|
195
198
|
let table_matches = OINODbBunSqlite._tableDescriptionRegex.exec(sql_desc);
|
|
196
199
|
// OINOLog.debug("OINODbBunSqlite.initDatamodel", {table_matches:table_matches})
|
|
@@ -208,7 +211,8 @@ class OINODbBunSqlite extends db_1.OINODb {
|
|
|
208
211
|
// OINOLog.debug("initDatamodel next field", {field_str:field_str, field_match:field_match, field_params:field_params})
|
|
209
212
|
if ((!field_match) || (field_match.length < 3)) {
|
|
210
213
|
let primarykey_match = OINODbBunSqlite._tablePrimarykeyRegex.exec(field_str);
|
|
211
|
-
|
|
214
|
+
let foreignkey_match = OINODbBunSqlite._tableForeignkeyRegex.exec(field_str);
|
|
215
|
+
db_1.OINOLog.debug("initDatamodel non-field definition", { primarykey_match: primarykey_match, foreignkey_match: foreignkey_match });
|
|
212
216
|
if (primarykey_match && primarykey_match.length >= 2) {
|
|
213
217
|
const primary_keys = primarykey_match[1].replaceAll("\"", "").split(','); // not sure if will have space or not so split by comma and trim later
|
|
214
218
|
for (let i = 0; i < primary_keys.length; i++) {
|
|
@@ -220,6 +224,14 @@ class OINODbBunSqlite extends db_1.OINODb {
|
|
|
220
224
|
}
|
|
221
225
|
}
|
|
222
226
|
}
|
|
227
|
+
else if (foreignkey_match && foreignkey_match.length >= 2) {
|
|
228
|
+
const fk = foreignkey_match[1].trim();
|
|
229
|
+
for (let j = 0; j < api.datamodel.fields.length; j++) {
|
|
230
|
+
if (api.datamodel.fields[j].name == fk) {
|
|
231
|
+
api.datamodel.fields[j].fieldParams.isForeignKey = true;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
223
235
|
else {
|
|
224
236
|
db_1.OINOLog.info("OINODbBunSqlite.initializeApiDatamodel: Unsupported field definition skipped.", { field: field_str });
|
|
225
237
|
}
|
|
@@ -21,6 +21,7 @@ class OINOBunSqliteDataset extends OINODbMemoryDataSet {
|
|
|
21
21
|
export class OINODbBunSqlite extends OINODb {
|
|
22
22
|
static _tableDescriptionRegex = /^CREATE TABLE\s*[\"\[]?\w+[\"\]]?\s*\(\s*(.*)\s*\)\s*(WITHOUT ROWID)?$/msi;
|
|
23
23
|
static _tablePrimarykeyRegex = /PRIMARY KEY \(([^\)]+)\)/i;
|
|
24
|
+
static _tableForeignkeyRegex = /FOREIGN KEY \(\[([^\)]+)\]\)/i;
|
|
24
25
|
static _tableFieldTypeRegex = /[\"\[\s]?(\w+)[\"\]\s]\s?(INTEGER|REAL|DOUBLE|NUMERIC|DECIMAL|TEXT|BLOB|VARCHAR|DATETIME|DATE|BOOLEAN)(\s?\((\d+)\s?\,?\s?(\d*)?\))?/i;
|
|
25
26
|
_db;
|
|
26
27
|
/**
|
|
@@ -33,7 +34,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
33
34
|
if (!this._params.url.startsWith("file://")) {
|
|
34
35
|
throw new Error(OINO_ERROR_PREFIX + ": OINODbBunSqlite url must be a file://-url!");
|
|
35
36
|
}
|
|
36
|
-
OINOLog.debug("OINODbBunSqlite.constructor", {
|
|
37
|
+
// OINOLog.debug("OINODbBunSqlite.constructor", {params:params})
|
|
37
38
|
if (this._params.type !== "OINODbBunSqlite") {
|
|
38
39
|
throw new Error(OINO_ERROR_PREFIX + ": Not OINODbBunSqlite-type: " + this._params.type);
|
|
39
40
|
}
|
|
@@ -41,6 +42,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
41
42
|
_parseDbFieldParams(fieldStr) {
|
|
42
43
|
const result = {
|
|
43
44
|
isPrimaryKey: fieldStr.indexOf("PRIMARY KEY") >= 0,
|
|
45
|
+
isForeignKey: false,
|
|
44
46
|
isAutoInc: fieldStr.indexOf("AUTOINCREMENT") >= 0,
|
|
45
47
|
isNotNull: fieldStr.indexOf("NOT NULL") >= 0
|
|
46
48
|
};
|
|
@@ -131,7 +133,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
131
133
|
connect() {
|
|
132
134
|
const filepath = this._params.url.substring(7);
|
|
133
135
|
try {
|
|
134
|
-
OINOLog.debug("OINODbBunSqlite.connect", {
|
|
136
|
+
// OINOLog.debug("OINODbBunSqlite.connect", {params:this._params})
|
|
135
137
|
this._db = BunSqliteDb.open(filepath, { create: true, readonly: false, readwrite: true });
|
|
136
138
|
// OINOLog.debug("OINODbBunSqlite.connect done")
|
|
137
139
|
return Promise.resolve(true);
|
|
@@ -188,6 +190,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
188
190
|
async initializeApiDatamodel(api) {
|
|
189
191
|
const res = await this.sqlSelect("select sql from sqlite_schema WHERE name='" + api.params.tableName + "'");
|
|
190
192
|
const sql_desc = (res?.getRow()[0]);
|
|
193
|
+
const foreign_keys = [];
|
|
191
194
|
// OINOLog.debug("OINODbBunSqlite.initDatamodel.sql_desc=" + sql_desc)
|
|
192
195
|
let table_matches = OINODbBunSqlite._tableDescriptionRegex.exec(sql_desc);
|
|
193
196
|
// OINOLog.debug("OINODbBunSqlite.initDatamodel", {table_matches:table_matches})
|
|
@@ -205,7 +208,8 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
205
208
|
// OINOLog.debug("initDatamodel next field", {field_str:field_str, field_match:field_match, field_params:field_params})
|
|
206
209
|
if ((!field_match) || (field_match.length < 3)) {
|
|
207
210
|
let primarykey_match = OINODbBunSqlite._tablePrimarykeyRegex.exec(field_str);
|
|
208
|
-
|
|
211
|
+
let foreignkey_match = OINODbBunSqlite._tableForeignkeyRegex.exec(field_str);
|
|
212
|
+
OINOLog.debug("initDatamodel non-field definition", { primarykey_match: primarykey_match, foreignkey_match: foreignkey_match });
|
|
209
213
|
if (primarykey_match && primarykey_match.length >= 2) {
|
|
210
214
|
const primary_keys = primarykey_match[1].replaceAll("\"", "").split(','); // not sure if will have space or not so split by comma and trim later
|
|
211
215
|
for (let i = 0; i < primary_keys.length; i++) {
|
|
@@ -217,6 +221,14 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
217
221
|
}
|
|
218
222
|
}
|
|
219
223
|
}
|
|
224
|
+
else if (foreignkey_match && foreignkey_match.length >= 2) {
|
|
225
|
+
const fk = foreignkey_match[1].trim();
|
|
226
|
+
for (let j = 0; j < api.datamodel.fields.length; j++) {
|
|
227
|
+
if (api.datamodel.fields[j].name == fk) {
|
|
228
|
+
api.datamodel.fields[j].fieldParams.isForeignKey = true;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
220
232
|
else {
|
|
221
233
|
OINOLog.info("OINODbBunSqlite.initializeApiDatamodel: Unsupported field definition skipped.", { field: field_str });
|
|
222
234
|
}
|
|
@@ -6,6 +6,7 @@ import { OINODb, OINODbParams, OINODbDataSet, OINODbApi, OINODataCell } from "@o
|
|
|
6
6
|
export declare class OINODbBunSqlite extends OINODb {
|
|
7
7
|
private static _tableDescriptionRegex;
|
|
8
8
|
private static _tablePrimarykeyRegex;
|
|
9
|
+
private static _tableForeignkeyRegex;
|
|
9
10
|
private static _tableFieldTypeRegex;
|
|
10
11
|
private _db;
|
|
11
12
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oino-ts/db-bunsqlite",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "OINO TS package for using Bun Sqlite databases.",
|
|
5
5
|
"author": "Matias Kiviniemi (pragmatta)",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"module": "./dist/esm/index.js",
|
|
21
21
|
"types": "./dist/types/index.d.ts",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@oino-ts/db": "^0.0.
|
|
23
|
+
"@oino-ts/db": "^0.0.17"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^20.12.7",
|
package/src/OINODbBunSqlite.ts
CHANGED
|
@@ -25,6 +25,7 @@ class OINOBunSqliteDataset extends OINODbMemoryDataSet {
|
|
|
25
25
|
export class OINODbBunSqlite extends OINODb {
|
|
26
26
|
private static _tableDescriptionRegex = /^CREATE TABLE\s*[\"\[]?\w+[\"\]]?\s*\(\s*(.*)\s*\)\s*(WITHOUT ROWID)?$/msi
|
|
27
27
|
private static _tablePrimarykeyRegex = /PRIMARY KEY \(([^\)]+)\)/i
|
|
28
|
+
private static _tableForeignkeyRegex = /FOREIGN KEY \(\[([^\)]+)\]\)/i
|
|
28
29
|
private static _tableFieldTypeRegex = /[\"\[\s]?(\w+)[\"\]\s]\s?(INTEGER|REAL|DOUBLE|NUMERIC|DECIMAL|TEXT|BLOB|VARCHAR|DATETIME|DATE|BOOLEAN)(\s?\((\d+)\s?\,?\s?(\d*)?\))?/i
|
|
29
30
|
|
|
30
31
|
private _db:BunSqliteDb|null
|
|
@@ -39,7 +40,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
39
40
|
if (!this._params.url.startsWith("file://")) {
|
|
40
41
|
throw new Error(OINO_ERROR_PREFIX + ": OINODbBunSqlite url must be a file://-url!")
|
|
41
42
|
}
|
|
42
|
-
OINOLog.debug("OINODbBunSqlite.constructor", {params:params})
|
|
43
|
+
// OINOLog.debug("OINODbBunSqlite.constructor", {params:params})
|
|
43
44
|
|
|
44
45
|
if (this._params.type !== "OINODbBunSqlite") {
|
|
45
46
|
throw new Error(OINO_ERROR_PREFIX + ": Not OINODbBunSqlite-type: " + this._params.type)
|
|
@@ -49,6 +50,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
49
50
|
private _parseDbFieldParams(fieldStr:string): OINODbDataFieldParams {
|
|
50
51
|
const result:OINODbDataFieldParams = {
|
|
51
52
|
isPrimaryKey: fieldStr.indexOf("PRIMARY KEY") >= 0,
|
|
53
|
+
isForeignKey: false,
|
|
52
54
|
isAutoInc: fieldStr.indexOf("AUTOINCREMENT") >= 0,
|
|
53
55
|
isNotNull: fieldStr.indexOf("NOT NULL") >= 0
|
|
54
56
|
}
|
|
@@ -144,7 +146,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
144
146
|
connect(): Promise<boolean> {
|
|
145
147
|
const filepath:string = this._params.url.substring(7)
|
|
146
148
|
try {
|
|
147
|
-
OINOLog.debug("OINODbBunSqlite.connect", {params:this._params})
|
|
149
|
+
// OINOLog.debug("OINODbBunSqlite.connect", {params:this._params})
|
|
148
150
|
this._db = BunSqliteDb.open(filepath, { create: true, readonly: false, readwrite: true })
|
|
149
151
|
// OINOLog.debug("OINODbBunSqlite.connect done")
|
|
150
152
|
return Promise.resolve(true)
|
|
@@ -203,6 +205,7 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
203
205
|
async initializeApiDatamodel(api:OINODbApi): Promise<void> {
|
|
204
206
|
const res:OINODbDataSet|null = await this.sqlSelect("select sql from sqlite_schema WHERE name='" + api.params.tableName + "'")
|
|
205
207
|
const sql_desc:string = (res?.getRow()[0]) as string
|
|
208
|
+
const foreign_keys:string[] = []
|
|
206
209
|
// OINOLog.debug("OINODbBunSqlite.initDatamodel.sql_desc=" + sql_desc)
|
|
207
210
|
let table_matches = OINODbBunSqlite._tableDescriptionRegex.exec(sql_desc)
|
|
208
211
|
// OINOLog.debug("OINODbBunSqlite.initDatamodel", {table_matches:table_matches})
|
|
@@ -220,7 +223,8 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
220
223
|
// OINOLog.debug("initDatamodel next field", {field_str:field_str, field_match:field_match, field_params:field_params})
|
|
221
224
|
if ((!field_match) || (field_match.length < 3)) {
|
|
222
225
|
let primarykey_match = OINODbBunSqlite._tablePrimarykeyRegex.exec(field_str)
|
|
223
|
-
|
|
226
|
+
let foreignkey_match = OINODbBunSqlite._tableForeignkeyRegex.exec(field_str)
|
|
227
|
+
OINOLog.debug("initDatamodel non-field definition", {primarykey_match:primarykey_match, foreignkey_match:foreignkey_match})
|
|
224
228
|
if (primarykey_match && primarykey_match.length >= 2) {
|
|
225
229
|
const primary_keys:string[] = primarykey_match[1].replaceAll("\"", "").split(',') // not sure if will have space or not so split by comma and trim later
|
|
226
230
|
for (let i:number=0; i<primary_keys.length; i++) {
|
|
@@ -232,6 +236,14 @@ export class OINODbBunSqlite extends OINODb {
|
|
|
232
236
|
}
|
|
233
237
|
}
|
|
234
238
|
|
|
239
|
+
} else if (foreignkey_match && foreignkey_match.length >= 2) {
|
|
240
|
+
const fk:string = foreignkey_match[1].trim()
|
|
241
|
+
for (let j:number=0; j<api.datamodel.fields.length; j++) {
|
|
242
|
+
if (api.datamodel.fields[j].name == fk) {
|
|
243
|
+
api.datamodel.fields[j].fieldParams.isForeignKey = true
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
235
247
|
} else {
|
|
236
248
|
OINOLog.info("OINODbBunSqlite.initializeApiDatamodel: Unsupported field definition skipped.", { field: field_str })
|
|
237
249
|
}
|