@ruiapp/rapid-core 0.5.0 → 0.5.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/index.js
CHANGED
|
@@ -202,8 +202,8 @@ const pgPropertyTypeColumnMap = {
|
|
|
202
202
|
"image[]": "jsonb",
|
|
203
203
|
};
|
|
204
204
|
|
|
205
|
-
const objLeftQuoteChar = "
|
|
206
|
-
const objRightQuoteChar = "
|
|
205
|
+
const objLeftQuoteChar = '"';
|
|
206
|
+
const objRightQuoteChar = '"';
|
|
207
207
|
const relationalOperatorsMap = new Map([
|
|
208
208
|
["eq", "="],
|
|
209
209
|
["ne", "<>"],
|
|
@@ -250,6 +250,9 @@ class QueryBuilder {
|
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
+
formatValueToSqlLiteral(value) {
|
|
254
|
+
return formatValueToSqlLiteral(value);
|
|
255
|
+
}
|
|
253
256
|
select(model, options) {
|
|
254
257
|
const ctx = {
|
|
255
258
|
model,
|
|
@@ -369,7 +372,7 @@ class QueryBuilder {
|
|
|
369
372
|
paramToLiteral: false,
|
|
370
373
|
};
|
|
371
374
|
let { filters } = options;
|
|
372
|
-
let command =
|
|
375
|
+
let command = 'SELECT COUNT(*)::int as "count" FROM ';
|
|
373
376
|
command += this.quoteTable(model);
|
|
374
377
|
if (filters && filters.length) {
|
|
375
378
|
command += " WHERE ";
|
|
@@ -389,7 +392,7 @@ class QueryBuilder {
|
|
|
389
392
|
paramToLiteral: false,
|
|
390
393
|
};
|
|
391
394
|
let { filters } = options;
|
|
392
|
-
let command =
|
|
395
|
+
let command = 'SELECT COUNT(*)::int as "count" FROM ';
|
|
393
396
|
command += `${this.quoteTable(derivedModel)} LEFT JOIN ${this.quoteTable(baseModel)} ON ${this.quoteObject(derivedModel.tableName)}.id = ${this.quoteObject(baseModel.tableName)}.id`;
|
|
394
397
|
if (filters && filters.length) {
|
|
395
398
|
command += " WHERE ";
|
|
@@ -4638,7 +4641,7 @@ function listDataDictionaries(server) {
|
|
|
4638
4641
|
async function syncDatabaseSchema(server, applicationConfig) {
|
|
4639
4642
|
const logger = server.getLogger();
|
|
4640
4643
|
logger.info("Synchronizing database schema...");
|
|
4641
|
-
const sqlQueryTableInformations = `SELECT table_schema, table_name FROM information_schema.tables`;
|
|
4644
|
+
const sqlQueryTableInformations = `SELECT table_schema, table_name, obj_description((table_schema||'.'||quote_ident(table_name))::regclass) as table_description FROM information_schema.tables`;
|
|
4642
4645
|
const tablesInDb = await server.queryDatabaseObject(sqlQueryTableInformations);
|
|
4643
4646
|
const { queryBuilder } = server;
|
|
4644
4647
|
for (const model of applicationConfig.models) {
|
|
@@ -4649,9 +4652,14 @@ async function syncDatabaseSchema(server, applicationConfig) {
|
|
|
4649
4652
|
if (!tableInDb) {
|
|
4650
4653
|
await server.queryDatabaseObject(`CREATE TABLE IF NOT EXISTS ${queryBuilder.quoteTable(model)} ()`, []);
|
|
4651
4654
|
}
|
|
4655
|
+
if (!tableInDb || tableInDb.table_description != model.name) {
|
|
4656
|
+
await server.queryDatabaseObject(`COMMENT ON TABLE ${queryBuilder.quoteTable(model)} IS ${queryBuilder.formatValueToSqlLiteral(model.name)};`, []);
|
|
4657
|
+
}
|
|
4652
4658
|
}
|
|
4653
|
-
const sqlQueryColumnInformations = `SELECT table_schema, table_name, column_name, data_type,
|
|
4654
|
-
|
|
4659
|
+
const sqlQueryColumnInformations = `SELECT c.table_schema, c.table_name, c.column_name, c.ordinal_position, d.description, c.data_type, c.udt_name, c.is_nullable, c.column_default, c.character_maximum_length, c.numeric_precision, c.numeric_scale
|
|
4660
|
+
FROM information_schema.columns c
|
|
4661
|
+
INNER JOIN pg_catalog.pg_statio_all_tables st ON (st.schemaname = c.table_schema and st.relname = c.table_name)
|
|
4662
|
+
LEFT JOIN pg_catalog.pg_description d ON (d.objoid = st.relid and d.objsubid = c.ordinal_position);`;
|
|
4655
4663
|
const columnsInDb = await server.queryDatabaseObject(sqlQueryColumnInformations, []);
|
|
4656
4664
|
for (const model of applicationConfig.models) {
|
|
4657
4665
|
logger.debug(`Checking data columns for '${model.namespace}.${model.singularCode}'...`);
|
|
@@ -4678,6 +4686,9 @@ async function syncDatabaseSchema(server, applicationConfig) {
|
|
|
4678
4686
|
notNull: property.required,
|
|
4679
4687
|
});
|
|
4680
4688
|
}
|
|
4689
|
+
if (!columnInDb || columnInDb.description != property.name) {
|
|
4690
|
+
await server.queryDatabaseObject(`COMMENT ON COLUMN ${queryBuilder.quoteTable(model)}.${queryBuilder.quoteObject(property.targetIdColumnName)} IS ${queryBuilder.formatValueToSqlLiteral(property.name)};`, []);
|
|
4691
|
+
}
|
|
4681
4692
|
}
|
|
4682
4693
|
else if (property.relation === "many") {
|
|
4683
4694
|
if (property.linkTableName) {
|
|
@@ -4780,6 +4791,9 @@ async function syncDatabaseSchema(server, applicationConfig) {
|
|
|
4780
4791
|
}
|
|
4781
4792
|
}
|
|
4782
4793
|
}
|
|
4794
|
+
if (!columnInDb || columnInDb.description != property.name) {
|
|
4795
|
+
await server.queryDatabaseObject(`COMMENT ON COLUMN ${queryBuilder.quoteTable(model)}.${queryBuilder.quoteObject(property.columnName || property.code)} IS ${queryBuilder.formatValueToSqlLiteral(property.name)};`, []);
|
|
4796
|
+
}
|
|
4783
4797
|
}
|
|
4784
4798
|
}
|
|
4785
4799
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RpdDataModel, CreateEntityOptions, QuoteTableOptions, DatabaseQuery } from "../types";
|
|
1
|
+
import { RpdDataModel, CreateEntityOptions, QuoteTableOptions, DatabaseQuery, IQueryBuilder } from "../types";
|
|
2
2
|
import { CountRowOptions, DeleteRowOptions, FindRowOptions, RowFilterOptions, UpdateRowOptions, ColumnSelectOptions } from "../dataAccess/dataAccessTypes";
|
|
3
3
|
export interface BuildQueryContext {
|
|
4
4
|
model: RpdDataModel;
|
|
@@ -13,12 +13,13 @@ export interface BuildQueryContext {
|
|
|
13
13
|
export interface InitQueryBuilderOptions {
|
|
14
14
|
dbDefaultSchema: string;
|
|
15
15
|
}
|
|
16
|
-
export default class QueryBuilder {
|
|
16
|
+
export default class QueryBuilder implements IQueryBuilder {
|
|
17
17
|
#private;
|
|
18
18
|
constructor(options: InitQueryBuilderOptions);
|
|
19
19
|
quoteTable(options: QuoteTableOptions): string;
|
|
20
20
|
quoteObject(name: string): string;
|
|
21
21
|
quoteColumn(model: RpdDataModel, column: ColumnSelectOptions, emitTableAlias: boolean): string;
|
|
22
|
+
formatValueToSqlLiteral(value: any): string;
|
|
22
23
|
select(model: RpdDataModel, options: FindRowOptions): DatabaseQuery;
|
|
23
24
|
selectDerived(derivedModel: RpdDataModel, baseModel: RpdDataModel, options: FindRowOptions): DatabaseQuery;
|
|
24
25
|
count(model: RpdDataModel, options: CountRowOptions): DatabaseQuery;
|
package/dist/types.d.ts
CHANGED
|
@@ -154,6 +154,7 @@ export interface IQueryBuilder {
|
|
|
154
154
|
quoteTable: (options: QuoteTableOptions) => string;
|
|
155
155
|
quoteObject: (name: string) => string;
|
|
156
156
|
buildFiltersExpression(model: RpdDataModel, filters: RowFilterOptions[]): any;
|
|
157
|
+
formatValueToSqlLiteral: (value: any) => string;
|
|
157
158
|
}
|
|
158
159
|
export interface RpdApplicationConfig {
|
|
159
160
|
code?: string;
|
package/package.json
CHANGED
|
@@ -181,12 +181,15 @@ function listDataDictionaries(server: IRpdServer) {
|
|
|
181
181
|
type TableInformation = {
|
|
182
182
|
table_schema: string;
|
|
183
183
|
table_name: string;
|
|
184
|
+
table_description: string;
|
|
184
185
|
};
|
|
185
186
|
|
|
186
187
|
type ColumnInformation = {
|
|
187
188
|
table_schema: string;
|
|
188
189
|
table_name: string;
|
|
189
190
|
column_name: string;
|
|
191
|
+
ordinal_position: number;
|
|
192
|
+
description?: string;
|
|
190
193
|
data_type: string;
|
|
191
194
|
udt_name: string;
|
|
192
195
|
is_nullable: "YES" | "NO";
|
|
@@ -206,7 +209,7 @@ type ConstraintInformation = {
|
|
|
206
209
|
async function syncDatabaseSchema(server: IRpdServer, applicationConfig: RpdApplicationConfig) {
|
|
207
210
|
const logger = server.getLogger();
|
|
208
211
|
logger.info("Synchronizing database schema...");
|
|
209
|
-
const sqlQueryTableInformations = `SELECT table_schema, table_name FROM information_schema.tables`;
|
|
212
|
+
const sqlQueryTableInformations = `SELECT table_schema, table_name, obj_description((table_schema||'.'||quote_ident(table_name))::regclass) as table_description FROM information_schema.tables`;
|
|
210
213
|
const tablesInDb: TableInformation[] = await server.queryDatabaseObject(sqlQueryTableInformations);
|
|
211
214
|
const { queryBuilder } = server;
|
|
212
215
|
|
|
@@ -219,10 +222,15 @@ async function syncDatabaseSchema(server: IRpdServer, applicationConfig: RpdAppl
|
|
|
219
222
|
if (!tableInDb) {
|
|
220
223
|
await server.queryDatabaseObject(`CREATE TABLE IF NOT EXISTS ${queryBuilder.quoteTable(model)} ()`, []);
|
|
221
224
|
}
|
|
225
|
+
if (!tableInDb || tableInDb.table_description != model.name) {
|
|
226
|
+
await server.queryDatabaseObject(`COMMENT ON TABLE ${queryBuilder.quoteTable(model)} IS ${queryBuilder.formatValueToSqlLiteral(model.name)};`, []);
|
|
227
|
+
}
|
|
222
228
|
}
|
|
223
229
|
|
|
224
|
-
const sqlQueryColumnInformations = `SELECT table_schema, table_name, column_name, data_type,
|
|
225
|
-
|
|
230
|
+
const sqlQueryColumnInformations = `SELECT c.table_schema, c.table_name, c.column_name, c.ordinal_position, d.description, c.data_type, c.udt_name, c.is_nullable, c.column_default, c.character_maximum_length, c.numeric_precision, c.numeric_scale
|
|
231
|
+
FROM information_schema.columns c
|
|
232
|
+
INNER JOIN pg_catalog.pg_statio_all_tables st ON (st.schemaname = c.table_schema and st.relname = c.table_name)
|
|
233
|
+
LEFT JOIN pg_catalog.pg_description d ON (d.objoid = st.relid and d.objsubid = c.ordinal_position);`;
|
|
226
234
|
const columnsInDb: ColumnInformation[] = await server.queryDatabaseObject(sqlQueryColumnInformations, []);
|
|
227
235
|
|
|
228
236
|
for (const model of applicationConfig.models) {
|
|
@@ -253,6 +261,15 @@ async function syncDatabaseSchema(server: IRpdServer, applicationConfig: RpdAppl
|
|
|
253
261
|
notNull: property.required,
|
|
254
262
|
});
|
|
255
263
|
}
|
|
264
|
+
|
|
265
|
+
if (!columnInDb || columnInDb.description != property.name) {
|
|
266
|
+
await server.queryDatabaseObject(
|
|
267
|
+
`COMMENT ON COLUMN ${queryBuilder.quoteTable(model)}.${queryBuilder.quoteObject(
|
|
268
|
+
property.targetIdColumnName,
|
|
269
|
+
)} IS ${queryBuilder.formatValueToSqlLiteral(property.name)};`,
|
|
270
|
+
[],
|
|
271
|
+
);
|
|
272
|
+
}
|
|
256
273
|
} else if (property.relation === "many") {
|
|
257
274
|
if (property.linkTableName) {
|
|
258
275
|
const tableInDb = find(tablesInDb, {
|
|
@@ -359,6 +376,15 @@ async function syncDatabaseSchema(server: IRpdServer, applicationConfig: RpdAppl
|
|
|
359
376
|
}
|
|
360
377
|
}
|
|
361
378
|
}
|
|
379
|
+
|
|
380
|
+
if (!columnInDb || columnInDb.description != property.name) {
|
|
381
|
+
await server.queryDatabaseObject(
|
|
382
|
+
`COMMENT ON COLUMN ${queryBuilder.quoteTable(model)}.${queryBuilder.quoteObject(
|
|
383
|
+
property.columnName || property.code,
|
|
384
|
+
)} IS ${queryBuilder.formatValueToSqlLiteral(property.name)};`,
|
|
385
|
+
[],
|
|
386
|
+
);
|
|
387
|
+
}
|
|
362
388
|
}
|
|
363
389
|
}
|
|
364
390
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { find, isBoolean, isNull, isNumber, isString, isUndefined } from "lodash";
|
|
2
|
-
import { RpdDataModel, RpdDataModelProperty, CreateEntityOptions, QuoteTableOptions, DatabaseQuery } from "../types";
|
|
2
|
+
import { RpdDataModel, RpdDataModelProperty, CreateEntityOptions, QuoteTableOptions, DatabaseQuery, IQueryBuilder } from "../types";
|
|
3
3
|
import {
|
|
4
4
|
CountRowOptions,
|
|
5
5
|
DeleteRowOptions,
|
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
} from "~/dataAccess/dataAccessTypes";
|
|
20
20
|
import { pgPropertyTypeColumnMap } from "~/dataAccess/columnTypeMapper";
|
|
21
21
|
|
|
22
|
-
const objLeftQuoteChar = "
|
|
23
|
-
const objRightQuoteChar = "
|
|
22
|
+
const objLeftQuoteChar = '"';
|
|
23
|
+
const objRightQuoteChar = '"';
|
|
24
24
|
|
|
25
25
|
const relationalOperatorsMap = new Map<RowFilterRelationalOperators, string>([
|
|
26
26
|
["eq", "="],
|
|
@@ -46,7 +46,7 @@ export interface InitQueryBuilderOptions {
|
|
|
46
46
|
dbDefaultSchema: string;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export default class QueryBuilder {
|
|
49
|
+
export default class QueryBuilder implements IQueryBuilder {
|
|
50
50
|
#dbDefaultSchema: string;
|
|
51
51
|
|
|
52
52
|
constructor(options: InitQueryBuilderOptions) {
|
|
@@ -84,6 +84,10 @@ export default class QueryBuilder {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
formatValueToSqlLiteral(value: any) {
|
|
88
|
+
return formatValueToSqlLiteral(value);
|
|
89
|
+
}
|
|
90
|
+
|
|
87
91
|
select(model: RpdDataModel, options: FindRowOptions): DatabaseQuery {
|
|
88
92
|
const ctx: BuildQueryContext = {
|
|
89
93
|
model,
|
|
@@ -223,7 +227,7 @@ export default class QueryBuilder {
|
|
|
223
227
|
paramToLiteral: false,
|
|
224
228
|
};
|
|
225
229
|
let { filters } = options;
|
|
226
|
-
let command =
|
|
230
|
+
let command = 'SELECT COUNT(*)::int as "count" FROM ';
|
|
227
231
|
|
|
228
232
|
command += this.quoteTable(model);
|
|
229
233
|
|
|
@@ -247,7 +251,7 @@ export default class QueryBuilder {
|
|
|
247
251
|
paramToLiteral: false,
|
|
248
252
|
};
|
|
249
253
|
let { filters } = options;
|
|
250
|
-
let command =
|
|
254
|
+
let command = 'SELECT COUNT(*)::int as "count" FROM ';
|
|
251
255
|
|
|
252
256
|
command += `${this.quoteTable(derivedModel)} LEFT JOIN ${this.quoteTable(baseModel)} ON ${this.quoteObject(derivedModel.tableName)}.id = ${this.quoteObject(
|
|
253
257
|
baseModel.tableName,
|
|
@@ -498,11 +502,10 @@ function buildRangeFilterQuery(ctx: BuildQueryContext, filter: FindRowRangeFilte
|
|
|
498
502
|
ctx.params.push(filter.value[0]);
|
|
499
503
|
command += `$${ctx.params.length}`;
|
|
500
504
|
|
|
501
|
-
command += " AND "
|
|
505
|
+
command += " AND ";
|
|
502
506
|
|
|
503
507
|
ctx.params.push(filter.value[1]);
|
|
504
508
|
command += `$${ctx.params.length}`;
|
|
505
|
-
|
|
506
509
|
} else {
|
|
507
510
|
throw new Error(`Filter operator '${filter.operator}' is not supported.`);
|
|
508
511
|
}
|
package/src/types.ts
CHANGED
|
@@ -179,6 +179,7 @@ export interface IQueryBuilder {
|
|
|
179
179
|
quoteTable: (options: QuoteTableOptions) => string;
|
|
180
180
|
quoteObject: (name: string) => string;
|
|
181
181
|
buildFiltersExpression(model: RpdDataModel, filters: RowFilterOptions[]);
|
|
182
|
+
formatValueToSqlLiteral: (value: any) => string;
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
export interface RpdApplicationConfig {
|