Fixing response types of DS+ query function.
This commit is contained in:
parent
45d2e67905
commit
cb19e1f24c
|
@ -332,7 +332,7 @@ export class ExternalRequest<T extends Operation> {
|
|||
endpoint: getEndpoint(table._id!, Operation.READ),
|
||||
filters: buildFilters(rowId, {}, table),
|
||||
})
|
||||
if (response.length > 0) {
|
||||
if (Array.isArray(response)) {
|
||||
return response[0]
|
||||
} else {
|
||||
throw new Error(`Cannot fetch row by ID "${rowId}"`)
|
||||
|
@ -646,7 +646,7 @@ export class ExternalRequest<T extends Operation> {
|
|||
},
|
||||
})
|
||||
// this is the response from knex if no rows found
|
||||
const rows: Row[] = !response[0].read ? response : []
|
||||
const rows: Row[] = response?.[0].read ? [] : (response as Row[])
|
||||
const storeTo = isMany ? field.throughFrom || linkPrimaryKey : fieldName
|
||||
related[storeTo] = { rows, isMany, tableId }
|
||||
}
|
||||
|
@ -899,15 +899,16 @@ export class ExternalRequest<T extends Operation> {
|
|||
response = await getDatasourceAndQuery(json)
|
||||
}
|
||||
|
||||
const responseRows = Array.isArray(response) ? response : []
|
||||
// handle many-to-many relationships now if we know the ID (could be auto increment)
|
||||
if (operation !== Operation.READ) {
|
||||
await this.handleManyRelationships(
|
||||
table._id || "",
|
||||
response[0],
|
||||
responseRows[0],
|
||||
processed.manyRelationships
|
||||
)
|
||||
}
|
||||
const output = this.outputProcessing(response, table, relationships)
|
||||
const output = this.outputProcessing(responseRows, table, relationships)
|
||||
// if reading it'll just be an array of rows, return whole thing
|
||||
if (operation === Operation.READ) {
|
||||
return (
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { QueryJson, SearchFilters, Table, Row } from "@budibase/types"
|
||||
import {
|
||||
QueryJson,
|
||||
SearchFilters,
|
||||
Table,
|
||||
Row,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import { getDatasourceAndQuery } from "../../../sdk/app/rows/utils"
|
||||
import { cloneDeep } from "lodash"
|
||||
|
||||
|
@ -68,9 +74,8 @@ export default class AliasTables {
|
|||
return map
|
||||
}
|
||||
|
||||
async queryWithAliasing(json: QueryJson) {
|
||||
async queryWithAliasing(json: QueryJson): DatasourcePlusQueryResponse {
|
||||
json = cloneDeep(json)
|
||||
const aliasField = (field: string) => this.aliasField(field)
|
||||
const aliasTable = (table: Table) => ({
|
||||
...table,
|
||||
name: this.getAlias(table.name),
|
||||
|
@ -78,7 +83,7 @@ export default class AliasTables {
|
|||
// run through the query json to update anywhere a table may be used
|
||||
if (json.resource?.fields) {
|
||||
json.resource.fields = json.resource.fields.map(field =>
|
||||
aliasField(field)
|
||||
this.aliasField(field)
|
||||
)
|
||||
}
|
||||
if (json.filters) {
|
||||
|
@ -88,7 +93,7 @@ export default class AliasTables {
|
|||
}
|
||||
const aliasedFilters: typeof filter = {}
|
||||
for (let key of Object.keys(filter)) {
|
||||
aliasedFilters[aliasField(key)] = filter[key]
|
||||
aliasedFilters[this.aliasField(key)] = filter[key]
|
||||
}
|
||||
json.filters[filterKey as keyof SearchFilters] = aliasedFilters
|
||||
}
|
||||
|
@ -120,6 +125,10 @@ export default class AliasTables {
|
|||
}
|
||||
json.tableAliases = invertedTableAliases
|
||||
const response = await getDatasourceAndQuery(json)
|
||||
if (Array.isArray(response)) {
|
||||
return this.reverse(response)
|
||||
} else {
|
||||
return response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import { QueryJson, Datasource } from "@budibase/types"
|
||||
import {
|
||||
QueryJson,
|
||||
Datasource,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import { getIntegration } from "../index"
|
||||
import sdk from "../../sdk"
|
||||
|
||||
export async function makeExternalQuery(
|
||||
datasource: Datasource,
|
||||
json: QueryJson
|
||||
) {
|
||||
): DatasourcePlusQueryResponse {
|
||||
datasource = await sdk.datasources.enrich(datasource)
|
||||
const Integration = await getIntegration(datasource.source)
|
||||
// query is the opinionated function
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
Table,
|
||||
TableRequest,
|
||||
TableSourceType,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import { OAuth2Client } from "google-auth-library"
|
||||
import {
|
||||
|
@ -334,7 +335,7 @@ class GoogleSheetsIntegration implements DatasourcePlus {
|
|||
return { tables: externalTables, errors }
|
||||
}
|
||||
|
||||
async query(json: QueryJson) {
|
||||
async query(json: QueryJson): DatasourcePlusQueryResponse {
|
||||
const sheet = json.endpoint.entityId
|
||||
switch (json.endpoint.operation) {
|
||||
case Operation.CREATE:
|
||||
|
@ -384,7 +385,7 @@ class GoogleSheetsIntegration implements DatasourcePlus {
|
|||
}
|
||||
try {
|
||||
await this.connect()
|
||||
return await this.client.addSheet({ title: name, headerValues: [name] })
|
||||
await this.client.addSheet({ title: name, headerValues: [name] })
|
||||
} catch (err) {
|
||||
console.error("Error creating new table in google sheets", err)
|
||||
throw err
|
||||
|
@ -450,7 +451,7 @@ class GoogleSheetsIntegration implements DatasourcePlus {
|
|||
try {
|
||||
await this.connect()
|
||||
const sheetToDelete = this.client.sheetsByTitle[sheet]
|
||||
return await sheetToDelete.delete()
|
||||
await sheetToDelete.delete()
|
||||
} catch (err) {
|
||||
console.error("Error deleting table in google sheets", err)
|
||||
throw err
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
SourceName,
|
||||
Schema,
|
||||
TableSourceType,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import {
|
||||
getSqlQuery,
|
||||
|
@ -493,7 +494,7 @@ class SqlServerIntegration extends Sql implements DatasourcePlus {
|
|||
return response.recordset || [{ deleted: true }]
|
||||
}
|
||||
|
||||
async query(json: QueryJson) {
|
||||
async query(json: QueryJson): DatasourcePlusQueryResponse {
|
||||
const schema = this.config.schema
|
||||
await this.connect()
|
||||
if (schema && schema !== DEFAULT_SCHEMA && json?.endpoint) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
SourceName,
|
||||
Schema,
|
||||
TableSourceType,
|
||||
FieldType,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import {
|
||||
getSqlQuery,
|
||||
|
@ -381,7 +381,7 @@ class MySQLIntegration extends Sql implements DatasourcePlus {
|
|||
return results.length ? results : [{ deleted: true }]
|
||||
}
|
||||
|
||||
async query(json: QueryJson) {
|
||||
async query(json: QueryJson): DatasourcePlusQueryResponse {
|
||||
await this.connect()
|
||||
try {
|
||||
const queryFn = (query: any) =>
|
||||
|
|
|
@ -12,6 +12,8 @@ import {
|
|||
ConnectionInfo,
|
||||
Schema,
|
||||
TableSourceType,
|
||||
Row,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import {
|
||||
buildExternalTableId,
|
||||
|
@ -420,7 +422,7 @@ class OracleIntegration extends Sql implements DatasourcePlus {
|
|||
: [{ deleted: true }]
|
||||
}
|
||||
|
||||
async query(json: QueryJson) {
|
||||
async query(json: QueryJson): DatasourcePlusQueryResponse {
|
||||
const operation = this._operation(json)
|
||||
const input = this._query(json, { disableReturning: true })
|
||||
if (Array.isArray(input)) {
|
||||
|
@ -444,7 +446,7 @@ class OracleIntegration extends Sql implements DatasourcePlus {
|
|||
if (deletedRows?.rows?.length) {
|
||||
return deletedRows.rows
|
||||
} else if (response.rows?.length) {
|
||||
return response.rows
|
||||
return response.rows as Row[]
|
||||
} else {
|
||||
// get the last row that was updated
|
||||
if (
|
||||
|
@ -455,7 +457,7 @@ class OracleIntegration extends Sql implements DatasourcePlus {
|
|||
const lastRow = await this.internalQuery({
|
||||
sql: `SELECT * FROM \"${json.endpoint.entityId}\" WHERE ROWID = '${response.lastRowid}'`,
|
||||
})
|
||||
return lastRow.rows
|
||||
return lastRow.rows as Row[]
|
||||
} else {
|
||||
return [{ [operation.toLowerCase()]: true }]
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
SourceName,
|
||||
Schema,
|
||||
TableSourceType,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
import {
|
||||
getSqlQuery,
|
||||
|
@ -419,7 +420,7 @@ class PostgresIntegration extends Sql implements DatasourcePlus {
|
|||
return response.rows.length ? response.rows : [{ deleted: true }]
|
||||
}
|
||||
|
||||
async query(json: QueryJson) {
|
||||
async query(json: QueryJson): DatasourcePlusQueryResponse {
|
||||
const operation = this._operation(json).toLowerCase()
|
||||
const input = this._query(json)
|
||||
if (Array.isArray(input)) {
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
import cloneDeep from "lodash/cloneDeep"
|
||||
import validateJs from "validate.js"
|
||||
import { FieldType, QueryJson, Row, Table, TableSchema } from "@budibase/types"
|
||||
import {
|
||||
FieldType,
|
||||
QueryJson,
|
||||
Row,
|
||||
Table,
|
||||
TableSchema,
|
||||
DatasourcePlusQueryResponse,
|
||||
} from "@budibase/types"
|
||||
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: QueryJson) {
|
||||
export async function getDatasourceAndQuery(
|
||||
json: QueryJson
|
||||
): DatasourcePlusQueryResponse {
|
||||
const datasourceId = json.endpoint.datasourceId
|
||||
const datasource = await sdk.datasources.get(datasourceId)
|
||||
return makeExternalQuery(datasource, json)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Table } from "../documents"
|
||||
import { Table, Row } from "../documents"
|
||||
import { QueryJson } from "./search"
|
||||
|
||||
export const PASSWORD_REPLACEMENT = "--secret-value--"
|
||||
|
||||
|
@ -180,11 +181,24 @@ export interface Schema {
|
|||
errors: Record<string, string>
|
||||
}
|
||||
|
||||
// return these when an operation occurred but we got no response
|
||||
enum DSPlusOperation {
|
||||
CREATE = "create",
|
||||
READ = "read",
|
||||
UPDATE = "update",
|
||||
DELETE = "delete",
|
||||
}
|
||||
|
||||
export type DatasourcePlusQueryResponse = Promise<
|
||||
Row[] | Record<DSPlusOperation, boolean>[] | void
|
||||
>
|
||||
|
||||
export interface DatasourcePlus extends IntegrationBase {
|
||||
// if the datasource supports the use of bindings directly (to protect against SQL injection)
|
||||
// this returns the format of the identifier
|
||||
getBindingIdentifier(): string
|
||||
getStringConcat(parts: string[]): string
|
||||
query(json: QueryJson): DatasourcePlusQueryResponse
|
||||
buildSchema(
|
||||
datasourceId: string,
|
||||
entities: Record<string, Table>
|
||||
|
|
Loading…
Reference in New Issue