1
0
Fork 0
mirror of synced 2024-07-08 15:56:23 +12:00

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

View file

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

View file

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

View file

@ -1,13 +1,13 @@
import cloneDeep from "lodash/cloneDeep" import cloneDeep from "lodash/cloneDeep"
import validateJs from "validate.js" 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 { FieldTypes } from "../../../constants"
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"
export async function getDatasourceAndQuery(json: any) { export async function getDatasourceAndQuery(json: QueryJson) {
const datasourceId = json.endpoint.datasourceId const datasourceId = json.endpoint.datasourceId
const datasource = await sdk.datasources.get(datasourceId) const datasource = await sdk.datasources.get(datasourceId)
return makeExternalQuery(datasource, json) return makeExternalQuery(datasource, json)

View file

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