@budibase/server 1.0.78 → 1.0.79-alpha.10
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/__mocks__/node-fetch.ts +1 -0
- package/builder/assets/index.1a081633.js +1288 -0
- package/builder/assets/{index.c8d1e8f0.css → index.c57242d4.css} +2 -2
- package/builder/assets/{vendor.20f80cec.js → vendor.a7c6ad0a.js} +190 -216
- package/builder/index.html +3 -3
- package/coverage/clover.xml +2399 -2336
- package/coverage/coverage-final.json +138 -137
- package/coverage/lcov-report/api/controllers/analytics.js.html +6 -6
- package/coverage/lcov-report/api/controllers/apikeys.js.html +6 -6
- package/coverage/lcov-report/api/controllers/application.js.html +152 -149
- package/coverage/lcov-report/api/controllers/auth.js.html +7 -7
- package/coverage/lcov-report/api/controllers/automation.js.html +21 -21
- package/coverage/lcov-report/api/controllers/backup.js.html +3 -3
- package/coverage/lcov-report/api/controllers/cloud.js.html +11 -11
- package/coverage/lcov-report/api/controllers/component.js.html +5 -5
- package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
- package/coverage/lcov-report/api/controllers/dev.js.html +19 -19
- package/coverage/lcov-report/api/controllers/index.html +16 -16
- package/coverage/lcov-report/api/controllers/integration.js.html +4 -4
- package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
- package/coverage/lcov-report/api/controllers/metadata.js.html +9 -9
- package/coverage/lcov-report/api/controllers/migrations.js.html +4 -4
- package/coverage/lcov-report/api/controllers/permission.js.html +15 -15
- package/coverage/lcov-report/api/controllers/query/index.html +1 -1
- package/coverage/lcov-report/api/controllers/query/index.js.html +26 -26
- package/coverage/lcov-report/api/controllers/query/validation.js.html +10 -10
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +9 -9
- package/coverage/lcov-report/api/controllers/row/external.js.html +16 -16
- package/coverage/lcov-report/api/controllers/row/index.html +27 -27
- package/coverage/lcov-report/api/controllers/row/index.js.html +46 -46
- package/coverage/lcov-report/api/controllers/row/internal.js.html +94 -82
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +204 -204
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +24 -24
- package/coverage/lcov-report/api/controllers/row/utils.js.html +29 -29
- package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
- package/coverage/lcov-report/api/controllers/script.js.html +4 -4
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +49 -49
- package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
- package/coverage/lcov-report/api/controllers/table/index.html +11 -11
- package/coverage/lcov-report/api/controllers/table/index.js.html +47 -44
- package/coverage/lcov-report/api/controllers/table/internal.js.html +50 -50
- package/coverage/lcov-report/api/controllers/table/utils.js.html +80 -80
- package/coverage/lcov-report/api/controllers/templates.js.html +5 -5
- package/coverage/lcov-report/api/controllers/user.js.html +19 -19
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +14 -14
- package/coverage/lcov-report/api/controllers/view/utils.js.html +12 -12
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
- package/coverage/lcov-report/api/controllers/webhook.js.html +18 -27
- package/coverage/lcov-report/api/index.html +10 -10
- package/coverage/lcov-report/api/index.js.html +37 -28
- package/coverage/lcov-report/api/routes/analytics.js.html +6 -6
- package/coverage/lcov-report/api/routes/apikeys.js.html +8 -8
- package/coverage/lcov-report/api/routes/application.js.html +9 -9
- package/coverage/lcov-report/api/routes/auth.js.html +6 -6
- package/coverage/lcov-report/api/routes/automation.js.html +19 -109
- package/coverage/lcov-report/api/routes/backup.js.html +8 -8
- package/coverage/lcov-report/api/routes/cloud.js.html +8 -8
- package/coverage/lcov-report/api/routes/component.js.html +8 -8
- package/coverage/lcov-report/api/routes/datasource.js.html +18 -156
- package/coverage/lcov-report/api/routes/deploy.js.html +8 -8
- package/coverage/lcov-report/api/routes/dev.js.html +13 -13
- package/coverage/lcov-report/api/routes/index.html +35 -35
- package/coverage/lcov-report/api/routes/index.js.html +38 -32
- package/coverage/lcov-report/api/routes/integration.js.html +8 -8
- package/coverage/lcov-report/api/routes/layout.js.html +8 -8
- package/coverage/lcov-report/api/routes/metadata.js.html +9 -9
- package/coverage/lcov-report/api/routes/migrations.js.html +7 -7
- package/coverage/lcov-report/api/routes/permission.js.html +16 -58
- package/coverage/lcov-report/api/routes/query.js.html +10 -10
- package/coverage/lcov-report/api/routes/role.js.html +15 -78
- package/coverage/lcov-report/api/routes/routing.js.html +8 -8
- package/coverage/lcov-report/api/routes/row.js.html +17 -14
- package/coverage/lcov-report/api/routes/screen.js.html +14 -95
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/static.js.html +13 -13
- package/coverage/lcov-report/api/routes/table.js.html +17 -62
- package/coverage/lcov-report/api/routes/templates.js.html +8 -8
- package/coverage/lcov-report/api/routes/user.js.html +8 -8
- package/coverage/lcov-report/api/routes/utils/index.html +111 -0
- package/coverage/lcov-report/api/routes/utils/validators.js.html +737 -0
- package/coverage/lcov-report/api/routes/view.js.html +10 -10
- package/coverage/lcov-report/api/routes/webhook.js.html +14 -62
- package/coverage/lcov-report/automations/actions.js.html +24 -24
- package/coverage/lcov-report/automations/automationUtils.js.html +5 -5
- package/coverage/lcov-report/automations/bullboard.js.html +16 -16
- package/coverage/lcov-report/automations/index.html +1 -1
- package/coverage/lcov-report/automations/index.js.html +7 -7
- package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
- package/coverage/lcov-report/automations/steps/createRow.js.html +7 -7
- package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +7 -7
- package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
- package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
- package/coverage/lcov-report/automations/steps/filter.js.html +12 -9
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
- package/coverage/lcov-report/automations/steps/queryRows.js.html +11 -11
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
- package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
- package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
- package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
- package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
- package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
- 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 +26 -26
- package/coverage/lcov-report/automations/utils.js.html +35 -35
- package/coverage/lcov-report/constants/index.html +5 -5
- package/coverage/lcov-report/constants/index.js.html +40 -28
- package/coverage/lcov-report/constants/layouts.js.html +5 -5
- package/coverage/lcov-report/constants/screens.js.html +4 -4
- package/coverage/lcov-report/db/client.js.html +18 -18
- package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
- package/coverage/lcov-report/db/index.html +15 -15
- package/coverage/lcov-report/db/index.js.html +3 -3
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +21 -21
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +36 -36
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +30 -30
- package/coverage/lcov-report/db/newid.js.html +4 -4
- package/coverage/lcov-report/db/utils.js.html +123 -87
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +8 -8
- package/coverage/lcov-report/events/utils.js.html +18 -18
- package/coverage/lcov-report/index.html +89 -74
- 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 +5 -5
- package/coverage/lcov-report/middleware/authorized.js.html +29 -29
- package/coverage/lcov-report/middleware/builder.js.html +16 -16
- package/coverage/lcov-report/middleware/currentapp.js.html +44 -44
- package/coverage/lcov-report/middleware/index.html +1 -1
- package/coverage/lcov-report/middleware/joi-validator.js.html +14 -14
- package/coverage/lcov-report/middleware/resourceId.js.html +29 -29
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/usageQuota.js.html +17 -17
- package/coverage/lcov-report/middleware/utils.js.html +4 -4
- package/coverage/lcov-report/threads/automation.js.html +1 -1
- package/coverage/lcov-report/threads/index.html +19 -19
- package/coverage/lcov-report/threads/index.js.html +10 -10
- package/coverage/lcov-report/threads/query.js.html +123 -39
- package/coverage/lcov-report/threads/utils.js.html +14 -14
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
- package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
- package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
- package/coverage/lcov-report/utilities/global.js.html +28 -28
- package/coverage/lcov-report/utilities/index.html +18 -18
- package/coverage/lcov-report/utilities/index.js.html +24 -24
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +9 -9
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +6 -6
- package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +60 -60
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +13 -13
- package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
- package/coverage/lcov-report/utilities/security.js.html +8 -8
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.js.html +12 -12
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +8 -8
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +5 -5
- package/coverage/lcov-report/utilities/workerRequests.js.html +200 -53
- package/coverage/lcov.info +3323 -3224
- package/dist/api/controllers/application.js +1 -0
- package/dist/api/controllers/public/applications.js +94 -0
- package/dist/api/controllers/public/mapping/applications.js +29 -0
- package/dist/api/controllers/public/mapping/index.js +11 -0
- package/dist/api/controllers/public/mapping/queries.js +36 -0
- package/dist/api/controllers/public/mapping/rows.js +24 -0
- package/dist/api/controllers/public/mapping/tables.js +23 -0
- package/dist/api/controllers/public/mapping/types.js +2 -0
- package/dist/api/controllers/public/mapping/users.js +29 -0
- package/dist/api/controllers/public/queries.js +38 -0
- package/dist/api/controllers/public/rows.js +97 -0
- package/dist/api/controllers/public/tables.js +75 -0
- package/dist/api/controllers/public/users.js +95 -0
- package/dist/api/controllers/public/utils.js +49 -0
- package/dist/api/controllers/row/internal.js +4 -1
- package/dist/api/controllers/table/index.js +2 -1
- package/dist/api/controllers/webhook.js +3 -5
- package/dist/api/index.js +3 -1
- package/dist/api/routes/automation.js +3 -31
- package/dist/api/routes/datasource.js +3 -50
- package/dist/api/routes/index.js +2 -0
- package/dist/api/routes/permission.js +4 -14
- package/dist/api/routes/public/applications.js +141 -0
- package/dist/api/routes/public/index.js +68 -0
- package/dist/api/routes/public/middleware/mapper.js +94 -0
- package/dist/api/routes/public/queries.js +77 -0
- package/dist/api/routes/public/rows.js +229 -0
- package/dist/api/routes/public/tables.js +154 -0
- package/dist/api/routes/public/users.js +137 -0
- package/dist/api/routes/public/utils/Endpoint.js +36 -0
- package/dist/api/routes/role.js +3 -19
- package/dist/api/routes/row.js +3 -4
- package/dist/api/routes/screen.js +2 -23
- package/dist/api/routes/table.js +3 -17
- package/dist/api/routes/tests/utilities/index.js +23 -0
- package/dist/api/routes/utils/validators.js +200 -0
- package/dist/api/routes/webhook.js +2 -17
- package/dist/automations/steps/filter.js +2 -2
- package/dist/automations/steps/queryRows.js +1 -1
- package/dist/automations/utils.js +2 -2
- package/dist/constants/index.js +3 -0
- package/dist/db/utils.js +11 -0
- package/dist/definitions/openapi.js +6 -0
- package/dist/integrations/googlesheets.js +3 -0
- package/dist/integrations/microsoftSqlServer.js +35 -29
- package/dist/integrations/mysql.js +30 -26
- package/dist/integrations/oracle.js +14 -19
- package/dist/integrations/postgres.js +34 -28
- package/dist/package.json +8 -7
- package/dist/tests/utilities/TestConfiguration.js +25 -8
- package/dist/threads/query.js +33 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/workerRequests.js +50 -15
- package/package.json +9 -8
- package/scripts/integrations/oracle/oracle.md +2 -2
- package/scripts/integrations/postgres/init.sql +5 -3
- package/scripts/likeCypress.ts +9 -6
- package/specs/generate.js +83 -0
- package/specs/openapi.json +2222 -0
- package/specs/openapi.yaml +1530 -0
- package/specs/parameters.js +59 -0
- package/specs/resources/application.js +101 -0
- package/specs/resources/index.js +24 -0
- package/specs/resources/misc.js +12 -0
- package/specs/resources/query.js +189 -0
- package/specs/resources/row.js +125 -0
- package/specs/resources/table.js +191 -0
- package/specs/resources/user.js +126 -0
- package/specs/resources/utils/Resource.js +26 -0
- package/specs/resources/utils/index.js +11 -0
- package/specs/security.js +7 -0
- package/src/api/controllers/application.js +1 -0
- package/src/api/controllers/public/applications.ts +74 -0
- package/src/api/controllers/public/mapping/applications.ts +32 -0
- package/src/api/controllers/public/mapping/index.ts +13 -0
- package/src/api/controllers/public/mapping/queries.ts +39 -0
- package/src/api/controllers/public/mapping/rows.ts +31 -0
- package/src/api/controllers/public/mapping/tables.ts +26 -0
- package/src/api/controllers/public/mapping/types.ts +13 -0
- package/src/api/controllers/public/mapping/users.ts +32 -0
- package/src/api/controllers/public/queries.ts +20 -0
- package/src/api/controllers/public/rows.ts +77 -0
- package/src/api/controllers/public/tables.ts +56 -0
- package/src/api/controllers/public/users.ts +82 -0
- package/src/api/controllers/public/utils.ts +38 -0
- package/src/api/controllers/row/internal.js +4 -0
- package/src/api/controllers/table/index.js +2 -1
- package/src/api/controllers/webhook.js +3 -6
- package/src/api/index.js +4 -1
- package/src/api/routes/automation.js +3 -33
- package/src/api/routes/datasource.js +6 -52
- package/src/api/routes/index.js +2 -0
- package/src/api/routes/permission.js +4 -18
- package/src/api/routes/public/applications.ts +156 -0
- package/src/api/routes/public/index.ts +82 -0
- package/src/api/routes/public/middleware/mapper.ts +81 -0
- package/src/api/routes/public/queries.ts +81 -0
- package/src/api/routes/public/rows.ts +242 -0
- package/src/api/routes/public/tables.ts +169 -0
- package/src/api/routes/public/tests/compare.spec.js +184 -0
- package/src/api/routes/public/users.ts +144 -0
- package/src/api/routes/public/utils/Endpoint.ts +51 -0
- package/src/api/routes/role.js +3 -24
- package/src/api/routes/row.js +3 -2
- package/src/api/routes/screen.js +2 -29
- package/src/api/routes/table.js +4 -19
- package/src/api/routes/tests/utilities/index.js +24 -0
- package/src/api/routes/utils/validators.js +219 -0
- package/src/api/routes/webhook.js +2 -18
- package/src/automations/steps/filter.js +3 -2
- package/src/automations/steps/queryRows.js +1 -1
- package/src/automations/utils.js +2 -2
- package/src/constants/index.js +4 -0
- package/src/db/utils.js +12 -0
- package/src/definitions/common.ts +4 -0
- package/src/definitions/openapi.ts +943 -0
- package/src/integrations/base/datasourcePlus.ts +3 -0
- package/src/integrations/googlesheets.ts +5 -2
- package/src/integrations/microsoftSqlServer.ts +38 -33
- package/src/integrations/mysql.ts +38 -36
- package/src/integrations/oracle.ts +27 -35
- package/src/integrations/postgres.ts +33 -26
- package/src/tests/utilities/TestConfiguration.js +23 -2
- package/src/threads/query.js +37 -9
- package/src/utilities/workerRequests.js +65 -16
- package/builder/assets/index.ab059cf2.js +0 -1352
- package/scripts/proxy/generateProxyConfig.js +0 -70
|
@@ -5,5 +5,8 @@ export interface DatasourcePlus extends IntegrationBase {
|
|
|
5
5
|
tables: Record<string, Table>
|
|
6
6
|
schemaErrors: Record<string, string>
|
|
7
7
|
|
|
8
|
+
// if the datasource supports the use of bindings directly (to protect against SQL injection)
|
|
9
|
+
// this returns the format of the identifier
|
|
10
|
+
getBindingIdentifier(): string
|
|
8
11
|
buildSchema(datasourceId: string, entities: Record<string, Table>): any
|
|
9
12
|
}
|
|
@@ -6,11 +6,10 @@ import {
|
|
|
6
6
|
} from "../definitions/datasource"
|
|
7
7
|
import { OAuth2Client } from "google-auth-library"
|
|
8
8
|
import { DatasourcePlus } from "./base/datasourcePlus"
|
|
9
|
-
import {
|
|
9
|
+
import { Table, TableSchema } from "../definitions/common"
|
|
10
10
|
import { buildExternalTableId } from "./utils"
|
|
11
11
|
import { DataSourceOperation, FieldTypes } from "../constants"
|
|
12
12
|
import { GoogleSpreadsheet } from "google-spreadsheet"
|
|
13
|
-
import { table } from "console"
|
|
14
13
|
|
|
15
14
|
module GoogleSheetsModule {
|
|
16
15
|
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
@@ -112,6 +111,10 @@ module GoogleSheetsModule {
|
|
|
112
111
|
this.client = new GoogleSpreadsheet(spreadsheetId)
|
|
113
112
|
}
|
|
114
113
|
|
|
114
|
+
getBindingIdentifier() {
|
|
115
|
+
return ""
|
|
116
|
+
}
|
|
117
|
+
|
|
115
118
|
/**
|
|
116
119
|
* Pull the spreadsheet ID out from a valid google sheets URL
|
|
117
120
|
* @param spreadsheetId - the URL or standard spreadsheetId of the google sheet
|
|
@@ -79,34 +79,9 @@ module MSSQLModule {
|
|
|
79
79
|
},
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
async function internalQuery(
|
|
83
|
-
client: any,
|
|
84
|
-
query: SqlQuery,
|
|
85
|
-
operation: string | undefined = undefined
|
|
86
|
-
) {
|
|
87
|
-
const request = client.request()
|
|
88
|
-
try {
|
|
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)
|
|
102
|
-
} catch (err) {
|
|
103
|
-
// @ts-ignore
|
|
104
|
-
throw new Error(err)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
82
|
class SqlServerIntegration extends Sql implements DatasourcePlus {
|
|
109
83
|
private readonly config: MSSQLConfig
|
|
84
|
+
private index: number = 0
|
|
110
85
|
static pool: any
|
|
111
86
|
public tables: Record<string, Table> = {}
|
|
112
87
|
public schemaErrors: Record<string, string> = {}
|
|
@@ -121,6 +96,33 @@ module MSSQLModule {
|
|
|
121
96
|
TABLES_SQL =
|
|
122
97
|
"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'"
|
|
123
98
|
|
|
99
|
+
async internalQuery(
|
|
100
|
+
query: SqlQuery,
|
|
101
|
+
operation: string | undefined = undefined
|
|
102
|
+
) {
|
|
103
|
+
const client = this.client
|
|
104
|
+
const request = client.request()
|
|
105
|
+
this.index = 0
|
|
106
|
+
try {
|
|
107
|
+
if (Array.isArray(query.bindings)) {
|
|
108
|
+
let count = 0
|
|
109
|
+
for (let binding of query.bindings) {
|
|
110
|
+
request.input(`p${count++}`, binding)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// this is a hack to get the inserted ID back,
|
|
114
|
+
// no way to do this with Knex nicely
|
|
115
|
+
const sql =
|
|
116
|
+
operation === Operation.CREATE
|
|
117
|
+
? `${query.sql}; SELECT SCOPE_IDENTITY() AS id;`
|
|
118
|
+
: query.sql
|
|
119
|
+
return await request.query(sql)
|
|
120
|
+
} catch (err) {
|
|
121
|
+
// @ts-ignore
|
|
122
|
+
throw new Error(err)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
124
126
|
getDefinitionSQL(tableName: string) {
|
|
125
127
|
return `select *
|
|
126
128
|
from INFORMATION_SCHEMA.COLUMNS
|
|
@@ -165,6 +167,10 @@ module MSSQLModule {
|
|
|
165
167
|
}
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
getBindingIdentifier(): string {
|
|
171
|
+
return `(@p${this.index++})`
|
|
172
|
+
}
|
|
173
|
+
|
|
168
174
|
async connect() {
|
|
169
175
|
try {
|
|
170
176
|
this.client = await this.pool.connect()
|
|
@@ -175,7 +181,7 @@ module MSSQLModule {
|
|
|
175
181
|
}
|
|
176
182
|
|
|
177
183
|
async runSQL(sql: string) {
|
|
178
|
-
return (await internalQuery(
|
|
184
|
+
return (await this.internalQuery(getSqlQuery(sql))).recordset
|
|
179
185
|
}
|
|
180
186
|
|
|
181
187
|
/**
|
|
@@ -238,33 +244,32 @@ module MSSQLModule {
|
|
|
238
244
|
|
|
239
245
|
async read(query: SqlQuery | string) {
|
|
240
246
|
await this.connect()
|
|
241
|
-
const response = await internalQuery(
|
|
247
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
242
248
|
return response.recordset
|
|
243
249
|
}
|
|
244
250
|
|
|
245
251
|
async create(query: SqlQuery | string) {
|
|
246
252
|
await this.connect()
|
|
247
|
-
const response = await internalQuery(
|
|
253
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
248
254
|
return response.recordset || [{ created: true }]
|
|
249
255
|
}
|
|
250
256
|
|
|
251
257
|
async update(query: SqlQuery | string) {
|
|
252
258
|
await this.connect()
|
|
253
|
-
const response = await internalQuery(
|
|
259
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
254
260
|
return response.recordset || [{ updated: true }]
|
|
255
261
|
}
|
|
256
262
|
|
|
257
263
|
async delete(query: SqlQuery | string) {
|
|
258
264
|
await this.connect()
|
|
259
|
-
const response = await internalQuery(
|
|
265
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
260
266
|
return response.recordset || [{ deleted: true }]
|
|
261
267
|
}
|
|
262
268
|
|
|
263
269
|
async query(json: QueryJson) {
|
|
264
270
|
await this.connect()
|
|
265
271
|
const operation = this._operation(json)
|
|
266
|
-
const queryFn = (query: any, op: string) =>
|
|
267
|
-
internalQuery(this.client, query, op)
|
|
272
|
+
const queryFn = (query: any, op: string) => this.internalQuery(query, op)
|
|
268
273
|
const processFn = (result: any) =>
|
|
269
274
|
result.recordset ? result.recordset : [{ [operation]: true }]
|
|
270
275
|
return this.queryWithReturning(json, queryFn, processFn)
|
|
@@ -80,33 +80,6 @@ module MySQLModule {
|
|
|
80
80
|
},
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
function internalQuery(
|
|
84
|
-
client: any,
|
|
85
|
-
query: SqlQuery,
|
|
86
|
-
connect: boolean = true
|
|
87
|
-
): Promise<any[] | any> {
|
|
88
|
-
// Node MySQL is callback based, so we must wrap our call in a promise
|
|
89
|
-
return new Promise((resolve, reject) => {
|
|
90
|
-
if (connect) {
|
|
91
|
-
client.connect()
|
|
92
|
-
}
|
|
93
|
-
return client.query(
|
|
94
|
-
query.sql,
|
|
95
|
-
query.bindings || {},
|
|
96
|
-
(error: any, results: object[]) => {
|
|
97
|
-
if (error) {
|
|
98
|
-
reject(error)
|
|
99
|
-
} else {
|
|
100
|
-
resolve(results)
|
|
101
|
-
}
|
|
102
|
-
if (connect) {
|
|
103
|
-
client.end()
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
)
|
|
107
|
-
})
|
|
108
|
-
}
|
|
109
|
-
|
|
110
83
|
class MySQLIntegration extends Sql implements DatasourcePlus {
|
|
111
84
|
private config: MySQLConfig
|
|
112
85
|
private readonly client: any
|
|
@@ -122,14 +95,44 @@ module MySQLModule {
|
|
|
122
95
|
this.client = mysql.createConnection(config)
|
|
123
96
|
}
|
|
124
97
|
|
|
98
|
+
getBindingIdentifier(): string {
|
|
99
|
+
return "?"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
internalQuery(
|
|
103
|
+
query: SqlQuery,
|
|
104
|
+
connect: boolean = true
|
|
105
|
+
): Promise<any[] | any> {
|
|
106
|
+
const client = this.client
|
|
107
|
+
// Node MySQL is callback based, so we must wrap our call in a promise
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
if (connect) {
|
|
110
|
+
client.connect()
|
|
111
|
+
}
|
|
112
|
+
return client.query(
|
|
113
|
+
query.sql,
|
|
114
|
+
query.bindings || {},
|
|
115
|
+
(error: any, results: object[]) => {
|
|
116
|
+
if (error) {
|
|
117
|
+
reject(error)
|
|
118
|
+
} else {
|
|
119
|
+
resolve(results)
|
|
120
|
+
}
|
|
121
|
+
if (connect) {
|
|
122
|
+
client.end()
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
125
129
|
async buildSchema(datasourceId: string, entities: Record<string, Table>) {
|
|
126
130
|
const tables: { [key: string]: Table } = {}
|
|
127
131
|
const database = this.config.database
|
|
128
132
|
this.client.connect()
|
|
129
133
|
|
|
130
134
|
// get the tables first
|
|
131
|
-
const tablesResp = await internalQuery(
|
|
132
|
-
this.client,
|
|
135
|
+
const tablesResp = await this.internalQuery(
|
|
133
136
|
{ sql: "SHOW TABLES;" },
|
|
134
137
|
false
|
|
135
138
|
)
|
|
@@ -141,8 +144,7 @@ module MySQLModule {
|
|
|
141
144
|
for (let tableName of tableNames) {
|
|
142
145
|
const primaryKeys = []
|
|
143
146
|
const schema: TableSchema = {}
|
|
144
|
-
const descResp = await internalQuery(
|
|
145
|
-
this.client,
|
|
147
|
+
const descResp = await this.internalQuery(
|
|
146
148
|
{ sql: `DESCRIBE \`${tableName}\`;` },
|
|
147
149
|
false
|
|
148
150
|
)
|
|
@@ -182,27 +184,27 @@ module MySQLModule {
|
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
async create(query: SqlQuery | string) {
|
|
185
|
-
const results = await internalQuery(
|
|
187
|
+
const results = await this.internalQuery(getSqlQuery(query))
|
|
186
188
|
return results.length ? results : [{ created: true }]
|
|
187
189
|
}
|
|
188
190
|
|
|
189
191
|
async read(query: SqlQuery | string) {
|
|
190
|
-
return internalQuery(
|
|
192
|
+
return this.internalQuery(getSqlQuery(query))
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
async update(query: SqlQuery | string) {
|
|
194
|
-
const results = await internalQuery(
|
|
196
|
+
const results = await this.internalQuery(getSqlQuery(query))
|
|
195
197
|
return results.length ? results : [{ updated: true }]
|
|
196
198
|
}
|
|
197
199
|
|
|
198
200
|
async delete(query: SqlQuery | string) {
|
|
199
|
-
const results = await internalQuery(
|
|
201
|
+
const results = await this.internalQuery(getSqlQuery(query))
|
|
200
202
|
return results.length ? results : [{ deleted: true }]
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
async query(json: QueryJson) {
|
|
204
206
|
this.client.connect()
|
|
205
|
-
const queryFn = (query: any) => internalQuery(
|
|
207
|
+
const queryFn = (query: any) => this.internalQuery(query, false)
|
|
206
208
|
const output = await this.queryWithReturning(json, queryFn)
|
|
207
209
|
this.client.end()
|
|
208
210
|
return output
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Integration,
|
|
3
2
|
DatasourceFieldTypes,
|
|
3
|
+
Integration,
|
|
4
|
+
Operation,
|
|
5
|
+
QueryJson,
|
|
4
6
|
QueryTypes,
|
|
5
7
|
SqlQuery,
|
|
6
|
-
QueryJson,
|
|
7
|
-
Operation,
|
|
8
8
|
} from "../definitions/datasource"
|
|
9
9
|
import {
|
|
10
|
-
finaliseExternalTables,
|
|
11
|
-
getSqlQuery,
|
|
12
10
|
buildExternalTableId,
|
|
13
11
|
convertSqlType,
|
|
12
|
+
finaliseExternalTables,
|
|
13
|
+
getSqlQuery,
|
|
14
14
|
SqlClients,
|
|
15
15
|
} from "./utils"
|
|
16
16
|
import oracledb, {
|
|
17
|
-
|
|
18
|
-
Result,
|
|
17
|
+
BindParameters,
|
|
19
18
|
Connection,
|
|
20
19
|
ConnectionAttributes,
|
|
21
|
-
|
|
20
|
+
ExecuteOptions,
|
|
21
|
+
Result,
|
|
22
22
|
} from "oracledb"
|
|
23
23
|
import Sql from "./base/sql"
|
|
24
24
|
import { Table } from "../definitions/common"
|
|
@@ -137,6 +137,7 @@ module OracleModule {
|
|
|
137
137
|
|
|
138
138
|
class OracleIntegration extends Sql implements DatasourcePlus {
|
|
139
139
|
private readonly config: OracleConfig
|
|
140
|
+
private index: number = 1
|
|
140
141
|
|
|
141
142
|
public tables: Record<string, Table> = {}
|
|
142
143
|
public schemaErrors: Record<string, string> = {}
|
|
@@ -174,6 +175,10 @@ module OracleModule {
|
|
|
174
175
|
this.config = config
|
|
175
176
|
}
|
|
176
177
|
|
|
178
|
+
getBindingIdentifier(): string {
|
|
179
|
+
return `:${this.index++}`
|
|
180
|
+
}
|
|
181
|
+
|
|
177
182
|
/**
|
|
178
183
|
* Map the flat tabular columns and constraints data into a nested object
|
|
179
184
|
*/
|
|
@@ -233,20 +238,14 @@ module OracleModule {
|
|
|
233
238
|
return oracleTables
|
|
234
239
|
}
|
|
235
240
|
|
|
236
|
-
private isSupportedColumn(column: OracleColumn) {
|
|
237
|
-
|
|
238
|
-
return false
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return true
|
|
241
|
+
private static isSupportedColumn(column: OracleColumn) {
|
|
242
|
+
return !UNSUPPORTED_TYPES.includes(column.type)
|
|
242
243
|
}
|
|
243
244
|
|
|
244
|
-
private isAutoColumn(column: OracleColumn) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
return false
|
|
245
|
+
private static isAutoColumn(column: OracleColumn) {
|
|
246
|
+
return !!(
|
|
247
|
+
column.default && column.default.toLowerCase().includes("nextval")
|
|
248
|
+
)
|
|
250
249
|
}
|
|
251
250
|
|
|
252
251
|
/**
|
|
@@ -254,7 +253,7 @@ module OracleModule {
|
|
|
254
253
|
* This matches the default behaviour for generating DDL used in knex.
|
|
255
254
|
*/
|
|
256
255
|
private isBooleanType(column: OracleColumn): boolean {
|
|
257
|
-
|
|
256
|
+
return (
|
|
258
257
|
column.type.toLowerCase() === "number" &&
|
|
259
258
|
Object.values(column.constraints).filter(c => {
|
|
260
259
|
if (
|
|
@@ -273,11 +272,7 @@ module OracleModule {
|
|
|
273
272
|
}
|
|
274
273
|
return false
|
|
275
274
|
}).length > 0
|
|
276
|
-
)
|
|
277
|
-
return true
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return false
|
|
275
|
+
)
|
|
281
276
|
}
|
|
282
277
|
|
|
283
278
|
private internalConvertType(column: OracleColumn): string {
|
|
@@ -317,7 +312,9 @@ module OracleModule {
|
|
|
317
312
|
// iterate each column on the table
|
|
318
313
|
Object.values(oracleTable.columns)
|
|
319
314
|
// remove columns that we can't read / save
|
|
320
|
-
.filter(oracleColumn =>
|
|
315
|
+
.filter(oracleColumn =>
|
|
316
|
+
OracleIntegration.isSupportedColumn(oracleColumn)
|
|
317
|
+
)
|
|
321
318
|
// match the order of the columns in the db
|
|
322
319
|
.sort((c1, c2) => c1.id - c2.id)
|
|
323
320
|
.forEach(oracleColumn => {
|
|
@@ -325,7 +322,7 @@ module OracleModule {
|
|
|
325
322
|
let fieldSchema = table.schema[columnName]
|
|
326
323
|
if (!fieldSchema) {
|
|
327
324
|
fieldSchema = {
|
|
328
|
-
autocolumn:
|
|
325
|
+
autocolumn: OracleIntegration.isAutoColumn(oracleColumn),
|
|
329
326
|
name: columnName,
|
|
330
327
|
type: this.internalConvertType(oracleColumn),
|
|
331
328
|
}
|
|
@@ -351,18 +348,13 @@ module OracleModule {
|
|
|
351
348
|
private async internalQuery<T>(query: SqlQuery): Promise<Result<T>> {
|
|
352
349
|
let connection
|
|
353
350
|
try {
|
|
351
|
+
this.index = 1
|
|
354
352
|
connection = await this.getConnection()
|
|
355
353
|
|
|
356
354
|
const options: ExecuteOptions = { autoCommit: true }
|
|
357
355
|
const bindings: BindParameters = query.bindings || []
|
|
358
356
|
|
|
359
|
-
|
|
360
|
-
query.sql,
|
|
361
|
-
bindings,
|
|
362
|
-
options
|
|
363
|
-
)
|
|
364
|
-
|
|
365
|
-
return result
|
|
357
|
+
return await connection.execute<T>(query.sql, bindings, options)
|
|
366
358
|
} finally {
|
|
367
359
|
if (connection) {
|
|
368
360
|
try {
|
|
@@ -103,30 +103,11 @@ module PostgresModule {
|
|
|
103
103
|
},
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
async function internalQuery(client: any, query: SqlQuery) {
|
|
107
|
-
// need to handle a specific issue with json data types in postgres,
|
|
108
|
-
// new lines inside the JSON data will break it
|
|
109
|
-
if (query && query.sql) {
|
|
110
|
-
const matches = query.sql.match(JSON_REGEX)
|
|
111
|
-
if (matches && matches.length > 0) {
|
|
112
|
-
for (let match of matches) {
|
|
113
|
-
const escaped = escapeDangerousCharacters(match)
|
|
114
|
-
query.sql = query.sql.replace(match, escaped)
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
try {
|
|
119
|
-
return await client.query(query.sql, query.bindings || [])
|
|
120
|
-
} catch (err) {
|
|
121
|
-
// @ts-ignore
|
|
122
|
-
throw new Error(err)
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
106
|
class PostgresIntegration extends Sql implements DatasourcePlus {
|
|
127
107
|
static pool: any
|
|
128
108
|
private readonly client: any
|
|
129
109
|
private readonly config: PostgresConfig
|
|
110
|
+
private index: number = 1
|
|
130
111
|
public tables: Record<string, Table> = {}
|
|
131
112
|
public schemaErrors: Record<string, string> = {}
|
|
132
113
|
|
|
@@ -163,6 +144,32 @@ module PostgresModule {
|
|
|
163
144
|
this.setSchema()
|
|
164
145
|
}
|
|
165
146
|
|
|
147
|
+
getBindingIdentifier(): string {
|
|
148
|
+
return `$${this.index++}`
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async internalQuery(query: SqlQuery) {
|
|
152
|
+
const client = this.client
|
|
153
|
+
this.index = 1
|
|
154
|
+
// need to handle a specific issue with json data types in postgres,
|
|
155
|
+
// new lines inside the JSON data will break it
|
|
156
|
+
if (query && query.sql) {
|
|
157
|
+
const matches = query.sql.match(JSON_REGEX)
|
|
158
|
+
if (matches && matches.length > 0) {
|
|
159
|
+
for (let match of matches) {
|
|
160
|
+
const escaped = escapeDangerousCharacters(match)
|
|
161
|
+
query.sql = query.sql.replace(match, escaped)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
return await client.query(query.sql, query.bindings || [])
|
|
167
|
+
} catch (err) {
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
throw new Error(err)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
166
173
|
setSchema() {
|
|
167
174
|
if (!this.config.schema) {
|
|
168
175
|
this.config.schema = "public"
|
|
@@ -241,22 +248,22 @@ module PostgresModule {
|
|
|
241
248
|
}
|
|
242
249
|
|
|
243
250
|
async create(query: SqlQuery | string) {
|
|
244
|
-
const response = await internalQuery(
|
|
251
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
245
252
|
return response.rows.length ? response.rows : [{ created: true }]
|
|
246
253
|
}
|
|
247
254
|
|
|
248
255
|
async read(query: SqlQuery | string) {
|
|
249
|
-
const response = await internalQuery(
|
|
256
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
250
257
|
return response.rows
|
|
251
258
|
}
|
|
252
259
|
|
|
253
260
|
async update(query: SqlQuery | string) {
|
|
254
|
-
const response = await internalQuery(
|
|
261
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
255
262
|
return response.rows.length ? response.rows : [{ updated: true }]
|
|
256
263
|
}
|
|
257
264
|
|
|
258
265
|
async delete(query: SqlQuery | string) {
|
|
259
|
-
const response = await internalQuery(
|
|
266
|
+
const response = await this.internalQuery(getSqlQuery(query))
|
|
260
267
|
return response.rows.length ? response.rows : [{ deleted: true }]
|
|
261
268
|
}
|
|
262
269
|
|
|
@@ -266,11 +273,11 @@ module PostgresModule {
|
|
|
266
273
|
if (Array.isArray(input)) {
|
|
267
274
|
const responses = []
|
|
268
275
|
for (let query of input) {
|
|
269
|
-
responses.push(await internalQuery(
|
|
276
|
+
responses.push(await this.internalQuery(query))
|
|
270
277
|
}
|
|
271
278
|
return responses
|
|
272
279
|
} else {
|
|
273
|
-
const response = await internalQuery(
|
|
280
|
+
const response = await this.internalQuery(input)
|
|
274
281
|
return response.rows.length ? response.rows : [{ [operation]: true }]
|
|
275
282
|
}
|
|
276
283
|
}
|
|
@@ -25,6 +25,8 @@ const { createASession } = require("@budibase/backend-core/sessions")
|
|
|
25
25
|
const { user: userCache } = require("@budibase/backend-core/cache")
|
|
26
26
|
const newid = require("../../db/newid")
|
|
27
27
|
const context = require("@budibase/backend-core/context")
|
|
28
|
+
const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db")
|
|
29
|
+
const { encrypt } = require("@budibase/backend-core/encryption")
|
|
28
30
|
|
|
29
31
|
const GLOBAL_USER_ID = "us_uuid1"
|
|
30
32
|
const EMAIL = "babs@babs.com"
|
|
@@ -47,6 +49,10 @@ class TestConfiguration {
|
|
|
47
49
|
return this.request
|
|
48
50
|
}
|
|
49
51
|
|
|
52
|
+
getApp() {
|
|
53
|
+
return this.app
|
|
54
|
+
}
|
|
55
|
+
|
|
50
56
|
getAppId() {
|
|
51
57
|
return this.appId
|
|
52
58
|
}
|
|
@@ -83,6 +89,20 @@ class TestConfiguration {
|
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
|
|
92
|
+
async generateApiKey(userId = GLOBAL_USER_ID) {
|
|
93
|
+
const db = getGlobalDB(TENANT_ID)
|
|
94
|
+
const id = generateDevInfoID(userId)
|
|
95
|
+
let devInfo
|
|
96
|
+
try {
|
|
97
|
+
devInfo = await db.get(id)
|
|
98
|
+
} catch (err) {
|
|
99
|
+
devInfo = { _id: id, userId }
|
|
100
|
+
}
|
|
101
|
+
devInfo.apiKey = encrypt(`${TENANT_ID}${SEPARATOR}${newid()}`)
|
|
102
|
+
await db.put(devInfo)
|
|
103
|
+
return devInfo.apiKey
|
|
104
|
+
}
|
|
105
|
+
|
|
86
106
|
async globalUser({
|
|
87
107
|
id = GLOBAL_USER_ID,
|
|
88
108
|
builder = true,
|
|
@@ -135,7 +155,7 @@ class TestConfiguration {
|
|
|
135
155
|
cleanup(this.allApps.map(app => app.appId))
|
|
136
156
|
}
|
|
137
157
|
|
|
138
|
-
defaultHeaders() {
|
|
158
|
+
defaultHeaders(extras = {}) {
|
|
139
159
|
const auth = {
|
|
140
160
|
userId: GLOBAL_USER_ID,
|
|
141
161
|
sessionId: "sessionid",
|
|
@@ -154,6 +174,7 @@ class TestConfiguration {
|
|
|
154
174
|
`${Cookies.CurrentApp}=${appToken}`,
|
|
155
175
|
],
|
|
156
176
|
[Headers.CSRF_TOKEN]: CSRF_TOKEN,
|
|
177
|
+
...extras,
|
|
157
178
|
}
|
|
158
179
|
if (this.appId) {
|
|
159
180
|
headers[Headers.APP_ID] = this.appId
|
|
@@ -226,7 +247,7 @@ class TestConfiguration {
|
|
|
226
247
|
|
|
227
248
|
async getTable(tableId = null) {
|
|
228
249
|
tableId = tableId || this.table._id
|
|
229
|
-
return this._req(null, {
|
|
250
|
+
return this._req(null, { tableId }, controllers.table.find)
|
|
230
251
|
}
|
|
231
252
|
|
|
232
253
|
async createLinkedTable(relationshipType = null, links = ["link"]) {
|
package/src/threads/query.js
CHANGED
|
@@ -2,8 +2,12 @@ const threadUtils = require("./utils")
|
|
|
2
2
|
threadUtils.threadSetup()
|
|
3
3
|
const ScriptRunner = require("../utilities/scriptRunner")
|
|
4
4
|
const { integrations } = require("../integrations")
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
processStringSync,
|
|
7
|
+
findHBSBlocks,
|
|
8
|
+
} = require("@budibase/string-templates")
|
|
6
9
|
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
|
10
|
+
const { isSQL } = require("../integrations/utils")
|
|
7
11
|
|
|
8
12
|
class QueryRunner {
|
|
9
13
|
constructor(input, flags = { noRecursiveQuery: false }) {
|
|
@@ -23,23 +27,47 @@ class QueryRunner {
|
|
|
23
27
|
this.hasRerun = false
|
|
24
28
|
}
|
|
25
29
|
|
|
30
|
+
interpolateSQL(fields, parameters, integration) {
|
|
31
|
+
let sql = fields.sql
|
|
32
|
+
if (!sql) {
|
|
33
|
+
return fields
|
|
34
|
+
}
|
|
35
|
+
const bindings = findHBSBlocks(sql)
|
|
36
|
+
let variables = []
|
|
37
|
+
for (let binding of bindings) {
|
|
38
|
+
let variable = integration.getBindingIdentifier()
|
|
39
|
+
variables.push(binding)
|
|
40
|
+
sql = sql.replace(binding, variable)
|
|
41
|
+
}
|
|
42
|
+
// replicate the knex structure
|
|
43
|
+
fields.sql = sql
|
|
44
|
+
fields.bindings = this.enrichQueryFields(variables, parameters)
|
|
45
|
+
return fields
|
|
46
|
+
}
|
|
47
|
+
|
|
26
48
|
async execute() {
|
|
27
49
|
let { datasource, fields, queryVerb, transformer } = this
|
|
50
|
+
const Integration = integrations[datasource.source]
|
|
51
|
+
if (!Integration) {
|
|
52
|
+
throw "Integration type does not exist."
|
|
53
|
+
}
|
|
54
|
+
const integration = new Integration(datasource.config)
|
|
55
|
+
|
|
28
56
|
// pre-query, make sure datasource variables are added to parameters
|
|
29
57
|
const parameters = await this.addDatasourceVariables()
|
|
30
|
-
let query
|
|
58
|
+
let query
|
|
59
|
+
// handle SQL injections by interpolating the variables
|
|
60
|
+
if (isSQL(datasource)) {
|
|
61
|
+
query = this.interpolateSQL(fields, parameters, integration)
|
|
62
|
+
} else {
|
|
63
|
+
query = this.enrichQueryFields(fields, parameters)
|
|
64
|
+
}
|
|
31
65
|
|
|
32
66
|
// Add pagination values for REST queries
|
|
33
67
|
if (this.pagination) {
|
|
34
68
|
query.paginationValues = this.pagination
|
|
35
69
|
}
|
|
36
70
|
|
|
37
|
-
const Integration = integrations[datasource.source]
|
|
38
|
-
if (!Integration) {
|
|
39
|
-
throw "Integration type does not exist."
|
|
40
|
-
}
|
|
41
|
-
const integration = new Integration(datasource.config)
|
|
42
|
-
|
|
43
71
|
let output = threadUtils.formatResponse(await integration[queryVerb](query))
|
|
44
72
|
let rows = output,
|
|
45
73
|
info = undefined,
|
|
@@ -179,7 +207,7 @@ class QueryRunner {
|
|
|
179
207
|
}
|
|
180
208
|
|
|
181
209
|
enrichQueryFields(fields, parameters = {}) {
|
|
182
|
-
const enrichedQuery = {}
|
|
210
|
+
const enrichedQuery = Array.isArray(fields) ? [] : {}
|
|
183
211
|
|
|
184
212
|
// enrich the fields with dynamic parameters
|
|
185
213
|
for (let key of Object.keys(fields)) {
|