Adding missing files.
This commit is contained in:
parent
7b7d10d1ff
commit
02e3b36cd8
|
@ -107,57 +107,62 @@ export default class AliasTables {
|
||||||
}
|
}
|
||||||
|
|
||||||
async queryWithAliasing(json: QueryJson): DatasourcePlusQueryResponse {
|
async queryWithAliasing(json: QueryJson): DatasourcePlusQueryResponse {
|
||||||
json = cloneDeep(json)
|
const fieldLength = json.resource?.fields?.length
|
||||||
const aliasTable = (table: Table) => ({
|
const aliasingEnabled = fieldLength && fieldLength > 0
|
||||||
...table,
|
if (aliasingEnabled) {
|
||||||
name: this.getAlias(table.name),
|
json = cloneDeep(json)
|
||||||
})
|
const aliasTable = (table: Table) => ({
|
||||||
// run through the query json to update anywhere a table may be used
|
...table,
|
||||||
if (json.resource?.fields) {
|
name: this.getAlias(table.name),
|
||||||
json.resource.fields = json.resource.fields.map(field =>
|
originalName: table.name,
|
||||||
this.aliasField(field)
|
})
|
||||||
)
|
// run through the query json to update anywhere a table may be used
|
||||||
}
|
if (json.resource?.fields) {
|
||||||
if (json.filters) {
|
json.resource.fields = json.resource.fields.map(field =>
|
||||||
for (let [filterKey, filter] of Object.entries(json.filters)) {
|
this.aliasField(field)
|
||||||
if (typeof filter !== "object") {
|
)
|
||||||
continue
|
|
||||||
}
|
|
||||||
const aliasedFilters: typeof filter = {}
|
|
||||||
for (let key of Object.keys(filter)) {
|
|
||||||
aliasedFilters[this.aliasField(key)] = filter[key]
|
|
||||||
}
|
|
||||||
json.filters[filterKey as keyof SearchFilters] = aliasedFilters
|
|
||||||
}
|
}
|
||||||
}
|
if (json.filters) {
|
||||||
if (json.relationships) {
|
for (let [filterKey, filter] of Object.entries(json.filters)) {
|
||||||
json.relationships = json.relationships.map(relationship => ({
|
if (typeof filter !== "object") {
|
||||||
...relationship,
|
continue
|
||||||
aliases: this.aliasMap([
|
}
|
||||||
relationship.through,
|
const aliasedFilters: typeof filter = {}
|
||||||
relationship.tableName,
|
for (let key of Object.keys(filter)) {
|
||||||
json.endpoint.entityId,
|
aliasedFilters[this.aliasField(key)] = filter[key]
|
||||||
]),
|
}
|
||||||
}))
|
json.filters[filterKey as keyof SearchFilters] = aliasedFilters
|
||||||
}
|
}
|
||||||
if (json.meta?.table) {
|
|
||||||
json.meta.table = aliasTable(json.meta.table)
|
|
||||||
}
|
|
||||||
if (json.meta?.tables) {
|
|
||||||
const aliasedTables: Record<string, Table> = {}
|
|
||||||
for (let [tableName, table] of Object.entries(json.meta.tables)) {
|
|
||||||
aliasedTables[this.getAlias(tableName)] = aliasTable(table)
|
|
||||||
}
|
}
|
||||||
json.meta.tables = aliasedTables
|
if (json.relationships) {
|
||||||
|
json.relationships = json.relationships.map(relationship => ({
|
||||||
|
...relationship,
|
||||||
|
aliases: this.aliasMap([
|
||||||
|
relationship.through,
|
||||||
|
relationship.tableName,
|
||||||
|
json.endpoint.entityId,
|
||||||
|
]),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
if (json.meta?.table) {
|
||||||
|
json.meta.table = aliasTable(json.meta.table)
|
||||||
|
}
|
||||||
|
if (json.meta?.tables) {
|
||||||
|
const aliasedTables: Record<string, Table> = {}
|
||||||
|
for (let [tableName, table] of Object.entries(json.meta.tables)) {
|
||||||
|
aliasedTables[this.getAlias(tableName)] = aliasTable(table)
|
||||||
|
}
|
||||||
|
json.meta.tables = aliasedTables
|
||||||
|
}
|
||||||
|
// invert and return
|
||||||
|
const invertedTableAliases: Record<string, string> = {}
|
||||||
|
for (let [key, value] of Object.entries(this.tableAliases)) {
|
||||||
|
invertedTableAliases[value] = key
|
||||||
|
}
|
||||||
|
json.tableAliases = invertedTableAliases
|
||||||
}
|
}
|
||||||
// invert and return
|
|
||||||
const invertedTableAliases: Record<string, string> = {}
|
|
||||||
for (let [key, value] of Object.entries(this.tableAliases)) {
|
|
||||||
invertedTableAliases[value] = key
|
|
||||||
}
|
|
||||||
json.tableAliases = invertedTableAliases
|
|
||||||
const response = await getDatasourceAndQuery(json)
|
const response = await getDatasourceAndQuery(json)
|
||||||
if (Array.isArray(response)) {
|
if (Array.isArray(response) && aliasingEnabled) {
|
||||||
return this.reverse(response)
|
return this.reverse(response)
|
||||||
} else {
|
} else {
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -9,9 +9,12 @@ import {
|
||||||
RelationshipsJson,
|
RelationshipsJson,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
SortDirection,
|
SortDirection,
|
||||||
|
Table,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import environment from "../../environment"
|
import environment from "../../environment"
|
||||||
|
|
||||||
|
type QueryFunction = (query: Knex.SqlNative, operation: Operation) => any
|
||||||
|
|
||||||
const envLimit = environment.SQL_MAX_ROWS
|
const envLimit = environment.SQL_MAX_ROWS
|
||||||
? parseInt(environment.SQL_MAX_ROWS)
|
? parseInt(environment.SQL_MAX_ROWS)
|
||||||
: null
|
: null
|
||||||
|
@ -117,6 +120,29 @@ function generateSelectStatement(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function disableAliasing(json: QueryJson) {
|
||||||
|
if (json.tableAliases) {
|
||||||
|
json.tableAliases = undefined
|
||||||
|
}
|
||||||
|
const removeTableAlias = (table: Table) => {
|
||||||
|
if (table.originalName) {
|
||||||
|
table.name = table.originalName
|
||||||
|
}
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
if (json.meta?.table) {
|
||||||
|
json.meta.table = removeTableAlias(json.meta.table)
|
||||||
|
}
|
||||||
|
if (json.meta?.tables) {
|
||||||
|
for (let tableName of Object.keys(json.meta.tables)) {
|
||||||
|
json.meta.tables[tableName] = removeTableAlias(
|
||||||
|
json.meta.tables[tableName]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
||||||
class InternalBuilder {
|
class InternalBuilder {
|
||||||
private readonly client: string
|
private readonly client: string
|
||||||
|
|
||||||
|
@ -605,10 +631,12 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
||||||
return query.toSQL().toNative()
|
return query.toSQL().toNative()
|
||||||
}
|
}
|
||||||
|
|
||||||
async getReturningRow(queryFn: Function, json: QueryJson) {
|
async getReturningRow(queryFn: QueryFunction, json: QueryJson) {
|
||||||
if (!json.extra || !json.extra.idFilter) {
|
if (!json.extra || !json.extra.idFilter) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
// disable aliasing if it is enabled
|
||||||
|
json = disableAliasing(json)
|
||||||
const input = this._query({
|
const input = this._query({
|
||||||
endpoint: {
|
endpoint: {
|
||||||
...json.endpoint,
|
...json.endpoint,
|
||||||
|
@ -617,7 +645,7 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
||||||
resource: {
|
resource: {
|
||||||
fields: [],
|
fields: [],
|
||||||
},
|
},
|
||||||
filters: json.extra.idFilter,
|
filters: json.extra?.idFilter,
|
||||||
paginate: {
|
paginate: {
|
||||||
limit: 1,
|
limit: 1,
|
||||||
},
|
},
|
||||||
|
@ -646,7 +674,7 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
||||||
// this function recreates the returning functionality of postgres
|
// this function recreates the returning functionality of postgres
|
||||||
async queryWithReturning(
|
async queryWithReturning(
|
||||||
json: QueryJson,
|
json: QueryJson,
|
||||||
queryFn: Function,
|
queryFn: QueryFunction,
|
||||||
processFn: Function = (result: any) => result
|
processFn: Function = (result: any) => result
|
||||||
) {
|
) {
|
||||||
const sqlClient = this.getSqlClient()
|
const sqlClient = this.getSqlClient()
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Sql from "../base/sql"
|
||||||
import { SqlClient } from "../utils"
|
import { SqlClient } from "../utils"
|
||||||
import AliasTables from "../../api/controllers/row/alias"
|
import AliasTables from "../../api/controllers/row/alias"
|
||||||
import { generator } from "@budibase/backend-core/tests"
|
import { generator } from "@budibase/backend-core/tests"
|
||||||
|
import { Knex } from "knex"
|
||||||
|
|
||||||
function multiline(sql: string) {
|
function multiline(sql: string) {
|
||||||
return sql.replace(/\n/g, "").replace(/ +/g, " ")
|
return sql.replace(/\n/g, "").replace(/ +/g, " ")
|
||||||
|
@ -160,6 +161,28 @@ describe("Captures of real examples", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("returning (everything bar Postgres)", () => {
|
||||||
|
it("should be able to handle row returning", () => {
|
||||||
|
const queryJson = getJson("createSimple.json")
|
||||||
|
const SQL = new Sql(SqlClient.MS_SQL, limit)
|
||||||
|
let query = SQL._query(queryJson, { disableReturning: true })
|
||||||
|
expect(query).toEqual({
|
||||||
|
sql: "insert into [people] ([age], [name]) values (@p0, @p1)",
|
||||||
|
bindings: [222, "awfawf"],
|
||||||
|
})
|
||||||
|
|
||||||
|
// now check returning
|
||||||
|
let returningQuery: Knex.SqlNative = { sql: "", bindings: [] }
|
||||||
|
SQL.getReturningRow((input: Knex.SqlNative) => {
|
||||||
|
returningQuery = input
|
||||||
|
}, queryJson)
|
||||||
|
expect(returningQuery).toEqual({
|
||||||
|
sql: "select * from (select top (@p0) * from [people] where [people].[name] = @p1 and [people].[age] = @p2 order by [people].[name] asc) as [people]",
|
||||||
|
bindings: [1, "awfawf", 222],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("check max character aliasing", () => {
|
describe("check max character aliasing", () => {
|
||||||
it("should handle over 'z' max character alias", () => {
|
it("should handle over 'z' max character alias", () => {
|
||||||
const tableNames = []
|
const tableNames = []
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"datasourceId": "datasource_plus_0ed5835e5552496285df546030f7c4ae",
|
||||||
|
"entityId": "people",
|
||||||
|
"operation": "CREATE"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"fields": [
|
||||||
|
"a.name",
|
||||||
|
"a.age"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filters": {},
|
||||||
|
"relationships": [],
|
||||||
|
"body": {
|
||||||
|
"name": "awfawf",
|
||||||
|
"age": 222
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"idFilter": {
|
||||||
|
"equal": {
|
||||||
|
"name": "awfawf",
|
||||||
|
"age": 222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"table": {
|
||||||
|
"_id": "datasource_plus_0ed5835e5552496285df546030f7c4ae__people",
|
||||||
|
"type": "table",
|
||||||
|
"sourceId": "datasource_plus_0ed5835e5552496285df546030f7c4ae",
|
||||||
|
"sourceType": "external",
|
||||||
|
"primary": [
|
||||||
|
"name",
|
||||||
|
"age"
|
||||||
|
],
|
||||||
|
"name": "a",
|
||||||
|
"schema": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"externalType": "varchar",
|
||||||
|
"autocolumn": false,
|
||||||
|
"name": "name",
|
||||||
|
"constraints": {
|
||||||
|
"presence": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"age": {
|
||||||
|
"type": "number",
|
||||||
|
"externalType": "int",
|
||||||
|
"autocolumn": false,
|
||||||
|
"name": "age",
|
||||||
|
"constraints": {
|
||||||
|
"presence": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"primaryDisplay": "name",
|
||||||
|
"originalName": "people"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tableAliases": {
|
||||||
|
"people": "a"
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ export interface Table extends Document {
|
||||||
sourceType: TableSourceType
|
sourceType: TableSourceType
|
||||||
views?: { [key: string]: View | ViewV2 }
|
views?: { [key: string]: View | ViewV2 }
|
||||||
name: string
|
name: string
|
||||||
|
originalName?: string
|
||||||
sourceId: string
|
sourceId: string
|
||||||
primary?: string[]
|
primary?: string[]
|
||||||
schema: TableSchema
|
schema: TableSchema
|
||||||
|
|
Loading…
Reference in New Issue