@oino-ts/db-postgresql 0.0.16 → 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 +5 -37
- package/dist/cjs/OINODbPostgresql.js +9 -6
- package/dist/esm/OINODbPostgresql.js +9 -6
- package/package.json +2 -2
- package/src/OINODbPostgresql.ts +9 -6
package/README.md
CHANGED
|
@@ -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
|
-
|
|
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
73
|
|
|
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).
|
|
@@ -135,7 +104,7 @@
|
|
|
135
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`.
|
|
136
105
|
|
|
137
106
|
## Power Of SQL
|
|
138
|
-
Since OINO is just generating SQL, WHERE-conditions can be defined with [`OINOSqlFilter`](https://pragmatta.github.io/oino-ts/classes/db_src.OINODbSqlFilter.html)
|
|
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.
|
|
139
108
|
|
|
140
109
|
## Swagger Support
|
|
141
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.
|
|
@@ -179,8 +148,8 @@
|
|
|
179
148
|
### Batch updates
|
|
180
149
|
Supporting batch updates similar to batch inserts is slightly bending the RESTfull principles but would still be a useful optional feature.
|
|
181
150
|
|
|
182
|
-
### Aggregation
|
|
183
|
-
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.
|
|
184
153
|
|
|
185
154
|
### Streaming
|
|
186
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.
|
|
@@ -222,4 +191,3 @@
|
|
|
222
191
|
|
|
223
192
|
## SQL Scripts
|
|
224
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).
|
|
225
|
-
|
|
@@ -273,22 +273,23 @@ class OINODbPostgresql extends db_1.OINODb {
|
|
|
273
273
|
col.data_type,
|
|
274
274
|
col.character_maximum_length,
|
|
275
275
|
col.is_nullable,
|
|
276
|
-
|
|
276
|
+
con.constraint_type,
|
|
277
277
|
col.numeric_precision,
|
|
278
278
|
col.numeric_scale,
|
|
279
279
|
col.column_default
|
|
280
280
|
FROM information_schema.columns col
|
|
281
281
|
LEFT JOIN LATERAL
|
|
282
|
-
(select kcu.column_name, '
|
|
282
|
+
(select kcu.column_name, STRING_AGG(tco.constraint_type,',') as constraint_type
|
|
283
283
|
from
|
|
284
284
|
information_schema.table_constraints tco,
|
|
285
285
|
information_schema.key_column_usage kcu
|
|
286
286
|
where
|
|
287
287
|
kcu.constraint_name = tco.constraint_name
|
|
288
288
|
and kcu.constraint_schema = tco.constraint_schema
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
and tco.table_catalog = col.table_catalog
|
|
290
|
+
and tco.table_name = col.table_name
|
|
291
|
+
and (tco.constraint_type = 'PRIMARY KEY' OR tco.constraint_type = 'FOREIGN KEY')
|
|
292
|
+
group by kcu.column_name) con on col.column_name = con.column_name
|
|
292
293
|
WHERE col.table_catalog = '${dbName}' AND col.table_name = '${tableName}'`;
|
|
293
294
|
return sql;
|
|
294
295
|
}
|
|
@@ -308,11 +309,13 @@ WHERE col.table_catalog = '${dbName}' AND col.table_name = '${tableName}'`;
|
|
|
308
309
|
const field_name = row[0]?.toString() || "";
|
|
309
310
|
const sql_type = row[1]?.toString() || "";
|
|
310
311
|
const field_length = this._parseFieldLength(row[2]);
|
|
312
|
+
const constraints = row[4]?.toString() || "";
|
|
311
313
|
const numeric_precision = this._parseFieldLength(row[5]);
|
|
312
314
|
const numeric_scale = this._parseFieldLength(row[6]);
|
|
313
315
|
const default_val = row[7]?.toString() || "";
|
|
314
316
|
const field_params = {
|
|
315
|
-
isPrimaryKey:
|
|
317
|
+
isPrimaryKey: constraints.indexOf('PRIMARY KEY') >= 0 || false,
|
|
318
|
+
isForeignKey: constraints.indexOf('FOREIGN KEY') >= 0 || false,
|
|
316
319
|
isNotNull: row[3] == "NO",
|
|
317
320
|
isAutoInc: default_val.startsWith("nextval(")
|
|
318
321
|
};
|
|
@@ -270,22 +270,23 @@ export class OINODbPostgresql extends OINODb {
|
|
|
270
270
|
col.data_type,
|
|
271
271
|
col.character_maximum_length,
|
|
272
272
|
col.is_nullable,
|
|
273
|
-
|
|
273
|
+
con.constraint_type,
|
|
274
274
|
col.numeric_precision,
|
|
275
275
|
col.numeric_scale,
|
|
276
276
|
col.column_default
|
|
277
277
|
FROM information_schema.columns col
|
|
278
278
|
LEFT JOIN LATERAL
|
|
279
|
-
(select kcu.column_name, '
|
|
279
|
+
(select kcu.column_name, STRING_AGG(tco.constraint_type,',') as constraint_type
|
|
280
280
|
from
|
|
281
281
|
information_schema.table_constraints tco,
|
|
282
282
|
information_schema.key_column_usage kcu
|
|
283
283
|
where
|
|
284
284
|
kcu.constraint_name = tco.constraint_name
|
|
285
285
|
and kcu.constraint_schema = tco.constraint_schema
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
286
|
+
and tco.table_catalog = col.table_catalog
|
|
287
|
+
and tco.table_name = col.table_name
|
|
288
|
+
and (tco.constraint_type = 'PRIMARY KEY' OR tco.constraint_type = 'FOREIGN KEY')
|
|
289
|
+
group by kcu.column_name) con on col.column_name = con.column_name
|
|
289
290
|
WHERE col.table_catalog = '${dbName}' AND col.table_name = '${tableName}'`;
|
|
290
291
|
return sql;
|
|
291
292
|
}
|
|
@@ -305,11 +306,13 @@ WHERE col.table_catalog = '${dbName}' AND col.table_name = '${tableName}'`;
|
|
|
305
306
|
const field_name = row[0]?.toString() || "";
|
|
306
307
|
const sql_type = row[1]?.toString() || "";
|
|
307
308
|
const field_length = this._parseFieldLength(row[2]);
|
|
309
|
+
const constraints = row[4]?.toString() || "";
|
|
308
310
|
const numeric_precision = this._parseFieldLength(row[5]);
|
|
309
311
|
const numeric_scale = this._parseFieldLength(row[6]);
|
|
310
312
|
const default_val = row[7]?.toString() || "";
|
|
311
313
|
const field_params = {
|
|
312
|
-
isPrimaryKey:
|
|
314
|
+
isPrimaryKey: constraints.indexOf('PRIMARY KEY') >= 0 || false,
|
|
315
|
+
isForeignKey: constraints.indexOf('FOREIGN KEY') >= 0 || false,
|
|
313
316
|
isNotNull: row[3] == "NO",
|
|
314
317
|
isAutoInc: default_val.startsWith("nextval(")
|
|
315
318
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oino-ts/db-postgresql",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "OINO TS package for using Postgresql 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
|
"pg": "^8.11.3"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
package/src/OINODbPostgresql.ts
CHANGED
|
@@ -290,22 +290,23 @@ export class OINODbPostgresql extends OINODb {
|
|
|
290
290
|
col.data_type,
|
|
291
291
|
col.character_maximum_length,
|
|
292
292
|
col.is_nullable,
|
|
293
|
-
|
|
293
|
+
con.constraint_type,
|
|
294
294
|
col.numeric_precision,
|
|
295
295
|
col.numeric_scale,
|
|
296
296
|
col.column_default
|
|
297
297
|
FROM information_schema.columns col
|
|
298
298
|
LEFT JOIN LATERAL
|
|
299
|
-
(select kcu.column_name, '
|
|
299
|
+
(select kcu.column_name, STRING_AGG(tco.constraint_type,',') as constraint_type
|
|
300
300
|
from
|
|
301
301
|
information_schema.table_constraints tco,
|
|
302
302
|
information_schema.key_column_usage kcu
|
|
303
303
|
where
|
|
304
304
|
kcu.constraint_name = tco.constraint_name
|
|
305
305
|
and kcu.constraint_schema = tco.constraint_schema
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
306
|
+
and tco.table_catalog = col.table_catalog
|
|
307
|
+
and tco.table_name = col.table_name
|
|
308
|
+
and (tco.constraint_type = 'PRIMARY KEY' OR tco.constraint_type = 'FOREIGN KEY')
|
|
309
|
+
group by kcu.column_name) con on col.column_name = con.column_name
|
|
309
310
|
WHERE col.table_catalog = '${dbName}' AND col.table_name = '${tableName}'`
|
|
310
311
|
return sql
|
|
311
312
|
}
|
|
@@ -327,11 +328,13 @@ WHERE col.table_catalog = '${dbName}' AND col.table_name = '${tableName}'`
|
|
|
327
328
|
const field_name:string = row[0]?.toString() || ""
|
|
328
329
|
const sql_type:string = row[1]?.toString() || ""
|
|
329
330
|
const field_length:number = this._parseFieldLength(row[2])
|
|
331
|
+
const constraints = row[4]?.toString() || ""
|
|
330
332
|
const numeric_precision:number = this._parseFieldLength(row[5])
|
|
331
333
|
const numeric_scale:number = this._parseFieldLength(row[6])
|
|
332
334
|
const default_val:string = row[7]?.toString() || ""
|
|
333
335
|
const field_params:OINODbDataFieldParams = {
|
|
334
|
-
isPrimaryKey:
|
|
336
|
+
isPrimaryKey: constraints.indexOf('PRIMARY KEY') >= 0 || false,
|
|
337
|
+
isForeignKey: constraints.indexOf('FOREIGN KEY') >= 0 || false,
|
|
335
338
|
isNotNull: row[3] == "NO",
|
|
336
339
|
isAutoInc: default_val.startsWith("nextval(")
|
|
337
340
|
}
|