Getting basic aliasing working after some testing.

This commit is contained in:
mike12345567 2023-11-27 19:02:06 +00:00
parent c16ad86142
commit cb7c1898f2
5 changed files with 36 additions and 25 deletions

View File

@ -32,6 +32,7 @@ import { processObjectSync } from "@budibase/string-templates"
import { cloneDeep } from "lodash/fp"
import { processDates, processFormulas } from "../../../utilities/rowProcessor"
import { db as dbCore } from "@budibase/backend-core"
import AliasTables from "./alias"
import sdk from "../../../sdk"
export interface ManyRelationship {
@ -178,13 +179,13 @@ function generateIdForRow(
function getEndpoint(tableId: string | undefined, operation: string) {
if (!tableId) {
return {}
throw new Error("Cannot get endpoint information - no table ID specified")
}
const { datasourceId, tableName } = breakExternalTableId(tableId)
return {
datasourceId,
entityId: tableName,
operation,
datasourceId: datasourceId!,
entityId: tableName!,
operation: operation as Operation,
}
}
@ -704,7 +705,7 @@ export class ExternalRequest<T extends Operation> {
// safety check, if there are no filters on deletion bad things happen
if (Object.keys(filters).length !== 0) {
const op = isMany ? Operation.DELETE : Operation.UPDATE
const body = isMany ? null : { [colName]: null }
const body = isMany ? undefined : { [colName]: null }
promises.push(
getDatasourceAndQuery({
endpoint: getEndpoint(tableId, op),
@ -807,7 +808,7 @@ export class ExternalRequest<T extends Operation> {
}
let json = {
endpoint: {
datasourceId,
datasourceId: datasourceId!,
entityId: tableName,
operation,
},
@ -829,9 +830,9 @@ export class ExternalRequest<T extends Operation> {
},
}
// can't really use response right now
const response = await getDatasourceAndQuery(json)
// handle many to many relationships now if we know the ID (could be auto increment)
const aliasing = new AliasTables(Object.keys(this.tables))
const response = await aliasing.queryWithAliasing(json)
// handle many-to-many relationships now if we know the ID (could be auto increment)
if (operation !== Operation.READ) {
await this.handleManyRelationships(
table._id || "",

View File

@ -2,12 +2,14 @@ import { QueryJson, SearchFilters, Table, Row } from "@budibase/types"
import { getDatasourceAndQuery } from "../../../sdk/app/rows/utils"
import { cloneDeep } from "lodash"
class AliasTables {
export default class AliasTables {
character: string
aliases: Record<string, string>
tableAliases: Record<string, string>
tableNames: string[]
constructor() {
constructor(tableNames: string[]) {
this.tableNames = tableNames
this.character = "a"
this.aliases = {}
this.tableAliases = {}
@ -17,13 +19,15 @@ class AliasTables {
if (this.aliases[tableName]) {
return this.aliases[tableName]
}
this.character = String.fromCharCode(this.character.charCodeAt(0) + 1)
this.aliases[tableName] = this.character
this.tableAliases[this.character] = tableName
return this.character
const char = this.character
this.aliases[tableName] = char
this.tableAliases[char] = tableName
this.character = String.fromCharCode(char.charCodeAt(0) + 1)
return char
}
aliasField(tableNames: string[], field: string) {
aliasField(field: string) {
const tableNames = this.tableNames
if (field.includes(".")) {
const [tableName, column] = field.split(".")
if (tableNames.includes(tableName)) {
@ -54,9 +58,9 @@ class AliasTables {
}
}
async queryWithAliasing(tableNames: string[], json: QueryJson) {
async queryWithAliasing(json: QueryJson) {
json = cloneDeep(json)
const aliasField = (field: string) => this.aliasField(tableNames, field)
const aliasField = (field: string) => this.aliasField(field)
const aliasTable = (table: Table) => ({
...table,
name: this.getAlias(table.name),
@ -82,7 +86,7 @@ class AliasTables {
if (json.relationships) {
json.relationships = json.relationships.map(relationship => ({
...relationship,
tableName: this.getAlias(relationship.tableName),
alias: this.getAlias(relationship.tableName),
}))
}
if (json.meta?.table) {
@ -95,6 +99,7 @@ class AliasTables {
}
json.meta.tables = aliasedTables
}
json.endpoint.alias = this.getAlias(json.endpoint.entityId)
const response = await getDatasourceAndQuery(json)
return this.reverse(response)
}

View File

@ -439,6 +439,9 @@ class InternalBuilder {
let { endpoint, resource, filters, paginate, relationships } = json
const tableName = endpoint.entityId
const alias = endpoint.alias
const aliased = alias ? alias : tableName
const tableAliased = alias ? `${tableName} as ${alias}` : tableName
// select all if not specified
if (!resource) {
resource = { fields: [] }
@ -463,20 +466,20 @@ class InternalBuilder {
foundLimit = paginate.limit
}
// start building the query
let query: KnexQuery = knex(tableName).limit(foundLimit)
let query: KnexQuery = knex(tableAliased).limit(foundLimit)
if (endpoint.schema) {
query = query.withSchema(endpoint.schema)
}
if (foundOffset) {
query = query.offset(foundOffset)
}
query = this.addFilters(query, filters, { tableName })
query = this.addFilters(query, filters, { tableName: aliased })
// add sorting to pre-query
query = this.addSorting(query, json)
// @ts-ignore
let preQuery: KnexQuery = knex({
// @ts-ignore
[tableName]: query,
[aliased]: query,
}).select(selectStatement)
// have to add after as well (this breaks MS-SQL)
if (this.client !== SqlClient.MS_SQL) {
@ -485,7 +488,7 @@ class InternalBuilder {
// handle joins
query = this.addRelationships(
preQuery,
tableName,
aliased,
relationships,
endpoint.schema
)

View File

@ -1,13 +1,13 @@
import cloneDeep from "lodash/cloneDeep"
import validateJs from "validate.js"
import { Row, Table, TableSchema } from "@budibase/types"
import { QueryJson, Row, Table, TableSchema } from "@budibase/types"
import { FieldTypes } from "../../../constants"
import { makeExternalQuery } from "../../../integrations/base/query"
import { Format } from "../../../api/controllers/view/exporters"
import sdk from "../.."
import { isRelationshipColumn } from "../../../db/utils"
export async function getDatasourceAndQuery(json: any) {
export async function getDatasourceAndQuery(json: QueryJson) {
const datasourceId = json.endpoint.datasourceId
const datasource = await sdk.datasources.get(datasourceId)
return makeExternalQuery(datasource, json)

View File

@ -67,6 +67,7 @@ export interface RelationshipsJson {
fromPrimary?: string
toPrimary?: string
tableName: string
alias?: string
column: string
}
@ -74,6 +75,7 @@ export interface QueryJson {
endpoint: {
datasourceId: string
entityId: string
alias?: string
operation: Operation
schema?: string
}