af-db-ts 2.0.19 → 2.0.73
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/cjs/__tests__/db/ms/@gen-types/test-table_schema.js +3 -0
- package/dist/cjs/__tests__/db/ms/@gen-types/test-table_schema.js.map +1 -0
- package/dist/cjs/__tests__/db/ms/ddl/column-schema-for-test-table-schema-ms.json +216 -0
- package/dist/cjs/__tests__/db/ms/ms-get-sql.spec.js +190 -0
- package/dist/cjs/__tests__/db/ms/ms-get-sql.spec.js.map +1 -0
- package/dist/cjs/__tests__/db/ms/ms-prepare-sql-value.spec.js +584 -0
- package/dist/cjs/__tests__/db/ms/ms-prepare-sql-value.spec.js.map +1 -0
- package/dist/cjs/__tests__/db/ms/ms-table-schema.spec.js +107 -0
- package/dist/cjs/__tests__/db/ms/ms-table-schema.spec.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-hard_case.js +3 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-hard_case.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-only_one_serial.js +3 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-only_one_serial.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-only_one_uniq.js +3 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-only_one_uniq.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-serial_and_uniq.js +3 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-serial_and_uniq.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-table_schema.js +3 -0
- package/dist/cjs/__tests__/db/pg/@gen-types/test-table_schema.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/ddl/column-schema-for-test-table-schema-pg.json +170 -0
- package/dist/cjs/__tests__/db/pg/gen-table-interfaces-4-test-pg.js +36 -0
- package/dist/cjs/__tests__/db/pg/gen-table-interfaces-4-test-pg.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/pg-get-sql.spec.js +261 -0
- package/dist/cjs/__tests__/db/pg/pg-get-sql.spec.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/pg-insert.spec.js +294 -0
- package/dist/cjs/__tests__/db/pg/pg-insert.spec.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/pg-prepare-sql-value.spec.js +575 -0
- package/dist/cjs/__tests__/db/pg/pg-prepare-sql-value.spec.js.map +1 -0
- package/dist/cjs/__tests__/db/pg/pg-table-schema.spec.js +117 -0
- package/dist/cjs/__tests__/db/pg/pg-table-schema.spec.js.map +1 -0
- package/dist/cjs/src/@types/i-data-types-ms.js +3 -0
- package/dist/cjs/src/@types/i-data-types-ms.js.map +1 -0
- package/dist/cjs/src/@types/i-data-types-pg.js +7 -0
- package/dist/cjs/src/@types/i-data-types-pg.js.map +1 -0
- package/dist/cjs/src/@types/i-pg.js +0 -21
- package/dist/cjs/src/@types/i-pg.js.map +1 -1
- package/dist/cjs/src/common.js +6 -5
- package/dist/cjs/src/common.js.map +1 -1
- package/dist/cjs/src/index.js +75 -54
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/ms/gen-table-interfaces-ms.js +64 -0
- package/dist/cjs/src/ms/gen-table-interfaces-ms.js.map +1 -0
- package/dist/cjs/src/ms/get-sql/insert.js +37 -0
- package/dist/cjs/src/ms/get-sql/insert.js.map +1 -0
- package/dist/cjs/src/ms/get-sql/merge.js +93 -0
- package/dist/cjs/src/ms/get-sql/merge.js.map +1 -0
- package/dist/cjs/src/ms/get-sql/update.js +32 -0
- package/dist/cjs/src/ms/get-sql/update.js.map +1 -0
- package/dist/cjs/src/{mssql → ms}/pool-ms.js +6 -23
- package/dist/cjs/src/ms/pool-ms.js.map +1 -0
- package/dist/cjs/src/ms/prepare-value.js +178 -0
- package/dist/cjs/src/ms/prepare-value.js.map +1 -0
- package/dist/cjs/src/{mssql → ms}/query-ms.js +1 -1
- package/dist/cjs/src/ms/query-ms.js.map +1 -0
- package/dist/cjs/src/ms/table-schema-ms.js +241 -0
- package/dist/cjs/src/ms/table-schema-ms.js.map +1 -0
- package/dist/cjs/src/ms/utils-ms.js +92 -0
- package/dist/cjs/src/ms/utils-ms.js.map +1 -0
- package/dist/cjs/src/ms/wrap-transaction-ms.js +32 -0
- package/dist/cjs/src/ms/wrap-transaction-ms.js.map +1 -0
- package/dist/cjs/src/pg/gen-table-interfaces-pg.js +83 -0
- package/dist/cjs/src/pg/gen-table-interfaces-pg.js.map +1 -0
- package/dist/cjs/src/pg/get-sql/insert.js +38 -0
- package/dist/cjs/src/pg/get-sql/insert.js.map +1 -0
- package/dist/cjs/src/pg/get-sql/merge.js +60 -0
- package/dist/cjs/src/pg/get-sql/merge.js.map +1 -0
- package/dist/cjs/src/pg/get-sql/update.js +32 -0
- package/dist/cjs/src/pg/get-sql/update.js.map +1 -0
- package/dist/cjs/src/pg/{insert.js → insert-pg.js} +10 -10
- package/dist/cjs/src/pg/insert-pg.js.map +1 -0
- package/dist/cjs/src/pg/is-table-or-view-exists.js +1 -2
- package/dist/cjs/src/pg/is-table-or-view-exists.js.map +1 -1
- package/dist/cjs/src/pg/{pg-pool.js → pool-pg.js} +6 -7
- package/dist/cjs/src/pg/pool-pg.js.map +1 -0
- package/dist/cjs/src/pg/prepare-value.js +116 -69
- package/dist/cjs/src/pg/prepare-value.js.map +1 -1
- package/dist/cjs/src/pg/query-pg.js +2 -2
- package/dist/cjs/src/pg/query-pg.js.map +1 -1
- package/dist/cjs/src/pg/table-schema-pg.js +183 -0
- package/dist/cjs/src/pg/table-schema-pg.js.map +1 -0
- package/dist/cjs/src/pg/utils-pg.js +99 -0
- package/dist/cjs/src/pg/utils-pg.js.map +1 -0
- package/dist/cjs/src/utils/utils-array.js +152 -0
- package/dist/cjs/src/utils/utils-array.js.map +1 -0
- package/dist/cjs/src/utils/utils-dt.js +121 -0
- package/dist/cjs/src/utils/utils-dt.js.map +1 -0
- package/dist/cjs/src/utils/utils-num.js +127 -0
- package/dist/cjs/src/utils/utils-num.js.map +1 -0
- package/dist/cjs/src/utils/utils.js +66 -0
- package/dist/cjs/src/utils/utils.js.map +1 -0
- package/dist/esm/src/@types/i-data-types-ms.js +2 -0
- package/dist/esm/src/@types/i-data-types-ms.js.map +1 -0
- package/dist/esm/src/@types/i-data-types-pg.js +6 -0
- package/dist/esm/src/@types/i-data-types-pg.js.map +1 -0
- package/dist/esm/src/@types/i-pg.js +1 -20
- package/dist/esm/src/@types/i-pg.js.map +1 -1
- package/dist/esm/src/common.js +3 -2
- package/dist/esm/src/common.js.map +1 -1
- package/dist/esm/src/index.js +24 -15
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/ms/gen-table-interfaces-ms.js +36 -0
- package/dist/esm/src/ms/gen-table-interfaces-ms.js.map +1 -0
- package/dist/esm/src/ms/get-sql/insert.js +33 -0
- package/dist/esm/src/ms/get-sql/insert.js.map +1 -0
- package/dist/esm/src/ms/get-sql/merge.js +89 -0
- package/dist/esm/src/ms/get-sql/merge.js.map +1 -0
- package/dist/esm/src/ms/get-sql/update.js +28 -0
- package/dist/esm/src/ms/get-sql/update.js.map +1 -0
- package/dist/esm/src/{mssql → ms}/pool-ms.js +5 -20
- package/dist/esm/src/ms/pool-ms.js.map +1 -0
- package/dist/esm/src/ms/prepare-value.js +149 -0
- package/dist/esm/src/ms/prepare-value.js.map +1 -0
- package/dist/esm/src/{mssql → ms}/query-ms.js +1 -1
- package/dist/esm/src/ms/query-ms.js.map +1 -0
- package/dist/esm/src/ms/table-schema-ms.js +213 -0
- package/dist/esm/src/ms/table-schema-ms.js.map +1 -0
- package/dist/esm/src/ms/utils-ms.js +65 -0
- package/dist/esm/src/ms/utils-ms.js.map +1 -0
- package/dist/esm/src/ms/wrap-transaction-ms.js +28 -0
- package/dist/esm/src/ms/wrap-transaction-ms.js.map +1 -0
- package/dist/esm/src/pg/gen-table-interfaces-pg.js +55 -0
- package/dist/esm/src/pg/gen-table-interfaces-pg.js.map +1 -0
- package/dist/esm/src/pg/get-sql/insert.js +34 -0
- package/dist/esm/src/pg/get-sql/insert.js.map +1 -0
- package/dist/esm/src/pg/get-sql/merge.js +56 -0
- package/dist/esm/src/pg/get-sql/merge.js.map +1 -0
- package/dist/esm/src/pg/get-sql/update.js +28 -0
- package/dist/esm/src/pg/get-sql/update.js.map +1 -0
- package/dist/esm/src/pg/{insert.js → insert-pg.js} +10 -10
- package/dist/esm/src/pg/insert-pg.js.map +1 -0
- package/dist/esm/src/pg/is-table-or-view-exists.js +1 -2
- package/dist/esm/src/pg/is-table-or-view-exists.js.map +1 -1
- package/dist/esm/src/pg/{pg-pool.js → pool-pg.js} +6 -7
- package/dist/esm/src/pg/pool-pg.js.map +1 -0
- package/dist/esm/src/pg/prepare-value.js +113 -67
- package/dist/esm/src/pg/prepare-value.js.map +1 -1
- package/dist/esm/src/pg/query-pg.js +1 -1
- package/dist/esm/src/pg/query-pg.js.map +1 -1
- package/dist/esm/src/pg/table-schema-pg.js +178 -0
- package/dist/esm/src/pg/table-schema-pg.js.map +1 -0
- package/dist/esm/src/pg/utils-pg.js +93 -0
- package/dist/esm/src/pg/utils-pg.js.map +1 -0
- package/dist/esm/src/utils/utils-array.js +125 -0
- package/dist/esm/src/utils/utils-array.js.map +1 -0
- package/dist/esm/src/utils/utils-dt.js +114 -0
- package/dist/esm/src/utils/utils-dt.js.map +1 -0
- package/dist/esm/src/utils/utils-num.js +117 -0
- package/dist/esm/src/utils/utils-num.js.map +1 -0
- package/dist/esm/src/utils/utils.js +58 -0
- package/dist/esm/src/utils/utils.js.map +1 -0
- package/dist/types/src/@types/i-common.d.ts +35 -3
- package/dist/types/src/@types/i-common.d.ts.map +1 -1
- package/dist/types/src/@types/i-data-types-ms.d.ts +3 -0
- package/dist/types/src/@types/i-data-types-ms.d.ts.map +1 -0
- package/dist/types/src/@types/i-data-types-pg.d.ts +35 -0
- package/dist/types/src/@types/i-data-types-pg.d.ts.map +1 -0
- package/dist/types/src/@types/i-ms.d.ts +26 -126
- package/dist/types/src/@types/i-ms.d.ts.map +1 -1
- package/dist/types/src/@types/i-pg.d.ts +11 -35
- package/dist/types/src/@types/i-pg.d.ts.map +1 -1
- package/dist/types/src/common.d.ts +1 -0
- package/dist/types/src/common.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +28 -16
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/ms/gen-table-interfaces-ms.d.ts +3 -0
- package/dist/types/src/ms/gen-table-interfaces-ms.d.ts.map +1 -0
- package/dist/types/src/ms/get-sql/insert.d.ts +9 -0
- package/dist/types/src/ms/get-sql/insert.d.ts.map +1 -0
- package/dist/types/src/ms/get-sql/merge.d.ts +14 -0
- package/dist/types/src/ms/get-sql/merge.d.ts.map +1 -0
- package/dist/types/src/ms/get-sql/update.d.ts +9 -0
- package/dist/types/src/ms/get-sql/update.d.ts.map +1 -0
- package/dist/types/src/{mssql → ms}/pool-ms.d.ts +0 -8
- package/dist/types/src/ms/pool-ms.d.ts.map +1 -0
- package/dist/types/src/ms/prepare-value.d.ts +12 -0
- package/dist/types/src/ms/prepare-value.d.ts.map +1 -0
- package/dist/types/src/ms/query-ms.d.ts +3 -0
- package/dist/types/src/ms/query-ms.d.ts.map +1 -0
- package/dist/types/src/ms/table-schema-ms.d.ts +9 -0
- package/dist/types/src/ms/table-schema-ms.d.ts.map +1 -0
- package/dist/types/src/ms/utils-ms.d.ts +3 -0
- package/dist/types/src/ms/utils-ms.d.ts.map +1 -0
- package/dist/types/src/ms/wrap-transaction-ms.d.ts +5 -0
- package/dist/types/src/ms/wrap-transaction-ms.d.ts.map +1 -0
- package/dist/types/src/pg/gen-table-interfaces-pg.d.ts +3 -0
- package/dist/types/src/pg/gen-table-interfaces-pg.d.ts.map +1 -0
- package/dist/types/src/pg/get-sql/insert.d.ts +9 -0
- package/dist/types/src/pg/get-sql/insert.d.ts.map +1 -0
- package/dist/types/src/pg/get-sql/merge.d.ts +10 -0
- package/dist/types/src/pg/get-sql/merge.d.ts.map +1 -0
- package/dist/types/src/pg/get-sql/update.d.ts +9 -0
- package/dist/types/src/pg/get-sql/update.d.ts.map +1 -0
- package/dist/types/src/pg/{insert.d.ts → insert-pg.d.ts} +3 -3
- package/dist/types/src/pg/insert-pg.d.ts.map +1 -0
- package/dist/types/src/pg/{pg-pool.d.ts → pool-pg.d.ts} +1 -1
- package/dist/types/src/pg/{pg-pool.d.ts.map → pool-pg.d.ts.map} +1 -1
- package/dist/types/src/pg/prepare-value.d.ts +3 -1
- package/dist/types/src/pg/prepare-value.d.ts.map +1 -1
- package/dist/types/src/pg/query-pg.d.ts +3 -2
- package/dist/types/src/pg/query-pg.d.ts.map +1 -1
- package/dist/types/src/pg/table-schema-pg.d.ts +12 -0
- package/dist/types/src/pg/table-schema-pg.d.ts.map +1 -0
- package/dist/types/src/pg/utils-pg.d.ts +5 -0
- package/dist/types/src/pg/utils-pg.d.ts.map +1 -0
- package/dist/types/src/utils/utils-array.d.ts +5 -0
- package/dist/types/src/utils/utils-array.d.ts.map +1 -0
- package/dist/types/src/utils/utils-dt.d.ts +15 -0
- package/dist/types/src/utils/utils-dt.d.ts.map +1 -0
- package/dist/types/src/utils/utils-num.d.ts +9 -0
- package/dist/types/src/utils/utils-num.d.ts.map +1 -0
- package/dist/types/src/utils/utils.d.ts +18 -0
- package/dist/types/src/utils/utils.d.ts.map +1 -0
- package/package.json +13 -13
- package/src/@types/i-common.ts +42 -4
- package/src/@types/i-data-types-ms.ts +81 -0
- package/src/@types/i-data-types-pg.ts +120 -0
- package/src/@types/i-ms.ts +29 -153
- package/src/@types/i-pg.ts +11 -36
- package/src/common.ts +4 -2
- package/src/index.ts +101 -59
- package/src/ms/gen-table-interfaces-ms.ts +52 -0
- package/src/ms/get-sql/insert.ts +45 -0
- package/src/ms/get-sql/merge.ts +118 -0
- package/src/ms/get-sql/update.ts +46 -0
- package/src/{mssql → ms}/pool-ms.ts +0 -16
- package/src/ms/prepare-value.ts +175 -0
- package/src/{mssql → ms}/query-ms.ts +2 -2
- package/src/ms/table-schema-ms.ts +231 -0
- package/src/ms/utils-ms.ts +72 -0
- package/src/ms/wrap-transaction-ms.ts +27 -0
- package/src/pg/gen-table-interfaces-pg.ts +74 -0
- package/src/pg/get-sql/insert.ts +46 -0
- package/src/pg/get-sql/merge.ts +70 -0
- package/src/pg/get-sql/update.ts +46 -0
- package/src/pg/{insert.ts → insert-pg.ts} +9 -9
- package/src/pg/prepare-value.ts +129 -67
- package/src/pg/query-pg.ts +4 -3
- package/src/pg/table-schema-pg.ts +196 -0
- package/src/pg/utils-pg.ts +97 -0
- package/src/utils/utils-array.ts +133 -0
- package/src/utils/utils-dt.ts +123 -0
- package/src/utils/utils-num.ts +131 -0
- package/src/utils/utils.ts +64 -0
- package/dist/cjs/__tests__/02_getValueForSqlMs.spec.js +0 -50
- package/dist/cjs/__tests__/02_getValueForSqlMs.spec.js.map +0 -1
- package/dist/cjs/src/mssql/get-value-for-sql.js +0 -277
- package/dist/cjs/src/mssql/get-value-for-sql.js.map +0 -1
- package/dist/cjs/src/mssql/pool-ms.js.map +0 -1
- package/dist/cjs/src/mssql/query-ms.js.map +0 -1
- package/dist/cjs/src/mssql/sql.js +0 -427
- package/dist/cjs/src/mssql/sql.js.map +0 -1
- package/dist/cjs/src/mssql/utils.js +0 -36
- package/dist/cjs/src/mssql/utils.js.map +0 -1
- package/dist/cjs/src/pg/get-merge-sql.js +0 -52
- package/dist/cjs/src/pg/get-merge-sql.js.map +0 -1
- package/dist/cjs/src/pg/get-update-sql.js +0 -30
- package/dist/cjs/src/pg/get-update-sql.js.map +0 -1
- package/dist/cjs/src/pg/insert.js.map +0 -1
- package/dist/cjs/src/pg/pg-pool.js.map +0 -1
- package/dist/cjs/src/pg/table-schema.js +0 -179
- package/dist/cjs/src/pg/table-schema.js.map +0 -1
- package/dist/cjs/src/utils.js +0 -17
- package/dist/cjs/src/utils.js.map +0 -1
- package/dist/esm/src/mssql/get-value-for-sql.js +0 -272
- package/dist/esm/src/mssql/get-value-for-sql.js.map +0 -1
- package/dist/esm/src/mssql/pool-ms.js.map +0 -1
- package/dist/esm/src/mssql/query-ms.js.map +0 -1
- package/dist/esm/src/mssql/sql.js +0 -390
- package/dist/esm/src/mssql/sql.js.map +0 -1
- package/dist/esm/src/mssql/utils.js +0 -31
- package/dist/esm/src/mssql/utils.js.map +0 -1
- package/dist/esm/src/pg/get-merge-sql.js +0 -48
- package/dist/esm/src/pg/get-merge-sql.js.map +0 -1
- package/dist/esm/src/pg/get-update-sql.js +0 -26
- package/dist/esm/src/pg/get-update-sql.js.map +0 -1
- package/dist/esm/src/pg/insert.js.map +0 -1
- package/dist/esm/src/pg/pg-pool.js.map +0 -1
- package/dist/esm/src/pg/table-schema.js +0 -174
- package/dist/esm/src/pg/table-schema.js.map +0 -1
- package/dist/esm/src/utils.js +0 -14
- package/dist/esm/src/utils.js.map +0 -1
- package/dist/types/src/mssql/get-value-for-sql.d.ts +0 -11
- package/dist/types/src/mssql/get-value-for-sql.d.ts.map +0 -1
- package/dist/types/src/mssql/pool-ms.d.ts.map +0 -1
- package/dist/types/src/mssql/query-ms.d.ts +0 -3
- package/dist/types/src/mssql/query-ms.d.ts.map +0 -1
- package/dist/types/src/mssql/sql.d.ts +0 -57
- package/dist/types/src/mssql/sql.d.ts.map +0 -1
- package/dist/types/src/mssql/utils.d.ts +0 -10
- package/dist/types/src/mssql/utils.d.ts.map +0 -1
- package/dist/types/src/pg/get-merge-sql.d.ts +0 -9
- package/dist/types/src/pg/get-merge-sql.d.ts.map +0 -1
- package/dist/types/src/pg/get-update-sql.d.ts +0 -3
- package/dist/types/src/pg/get-update-sql.d.ts.map +0 -1
- package/dist/types/src/pg/insert.d.ts.map +0 -1
- package/dist/types/src/pg/table-schema.d.ts +0 -12
- package/dist/types/src/pg/table-schema.d.ts.map +0 -1
- package/dist/types/src/utils.d.ts +0 -9
- package/dist/types/src/utils.d.ts.map +0 -1
- package/src/mssql/get-value-for-sql.ts +0 -325
- package/src/mssql/sql.ts +0 -430
- package/src/mssql/utils.ts +0 -31
- package/src/pg/get-merge-sql.ts +0 -62
- package/src/pg/get-update-sql.ts +0 -32
- package/src/pg/table-schema.ts +0 -189
- package/src/utils.ts +0 -14
- /package/src/pg/{pg-pool.ts → pool-pg.ts} +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { getTableSchemaPg } from '../table-schema-pg';
|
|
2
|
+
import { prepareSqlValuePg } from '../prepare-value';
|
|
3
|
+
import { ITableSchemaPg } from '../../@types/i-pg';
|
|
4
|
+
import { schemaTable } from '../../utils/utils';
|
|
5
|
+
import { TDBRecord, TRecordSet } from '../../@types/i-common';
|
|
6
|
+
|
|
7
|
+
export const getMergeSqlPg = async <U extends TDBRecord = TDBRecord> (arg: {
|
|
8
|
+
connectionId: string,
|
|
9
|
+
commonSchemaAndTable: string,
|
|
10
|
+
recordset: TRecordSet<U>,
|
|
11
|
+
omitFields?: string[],
|
|
12
|
+
noUpdateIfNull?: boolean,
|
|
13
|
+
mergeCorrection?: (_sql: string) => string,
|
|
14
|
+
}): Promise<string> => {
|
|
15
|
+
const { connectionId, commonSchemaAndTable, recordset, omitFields = [], noUpdateIfNull } = arg;
|
|
16
|
+
if (!recordset?.length) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
const schemaTableStr = schemaTable.to.pg(commonSchemaAndTable);
|
|
20
|
+
const tableSchema: ITableSchemaPg = await getTableSchemaPg(connectionId, commonSchemaAndTable);
|
|
21
|
+
const { columnsSchema, pk, fieldsWoSerialsAndRO, defaults } = tableSchema;
|
|
22
|
+
|
|
23
|
+
let mergeFieldsArr: string[] = fieldsWoSerialsAndRO;
|
|
24
|
+
if (omitFields.length) {
|
|
25
|
+
const set = new Set(omitFields);
|
|
26
|
+
mergeFieldsArr = fieldsWoSerialsAndRO.filter((fieldName) => !set.has(fieldName));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const mergeValues = recordset.map((record: U) => {
|
|
30
|
+
const preparedValues: (string | number)[] = [];
|
|
31
|
+
|
|
32
|
+
mergeFieldsArr.forEach((f) => {
|
|
33
|
+
const value = record[f];
|
|
34
|
+
let sqlValue = prepareSqlValuePg({ value, fieldDef: columnsSchema[f] });
|
|
35
|
+
if (defaults[f] != null && (sqlValue == null || sqlValue === 'null')) {
|
|
36
|
+
sqlValue = defaults[f];
|
|
37
|
+
}
|
|
38
|
+
preparedValues.push(sqlValue);
|
|
39
|
+
});
|
|
40
|
+
return `(${preparedValues.join(', ')})`;
|
|
41
|
+
}).join(',\n ').trim();
|
|
42
|
+
|
|
43
|
+
const updateSetStr = mergeFieldsArr.map((f) => {
|
|
44
|
+
const vArr = [`EXCLUDED."${f}"`];
|
|
45
|
+
if (noUpdateIfNull) {
|
|
46
|
+
vArr.push(`${schemaTableStr}."${f}"`);
|
|
47
|
+
}
|
|
48
|
+
if (defaults[f]) {
|
|
49
|
+
vArr.push(defaults[f]);
|
|
50
|
+
}
|
|
51
|
+
return `"${f}" = ${vArr.length > 1 ? `COALESCE(${vArr.join(', ')})` : vArr[0]}`;
|
|
52
|
+
}).join(',\n ');
|
|
53
|
+
|
|
54
|
+
const mergeFieldsList = mergeFieldsArr.map((f) => `"${f}"`).join(',\n ');
|
|
55
|
+
// noinspection UnnecessaryLocalVariableJS
|
|
56
|
+
let mergeSQL = `--
|
|
57
|
+
INSERT INTO ${schemaTableStr} (
|
|
58
|
+
${mergeFieldsList}
|
|
59
|
+
)
|
|
60
|
+
VALUES
|
|
61
|
+
${mergeValues}
|
|
62
|
+
ON CONFLICT (${pk.map((f) => `"${f}"`).join(', ')})
|
|
63
|
+
DO UPDATE SET
|
|
64
|
+
${updateSetStr}
|
|
65
|
+
;`;
|
|
66
|
+
if (typeof arg.mergeCorrection === 'function') {
|
|
67
|
+
mergeSQL = arg.mergeCorrection(mergeSQL);
|
|
68
|
+
}
|
|
69
|
+
return mergeSQL;
|
|
70
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getTableSchemaPg } from '../table-schema-pg';
|
|
2
|
+
import { prepareSqlValuePg } from '../prepare-value';
|
|
3
|
+
import { ITableSchemaPg } from '../../@types/i-pg';
|
|
4
|
+
import { TDBRecord } from '../../@types/i-common';
|
|
5
|
+
import { schemaTable } from '../../utils/utils';
|
|
6
|
+
|
|
7
|
+
export const getUpdateSqlPg = async <U extends TDBRecord = TDBRecord>(arg: {
|
|
8
|
+
connectionId: string,
|
|
9
|
+
commonSchemaAndTable: string,
|
|
10
|
+
record: U,
|
|
11
|
+
customSets: TDBRecord,
|
|
12
|
+
updateIdentity?: string[],
|
|
13
|
+
}): Promise<string> => {
|
|
14
|
+
const {
|
|
15
|
+
connectionId,
|
|
16
|
+
commonSchemaAndTable,
|
|
17
|
+
record,
|
|
18
|
+
customSets = {},
|
|
19
|
+
} = arg;
|
|
20
|
+
const tableSchema: ITableSchemaPg = await getTableSchemaPg(connectionId, commonSchemaAndTable);
|
|
21
|
+
const { columnsSchema, pk, fieldsWoSerialsAndRO } = tableSchema;
|
|
22
|
+
|
|
23
|
+
const { updateIdentity = pk } = arg;
|
|
24
|
+
|
|
25
|
+
const updateFields = fieldsWoSerialsAndRO.filter((f) => (!updateIdentity.includes(f)));
|
|
26
|
+
|
|
27
|
+
const getPreparedSqlValue = (f: string) => prepareSqlValuePg({ value: record[f], fieldDef: columnsSchema[f] });
|
|
28
|
+
|
|
29
|
+
const preparedRecord: TDBRecord = {};
|
|
30
|
+
updateFields.forEach((f) => {
|
|
31
|
+
if (customSets[f] !== undefined) {
|
|
32
|
+
preparedRecord[f] = customSets[f];
|
|
33
|
+
} else if (record[f] !== undefined) {
|
|
34
|
+
preparedRecord[f] = getPreparedSqlValue(f);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const sets = Object.entries(preparedRecord).map(([f, v]) => `"${f}" = ${v}`).join(', ');
|
|
38
|
+
|
|
39
|
+
const where = updateIdentity.map((f) => `"${f}" = ${getPreparedSqlValue(f)}`).join(' AND ');
|
|
40
|
+
|
|
41
|
+
// noinspection UnnecessaryLocalVariableJS
|
|
42
|
+
const updateSql = `${'UPDATE'} ${schemaTable.to.pg(commonSchemaAndTable)} SET
|
|
43
|
+
${sets}
|
|
44
|
+
WHERE ${where};`;
|
|
45
|
+
return updateSql;
|
|
46
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// noinspection SqlResolve
|
|
2
|
-
import { QueryResultRow } from 'pg';
|
|
3
2
|
import { omitBy } from 'af-tools-ts';
|
|
4
|
-
import { getFieldsAndValuesPg, getTableSchemaPg } from './table-schema';
|
|
3
|
+
import { getFieldsAndValuesPg, getTableSchemaPg } from './table-schema-pg';
|
|
5
4
|
import { queryPg } from './query-pg';
|
|
6
5
|
import { logger } from '../logger-error';
|
|
6
|
+
import { TDBRecord } from '../@types/i-common';
|
|
7
7
|
|
|
8
8
|
export enum EUpdateLevel {
|
|
9
9
|
NEVER_UPDATE,
|
|
@@ -11,9 +11,9 @@ export enum EUpdateLevel {
|
|
|
11
11
|
UPDATE_ALWAYS
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const hasAllValues = <T extends
|
|
14
|
+
const hasAllValues = <T extends TDBRecord> (fieldList: string[] | undefined, record: T) => fieldList?.length && fieldList.every((f) => record[f] !== undefined);
|
|
15
15
|
|
|
16
|
-
const selectByAnyIdentity = async <T extends
|
|
16
|
+
const selectByAnyIdentity = async <T extends TDBRecord, R extends TDBRecord = T> (
|
|
17
17
|
connectionId: string,
|
|
18
18
|
identities: string[][],
|
|
19
19
|
record: T,
|
|
@@ -40,7 +40,7 @@ const selectByAnyIdentity = async <T extends QueryResultRow, R extends QueryResu
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
export const insertPg = async <T extends
|
|
43
|
+
export const insertPg = async <T extends TDBRecord, R extends TDBRecord = T> (
|
|
44
44
|
{
|
|
45
45
|
connectionId,
|
|
46
46
|
record,
|
|
@@ -57,13 +57,13 @@ export const insertPg = async <T extends QueryResultRow, R extends QueryResultRo
|
|
|
57
57
|
updateLevel?: EUpdateLevel, // Flag: Update entry when unique constraints conflict.
|
|
58
58
|
},
|
|
59
59
|
): Promise<R | undefined> => {
|
|
60
|
-
const {
|
|
60
|
+
const { columnsSchema, pk = [], serialsFields = [], uc = [] } = await getTableSchemaPg(connectionId, target);
|
|
61
61
|
// Cleaning the record: deleting properties not included in the set of fields, with the value undefined and auto-incrementing fields
|
|
62
|
-
const recordWoSerials: T = omitBy(record, (fieldValue: any, fieldName: string) => !
|
|
62
|
+
const recordWoSerials: T = omitBy(record, (fieldValue: any, fieldName: string) => !columnsSchema[fieldName] || fieldValue === undefined || serialsFields.includes(fieldName)) as T;
|
|
63
63
|
|
|
64
64
|
// We form all possible sets of fields, which we then use to search for an added (or already existing) record
|
|
65
65
|
// Normalize (sort) sets
|
|
66
|
-
let identities: string[][] = [pk, ...
|
|
66
|
+
let identities: string[][] = [pk, ...serialsFields.map((f) => [f]), ...Object.values(uc)].filter((a) => a.length).map((a) => a.sort());
|
|
67
67
|
// Removing duplicates
|
|
68
68
|
identities = [...(new Set(identities.map((a) => a.join('|'))))].map((s) => s.split('|'));
|
|
69
69
|
source = source || target;
|
|
@@ -85,7 +85,7 @@ export const insertPg = async <T extends QueryResultRow, R extends QueryResultRo
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// There is no suitable record in the database, we insert it
|
|
88
|
-
const { values, positionsList, fieldsList, upsertFields } = getFieldsAndValuesPg(recordWoSerials,
|
|
88
|
+
const { values, positionsList, fieldsList, upsertFields } = getFieldsAndValuesPg(recordWoSerials, columnsSchema);
|
|
89
89
|
const insertSQL = `INSERT INTO ${target} (${fieldsList})
|
|
90
90
|
VALUES (${positionsList}) ON CONFLICT ${
|
|
91
91
|
updateLevel === EUpdateLevel.NEVER_UPDATE
|
package/src/pg/prepare-value.ts
CHANGED
|
@@ -1,92 +1,154 @@
|
|
|
1
1
|
// noinspection SqlResolve
|
|
2
2
|
import { DateTime } from 'luxon';
|
|
3
|
-
import {
|
|
3
|
+
import { getBool } from 'af-tools-ts';
|
|
4
|
+
import { IFieldDefPg } from '../@types/i-pg';
|
|
5
|
+
import { NULL } from '../common';
|
|
6
|
+
import { dateTimeValue, getDatetimeWithPrecisionAndOffset } from '../utils/utils-dt';
|
|
7
|
+
import { prepareBigIntNumber, prepareFloatNumber, prepareIntNumber, prepareNumeric } from '../utils/utils-num';
|
|
8
|
+
import { IFieldDef } from '../@types/i-common';
|
|
9
|
+
import { binToHexString, prepareJSON, prepareUUID, q } from '../utils/utils';
|
|
10
|
+
import { arrayToJsonList } from '../utils/utils-array';
|
|
4
11
|
|
|
5
|
-
const
|
|
6
|
-
|
|
12
|
+
export const quoteStringPg = (value: string): string => {
|
|
13
|
+
if (value == null) {
|
|
14
|
+
return NULL;
|
|
15
|
+
}
|
|
16
|
+
return /['\\]|\${2,}/.test(value) ? `$s$${value}$s$` : `'${value}'`;
|
|
17
|
+
};
|
|
7
18
|
|
|
8
|
-
export const prepareSqlStringPg = (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return `$s$${s}$s$`;
|
|
19
|
+
export const prepareSqlStringPg = (value: any, fieldDef: IFieldDefPg): string | typeof NULL => {
|
|
20
|
+
if (value == null) {
|
|
21
|
+
return NULL;
|
|
12
22
|
}
|
|
13
|
-
|
|
23
|
+
let v = String(value);
|
|
24
|
+
const { length = 0, noQuotes } = fieldDef;
|
|
25
|
+
if (length > 0 && v.length > length) {
|
|
26
|
+
v = v.substring(0, length);
|
|
27
|
+
}
|
|
28
|
+
if (noQuotes) {
|
|
29
|
+
return v;
|
|
30
|
+
}
|
|
31
|
+
return quoteStringPg(v);
|
|
14
32
|
};
|
|
15
33
|
|
|
16
|
-
|
|
34
|
+
const prepareDateTimeOffset = (
|
|
17
35
|
value: any,
|
|
18
|
-
fieldDef:
|
|
19
|
-
|
|
36
|
+
fieldDef: IFieldDef,
|
|
37
|
+
): string | typeof NULL => getDatetimeWithPrecisionAndOffset({ value, fieldDef, defaultDtPrecision: 6 });
|
|
38
|
+
|
|
39
|
+
const prepareTimeOffset = (value: any, fieldDefOriginal: IFieldDefPg): string | typeof NULL => {
|
|
40
|
+
const fieldDef: IFieldDefPg = { ...fieldDefOriginal, noQuotes: true };
|
|
41
|
+
fieldDef.dateTimeOptions = fieldDef.dateTimeOptions || {};
|
|
42
|
+
const { includeOffset = fieldDef.dataType === 'timetz' } = fieldDef.dateTimeOptions;
|
|
43
|
+
fieldDef.dateTimeOptions.includeOffset = includeOffset;
|
|
44
|
+
const dts = getDatetimeWithPrecisionAndOffset({ value, fieldDef, defaultDtPrecision: 6, stripTrailingZeros: true });
|
|
45
|
+
return dts === NULL ? NULL : `'${dts.substring(11, dts.length)}'::${fieldDef.dataType}`;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const prepareJsonPg = (value: any, dataType: 'json' | 'jsonb'): string | typeof NULL => {
|
|
49
|
+
const v = prepareJSON(value);
|
|
50
|
+
if (v === NULL) {
|
|
51
|
+
return NULL;
|
|
52
|
+
}
|
|
53
|
+
return `${quoteStringPg(v)}::${dataType}`;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const prepareSqlValuePg = (arg: { value: any, fieldDef: IFieldDefPg }): any => {
|
|
20
57
|
const { value, fieldDef } = arg;
|
|
21
|
-
if (value == null
|
|
58
|
+
if (value == null) {
|
|
22
59
|
return NULL;
|
|
23
60
|
}
|
|
24
|
-
|
|
25
|
-
case EDataTypePg.boolean: {
|
|
26
|
-
return value ? 'true' : 'false';
|
|
27
|
-
}
|
|
61
|
+
const fieldDefWithNoQuotes = { ...fieldDef, noQuotes: true };
|
|
28
62
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
63
|
+
let v = value;
|
|
64
|
+
const { noQuotes, dataType } = fieldDef;
|
|
32
65
|
|
|
33
|
-
|
|
34
|
-
case
|
|
35
|
-
|
|
36
|
-
return Number.isNaN(v) ? NULL : v;
|
|
37
|
-
}
|
|
66
|
+
switch (dataType) {
|
|
67
|
+
case 'bit':
|
|
68
|
+
return getBool(value) ? '1' : '0';
|
|
38
69
|
|
|
39
|
-
case
|
|
40
|
-
case
|
|
41
|
-
|
|
42
|
-
return Number.isNaN(v) ? NULL : Math.floor(v);
|
|
43
|
-
}
|
|
70
|
+
case 'bool':
|
|
71
|
+
case 'boolean':
|
|
72
|
+
return getBool(value) ? 'true' : 'false';
|
|
44
73
|
|
|
45
|
-
case
|
|
46
|
-
case
|
|
47
|
-
|
|
48
|
-
case
|
|
49
|
-
|
|
50
|
-
|
|
74
|
+
case 'smallint':
|
|
75
|
+
case 'int2':
|
|
76
|
+
return prepareIntNumber(value, -32768, 32767);
|
|
77
|
+
case 'int':
|
|
78
|
+
case 'integer':
|
|
79
|
+
case 'int4':
|
|
80
|
+
return prepareIntNumber(value, -2147483648, 2147483647);
|
|
81
|
+
case 'bigint':
|
|
82
|
+
case 'int8':
|
|
83
|
+
return prepareBigIntNumber(value);
|
|
84
|
+
|
|
85
|
+
case 'numeric':
|
|
86
|
+
case 'decimal':
|
|
87
|
+
return prepareNumeric(value, fieldDef.precision, fieldDef.scale);
|
|
88
|
+
|
|
89
|
+
case 'real':
|
|
90
|
+
case 'float4':
|
|
91
|
+
case 'money':
|
|
92
|
+
case 'double precision':
|
|
93
|
+
case 'float8':
|
|
94
|
+
return prepareFloatNumber(value);
|
|
95
|
+
|
|
96
|
+
case 'json':
|
|
97
|
+
case 'jsonb':
|
|
98
|
+
return prepareJsonPg(value, dataType);
|
|
51
99
|
|
|
52
|
-
case
|
|
53
|
-
|
|
54
|
-
|
|
100
|
+
case 'uuid':
|
|
101
|
+
return prepareUUID(v, true, fieldDef.noQuotes);
|
|
102
|
+
|
|
103
|
+
case 'string':
|
|
104
|
+
case 'text':
|
|
105
|
+
case 'character':
|
|
106
|
+
case 'char':
|
|
107
|
+
case 'varchar':
|
|
108
|
+
case 'character varying':
|
|
109
|
+
return prepareSqlStringPg(value, fieldDef);
|
|
110
|
+
|
|
111
|
+
case 'timestamp':
|
|
112
|
+
case 'timestamp without time zone': {
|
|
113
|
+
// '2023-09-05T02:23:54.105+03:00'::timestamp
|
|
114
|
+
// '2023-09-05T02:23:54.105'::timestamp
|
|
115
|
+
const { includeOffset = false } = fieldDef.dateTimeOptions || {}; // По умолчанию для timestamp includeOffset = false
|
|
116
|
+
const str = prepareDateTimeOffset(value, { ...fieldDef, noQuotes: true, dateTimeOptions: { ...(fieldDef.dateTimeOptions || {}), includeOffset } });
|
|
117
|
+
return str === NULL ? NULL : `'${str}'::timestamp`;
|
|
55
118
|
}
|
|
56
119
|
|
|
57
|
-
case
|
|
58
|
-
case
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
} else if (value instanceof DateTime) {
|
|
64
|
-
v = value.toMillis();
|
|
65
|
-
} else if (typeof value === 'string') {
|
|
66
|
-
v = DateTime.fromISO(value).toMillis();
|
|
67
|
-
}
|
|
68
|
-
switch (fieldDef.dataType) {
|
|
69
|
-
case EDataTypePg.date: {
|
|
70
|
-
return `'${typeof v === 'number' ? utc$(v).toISODate() : v}'::date`;
|
|
71
|
-
}
|
|
72
|
-
case EDataTypePg.timestamp:
|
|
73
|
-
case EDataTypePg.timestamptz: {
|
|
74
|
-
return `'${typeof v === 'number' ? utc$(v).toISO() : v}'::timestamptz`;
|
|
75
|
-
}
|
|
76
|
-
default:
|
|
77
|
-
return `'${v}'`;
|
|
78
|
-
}
|
|
120
|
+
case 'timestamptz':
|
|
121
|
+
case 'timestamp with time zone': {
|
|
122
|
+
// '2023-09-05T02:23:54.105'::timestamptz
|
|
123
|
+
// '2023-09-05T02:23:54.105+03:00'::timestamptz
|
|
124
|
+
const str = prepareDateTimeOffset(value, fieldDefWithNoQuotes);
|
|
125
|
+
return str === NULL ? NULL : `'${str}'::timestamptz`;
|
|
79
126
|
}
|
|
80
127
|
|
|
81
|
-
case
|
|
82
|
-
|
|
128
|
+
case 'date':
|
|
129
|
+
// '2023-09-05'::date
|
|
130
|
+
return dateTimeValue(value, fieldDefWithNoQuotes, (dt: DateTime) => `'${dt.toISODate()}'::date`);
|
|
83
131
|
|
|
84
|
-
case
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
132
|
+
case 'timetz': // '02:22:17.368+03:00'::time
|
|
133
|
+
case 'time with time zone':
|
|
134
|
+
case 'time': // '02:22:17.368'::time
|
|
135
|
+
case 'time without time zone':
|
|
136
|
+
return prepareTimeOffset(value, fieldDef);
|
|
137
|
+
|
|
138
|
+
case 'bytea':
|
|
139
|
+
v = binToHexString(value);
|
|
140
|
+
return v ? q(v, noQuotes) : NULL;
|
|
141
|
+
|
|
142
|
+
case 'ARRAY': {
|
|
143
|
+
v = arrayToJsonList(value, fieldDef.arrayType);
|
|
144
|
+
if (v === NULL) {
|
|
145
|
+
return NULL;
|
|
146
|
+
}
|
|
147
|
+
v = `{${v}}`;
|
|
148
|
+
return fieldDef.noQuotes ? v : quoteStringPg(v);
|
|
88
149
|
}
|
|
150
|
+
// 'USER_DEFINED'
|
|
89
151
|
default:
|
|
90
|
-
return prepareSqlStringPg(value);
|
|
152
|
+
return prepareSqlStringPg(value, fieldDef);
|
|
91
153
|
}
|
|
92
154
|
};
|
package/src/pg/query-pg.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { QueryResult
|
|
2
|
-
import { getPoolPg } from './pg
|
|
1
|
+
import { QueryResult } from 'pg';
|
|
2
|
+
import { getPoolPg } from './pool-pg';
|
|
3
3
|
import { logSqlError } from '../common';
|
|
4
4
|
import { IPoolPg } from '../@types/i-pg';
|
|
5
|
+
import { TDBRecord } from '../@types/i-common';
|
|
5
6
|
|
|
6
|
-
export const queryPg = async <R extends
|
|
7
|
+
export const queryPg = async <R extends TDBRecord = any> (
|
|
7
8
|
connectionId: string,
|
|
8
9
|
sqlText: string,
|
|
9
10
|
sqlValues?: any[],
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// noinspection SqlResolve
|
|
2
|
+
import { queryPg } from './query-pg';
|
|
3
|
+
import { logger } from '../logger-error';
|
|
4
|
+
import { graceExit } from '../common';
|
|
5
|
+
import { IFieldDefPg, ITableSchemaPg, TColumnsSchemaPg, TUniqueConstraintsPg } from '../@types/i-pg';
|
|
6
|
+
import { schemaTable } from '../utils/utils';
|
|
7
|
+
import { TDBRecord } from '../@types/i-common';
|
|
8
|
+
import { TDataTypePg } from '../@types/i-data-types-pg';
|
|
9
|
+
import { getNormalizedTypePg, getTypeByUdtNamePg } from './utils-pg';
|
|
10
|
+
|
|
11
|
+
// commonSchemaAndTable: <schema>.<table> : Staff.nnPersones-personGuid
|
|
12
|
+
// schemaAndTablePg: "<schema>"."<table>" : "Staff"."nnPersones-personGuid"
|
|
13
|
+
|
|
14
|
+
const tableSchemaHash: { [commonSchemaAndTable: string]: ITableSchemaPg } = {};
|
|
15
|
+
|
|
16
|
+
const getColumnsSchemaPg_ = async (connectionId: string, commonSchemaAndTable: string): Promise<TColumnsSchemaPg> => {
|
|
17
|
+
const [schema, table] = schemaTable.to.common(commonSchemaAndTable).split('.');
|
|
18
|
+
const sql = `SELECT column_name,
|
|
19
|
+
column_default,
|
|
20
|
+
is_nullable,
|
|
21
|
+
data_type,
|
|
22
|
+
character_maximum_length,
|
|
23
|
+
numeric_precision,
|
|
24
|
+
numeric_precision_radix,
|
|
25
|
+
numeric_scale,
|
|
26
|
+
datetime_precision,
|
|
27
|
+
udt_name,
|
|
28
|
+
is_generated
|
|
29
|
+
FROM information_schema.columns
|
|
30
|
+
WHERE table_name = '${table}'
|
|
31
|
+
AND table_schema = '${schema}';`;
|
|
32
|
+
const result = await queryPg(connectionId, sql);
|
|
33
|
+
const fields = result?.rows || [];
|
|
34
|
+
const columnsSchema: TColumnsSchemaPg = {};
|
|
35
|
+
fields.forEach((fieldDef) => {
|
|
36
|
+
const columnDefault = fieldDef.column_default != null ? fieldDef.column_default : undefined;
|
|
37
|
+
const name = fieldDef.column_name;
|
|
38
|
+
const dataType: TDataTypePg = getNormalizedTypePg(fieldDef.data_type);
|
|
39
|
+
const fieldSchema: IFieldDefPg = {
|
|
40
|
+
name,
|
|
41
|
+
isNullable: /yes/i.test(fieldDef.is_nullable || ''),
|
|
42
|
+
columnDefault: fieldDef.column_default,
|
|
43
|
+
hasDefault: columnDefault != null,
|
|
44
|
+
dataType,
|
|
45
|
+
length: fieldDef.character_maximum_length,
|
|
46
|
+
precision: fieldDef.numeric_precision,
|
|
47
|
+
scale: fieldDef.numeric_scale,
|
|
48
|
+
radix: fieldDef.numeric_precision_radix,
|
|
49
|
+
dtPrecision: fieldDef.datetime_precision,
|
|
50
|
+
arrayType: dataType === 'ARRAY' ? getTypeByUdtNamePg(fieldDef.udt_name) : undefined,
|
|
51
|
+
readOnly: fieldDef.is_generated === 'ALWAYS', // boolean;
|
|
52
|
+
};
|
|
53
|
+
Object.entries(fieldSchema).forEach(([prop, value]) => {
|
|
54
|
+
if (value == null) {
|
|
55
|
+
delete fieldSchema[prop as keyof IFieldDefPg];
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
columnsSchema[name] = fieldSchema;
|
|
59
|
+
});
|
|
60
|
+
return columnsSchema;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const getPrimaryKey = async (connectionId: string, commonSchemaAndTable: string): Promise<string[]> => {
|
|
64
|
+
const schemaTablePg = schemaTable.to.pg(commonSchemaAndTable);
|
|
65
|
+
const sql = `
|
|
66
|
+
SELECT a.attname as f
|
|
67
|
+
FROM pg_index i
|
|
68
|
+
JOIN pg_attribute a
|
|
69
|
+
ON a.attrelid = i.indrelid AND a.attnum = ANY (i.indkey)
|
|
70
|
+
WHERE i.indrelid = '${schemaTablePg}'::regclass
|
|
71
|
+
AND i.indisprimary;`;
|
|
72
|
+
const result = await queryPg(connectionId, sql);
|
|
73
|
+
|
|
74
|
+
return (result?.rows || []).map(({ f }) => f);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const getUniqueConstraints = async (connectionId: string, commonSchemaAndTable: string): Promise<TUniqueConstraintsPg> => {
|
|
78
|
+
const schemaTablePg = schemaTable.to.pg(commonSchemaAndTable);
|
|
79
|
+
const [schema, table] = schemaTable.to.common(commonSchemaAndTable).split('.');
|
|
80
|
+
const sql = `
|
|
81
|
+
SELECT UI.cn as cn, UI.cols as cols, CASE WHEN UC.cn IS NULL THEN 'UX' ELSE 'UC' END AS typ
|
|
82
|
+
FROM (SELECT c.relname as cn, array_to_json(array_agg(a.attname ORDER BY a.attname)) AS cols
|
|
83
|
+
FROM pg_index i
|
|
84
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY (i.indkey)
|
|
85
|
+
JOIN pg_class AS c ON c.oid = i.indexrelid
|
|
86
|
+
WHERE i.indrelid = '${schemaTablePg}'::regclass
|
|
87
|
+
AND i.indisunique
|
|
88
|
+
AND NOT i.indisprimary
|
|
89
|
+
GROUP BY c.relname) AS UI
|
|
90
|
+
LEFT OUTER JOIN (SELECT ccu.constraint_name AS cn
|
|
91
|
+
FROM information_schema.table_constraints tc
|
|
92
|
+
JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)
|
|
93
|
+
JOIN information_schema.columns AS c ON c.table_schema = tc.constraint_schema
|
|
94
|
+
AND tc.table_name = c.table_name AND ccu.column_name = c.column_name
|
|
95
|
+
WHERE tc.table_schema = '${schema}'
|
|
96
|
+
AND tc.table_name = '${table}'
|
|
97
|
+
AND tc.constraint_type = 'UNIQUE'
|
|
98
|
+
GROUP BY ccu.constraint_name) AS UC ON UC.cn = UI.cn
|
|
99
|
+
ORDER BY CASE WHEN UC.cn IS NULL THEN 2 ELSE 1 END
|
|
100
|
+
`;
|
|
101
|
+
const result = await queryPg(connectionId, sql);
|
|
102
|
+
const uc: TUniqueConstraintsPg = {};
|
|
103
|
+
result?.rows?.forEach(({ cn, cols }) => {
|
|
104
|
+
uc[cn] = cols;
|
|
105
|
+
});
|
|
106
|
+
return uc;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const getSerials = async (connectionId: string, commonSchemaAndTable: string): Promise<string[]> => {
|
|
110
|
+
const fqName = schemaTable.to.common(commonSchemaAndTable);
|
|
111
|
+
const sql = `
|
|
112
|
+
WITH fq_objects AS (SELECT c.oid,
|
|
113
|
+
n.nspname || '.' || c.relname AS fqname,
|
|
114
|
+
c.relkind,
|
|
115
|
+
c.relname AS relation
|
|
116
|
+
FROM pg_class c
|
|
117
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace),
|
|
118
|
+
sequences AS (SELECT oid, fqname FROM fq_objects WHERE relkind = 'S'),
|
|
119
|
+
tables AS (SELECT oid, fqname FROM fq_objects WHERE relkind = 'r')
|
|
120
|
+
SELECT t.fqname AS tbl, array_to_json(array_agg(a.attname ORDER BY a.attname)) AS cols
|
|
121
|
+
FROM pg_depend d
|
|
122
|
+
JOIN sequences s ON s.oid = d.objid
|
|
123
|
+
JOIN tables t ON t.oid = d.refobjid
|
|
124
|
+
JOIN pg_attribute a ON a.attrelid = d.refobjid and a.attnum = d.refobjsubid
|
|
125
|
+
WHERE d.deptype = 'a'
|
|
126
|
+
AND t.fqname = '${fqName}'
|
|
127
|
+
GROUP BY t.fqname
|
|
128
|
+
`;
|
|
129
|
+
const result = await queryPg(connectionId, sql);
|
|
130
|
+
return result?.rows?.[0]?.cols || [];
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const getTableSchemaPg = async (connectionId: string, commonSchemaAndTable: string): Promise<ITableSchemaPg> => {
|
|
134
|
+
let tableSchema = tableSchemaHash[commonSchemaAndTable];
|
|
135
|
+
if (tableSchema) {
|
|
136
|
+
return tableSchema;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const columnsSchema = await getColumnsSchemaPg_(connectionId, commonSchemaAndTable);
|
|
140
|
+
const pk = await getPrimaryKey(connectionId, commonSchemaAndTable);
|
|
141
|
+
const uc = await getUniqueConstraints(connectionId, commonSchemaAndTable);
|
|
142
|
+
const serialsFields = await getSerials(connectionId, commonSchemaAndTable);
|
|
143
|
+
const defaults: { [fieldName: string]: string } = {};
|
|
144
|
+
Object.values(columnsSchema).forEach((fieldDef) => {
|
|
145
|
+
const { name: f = '', columnDefault, hasDefault } = fieldDef;
|
|
146
|
+
if (hasDefault && !serialsFields.includes(f)) {
|
|
147
|
+
defaults[f] = `${columnDefault}`;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
const fieldsArray: string[] = Object.keys(columnsSchema);
|
|
151
|
+
const readOnlyFields: string[] = Object.values(columnsSchema).filter((s) => s.readOnly).map((s) => s.name as string);
|
|
152
|
+
const fieldsWoSerialsAndRO: string[] = fieldsArray.filter((f) => !serialsFields.includes(f) && !readOnlyFields.includes(f));
|
|
153
|
+
|
|
154
|
+
tableSchema = {
|
|
155
|
+
columnsSchema, pk, uc, defaults, serialsFields, fieldsArray, fieldsWoSerialsAndRO, readOnlyFields,
|
|
156
|
+
};
|
|
157
|
+
tableSchemaHash[commonSchemaAndTable] = tableSchema;
|
|
158
|
+
} catch (err) {
|
|
159
|
+
logger.error(`Failed to get schema for table ${commonSchemaAndTable}`);
|
|
160
|
+
logger.error(err);
|
|
161
|
+
await graceExit();
|
|
162
|
+
}
|
|
163
|
+
return tableSchema;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export const getFieldsAndValuesPg = <U extends TDBRecord = TDBRecord> (record: U, columnsSchema: TColumnsSchemaPg):
|
|
167
|
+
{
|
|
168
|
+
fields: string[],
|
|
169
|
+
fieldsList: string,
|
|
170
|
+
values: any[],
|
|
171
|
+
positionsList: string,
|
|
172
|
+
setFields: string,
|
|
173
|
+
upsertFields: string
|
|
174
|
+
} => {
|
|
175
|
+
const recordNormalized: TDBRecord = {};
|
|
176
|
+
Object.entries(record).forEach(([f, v]) => {
|
|
177
|
+
const { dataType } = columnsSchema[f] || {};
|
|
178
|
+
if (!dataType) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if ((dataType === 'jsonb' || dataType === 'json') && Array.isArray(v)) {
|
|
182
|
+
recordNormalized[f] = JSON.stringify(v);
|
|
183
|
+
} else {
|
|
184
|
+
recordNormalized[f] = v;
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
const fields: string[] = Object.keys(recordNormalized);
|
|
188
|
+
const fieldsList: string = fields.join(', ');
|
|
189
|
+
const values: any[] = Object.values(recordNormalized);
|
|
190
|
+
const positionsList: string = fields.map((__, i) => `$${++i}`).join(', ');
|
|
191
|
+
const setFields: string = fields.map((f, i) => `${f} = $${++i}`).join(', ');
|
|
192
|
+
const upsertFields: string = fields.map((f) => `${f} = EXCLUDED.${f}`).join(',\n');
|
|
193
|
+
return {
|
|
194
|
+
fields, fieldsList, values, positionsList, setFields, upsertFields,
|
|
195
|
+
};
|
|
196
|
+
};
|