@budibase/server 0.9.188 → 0.9.190-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +7 -1
- package/__mocks__/mssql.ts +1 -1
- package/__mocks__/oracledb.ts +31 -0
- package/__mocks__/pg.ts +3 -0
- package/builder/assets/bb-space-man.5be51a45.svg +290 -0
- package/builder/assets/index.7d405e74.css +1 -0
- package/builder/assets/index.edea4fa5.js +1316 -0
- package/builder/assets/oracle.66592424.png +0 -0
- package/builder/assets/vendor.470042a4.js +152 -0
- package/builder/assets/vendor.5e1fe644.css +1 -0
- package/builder/index.html +4 -4
- package/coverage/clover.xml +1507 -1081
- package/coverage/coverage-final.json +93 -89
- package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
- package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
- package/coverage/lcov-report/api/controllers/application.js.html +64 -13
- package/coverage/lcov-report/api/controllers/auth.js.html +19 -10
- package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +4 -4
- package/coverage/lcov-report/api/controllers/datasource.js.html +232 -28
- package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
- package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
- package/coverage/lcov-report/api/controllers/index.html +91 -91
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
- package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
- package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
- package/coverage/lcov-report/api/controllers/query.js.html +53 -209
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
- package/coverage/lcov-report/api/controllers/row/external.js.html +17 -8
- package/coverage/lcov-report/api/controllers/row/index.html +26 -26
- package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/utils.js.html +21 -30
- package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
- package/coverage/lcov-report/api/controllers/script.js.html +3 -3
- package/coverage/lcov-report/api/controllers/table/external.js.html +1001 -0
- package/coverage/lcov-report/api/controllers/table/index.html +56 -26
- package/coverage/lcov-report/api/controllers/table/index.js.html +80 -350
- package/coverage/lcov-report/api/controllers/table/internal.js.html +545 -0
- package/coverage/lcov-report/api/controllers/table/utils.js.html +175 -52
- package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
- package/coverage/lcov-report/api/controllers/user.js.html +390 -33
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +19 -4
- package/coverage/lcov-report/api/controllers/view/index.html +22 -22
- package/coverage/lcov-report/api/controllers/view/index.js.html +52 -13
- package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
- package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/application.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +2 -2
- package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +4 -4
- package/coverage/lcov-report/api/routes/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +5 -2
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/row.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/static.js.html +2 -2
- package/coverage/lcov-report/api/routes/table.js.html +35 -2
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +17 -2
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +2 -2
- package/coverage/lcov-report/automations/automationUtils.js.html +4 -4
- package/coverage/lcov-report/automations/bullboard.js.html +71 -20
- package/coverage/lcov-report/automations/index.html +35 -50
- package/coverage/lcov-report/automations/index.js.html +2 -2
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +14 -14
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
- package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
- package/coverage/lcov-report/automations/triggers.js.html +22 -10
- package/coverage/lcov-report/automations/utils.js.html +42 -12
- package/coverage/lcov-report/constants/index.html +5 -5
- package/coverage/lcov-report/constants/index.js.html +87 -21
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/client.js.html +2 -2
- package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
- package/coverage/lcov-report/db/index.html +2 -2
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
- package/coverage/lcov-report/db/linkedRows/index.html +10 -10
- package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
- package/coverage/lcov-report/db/newid.js.html +3 -3
- package/coverage/lcov-report/db/utils.js.html +57 -57
- package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
- package/coverage/lcov-report/events/index.html +6 -6
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +5 -5
- package/coverage/lcov-report/index.html +106 -91
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
- package/coverage/lcov-report/middleware/authorized.js.html +11 -8
- package/coverage/lcov-report/middleware/builder.js.html +16 -7
- package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
- package/coverage/lcov-report/middleware/index.html +23 -23
- package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
- package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
- package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
- package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +90 -33
- package/coverage/lcov-report/threads/index.html +141 -0
- package/coverage/lcov-report/threads/index.js.html +278 -0
- package/coverage/lcov-report/threads/query.js.html +278 -0
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +144 -15
- package/coverage/lcov-report/utilities/global.js.html +26 -11
- package/coverage/lcov-report/utilities/index.html +48 -48
- package/coverage/lcov-report/utilities/index.js.html +47 -14
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
- package/coverage/lcov-report/utilities/queue/index.html +14 -14
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +4 -4
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
- package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
- package/coverage/lcov-report/utilities/security.js.html +3 -3
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
- package/coverage/lcov.info +2495 -1737
- package/dist/api/controllers/application.js +15 -1
- package/dist/api/controllers/auth.js +3 -3
- package/dist/api/controllers/datasource.js +67 -16
- package/dist/api/controllers/deploy/index.js +2 -0
- package/dist/api/controllers/dev.js +4 -1
- package/dist/api/controllers/query.js +30 -58
- package/dist/api/controllers/row/ExternalRequest.js +78 -34
- package/dist/api/controllers/row/external.js +3 -1
- package/dist/api/controllers/row/utils.js +6 -12
- package/dist/api/controllers/table/external.js +249 -0
- package/dist/api/controllers/table/index.js +49 -123
- package/dist/api/controllers/table/internal.js +150 -0
- package/dist/api/controllers/table/utils.js +62 -28
- package/dist/api/controllers/user.js +123 -11
- package/dist/api/controllers/view/exporters.js +4 -0
- package/dist/api/controllers/view/index.js +14 -2
- package/dist/api/routes/query.js +1 -1
- package/dist/api/routes/table.js +7 -1
- package/dist/api/routes/user.js +2 -1
- package/dist/app.js +2 -11
- package/dist/automations/bullboard.js +37 -10
- package/dist/automations/triggers.js +7 -3
- package/dist/automations/utils.js +11 -2
- package/dist/constants/index.js +19 -0
- package/dist/definitions/datasource.js +5 -0
- package/dist/environment.js +13 -0
- package/dist/integrations/base/IntegrationBase.js +2 -0
- package/dist/integrations/base/datasourcePlus.js +2 -0
- package/dist/integrations/base/sql.js +353 -177
- package/dist/integrations/base/sqlTable.js +143 -0
- package/dist/integrations/base/utils.js +30 -0
- package/dist/integrations/index.js +6 -0
- package/dist/integrations/microsoftSqlServer.js +117 -9
- package/dist/integrations/mysql.js +16 -85
- package/dist/integrations/oracle.js +347 -0
- package/dist/integrations/postgres.js +35 -28
- package/dist/integrations/utils.js +71 -9
- package/dist/middleware/authorized.js +2 -1
- package/dist/middleware/builder.js +4 -1
- package/dist/package.json +12 -7
- package/dist/tests/utilities/TestConfiguration.js +2 -1
- package/dist/{automations/thread.js → threads/automation.js} +26 -8
- package/dist/threads/index.js +64 -0
- package/dist/threads/query.js +64 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/csvParser.js +46 -5
- package/dist/utilities/global.js +6 -2
- package/dist/utilities/index.js +11 -0
- package/dist/utilities/queue/inMemoryQueue.js +8 -0
- package/dist/utilities/scriptRunner.js +4 -1
- package/package.json +13 -8
- package/scripts/dev/manage.js +1 -0
- package/scripts/integrations/mssql/data/Dockerfile +9 -0
- package/scripts/integrations/mssql/data/entrypoint.sh +24 -0
- package/scripts/integrations/mssql/data/setup.sql +54 -0
- package/scripts/integrations/mssql/docker-compose.yaml +12 -0
- package/scripts/integrations/mssql/reset.sh +3 -0
- package/scripts/integrations/oracle/docker-compose.yml +19 -0
- package/scripts/integrations/oracle/instantclient/linux/x86-64/basiclite-21.4.zip +0 -0
- package/scripts/integrations/oracle/instantclient/linux/x86-64/install.sh +23 -0
- package/scripts/integrations/oracle/oracle.md +90 -0
- package/scripts/integrations/postgres/docker-compose.yml +3 -3
- package/scripts/likeCypress.ts +33 -0
- package/src/api/controllers/application.js +18 -1
- package/src/api/controllers/auth.js +3 -0
- package/src/api/controllers/datasource.js +84 -16
- package/src/api/controllers/deploy/index.js +2 -0
- package/src/api/controllers/dev.js +4 -1
- package/src/api/controllers/query.js +29 -81
- package/src/api/controllers/row/ExternalRequest.ts +91 -36
- package/src/api/controllers/row/external.js +4 -1
- package/src/api/controllers/row/utils.js +8 -11
- package/src/api/controllers/table/external.js +307 -0
- package/src/api/controllers/table/index.js +47 -137
- package/src/api/controllers/table/internal.js +155 -0
- package/src/api/controllers/table/utils.js +74 -33
- package/src/api/controllers/user.js +132 -13
- package/src/api/controllers/view/exporters.js +5 -0
- package/src/api/controllers/view/index.js +15 -2
- package/src/api/routes/query.js +1 -0
- package/src/api/routes/table.js +11 -0
- package/src/api/routes/tests/datasource.spec.js +2 -2
- package/src/api/routes/tests/misc.spec.js +5 -1
- package/src/api/routes/tests/query.spec.js +0 -1
- package/src/api/routes/user.js +5 -0
- package/src/app.ts +2 -10
- package/src/automations/bullboard.js +28 -11
- package/src/automations/tests/automation.spec.js +3 -4
- package/src/automations/triggers.js +7 -3
- package/src/automations/utils.js +12 -2
- package/src/constants/index.js +22 -0
- package/src/definitions/common.ts +7 -1
- package/src/definitions/datasource.ts +10 -3
- package/src/environment.js +15 -0
- package/src/integrations/airtable.ts +2 -1
- package/src/integrations/arangodb.ts +2 -1
- package/src/integrations/base/IntegrationBase.ts +6 -0
- package/src/integrations/base/datasourcePlus.ts +9 -0
- package/src/integrations/base/sql.ts +377 -218
- package/src/integrations/base/sqlTable.ts +180 -0
- package/src/integrations/base/utils.ts +22 -0
- package/src/integrations/couchdb.ts +2 -1
- package/src/integrations/dynamodb.ts +2 -1
- package/src/integrations/elasticsearch.ts +2 -1
- package/src/integrations/index.ts +7 -0
- package/src/integrations/microsoftSqlServer.ts +145 -13
- package/src/integrations/mongodb.ts +2 -1
- package/src/integrations/mysql.ts +23 -95
- package/src/integrations/oracle.ts +458 -0
- package/src/integrations/postgres.ts +45 -35
- package/src/integrations/rest.ts +2 -1
- package/src/integrations/s3.ts +2 -1
- package/src/integrations/tests/microsoftSqlServer.spec.js +22 -15
- package/src/integrations/tests/oracle.spec.js +94 -0
- package/src/integrations/tests/postgres.spec.js +4 -0
- package/src/integrations/utils.ts +78 -8
- package/src/middleware/authorized.js +2 -1
- package/src/middleware/builder.js +4 -1
- package/src/tests/utilities/TestConfiguration.js +2 -1
- package/src/{automations/thread.js → threads/automation.js} +27 -8
- package/src/threads/index.js +66 -0
- package/src/threads/query.js +66 -0
- package/src/utilities/csvParser.js +48 -5
- package/src/utilities/global.js +7 -2
- package/src/utilities/index.js +11 -0
- package/src/utilities/queue/inMemoryQueue.js +7 -0
- package/src/utilities/scriptRunner.js +4 -1
- package/src/utilities/tests/__snapshots__/csvParser.spec.js.snap +0 -6
- package/src/utilities/tests/csvParser.spec.js +3 -0
- package/tsconfig.json +1 -1
- package/builder/assets/index.550fdba7.js +0 -201
- package/builder/assets/index.7469e1e4.css +0 -29
- package/builder/assets/vendor.278a305c.js +0 -9
- package/builder/assets/vendor.d75d5eb7.css +0 -1
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Knex, knex } from "knex"
|
|
2
|
+
import { Table } from "../../definitions/common"
|
|
3
|
+
import { Operation, QueryJson } from "../../definitions/datasource"
|
|
4
|
+
import { breakExternalTableId } from "../utils"
|
|
5
|
+
import SchemaBuilder = Knex.SchemaBuilder
|
|
6
|
+
import CreateTableBuilder = Knex.CreateTableBuilder
|
|
7
|
+
const { FieldTypes, RelationshipTypes } = require("../../constants")
|
|
8
|
+
|
|
9
|
+
function generateSchema(
|
|
10
|
+
schema: CreateTableBuilder,
|
|
11
|
+
table: Table,
|
|
12
|
+
tables: Record<string, Table>,
|
|
13
|
+
oldTable: null | Table = null
|
|
14
|
+
) {
|
|
15
|
+
let primaryKey = table && table.primary ? table.primary[0] : null
|
|
16
|
+
const columns = Object.values(table.schema)
|
|
17
|
+
// all columns in a junction table will be meta
|
|
18
|
+
let metaCols = columns.filter(col => col.meta)
|
|
19
|
+
let isJunction = metaCols.length === columns.length
|
|
20
|
+
// can't change primary once its set for now
|
|
21
|
+
if (primaryKey && !oldTable && !isJunction) {
|
|
22
|
+
schema.increments(primaryKey).primary()
|
|
23
|
+
} else if (!oldTable && isJunction) {
|
|
24
|
+
schema.primary(metaCols.map(col => col.name))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// check if any columns need added
|
|
28
|
+
const foreignKeys = Object.values(table.schema).map(col => col.foreignKey)
|
|
29
|
+
for (let [key, column] of Object.entries(table.schema)) {
|
|
30
|
+
// skip things that are already correct
|
|
31
|
+
const oldColumn = oldTable ? oldTable.schema[key] : null
|
|
32
|
+
if ((oldColumn && oldColumn.type) || (primaryKey === key && !isJunction)) {
|
|
33
|
+
continue
|
|
34
|
+
}
|
|
35
|
+
switch (column.type) {
|
|
36
|
+
case FieldTypes.STRING:
|
|
37
|
+
case FieldTypes.OPTIONS:
|
|
38
|
+
case FieldTypes.LONGFORM:
|
|
39
|
+
schema.string(key)
|
|
40
|
+
break
|
|
41
|
+
case FieldTypes.NUMBER:
|
|
42
|
+
// if meta is specified then this is a junction table entry
|
|
43
|
+
if (column.meta && column.meta.toKey && column.meta.toTable) {
|
|
44
|
+
const { toKey, toTable } = column.meta
|
|
45
|
+
schema.integer(key).unsigned()
|
|
46
|
+
schema.foreign(key).references(`${toTable}.${toKey}`)
|
|
47
|
+
} else if (foreignKeys.indexOf(key) === -1) {
|
|
48
|
+
schema.float(key)
|
|
49
|
+
}
|
|
50
|
+
break
|
|
51
|
+
case FieldTypes.BOOLEAN:
|
|
52
|
+
schema.boolean(key)
|
|
53
|
+
break
|
|
54
|
+
case FieldTypes.DATETIME:
|
|
55
|
+
schema.datetime(key)
|
|
56
|
+
break
|
|
57
|
+
case FieldTypes.ARRAY:
|
|
58
|
+
schema.json(key)
|
|
59
|
+
break
|
|
60
|
+
case FieldTypes.LINK:
|
|
61
|
+
// this side of the relationship doesn't need any SQL work
|
|
62
|
+
if (
|
|
63
|
+
column.relationshipType !== RelationshipTypes.MANY_TO_ONE &&
|
|
64
|
+
column.relationshipType !== RelationshipTypes.MANY_TO_MANY
|
|
65
|
+
) {
|
|
66
|
+
if (!column.foreignKey || !column.tableId) {
|
|
67
|
+
throw "Invalid relationship schema"
|
|
68
|
+
}
|
|
69
|
+
const { tableName } = breakExternalTableId(column.tableId)
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
const relatedTable = tables[tableName]
|
|
72
|
+
if (!relatedTable) {
|
|
73
|
+
throw "Referenced table doesn't exist"
|
|
74
|
+
}
|
|
75
|
+
schema.integer(column.foreignKey).unsigned()
|
|
76
|
+
schema
|
|
77
|
+
.foreign(column.foreignKey)
|
|
78
|
+
.references(`${tableName}.${relatedTable.primary[0]}`)
|
|
79
|
+
}
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// need to check if any columns have been deleted
|
|
85
|
+
if (oldTable) {
|
|
86
|
+
const deletedColumns = Object.entries(oldTable.schema)
|
|
87
|
+
.filter(
|
|
88
|
+
([key, schema]) =>
|
|
89
|
+
schema.type !== FieldTypes.LINK && table.schema[key] == null
|
|
90
|
+
)
|
|
91
|
+
.map(([key]) => key)
|
|
92
|
+
deletedColumns.forEach(key => {
|
|
93
|
+
if (oldTable.constrained && oldTable.constrained.indexOf(key) !== -1) {
|
|
94
|
+
schema.dropForeign(key)
|
|
95
|
+
}
|
|
96
|
+
schema.dropColumn(key)
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return schema
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function buildCreateTable(
|
|
104
|
+
knex: Knex,
|
|
105
|
+
table: Table,
|
|
106
|
+
tables: Record<string, Table>
|
|
107
|
+
): SchemaBuilder {
|
|
108
|
+
return knex.schema.createTable(table.name, schema => {
|
|
109
|
+
generateSchema(schema, table, tables)
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function buildUpdateTable(
|
|
114
|
+
knex: Knex,
|
|
115
|
+
table: Table,
|
|
116
|
+
tables: Record<string, Table>,
|
|
117
|
+
oldTable: Table
|
|
118
|
+
): SchemaBuilder {
|
|
119
|
+
return knex.schema.alterTable(table.name, schema => {
|
|
120
|
+
generateSchema(schema, table, tables, oldTable)
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function buildDeleteTable(knex: Knex, table: Table): SchemaBuilder {
|
|
125
|
+
return knex.schema.dropTable(table.name)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
class SqlTableQueryBuilder {
|
|
129
|
+
private readonly sqlClient: string
|
|
130
|
+
|
|
131
|
+
// pass through client to get flavour of SQL
|
|
132
|
+
constructor(client: string) {
|
|
133
|
+
this.sqlClient = client
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getSqlClient(): string {
|
|
137
|
+
return this.sqlClient
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param json the input JSON structure from which an SQL query will be built.
|
|
142
|
+
* @return {string} the operation that was found in the JSON.
|
|
143
|
+
*/
|
|
144
|
+
_operation(json: QueryJson): Operation {
|
|
145
|
+
return json.endpoint.operation
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_tableQuery(json: QueryJson): any {
|
|
149
|
+
const client = knex({ client: this.sqlClient })
|
|
150
|
+
let query
|
|
151
|
+
if (!json.table || !json.meta || !json.meta.tables) {
|
|
152
|
+
throw "Cannot execute without table being specified"
|
|
153
|
+
}
|
|
154
|
+
switch (this._operation(json)) {
|
|
155
|
+
case Operation.CREATE_TABLE:
|
|
156
|
+
query = buildCreateTable(client, json.table, json.meta.tables)
|
|
157
|
+
break
|
|
158
|
+
case Operation.UPDATE_TABLE:
|
|
159
|
+
if (!json.meta || !json.meta.table) {
|
|
160
|
+
throw "Must specify old table for update"
|
|
161
|
+
}
|
|
162
|
+
query = buildUpdateTable(
|
|
163
|
+
client,
|
|
164
|
+
json.table,
|
|
165
|
+
json.meta.tables,
|
|
166
|
+
json.meta.table
|
|
167
|
+
)
|
|
168
|
+
break
|
|
169
|
+
case Operation.DELETE_TABLE:
|
|
170
|
+
query = buildDeleteTable(client, json.table)
|
|
171
|
+
break
|
|
172
|
+
default:
|
|
173
|
+
throw "Table operation is of unknown type"
|
|
174
|
+
}
|
|
175
|
+
return query.toSQL()
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export default SqlTableQueryBuilder
|
|
180
|
+
module.exports = SqlTableQueryBuilder
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { QueryJson } from "../../definitions/datasource"
|
|
2
|
+
import { Datasource } from "../../definitions/common"
|
|
3
|
+
|
|
4
|
+
module DatasourceUtils {
|
|
5
|
+
const { integrations } = require("../index")
|
|
6
|
+
|
|
7
|
+
export async function makeExternalQuery(
|
|
8
|
+
datasource: Datasource,
|
|
9
|
+
json: QueryJson
|
|
10
|
+
) {
|
|
11
|
+
const Integration = integrations[datasource.source]
|
|
12
|
+
// query is the opinionated function
|
|
13
|
+
if (Integration.prototype.query) {
|
|
14
|
+
const integration = new Integration(datasource.config)
|
|
15
|
+
return integration.query(json)
|
|
16
|
+
} else {
|
|
17
|
+
throw "Datasource does not support query."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports.makeExternalQuery = makeExternalQuery
|
|
22
|
+
}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
DatasourceFieldTypes,
|
|
4
4
|
QueryTypes,
|
|
5
5
|
} from "../definitions/datasource"
|
|
6
|
+
import { IntegrationBase } from "./base/IntegrationBase"
|
|
6
7
|
|
|
7
8
|
module CouchDBModule {
|
|
8
9
|
const PouchDB = require("pouchdb")
|
|
@@ -50,7 +51,7 @@ module CouchDBModule {
|
|
|
50
51
|
},
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
class CouchDBIntegration {
|
|
54
|
+
class CouchDBIntegration implements IntegrationBase {
|
|
54
55
|
private config: CouchDBConfig
|
|
55
56
|
private client: any
|
|
56
57
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
DatasourceFieldTypes,
|
|
4
4
|
QueryTypes,
|
|
5
5
|
} from "../definitions/datasource"
|
|
6
|
+
import { IntegrationBase } from "./base/IntegrationBase"
|
|
6
7
|
|
|
7
8
|
module DynamoModule {
|
|
8
9
|
const AWS = require("aws-sdk")
|
|
@@ -113,7 +114,7 @@ module DynamoModule {
|
|
|
113
114
|
},
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
class DynamoDBIntegration {
|
|
117
|
+
class DynamoDBIntegration implements IntegrationBase {
|
|
117
118
|
private config: DynamoDBConfig
|
|
118
119
|
private client: any
|
|
119
120
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
DatasourceFieldTypes,
|
|
4
4
|
QueryTypes,
|
|
5
5
|
} from "../definitions/datasource"
|
|
6
|
+
import { IntegrationBase } from "./base/IntegrationBase"
|
|
6
7
|
|
|
7
8
|
module ElasticsearchModule {
|
|
8
9
|
const { Client } = require("@elastic/elasticsearch")
|
|
@@ -74,7 +75,7 @@ module ElasticsearchModule {
|
|
|
74
75
|
},
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
class ElasticSearchIntegration {
|
|
78
|
+
class ElasticSearchIntegration implements IntegrationBase {
|
|
78
79
|
private config: ElasticsearchConfig
|
|
79
80
|
private client: any
|
|
80
81
|
|
|
@@ -39,6 +39,13 @@ const INTEGRATIONS = {
|
|
|
39
39
|
[SourceNames.REST]: rest.integration,
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// optionally add oracle integration if the oracle binary can be installed
|
|
43
|
+
if (!(process.arch === "arm64" && process.platform === "darwin")) {
|
|
44
|
+
const oracle = require("./oracle")
|
|
45
|
+
DEFINITIONS[SourceNames.ORACLE] = oracle.schema
|
|
46
|
+
INTEGRATIONS[SourceNames.ORACLE] = oracle.integration
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
module.exports = {
|
|
43
50
|
definitions: DEFINITIONS,
|
|
44
51
|
integrations: INTEGRATIONS,
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Integration,
|
|
3
2
|
DatasourceFieldTypes,
|
|
4
|
-
|
|
3
|
+
Integration,
|
|
4
|
+
Operation,
|
|
5
5
|
QueryJson,
|
|
6
|
+
QueryTypes,
|
|
6
7
|
SqlQuery,
|
|
7
8
|
} from "../definitions/datasource"
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getSqlQuery,
|
|
11
|
+
buildExternalTableId,
|
|
12
|
+
convertSqlType,
|
|
13
|
+
finaliseExternalTables,
|
|
14
|
+
SqlClients,
|
|
15
|
+
} from "./utils"
|
|
16
|
+
import { DatasourcePlus } from "./base/datasourcePlus"
|
|
17
|
+
import { Table, TableSchema } from "../definitions/common"
|
|
9
18
|
|
|
10
19
|
module MSSQLModule {
|
|
11
20
|
const sqlServer = require("mssql")
|
|
@@ -22,6 +31,7 @@ module MSSQLModule {
|
|
|
22
31
|
|
|
23
32
|
const SCHEMA: Integration = {
|
|
24
33
|
docs: "https://github.com/tediousjs/node-mssql",
|
|
34
|
+
plus: true,
|
|
25
35
|
description:
|
|
26
36
|
"Microsoft SQL Server is a relational database management system developed by Microsoft. ",
|
|
27
37
|
friendlyName: "MS SQL Server",
|
|
@@ -69,26 +79,84 @@ module MSSQLModule {
|
|
|
69
79
|
},
|
|
70
80
|
}
|
|
71
81
|
|
|
72
|
-
async function internalQuery(
|
|
82
|
+
async function internalQuery(
|
|
83
|
+
client: any,
|
|
84
|
+
query: SqlQuery,
|
|
85
|
+
operation: string | undefined = undefined
|
|
86
|
+
) {
|
|
87
|
+
const request = client.request()
|
|
73
88
|
try {
|
|
74
|
-
|
|
89
|
+
if (Array.isArray(query.bindings)) {
|
|
90
|
+
let count = 0
|
|
91
|
+
for (let binding of query.bindings) {
|
|
92
|
+
request.input(`p${count++}`, binding)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// this is a hack to get the inserted ID back,
|
|
96
|
+
// no way to do this with Knex nicely
|
|
97
|
+
const sql =
|
|
98
|
+
operation === Operation.CREATE
|
|
99
|
+
? `${query.sql}; SELECT SCOPE_IDENTITY() AS id;`
|
|
100
|
+
: query.sql
|
|
101
|
+
return await request.query(sql)
|
|
75
102
|
} catch (err) {
|
|
76
103
|
// @ts-ignore
|
|
77
104
|
throw new Error(err)
|
|
78
105
|
}
|
|
79
106
|
}
|
|
80
107
|
|
|
81
|
-
class SqlServerIntegration extends Sql {
|
|
108
|
+
class SqlServerIntegration extends Sql implements DatasourcePlus {
|
|
82
109
|
private readonly config: MSSQLConfig
|
|
83
110
|
static pool: any
|
|
111
|
+
public tables: Record<string, Table> = {}
|
|
112
|
+
public schemaErrors: Record<string, string> = {}
|
|
113
|
+
|
|
114
|
+
MASTER_TABLES = [
|
|
115
|
+
"spt_fallback_db",
|
|
116
|
+
"spt_fallback_dev",
|
|
117
|
+
"spt_fallback_usg",
|
|
118
|
+
"spt_monitor",
|
|
119
|
+
"MSreplication_options",
|
|
120
|
+
]
|
|
121
|
+
TABLES_SQL =
|
|
122
|
+
"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'"
|
|
123
|
+
|
|
124
|
+
getDefinitionSQL(tableName: string) {
|
|
125
|
+
return `select *
|
|
126
|
+
from INFORMATION_SCHEMA.COLUMNS
|
|
127
|
+
where TABLE_NAME='${tableName}'`
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getConstraintsSQL(tableName: string) {
|
|
131
|
+
return `SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
132
|
+
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU
|
|
133
|
+
ON TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
|
|
134
|
+
AND TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
|
|
135
|
+
AND KU.table_name='${tableName}'
|
|
136
|
+
ORDER BY
|
|
137
|
+
KU.TABLE_NAME,
|
|
138
|
+
KU.ORDINAL_POSITION;`
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getAutoColumnsSQL(tableName: string) {
|
|
142
|
+
return `SELECT
|
|
143
|
+
COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME),COLUMN_NAME,'IsComputed')
|
|
144
|
+
AS IS_COMPUTED,
|
|
145
|
+
COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity')
|
|
146
|
+
AS IS_IDENTITY,
|
|
147
|
+
*
|
|
148
|
+
FROM INFORMATION_SCHEMA.COLUMNS
|
|
149
|
+
WHERE TABLE_NAME='${tableName}'`
|
|
150
|
+
}
|
|
84
151
|
|
|
85
152
|
constructor(config: MSSQLConfig) {
|
|
86
|
-
super(
|
|
153
|
+
super(SqlClients.MS_SQL)
|
|
87
154
|
this.config = config
|
|
88
155
|
const clientCfg = {
|
|
89
156
|
...this.config,
|
|
90
157
|
options: {
|
|
91
158
|
encrypt: this.config.encrypt,
|
|
159
|
+
enableArithAbort: true,
|
|
92
160
|
},
|
|
93
161
|
}
|
|
94
162
|
delete clientCfg.encrypt
|
|
@@ -99,14 +167,75 @@ module MSSQLModule {
|
|
|
99
167
|
|
|
100
168
|
async connect() {
|
|
101
169
|
try {
|
|
102
|
-
|
|
103
|
-
this.client = client.request()
|
|
170
|
+
this.client = await this.pool.connect()
|
|
104
171
|
} catch (err) {
|
|
105
172
|
// @ts-ignore
|
|
106
173
|
throw new Error(err)
|
|
107
174
|
}
|
|
108
175
|
}
|
|
109
176
|
|
|
177
|
+
async runSQL(sql: string) {
|
|
178
|
+
return (await internalQuery(this.client, getSqlQuery(sql))).recordset
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Fetches the tables from the sql server database and assigns them to the datasource.
|
|
183
|
+
* @param {*} datasourceId - datasourceId to fetch
|
|
184
|
+
* @param entities - the tables that are to be built
|
|
185
|
+
*/
|
|
186
|
+
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
|
187
|
+
await this.connect()
|
|
188
|
+
let tableNames = await this.runSQL(this.TABLES_SQL)
|
|
189
|
+
if (tableNames == null || !Array.isArray(tableNames)) {
|
|
190
|
+
throw "Unable to get list of tables in database"
|
|
191
|
+
}
|
|
192
|
+
tableNames = tableNames
|
|
193
|
+
.map((record: any) => record.TABLE_NAME)
|
|
194
|
+
.filter((name: string) => this.MASTER_TABLES.indexOf(name) === -1)
|
|
195
|
+
|
|
196
|
+
const tables: Record<string, Table> = {}
|
|
197
|
+
for (let tableName of tableNames) {
|
|
198
|
+
// get the column definition (type)
|
|
199
|
+
const definition = await this.runSQL(this.getDefinitionSQL(tableName))
|
|
200
|
+
// find primary key constraints
|
|
201
|
+
const constraints = await this.runSQL(this.getConstraintsSQL(tableName))
|
|
202
|
+
// find the computed and identity columns (auto columns)
|
|
203
|
+
const columns = await this.runSQL(this.getAutoColumnsSQL(tableName))
|
|
204
|
+
const primaryKeys = constraints
|
|
205
|
+
.filter(
|
|
206
|
+
(constraint: any) => constraint.CONSTRAINT_TYPE === "PRIMARY KEY"
|
|
207
|
+
)
|
|
208
|
+
.map((constraint: any) => constraint.COLUMN_NAME)
|
|
209
|
+
const autoColumns = columns
|
|
210
|
+
.filter((col: any) => col.IS_COMPUTED || col.IS_IDENTITY)
|
|
211
|
+
.map((col: any) => col.COLUMN_NAME)
|
|
212
|
+
|
|
213
|
+
let schema: TableSchema = {}
|
|
214
|
+
for (let def of definition) {
|
|
215
|
+
const name = def.COLUMN_NAME
|
|
216
|
+
if (typeof name !== "string") {
|
|
217
|
+
continue
|
|
218
|
+
}
|
|
219
|
+
const type: string = convertSqlType(def.DATA_TYPE)
|
|
220
|
+
|
|
221
|
+
schema[name] = {
|
|
222
|
+
autocolumn: !!autoColumns.find((col: string) => col === name),
|
|
223
|
+
name: name,
|
|
224
|
+
type,
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
tables[tableName] = {
|
|
228
|
+
_id: buildExternalTableId(datasourceId, tableName),
|
|
229
|
+
primary: primaryKeys,
|
|
230
|
+
name: tableName,
|
|
231
|
+
schema,
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const final = finaliseExternalTables(tables, entities)
|
|
235
|
+
this.tables = final.tables
|
|
236
|
+
this.schemaErrors = final.errors
|
|
237
|
+
}
|
|
238
|
+
|
|
110
239
|
async read(query: SqlQuery | string) {
|
|
111
240
|
await this.connect()
|
|
112
241
|
const response = await internalQuery(this.client, getSqlQuery(query))
|
|
@@ -132,10 +261,13 @@ module MSSQLModule {
|
|
|
132
261
|
}
|
|
133
262
|
|
|
134
263
|
async query(json: QueryJson) {
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
|
|
264
|
+
await this.connect()
|
|
265
|
+
const operation = this._operation(json)
|
|
266
|
+
const queryFn = (query: any, op: string) =>
|
|
267
|
+
internalQuery(this.client, query, op)
|
|
268
|
+
const processFn = (result: any) =>
|
|
269
|
+
result.recordset ? result.recordset : [{ [operation]: true }]
|
|
270
|
+
return this.queryWithReturning(json, queryFn, processFn)
|
|
139
271
|
}
|
|
140
272
|
}
|
|
141
273
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
DatasourceFieldTypes,
|
|
4
4
|
QueryTypes,
|
|
5
5
|
} from "../definitions/datasource"
|
|
6
|
+
import { IntegrationBase } from "./base/IntegrationBase"
|
|
6
7
|
|
|
7
8
|
module MongoDBModule {
|
|
8
9
|
const { MongoClient } = require("mongodb")
|
|
@@ -62,7 +63,7 @@ module MongoDBModule {
|
|
|
62
63
|
},
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
class MongoIntegration {
|
|
66
|
+
class MongoIntegration implements IntegrationBase {
|
|
66
67
|
private config: MongoDBConfig
|
|
67
68
|
private client: any
|
|
68
69
|
|
|
@@ -2,22 +2,22 @@ import {
|
|
|
2
2
|
Integration,
|
|
3
3
|
DatasourceFieldTypes,
|
|
4
4
|
QueryTypes,
|
|
5
|
-
Operation,
|
|
6
5
|
QueryJson,
|
|
7
6
|
SqlQuery,
|
|
8
7
|
} from "../definitions/datasource"
|
|
9
8
|
import { Table, TableSchema } from "../definitions/common"
|
|
10
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getSqlQuery,
|
|
11
|
+
SqlClients,
|
|
12
|
+
buildExternalTableId,
|
|
13
|
+
convertSqlType,
|
|
14
|
+
finaliseExternalTables,
|
|
15
|
+
} from "./utils"
|
|
16
|
+
import { DatasourcePlus } from "./base/datasourcePlus"
|
|
11
17
|
|
|
12
18
|
module MySQLModule {
|
|
13
19
|
const mysql = require("mysql2")
|
|
14
20
|
const Sql = require("./base/sql")
|
|
15
|
-
const {
|
|
16
|
-
buildExternalTableId,
|
|
17
|
-
convertType,
|
|
18
|
-
copyExistingPropsOver,
|
|
19
|
-
} = require("./utils")
|
|
20
|
-
const { FieldTypes } = require("../constants")
|
|
21
21
|
|
|
22
22
|
interface MySQLConfig {
|
|
23
23
|
host: string
|
|
@@ -28,30 +28,6 @@ module MySQLModule {
|
|
|
28
28
|
ssl?: object
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
const TYPE_MAP = {
|
|
32
|
-
text: FieldTypes.LONGFORM,
|
|
33
|
-
blob: FieldTypes.LONGFORM,
|
|
34
|
-
enum: FieldTypes.STRING,
|
|
35
|
-
varchar: FieldTypes.STRING,
|
|
36
|
-
float: FieldTypes.NUMBER,
|
|
37
|
-
int: FieldTypes.NUMBER,
|
|
38
|
-
numeric: FieldTypes.NUMBER,
|
|
39
|
-
bigint: FieldTypes.NUMBER,
|
|
40
|
-
mediumint: FieldTypes.NUMBER,
|
|
41
|
-
decimal: FieldTypes.NUMBER,
|
|
42
|
-
dec: FieldTypes.NUMBER,
|
|
43
|
-
double: FieldTypes.NUMBER,
|
|
44
|
-
real: FieldTypes.NUMBER,
|
|
45
|
-
fixed: FieldTypes.NUMBER,
|
|
46
|
-
smallint: FieldTypes.NUMBER,
|
|
47
|
-
timestamp: FieldTypes.DATETIME,
|
|
48
|
-
date: FieldTypes.DATETIME,
|
|
49
|
-
datetime: FieldTypes.DATETIME,
|
|
50
|
-
time: FieldTypes.DATETIME,
|
|
51
|
-
tinyint: FieldTypes.BOOLEAN,
|
|
52
|
-
json: DatasourceFieldTypes.JSON,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
31
|
const SCHEMA: Integration = {
|
|
56
32
|
docs: "https://github.com/mysqljs/mysql",
|
|
57
33
|
plus: true,
|
|
@@ -131,12 +107,14 @@ module MySQLModule {
|
|
|
131
107
|
})
|
|
132
108
|
}
|
|
133
109
|
|
|
134
|
-
class MySQLIntegration extends Sql {
|
|
110
|
+
class MySQLIntegration extends Sql implements DatasourcePlus {
|
|
135
111
|
private config: MySQLConfig
|
|
136
112
|
private readonly client: any
|
|
113
|
+
public tables: Record<string, Table> = {}
|
|
114
|
+
public schemaErrors: Record<string, string> = {}
|
|
137
115
|
|
|
138
116
|
constructor(config: MySQLConfig) {
|
|
139
|
-
super(
|
|
117
|
+
super(SqlClients.MY_SQL)
|
|
140
118
|
this.config = config
|
|
141
119
|
if (config.ssl && Object.keys(config.ssl).length === 0) {
|
|
142
120
|
delete config.ssl
|
|
@@ -156,7 +134,9 @@ module MySQLModule {
|
|
|
156
134
|
false
|
|
157
135
|
)
|
|
158
136
|
const tableNames = tablesResp.map(
|
|
159
|
-
(obj: any) =>
|
|
137
|
+
(obj: any) =>
|
|
138
|
+
obj[`Tables_in_${database}`] ||
|
|
139
|
+
obj[`Tables_in_${database.toLowerCase()}`]
|
|
160
140
|
)
|
|
161
141
|
for (let tableName of tableNames) {
|
|
162
142
|
const primaryKeys = []
|
|
@@ -181,14 +161,10 @@ module MySQLModule {
|
|
|
181
161
|
schema[columnName] = {
|
|
182
162
|
name: columnName,
|
|
183
163
|
autocolumn: isAuto,
|
|
184
|
-
type:
|
|
164
|
+
type: convertSqlType(column.Type),
|
|
185
165
|
constraints,
|
|
186
166
|
}
|
|
187
167
|
}
|
|
188
|
-
// for now just default to first column
|
|
189
|
-
if (primaryKeys.length === 0) {
|
|
190
|
-
primaryKeys.push(descResp[0].Field)
|
|
191
|
-
}
|
|
192
168
|
if (!tables[tableName]) {
|
|
193
169
|
tables[tableName] = {
|
|
194
170
|
_id: buildExternalTableId(datasourceId, tableName),
|
|
@@ -197,12 +173,12 @@ module MySQLModule {
|
|
|
197
173
|
schema,
|
|
198
174
|
}
|
|
199
175
|
}
|
|
200
|
-
|
|
201
|
-
copyExistingPropsOver(tableName, tables, entities)
|
|
202
176
|
}
|
|
203
177
|
|
|
204
178
|
this.client.end()
|
|
205
|
-
|
|
179
|
+
const final = finaliseExternalTables(tables, entities)
|
|
180
|
+
this.tables = final.tables
|
|
181
|
+
this.schemaErrors = final.errors
|
|
206
182
|
}
|
|
207
183
|
|
|
208
184
|
async create(query: SqlQuery | string) {
|
|
@@ -210,7 +186,7 @@ module MySQLModule {
|
|
|
210
186
|
return results.length ? results : [{ created: true }]
|
|
211
187
|
}
|
|
212
188
|
|
|
213
|
-
read(query: SqlQuery | string) {
|
|
189
|
+
async read(query: SqlQuery | string) {
|
|
214
190
|
return internalQuery(this.client, getSqlQuery(query))
|
|
215
191
|
}
|
|
216
192
|
|
|
@@ -224,60 +200,12 @@ module MySQLModule {
|
|
|
224
200
|
return results.length ? results : [{ deleted: true }]
|
|
225
201
|
}
|
|
226
202
|
|
|
227
|
-
async getReturningRow(json: QueryJson) {
|
|
228
|
-
if (!json.extra || !json.extra.idFilter) {
|
|
229
|
-
return {}
|
|
230
|
-
}
|
|
231
|
-
const input = this._query({
|
|
232
|
-
endpoint: {
|
|
233
|
-
...json.endpoint,
|
|
234
|
-
operation: Operation.READ,
|
|
235
|
-
},
|
|
236
|
-
fields: [],
|
|
237
|
-
filters: json.extra.idFilter,
|
|
238
|
-
paginate: {
|
|
239
|
-
limit: 1,
|
|
240
|
-
},
|
|
241
|
-
})
|
|
242
|
-
return internalQuery(this.client, input, false)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// when creating if an ID has been inserted need to make sure
|
|
246
|
-
// the id filter is enriched with it before trying to retrieve the row
|
|
247
|
-
checkLookupKeys(results: any, json: QueryJson) {
|
|
248
|
-
if (!results?.insertId || !json.meta?.table || !json.meta.table.primary) {
|
|
249
|
-
return json
|
|
250
|
-
}
|
|
251
|
-
const primaryKey = json.meta.table.primary?.[0]
|
|
252
|
-
json.extra = {
|
|
253
|
-
idFilter: {
|
|
254
|
-
equal: {
|
|
255
|
-
[primaryKey]: results.insertId,
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
}
|
|
259
|
-
return json
|
|
260
|
-
}
|
|
261
|
-
|
|
262
203
|
async query(json: QueryJson) {
|
|
263
|
-
const operation = this._operation(json)
|
|
264
204
|
this.client.connect()
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
// need to manage returning, a feature mySQL can't do
|
|
268
|
-
if (operation === operation.DELETE) {
|
|
269
|
-
row = this.getReturningRow(json)
|
|
270
|
-
}
|
|
271
|
-
const results = await internalQuery(this.client, input, false)
|
|
272
|
-
// same as delete, manage returning
|
|
273
|
-
if (operation === Operation.CREATE || operation === Operation.UPDATE) {
|
|
274
|
-
row = this.getReturningRow(this.checkLookupKeys(results, json))
|
|
275
|
-
}
|
|
205
|
+
const queryFn = (query: any) => internalQuery(this.client, query, false)
|
|
206
|
+
const output = await this.queryWithReturning(json, queryFn)
|
|
276
207
|
this.client.end()
|
|
277
|
-
|
|
278
|
-
return row
|
|
279
|
-
}
|
|
280
|
-
return results.length ? results : [{ [operation.toLowerCase()]: true }]
|
|
208
|
+
return output
|
|
281
209
|
}
|
|
282
210
|
}
|
|
283
211
|
|