From 186f916b4084a0d99811d141b9533bf203421c72 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 09:57:59 +0000 Subject: [PATCH 1/9] Get tests passing against a real MySQL. --- packages/server/src/api/routes/tests/row.spec.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index a032f4324c..5051fb1a5b 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -38,11 +38,16 @@ import * as uuid from "uuid" const timestamp = new Date("2023-01-26T11:48:57.597Z").toISOString() tk.freeze(timestamp) +jest.setTimeout(99999999) +jest.unmock("mysql2") +jest.unmock("mysql2/promise") + const { basicRow } = setup.structures describe.each([ - ["internal", undefined], - ["postgres", databaseTestProviders.postgres], + // ["internal", undefined], + // ["postgres", databaseTestProviders.postgres], + ["mysql", databaseTestProviders.mysql], ])("/rows (%s)", (__, dsProvider) => { const isInternal = !dsProvider @@ -70,7 +75,7 @@ describe.each([ const generateTableConfig: () => SaveTableRequest = () => { return { - name: uuid.v4(), + name: uuid.v4().substring(0, 16), type: "table", primary: ["id"], primaryDisplay: "name", @@ -641,7 +646,7 @@ describe.each([ const createdRow = await config.createRow() const res = await config.api.row.bulkDelete(table._id!, { - rows: [createdRow, { _id: "2" }], + rows: [createdRow, { _id: "9999999" }], }) expect(res[0]._id).toEqual(createdRow._id) From ce209a16b3f85fbd6151b2a38cfa9e7976378be0 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 10:42:42 +0000 Subject: [PATCH 2/9] Get tests running with SQL Server. Need to make them pass next. --- .../server/src/api/routes/tests/row.spec.ts | 4 +- .../src/integrations/tests/utils/index.ts | 3 +- .../src/integrations/tests/utils/mssql.ts | 53 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 packages/server/src/integrations/tests/utils/mssql.ts diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 5051fb1a5b..bf96dd62b5 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -41,13 +41,15 @@ tk.freeze(timestamp) jest.setTimeout(99999999) jest.unmock("mysql2") jest.unmock("mysql2/promise") +jest.unmock("mssql") const { basicRow } = setup.structures describe.each([ // ["internal", undefined], // ["postgres", databaseTestProviders.postgres], - ["mysql", databaseTestProviders.mysql], + // ["mysql", databaseTestProviders.mysql], + ["mssql", databaseTestProviders.mssql], ])("/rows (%s)", (__, dsProvider) => { const isInternal = !dsProvider diff --git a/packages/server/src/integrations/tests/utils/index.ts b/packages/server/src/integrations/tests/utils/index.ts index b6e4e43e7a..a5282bff6f 100644 --- a/packages/server/src/integrations/tests/utils/index.ts +++ b/packages/server/src/integrations/tests/utils/index.ts @@ -4,6 +4,7 @@ import { Datasource } from "@budibase/types" import * as postgres from "./postgres" import * as mongodb from "./mongodb" import * as mysql from "./mysql" +import * as mssql from "./mssql" import { StartedTestContainer } from "testcontainers" jest.setTimeout(30000) @@ -14,4 +15,4 @@ export interface DatabaseProvider { datasource(): Promise } -export const databaseTestProviders = { postgres, mongodb, mysql } +export const databaseTestProviders = { postgres, mongodb, mysql, mssql } diff --git a/packages/server/src/integrations/tests/utils/mssql.ts b/packages/server/src/integrations/tests/utils/mssql.ts new file mode 100644 index 0000000000..f548f0c42c --- /dev/null +++ b/packages/server/src/integrations/tests/utils/mssql.ts @@ -0,0 +1,53 @@ +import { Datasource, SourceName } from "@budibase/types" +import { GenericContainer, Wait, StartedTestContainer } from "testcontainers" + +let container: StartedTestContainer | undefined + +export async function start(): Promise { + return await new GenericContainer( + "mcr.microsoft.com/mssql/server:2022-latest" + ) + .withExposedPorts(1433) + .withEnvironment({ + ACCEPT_EULA: "Y", + MSSQL_SA_PASSWORD: "Password_123", + // This is important, as Microsoft allow us to use the "Developer" edition + // of SQL Server for development and testing purposes. We can't use other + // versions without a valid license, and we cannot use the Developer + // version in production. + MSSQL_PID: "Developer", + }) + .withWaitStrategy( + Wait.forSuccessfulCommand( + "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Password_123 -q 'SELECT 1'" + ) + ) + .start() +} + +export async function datasource(): Promise { + if (!container) { + container = await start() + } + const host = container.getHost() + const port = container.getMappedPort(1433) + + return { + type: "datasource_plus", + source: SourceName.SQL_SERVER, + plus: true, + config: { + server: host, + port, + user: "sa", + password: "Password_123", + }, + } +} + +export async function stop() { + if (container) { + await container.stop() + container = undefined + } +} From d1f876d67f35541bc88d4fd034cdaf89b94893d9 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 10:55:58 +0000 Subject: [PATCH 3/9] Fix test that was failing because SQL Server doesn't allow you to insert values into primary key columns unless you set a setting. --- packages/server/src/api/routes/tests/row.spec.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index bf96dd62b5..cd8580c64b 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -438,7 +438,7 @@ describe.each([ }) describe("view save", () => { - it("views have extra data trimmed", async () => { + it.only("views have extra data trimmed", async () => { const table = await createTable({ type: "table", name: "orders", @@ -474,7 +474,6 @@ describe.each([ const createRowResponse = await config.api.row.save( createViewResponse.id, { - OrderID: "1111", Country: "Aussy", Story: "aaaaa", } @@ -484,7 +483,7 @@ describe.each([ expect(row.Story).toBeUndefined() expect(row).toEqual({ ...defaultRowFields, - OrderID: 1111, + OrderID: createRowResponse.OrderID, Country: "Aussy", _id: createRowResponse._id, _rev: createRowResponse._rev, From 477d17b53ecd2f904b470fb93b09631734a71610 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 12:25:30 +0000 Subject: [PATCH 4/9] Making progress on getting SQL Server working. --- .../server/src/api/routes/tests/row.spec.ts | 64 +++++++++---------- .../src/integrations/microsoftSqlServer.ts | 30 ++++++++- packages/server/src/sdk/app/rows/search.ts | 8 +-- 3 files changed, 61 insertions(+), 41 deletions(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index cd8580c64b..e95d441981 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -438,7 +438,7 @@ describe.each([ }) describe("view save", () => { - it.only("views have extra data trimmed", async () => { + it("views have extra data trimmed", async () => { const table = await createTable({ type: "table", name: "orders", @@ -1604,35 +1604,35 @@ describe.each([ }) describe.each([ - [ - "relationship fields", - (): Record => ({ - user: { - name: "user", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: o2mTable._id!, - fieldName: "fk_o2m", - }, - users: { - name: "users", - relationshipType: RelationshipType.MANY_TO_MANY, - type: FieldType.LINK, - tableId: m2mTable._id!, - fieldName: "fk_m2m", - }, - }), - (tableId: string) => - config.api.row.save(tableId, { - name: uuid.v4(), - description: generator.paragraph(), - tableId, - }), - (row: Row) => ({ - _id: row._id, - primaryDisplay: row.name, - }), - ], + // [ + // "relationship fields", + // (): Record => ({ + // user: { + // name: "user", + // relationshipType: RelationshipType.ONE_TO_MANY, + // type: FieldType.LINK, + // tableId: o2mTable._id!, + // fieldName: "fk_o2m", + // }, + // users: { + // name: "users", + // relationshipType: RelationshipType.MANY_TO_MANY, + // type: FieldType.LINK, + // tableId: m2mTable._id!, + // fieldName: "fk_m2m", + // }, + // }), + // (tableId: string) => + // config.api.row.save(tableId, { + // name: uuid.v4(), + // description: generator.paragraph(), + // tableId, + // }), + // (row: Row) => ({ + // _id: row._id, + // primaryDisplay: row.name, + // }), + // ], [ "bb reference fields", (): Record => ({ @@ -1960,8 +1960,8 @@ describe.each([ ] await config.api.row.save(tableId, rows[0]) - await config.api.row.save(tableId, rows[1]) - await config.api.row.save(tableId, rows[2]) + // await config.api.row.save(tableId, rows[1]) + // await config.api.row.save(tableId, rows[2]) const res = await config.api.row.search(tableId) diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index f87e248ac0..e53d2ddc44 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -14,6 +14,8 @@ import { Schema, TableSourceType, DatasourcePlusQueryResponse, + FieldType, + FieldSubtype, } from "@budibase/types" import { getSqlQuery, @@ -26,7 +28,7 @@ import { import Sql from "./base/sql" import { MSSQLTablesResponse, MSSQLColumn } from "./base/types" import { getReadableErrorMessage } from "./base/errorMapping" -import sqlServer from "mssql" +import sqlServer, { IRecordSet, IResult } from "mssql" const DEFAULT_SCHEMA = "dbo" @@ -503,10 +505,34 @@ class SqlServerIntegration extends Sql implements DatasourcePlus { const operation = this._operation(json) const queryFn = (query: any, op: string) => this.internalQuery(query, op) const processFn = (result: any) => - result.recordset ? result.recordset : [{ [operation]: true }] + result.recordset + ? this._postProcessJson(json, result.recordset) + : [{ [operation]: true }] return this.queryWithReturning(json, queryFn, processFn) } + _postProcessJson(json: QueryJson, results: IRecordSet) { + const table = json.meta?.table + if (!table) { + return results + } + for (const [name, field] of Object.entries(table.schema)) { + if ( + field.type === FieldType.JSON || + (field.type === FieldType.BB_REFERENCE && + field.subtype === FieldSubtype.USERS) + ) { + const fullName = `${table.name}.${name}` + for (let row of results) { + if (typeof row[fullName] === "string") { + row[fullName] = JSON.parse(row[fullName]) + } + } + } + } + return results + } + async getExternalSchema() { // Query to retrieve table schema const query = ` diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index 8b24f9bc5f..63bbd699fa 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -1,10 +1,4 @@ -import { - Row, - SearchFilters, - SearchParams, - SortOrder, - SortType, -} from "@budibase/types" +import { Row, SearchFilters, SearchParams, SortOrder } from "@budibase/types" import { isExternalTableID } from "../../../integrations/utils" import * as internal from "./search/internal" import * as external from "./search/external" From 1334f5dcc58066f3714cc675f11f69e1fd4650b9 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 14:46:52 +0000 Subject: [PATCH 5/9] SQL Server fully passing. --- .../server/src/api/routes/tests/row.spec.ts | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index e95d441981..f902084a48 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -46,9 +46,9 @@ jest.unmock("mssql") const { basicRow } = setup.structures describe.each([ - // ["internal", undefined], - // ["postgres", databaseTestProviders.postgres], - // ["mysql", databaseTestProviders.mysql], + ["internal", undefined], + ["postgres", databaseTestProviders.postgres], + ["mysql", databaseTestProviders.mysql], ["mssql", databaseTestProviders.mssql], ])("/rows (%s)", (__, dsProvider) => { const isInternal = !dsProvider @@ -1604,35 +1604,35 @@ describe.each([ }) describe.each([ - // [ - // "relationship fields", - // (): Record => ({ - // user: { - // name: "user", - // relationshipType: RelationshipType.ONE_TO_MANY, - // type: FieldType.LINK, - // tableId: o2mTable._id!, - // fieldName: "fk_o2m", - // }, - // users: { - // name: "users", - // relationshipType: RelationshipType.MANY_TO_MANY, - // type: FieldType.LINK, - // tableId: m2mTable._id!, - // fieldName: "fk_m2m", - // }, - // }), - // (tableId: string) => - // config.api.row.save(tableId, { - // name: uuid.v4(), - // description: generator.paragraph(), - // tableId, - // }), - // (row: Row) => ({ - // _id: row._id, - // primaryDisplay: row.name, - // }), - // ], + [ + "relationship fields", + (): Record => ({ + user: { + name: "user", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: o2mTable._id!, + fieldName: "fk_o2m", + }, + users: { + name: "users", + relationshipType: RelationshipType.MANY_TO_MANY, + type: FieldType.LINK, + tableId: m2mTable._id!, + fieldName: "fk_m2m", + }, + }), + (tableId: string) => + config.api.row.save(tableId, { + name: uuid.v4(), + description: generator.paragraph(), + tableId, + }), + (row: Row) => ({ + _id: row._id, + primaryDisplay: row.name, + }), + ], [ "bb reference fields", (): Record => ({ @@ -1960,8 +1960,8 @@ describe.each([ ] await config.api.row.save(tableId, rows[0]) - // await config.api.row.save(tableId, rows[1]) - // await config.api.row.save(tableId, rows[2]) + await config.api.row.save(tableId, rows[1]) + await config.api.row.save(tableId, rows[2]) const res = await config.api.row.search(tableId) From aff0209176e00fb9557a699687a8aa07636beec7 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 15:27:34 +0000 Subject: [PATCH 6/9] MariaDB tests passing. --- .../server/src/api/routes/tests/row.spec.ts | 1 + packages/server/src/integrations/base/sql.ts | 33 +++++++++++ .../src/integrations/microsoftSqlServer.ts | 32 +++------- packages/server/src/integrations/mysql.ts | 32 +++++++++- .../src/integrations/tests/utils/index.ts | 9 ++- .../src/integrations/tests/utils/mariadb.ts | 58 +++++++++++++++++++ 6 files changed, 138 insertions(+), 27 deletions(-) create mode 100644 packages/server/src/integrations/tests/utils/mariadb.ts diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index f902084a48..89da4175d9 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -50,6 +50,7 @@ describe.each([ ["postgres", databaseTestProviders.postgres], ["mysql", databaseTestProviders.mysql], ["mssql", databaseTestProviders.mssql], + ["mariadb", databaseTestProviders.mariadb], ])("/rows (%s)", (__, dsProvider) => { const isInternal = !dsProvider diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index be1883c8ec..e6b9f047b9 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -4,11 +4,15 @@ import { QueryOptions } from "../../definitions/datasource" import { isIsoDateString, SqlClient, isValidFilter } from "../utils" import SqlTableQueryBuilder from "./sqlTable" import { + FieldSchema, + FieldSubtype, + FieldType, Operation, QueryJson, RelationshipsJson, SearchFilters, SortDirection, + Table, } from "@budibase/types" import environment from "../../environment" @@ -691,6 +695,35 @@ class SqlQueryBuilder extends SqlTableQueryBuilder { return results.length ? results : [{ [operation.toLowerCase()]: true }] } + convertJsonStringColumns( + table: Table, + results: Record[] + ): Record[] { + for (const [name, field] of Object.entries(table.schema)) { + if (!this._isJsonColumn(field)) { + continue + } + const fullName = `${table.name}.${name}` + for (let row of results) { + if (typeof row[fullName] === "string") { + row[fullName] = JSON.parse(row[fullName]) + } + if (typeof row[name] === "string") { + row[name] = JSON.parse(row[name]) + } + } + } + return results + } + + _isJsonColumn(field: FieldSchema) { + return ( + field.type === FieldType.JSON || + (field.type === FieldType.BB_REFERENCE && + field.subtype === FieldSubtype.USERS) + ) + } + log(query: string, values?: any[]) { if (!environment.SQL_LOGGING_ENABLE) { return diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index e53d2ddc44..0c9b8f4547 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -504,33 +504,15 @@ class SqlServerIntegration extends Sql implements DatasourcePlus { } const operation = this._operation(json) const queryFn = (query: any, op: string) => this.internalQuery(query, op) - const processFn = (result: any) => - result.recordset - ? this._postProcessJson(json, result.recordset) - : [{ [operation]: true }] - return this.queryWithReturning(json, queryFn, processFn) - } - - _postProcessJson(json: QueryJson, results: IRecordSet) { - const table = json.meta?.table - if (!table) { - return results - } - for (const [name, field] of Object.entries(table.schema)) { - if ( - field.type === FieldType.JSON || - (field.type === FieldType.BB_REFERENCE && - field.subtype === FieldSubtype.USERS) - ) { - const fullName = `${table.name}.${name}` - for (let row of results) { - if (typeof row[fullName] === "string") { - row[fullName] = JSON.parse(row[fullName]) - } - } + const processFn = (result: any) => { + if (json?.meta?.table && result.recordset) { + return this.convertJsonStringColumns(json.meta.table, result.recordset) + } else if (result.recordset) { + return result.recordset } + return [{ [operation]: true }] } - return results + return this.queryWithReturning(json, queryFn, processFn) } async getExternalSchema() { diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index f629381807..1f50525675 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -13,6 +13,8 @@ import { Schema, TableSourceType, DatasourcePlusQueryResponse, + FieldType, + FieldSubtype, } from "@budibase/types" import { getSqlQuery, @@ -386,12 +388,40 @@ class MySQLIntegration extends Sql implements DatasourcePlus { try { const queryFn = (query: any) => this.internalQuery(query, { connect: false, disableCoercion: true }) - return await this.queryWithReturning(json, queryFn) + const processFn = (result: any) => { + if (json?.meta?.table && Array.isArray(result)) { + return this.convertJsonStringColumns(json.meta.table, result) + } + return result + } + return await this.queryWithReturning(json, queryFn, processFn) } finally { await this.disconnect() } } + _postProcessJson(json: QueryJson, results: any) { + const table = json.meta?.table + if (!table) { + return results + } + for (const [name, field] of Object.entries(table.schema)) { + if ( + field.type === FieldType.JSON || + (field.type === FieldType.BB_REFERENCE && + field.subtype === FieldSubtype.USERS) + ) { + const fullName = `${table.name}.${name}` + for (let row of results) { + if (typeof row[fullName] === "string") { + row[fullName] = JSON.parse(row[fullName]) + } + } + } + } + return results + } + async getExternalSchema() { try { const [databaseResult] = await this.internalQuery({ diff --git a/packages/server/src/integrations/tests/utils/index.ts b/packages/server/src/integrations/tests/utils/index.ts index a5282bff6f..b2be3df4e0 100644 --- a/packages/server/src/integrations/tests/utils/index.ts +++ b/packages/server/src/integrations/tests/utils/index.ts @@ -5,6 +5,7 @@ import * as postgres from "./postgres" import * as mongodb from "./mongodb" import * as mysql from "./mysql" import * as mssql from "./mssql" +import * as mariadb from "./mariadb" import { StartedTestContainer } from "testcontainers" jest.setTimeout(30000) @@ -15,4 +16,10 @@ export interface DatabaseProvider { datasource(): Promise } -export const databaseTestProviders = { postgres, mongodb, mysql, mssql } +export const databaseTestProviders = { + postgres, + mongodb, + mysql, + mssql, + mariadb, +} diff --git a/packages/server/src/integrations/tests/utils/mariadb.ts b/packages/server/src/integrations/tests/utils/mariadb.ts new file mode 100644 index 0000000000..a097e0aaa1 --- /dev/null +++ b/packages/server/src/integrations/tests/utils/mariadb.ts @@ -0,0 +1,58 @@ +import { Datasource, SourceName } from "@budibase/types" +import { GenericContainer, Wait, StartedTestContainer } from "testcontainers" +import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy" + +let container: StartedTestContainer | undefined + +class MariaDBWaitStrategy extends AbstractWaitStrategy { + async waitUntilReady(container: any, boundPorts: any, startTime?: Date) { + // Because MariaDB first starts itself up, runs an init script, then restarts, + // it's possible for the mysqladmin ping to succeed early and then tests to + // run against a MariaDB that's mid-restart and fail. To get around this, we + // wait for logs and then do a ping check. + + const logs = Wait.forLogMessage("mariadbd: ready for connections", 2) + await logs.waitUntilReady(container, boundPorts, startTime) + + const command = Wait.forSuccessfulCommand( + `mysqladmin ping -h localhost -P 3306 -u root -ppassword` + ) + await command.waitUntilReady(container) + } +} + +export async function start(): Promise { + return await new GenericContainer("mariadb:lts") + .withExposedPorts(3306) + .withEnvironment({ MARIADB_ROOT_PASSWORD: "password" }) + .withWaitStrategy(new MariaDBWaitStrategy()) + .start() +} + +export async function datasource(): Promise { + if (!container) { + container = await start() + } + const host = container.getHost() + const port = container.getMappedPort(3306) + + return { + type: "datasource_plus", + source: SourceName.MYSQL, + plus: true, + config: { + host, + port, + user: "root", + password: "password", + database: "mysql", + }, + } +} + +export async function stop() { + if (container) { + await container.stop() + container = undefined + } +} From a70cb903f6aa0cb61656e7345b08ee5e4b811fea Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 17:17:01 +0000 Subject: [PATCH 7/9] Remove jest timeout. --- packages/server/src/api/routes/tests/row.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 89da4175d9..d50dd8a3d9 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -38,7 +38,6 @@ import * as uuid from "uuid" const timestamp = new Date("2023-01-26T11:48:57.597Z").toISOString() tk.freeze(timestamp) -jest.setTimeout(99999999) jest.unmock("mysql2") jest.unmock("mysql2/promise") jest.unmock("mssql") From d061c19c80233f10f18514ac41f4e3fb8f4bfd09 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 12 Mar 2024 17:21:33 +0000 Subject: [PATCH 8/9] Remove some extraneous, unused code. --- .../src/integrations/microsoftSqlServer.ts | 2 +- packages/server/src/integrations/mysql.ts | 22 ------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index 0c9b8f4547..c79eb136ed 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -28,7 +28,7 @@ import { import Sql from "./base/sql" import { MSSQLTablesResponse, MSSQLColumn } from "./base/types" import { getReadableErrorMessage } from "./base/errorMapping" -import sqlServer, { IRecordSet, IResult } from "mssql" +import sqlServer from "mssql" const DEFAULT_SCHEMA = "dbo" diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index 1f50525675..9638afa8ea 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -400,28 +400,6 @@ class MySQLIntegration extends Sql implements DatasourcePlus { } } - _postProcessJson(json: QueryJson, results: any) { - const table = json.meta?.table - if (!table) { - return results - } - for (const [name, field] of Object.entries(table.schema)) { - if ( - field.type === FieldType.JSON || - (field.type === FieldType.BB_REFERENCE && - field.subtype === FieldSubtype.USERS) - ) { - const fullName = `${table.name}.${name}` - for (let row of results) { - if (typeof row[fullName] === "string") { - row[fullName] = JSON.parse(row[fullName]) - } - } - } - } - return results - } - async getExternalSchema() { try { const [databaseResult] = await this.internalQuery({ From a5c8e8845f92a02e24c77f2793c2fde31e56b010 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 13 Mar 2024 13:38:08 +0000 Subject: [PATCH 9/9] Implement Adri's type guard suggestion. --- packages/server/src/integrations/base/sql.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index e6b9f047b9..8342c45fd7 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -4,9 +4,11 @@ import { QueryOptions } from "../../definitions/datasource" import { isIsoDateString, SqlClient, isValidFilter } from "../utils" import SqlTableQueryBuilder from "./sqlTable" import { + BBReferenceFieldMetadata, FieldSchema, FieldSubtype, FieldType, + JsonFieldMetadata, Operation, QueryJson, RelationshipsJson, @@ -716,7 +718,9 @@ class SqlQueryBuilder extends SqlTableQueryBuilder { return results } - _isJsonColumn(field: FieldSchema) { + _isJsonColumn( + field: FieldSchema + ): field is JsonFieldMetadata | BBReferenceFieldMetadata { return ( field.type === FieldType.JSON || (field.type === FieldType.BB_REFERENCE &&