Disabling aliasing on writes (create, update, delete) for MySQL/MS-SQL datasources.
This commit is contained in:
parent
bc8fdeea6a
commit
a332c058ce
|
@ -1,12 +1,16 @@
|
||||||
import {
|
import {
|
||||||
QueryJson,
|
Datasource,
|
||||||
SearchFilters,
|
|
||||||
Table,
|
|
||||||
Row,
|
|
||||||
DatasourcePlusQueryResponse,
|
DatasourcePlusQueryResponse,
|
||||||
|
Operation,
|
||||||
|
QueryJson,
|
||||||
|
Row,
|
||||||
|
SearchFilters,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { getDatasourceAndQuery } from "../../../sdk/app/rows/utils"
|
import { getSQLClient } from "../../../sdk/app/rows/utils"
|
||||||
import { cloneDeep } from "lodash"
|
import { cloneDeep } from "lodash"
|
||||||
|
import sdk from "../../../sdk"
|
||||||
|
import { makeExternalQuery } from "../../../integrations/base/query"
|
||||||
|
import { SqlClient } from "../../../integrations/utils"
|
||||||
|
|
||||||
class CharSequence {
|
class CharSequence {
|
||||||
static alphabet = "abcdefghijklmnopqrstuvwxyz"
|
static alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
@ -43,6 +47,32 @@ export default class AliasTables {
|
||||||
this.charSeq = new CharSequence()
|
this.charSeq = new CharSequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isAliasingEnabled(json: QueryJson, datasource: Datasource) {
|
||||||
|
const fieldLength = json.resource?.fields?.length
|
||||||
|
if (!fieldLength || fieldLength <= 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const writeOperations = [
|
||||||
|
Operation.CREATE,
|
||||||
|
Operation.UPDATE,
|
||||||
|
Operation.DELETE,
|
||||||
|
]
|
||||||
|
try {
|
||||||
|
const sqlClient = getSQLClient(datasource)
|
||||||
|
const isWrite = writeOperations.includes(json.endpoint.operation)
|
||||||
|
if (
|
||||||
|
isWrite &&
|
||||||
|
(sqlClient === SqlClient.MY_SQL || sqlClient === SqlClient.MS_SQL)
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// if we can't get an SQL client, we can't alias
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
getAlias(tableName: string) {
|
getAlias(tableName: string) {
|
||||||
if (this.aliases[tableName]) {
|
if (this.aliases[tableName]) {
|
||||||
return this.aliases[tableName]
|
return this.aliases[tableName]
|
||||||
|
@ -111,8 +141,10 @@ export default class AliasTables {
|
||||||
}
|
}
|
||||||
|
|
||||||
async queryWithAliasing(json: QueryJson): DatasourcePlusQueryResponse {
|
async queryWithAliasing(json: QueryJson): DatasourcePlusQueryResponse {
|
||||||
const fieldLength = json.resource?.fields?.length
|
const datasourceId = json.endpoint.datasourceId
|
||||||
const aliasingEnabled = fieldLength && fieldLength > 0
|
const datasource = await sdk.datasources.get(datasourceId)
|
||||||
|
|
||||||
|
const aliasingEnabled = this.isAliasingEnabled(json, datasource)
|
||||||
if (aliasingEnabled) {
|
if (aliasingEnabled) {
|
||||||
json = cloneDeep(json)
|
json = cloneDeep(json)
|
||||||
// run through the query json to update anywhere a table may be used
|
// run through the query json to update anywhere a table may be used
|
||||||
|
@ -158,7 +190,7 @@ export default class AliasTables {
|
||||||
}
|
}
|
||||||
json.tableAliases = invertedTableAliases
|
json.tableAliases = invertedTableAliases
|
||||||
}
|
}
|
||||||
const response = await getDatasourceAndQuery(json)
|
const response = await makeExternalQuery(datasource, json)
|
||||||
if (Array.isArray(response) && aliasingEnabled) {
|
if (Array.isArray(response) && aliasingEnabled) {
|
||||||
return this.reverse(response)
|
return this.reverse(response)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -435,10 +435,12 @@ class InternalBuilder {
|
||||||
aliases?: QueryJson["tableAliases"]
|
aliases?: QueryJson["tableAliases"]
|
||||||
): Knex.QueryBuilder {
|
): Knex.QueryBuilder {
|
||||||
const tableName = endpoint.entityId
|
const tableName = endpoint.entityId
|
||||||
const tableAliased = aliases?.[tableName]
|
const tableAlias = aliases?.[tableName]
|
||||||
? `${tableName} as ${aliases?.[tableName]}`
|
let table: string | Record<string, string> = tableName
|
||||||
: tableName
|
if (tableAlias) {
|
||||||
let query = knex(tableAliased)
|
table = { [tableAlias]: tableName }
|
||||||
|
}
|
||||||
|
let query = knex(table)
|
||||||
if (endpoint.schema) {
|
if (endpoint.schema) {
|
||||||
query = query.withSchema(endpoint.schema)
|
query = query.withSchema(endpoint.schema)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,18 @@ import firebase from "./firebase"
|
||||||
import redis from "./redis"
|
import redis from "./redis"
|
||||||
import snowflake from "./snowflake"
|
import snowflake from "./snowflake"
|
||||||
import oracle from "./oracle"
|
import oracle from "./oracle"
|
||||||
import { SourceName, Integration, PluginType } from "@budibase/types"
|
import {
|
||||||
|
SourceName,
|
||||||
|
Integration,
|
||||||
|
PluginType,
|
||||||
|
IntegrationBase,
|
||||||
|
} from "@budibase/types"
|
||||||
import { getDatasourcePlugin } from "../utilities/fileSystem"
|
import { getDatasourcePlugin } from "../utilities/fileSystem"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import cloneDeep from "lodash/cloneDeep"
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
import sdk from "../sdk"
|
import sdk from "../sdk"
|
||||||
|
|
||||||
const DEFINITIONS: Record<SourceName, Integration | undefined> = {
|
const DEFINITIONS: { [key: SourceName]: Integration | undefined } = {
|
||||||
[SourceName.POSTGRES]: postgres.schema,
|
[SourceName.POSTGRES]: postgres.schema,
|
||||||
[SourceName.DYNAMODB]: dynamodb.schema,
|
[SourceName.DYNAMODB]: dynamodb.schema,
|
||||||
[SourceName.MONGODB]: mongodb.schema,
|
[SourceName.MONGODB]: mongodb.schema,
|
||||||
|
@ -40,7 +45,7 @@ const DEFINITIONS: Record<SourceName, Integration | undefined> = {
|
||||||
[SourceName.BUDIBASE]: undefined,
|
[SourceName.BUDIBASE]: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
const INTEGRATIONS: Record<SourceName, any> = {
|
const INTEGRATIONS: { [key: SourceName]: IntegrationBase | undefined } = {
|
||||||
[SourceName.POSTGRES]: postgres.integration,
|
[SourceName.POSTGRES]: postgres.integration,
|
||||||
[SourceName.DYNAMODB]: dynamodb.integration,
|
[SourceName.DYNAMODB]: dynamodb.integration,
|
||||||
[SourceName.MONGODB]: mongodb.integration,
|
[SourceName.MONGODB]: mongodb.integration,
|
||||||
|
|
|
@ -7,11 +7,31 @@ import {
|
||||||
Table,
|
Table,
|
||||||
TableSchema,
|
TableSchema,
|
||||||
DatasourcePlusQueryResponse,
|
DatasourcePlusQueryResponse,
|
||||||
|
Datasource,
|
||||||
|
SourceName,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { makeExternalQuery } from "../../../integrations/base/query"
|
import { makeExternalQuery } from "../../../integrations/base/query"
|
||||||
import { Format } from "../../../api/controllers/view/exporters"
|
import { Format } from "../../../api/controllers/view/exporters"
|
||||||
import sdk from "../.."
|
import sdk from "../.."
|
||||||
import { isRelationshipColumn } from "../../../db/utils"
|
import { isRelationshipColumn } from "../../../db/utils"
|
||||||
|
import { SqlClient } from "../../../integrations/utils"
|
||||||
|
|
||||||
|
export function getSQLClient(datasource: Datasource): SqlClient {
|
||||||
|
if (!datasource.isSQL) {
|
||||||
|
throw new Error("Cannot get SQL Client for non-SQL datasource")
|
||||||
|
}
|
||||||
|
switch (datasource.source) {
|
||||||
|
case SourceName.POSTGRES:
|
||||||
|
return SqlClient.POSTGRES
|
||||||
|
case SourceName.MYSQL:
|
||||||
|
return SqlClient.MY_SQL
|
||||||
|
case SourceName.ORACLE:
|
||||||
|
return SqlClient.ORACLE
|
||||||
|
case SourceName.SQL_SERVER:
|
||||||
|
return SqlClient.MS_SQL
|
||||||
|
}
|
||||||
|
throw new Error("Unable to find a valid SQL client")
|
||||||
|
}
|
||||||
|
|
||||||
export async function getDatasourceAndQuery(
|
export async function getDatasourceAndQuery(
|
||||||
json: QueryJson
|
json: QueryJson
|
||||||
|
|
Loading…
Reference in New Issue