diff --git a/packages/server/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap b/packages/server/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap index 8dc472173c..57d79db24b 100644 --- a/packages/server/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap +++ b/packages/server/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap @@ -81,6 +81,7 @@ exports[`/datasources fetch returns all the datasources from the server 1`] = ` { "config": {}, "createdAt": "2020-01-01T00:00:00.000Z", + "isSQL": true, "name": "Test", "source": "POSTGRES", "type": "datasource", diff --git a/packages/server/src/integration-test/mysql.spec.ts b/packages/server/src/integration-test/mysql.spec.ts index 2af886fe4c..b8f1affd4a 100644 --- a/packages/server/src/integration-test/mysql.spec.ts +++ b/packages/server/src/integration-test/mysql.spec.ts @@ -106,6 +106,7 @@ describe("mysql integrations", () => { plus: true, source: "MYSQL", type: "datasource_plus", + isSQL: true, _id: expect.any(String), _rev: expect.any(String), createdAt: expect.any(String), diff --git a/packages/server/src/integration-test/postgres.spec.ts b/packages/server/src/integration-test/postgres.spec.ts index 7c14bc2b69..107c4ade1e 100644 --- a/packages/server/src/integration-test/postgres.spec.ts +++ b/packages/server/src/integration-test/postgres.spec.ts @@ -319,6 +319,7 @@ describe("postgres integrations", () => { }, plus: true, source: "POSTGRES", + isSQL: true, type: "datasource_plus", _id: expect.any(String), _rev: expect.any(String), diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 8342c45fd7..2093d455b9 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -699,13 +699,15 @@ class SqlQueryBuilder extends SqlTableQueryBuilder { convertJsonStringColumns( table: Table, - results: Record[] + results: Record[], + aliases?: Record ): Record[] { for (const [name, field] of Object.entries(table.schema)) { if (!this._isJsonColumn(field)) { continue } - const fullName = `${table.name}.${name}` + const tableName = aliases?.[table.name] || table.name + const fullName = `${tableName}.${name}` for (let row of results) { if (typeof row[fullName] === "string") { row[fullName] = JSON.parse(row[fullName]) diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index c79eb136ed..36fdae980e 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -506,7 +506,11 @@ class SqlServerIntegration extends Sql implements DatasourcePlus { const queryFn = (query: any, op: string) => this.internalQuery(query, op) const processFn = (result: any) => { if (json?.meta?.table && result.recordset) { - return this.convertJsonStringColumns(json.meta.table, result.recordset) + return this.convertJsonStringColumns( + json.meta.table, + result.recordset, + json.tableAliases + ) } else if (result.recordset) { return result.recordset } diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index 9638afa8ea..f88162cf37 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -390,7 +390,11 @@ class MySQLIntegration extends Sql implements DatasourcePlus { this.internalQuery(query, { connect: false, disableCoercion: true }) const processFn = (result: any) => { if (json?.meta?.table && Array.isArray(result)) { - return this.convertJsonStringColumns(json.meta.table, result) + return this.convertJsonStringColumns( + json.meta.table, + result, + json.tableAliases + ) } return result } diff --git a/packages/server/src/sdk/app/datasources/datasources.ts b/packages/server/src/sdk/app/datasources/datasources.ts index fd0d291d91..336a94636b 100644 --- a/packages/server/src/sdk/app/datasources/datasources.ts +++ b/packages/server/src/sdk/app/datasources/datasources.ts @@ -30,9 +30,15 @@ import { } from "../../../db/utils" import sdk from "../../index" import { setupCreationAuth as googleSetupCreationAuth } from "../../../integrations/googlesheets" +import { helpers } from "@budibase/shared-core" const ENV_VAR_PREFIX = "env." +function addDatasourceFlags(datasource: Datasource) { + datasource.isSQL = helpers.isSQL(datasource) + return datasource +} + export async function fetch(opts?: { enriched: boolean }): Promise { @@ -56,7 +62,7 @@ export async function fetch(opts?: { } as Datasource // Get external datasources - const datasources = ( + let datasources = ( await db.allDocs( getDatasourceParams(null, { include_docs: true, @@ -75,6 +81,7 @@ export async function fetch(opts?: { } } + datasources = datasources.map(datasource => addDatasourceFlags(datasource)) if (opts?.enriched) { const envVars = await getEnvironmentVariables() const promises = datasources.map(datasource => @@ -150,6 +157,7 @@ async function enrichDatasourceWithValues( } export async function enrich(datasource: Datasource) { + datasource = addDatasourceFlags(datasource) const { datasource: response } = await enrichDatasourceWithValues(datasource) return response } @@ -159,7 +167,8 @@ export async function get( opts?: { enriched: boolean } ): Promise { const appDb = context.getAppDB() - const datasource = await appDb.get(datasourceId) + let datasource = await appDb.get(datasourceId) + datasource = addDatasourceFlags(datasource) if (opts?.enriched) { return (await enrichDatasourceWithValues(datasource)).datasource } else { @@ -271,13 +280,14 @@ export function mergeConfigs(update: Datasource, old: Datasource) { export async function getExternalDatasources(): Promise { const db = context.getAppDB() - const externalDatasources = await db.allDocs( + let dsResponse = await db.allDocs( getDatasourcePlusParams(undefined, { include_docs: true, }) ) - return externalDatasources.rows.map(r => r.doc!) + const externalDatasources = dsResponse.rows.map(r => r.doc!) + return externalDatasources.map(datasource => addDatasourceFlags(datasource)) } export async function save( @@ -290,11 +300,11 @@ export async function save( const fetchSchema = opts?.fetchSchema || false const tablesFilter = opts?.tablesFilter || [] - datasource = { + datasource = addDatasourceFlags({ _id: generateDatasourceID({ plus }), ...datasource, type: plus ? DocumentType.DATASOURCE_PLUS : DocumentType.DATASOURCE, - } + }) let errors: Record = {} if (fetchSchema) { diff --git a/packages/server/src/sdk/app/rows/utils.ts b/packages/server/src/sdk/app/rows/utils.ts index 6e3e25364e..8aa017d238 100644 --- a/packages/server/src/sdk/app/rows/utils.ts +++ b/packages/server/src/sdk/app/rows/utils.ts @@ -14,7 +14,7 @@ import { makeExternalQuery } from "../../../integrations/base/query" import { Format } from "../../../api/controllers/view/exporters" import sdk from "../.." import { isRelationshipColumn } from "../../../db/utils" -import { SqlClient } from "../../../integrations/utils" +import { SqlClient, isSQL } from "../../../integrations/utils" const SQL_CLIENT_SOURCE_MAP: Record = { [SourceName.POSTGRES]: SqlClient.POSTGRES, @@ -37,7 +37,7 @@ const SQL_CLIENT_SOURCE_MAP: Record = { } export function getSQLClient(datasource: Datasource): SqlClient { - if (!datasource.isSQL) { + if (!isSQL(datasource)) { throw new Error("Cannot get SQL Client for non-SQL datasource") } const lookup = SQL_CLIENT_SOURCE_MAP[datasource.source]