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 { 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 || "",
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue