Getting basic aliasing working after some testing.
This commit is contained in:
parent
c16ad86142
commit
cb7c1898f2
|
@ -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 || "",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue