diff --git a/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts b/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts index e8a38dcfaa..d44acb84d9 100644 --- a/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts +++ b/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts @@ -10,37 +10,11 @@ import * as setup from "../utilities" import { DatabaseName, getDatasource, - rawQuery, + knexClient, } from "../../../../integrations/tests/utils" import { Expectations } from "src/tests/utilities/api/base" import { events } from "@budibase/backend-core" - -const createTableSQL: Record = { - [SourceName.POSTGRES]: ` - CREATE TABLE test_table ( - id serial PRIMARY KEY, - name VARCHAR ( 50 ) NOT NULL, - birthday TIMESTAMP, - number INT - );`, - [SourceName.MYSQL]: ` - CREATE TABLE test_table ( - id INT AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(50) NOT NULL, - birthday TIMESTAMP, - number INT - );`, - [SourceName.SQL_SERVER]: ` - CREATE TABLE test_table ( - id INT IDENTITY(1,1) PRIMARY KEY, - name NVARCHAR(50) NOT NULL, - birthday DATETIME, - number INT - );`, -} - -const insertSQL = `INSERT INTO test_table (name) VALUES ('one'), ('two'), ('three'), ('four'), ('five')` -const dropTableSQL = `DROP TABLE test_table;` +import { Knex } from "knex" describe.each( [ @@ -53,6 +27,7 @@ describe.each( const config = setup.getConfig() let rawDatasource: Datasource let datasource: Datasource + let client: Knex async function createQuery( query: Partial, @@ -82,21 +57,34 @@ describe.each( rawDatasource = await dsProvider datasource = await config.api.datasource.create(rawDatasource) - // The Datasource API does not return the password, but we need - // it later to connect to the underlying database, so we fill it - // back in here. + // The Datasource API doesn ot return the password, but we need it later to + // connect to the underlying database, so we fill it back in here. datasource.config!.password = rawDatasource.config!.password - await rawQuery(datasource, createTableSQL[datasource.source]) - await rawQuery(datasource, insertSQL) + client = await knexClient(rawDatasource) + + await client.schema.createTable("test_table", table => { + table.increments("id").primary() + table.string("name") + table.timestamp("birthday") + table.integer("number") + }) + + await client("test_table").insert([ + { name: "one" }, + { name: "two" }, + { name: "three" }, + { name: "four" }, + { name: "five" }, + ]) jest.clearAllMocks() }) afterEach(async () => { const ds = await config.api.datasource.get(datasource._id!) - config.api.datasource.delete(ds) - await rawQuery(datasource, dropTableSQL) + await config.api.datasource.delete(ds) + await client.schema.dropTable("test_table") }) afterAll(async () => { @@ -207,7 +195,7 @@ describe.each( }, }) - await config.publish() + await config.api.application.publish(config.getAppId()) const prodQuery = await config.api.query.getProd(query._id!) expect(prodQuery._id).toEqual(query._id) @@ -429,11 +417,11 @@ describe.each( }, ]) - const rows = await rawQuery( - datasource, - "SELECT * FROM test_table WHERE name = 'baz'" - ) + const rows = await client("test_table").where({ name: "baz" }).select() expect(rows).toHaveLength(1) + for (const row of rows) { + expect(row).toMatchObject({ name: "baz" }) + } }) it("should not allow handlebars as parameters", async () => { @@ -490,11 +478,14 @@ describe.each( expect(result.data).toEqual([{ created: true }]) - const rows = await rawQuery( - datasource, - `SELECT * FROM test_table WHERE birthday = '${date.toISOString()}'` - ) + const rows = await client("test_table") + .where({ birthday: datetimeStr }) + .select() expect(rows).toHaveLength(1) + + for (const row of rows) { + expect(new Date(row.birthday)).toEqual(date) + } } ) @@ -522,10 +513,9 @@ describe.each( expect(result.data).toEqual([{ created: true }]) - const rows = await rawQuery( - datasource, - `SELECT * FROM test_table WHERE name = '${notDateStr}'` - ) + const rows = await client("test_table") + .where({ name: notDateStr }) + .select() expect(rows).toHaveLength(1) } ) @@ -660,10 +650,7 @@ describe.each( }, ]) - const rows = await rawQuery( - datasource, - "SELECT * FROM test_table WHERE id = 1" - ) + const rows = await client("test_table").where({ id: 1 }).select() expect(rows).toEqual([ { id: 1, name: "foo", birthday: null, number: null }, ]) @@ -731,10 +718,7 @@ describe.each( }, ]) - const rows = await rawQuery( - datasource, - "SELECT * FROM test_table WHERE id = 1" - ) + const rows = await client("test_table").where({ id: 1 }).select() expect(rows).toHaveLength(0) }) }) diff --git a/packages/server/src/integration-test/mysql.spec.ts b/packages/server/src/integration-test/mysql.spec.ts index eb81b8920f..eb6c840abc 100644 --- a/packages/server/src/integration-test/mysql.spec.ts +++ b/packages/server/src/integration-test/mysql.spec.ts @@ -18,13 +18,12 @@ function uniqueTableName(length?: number): string { const config = setup.getConfig()! describe("mysql integrations", () => { - let rawDatasource: Datasource let datasource: Datasource let client: Knex beforeAll(async () => { await config.init() - rawDatasource = await getDatasource(DatabaseName.MYSQL) + const rawDatasource = await getDatasource(DatabaseName.MYSQL) datasource = await config.api.datasource.create(rawDatasource) client = await knexClient(rawDatasource) }) diff --git a/packages/server/src/integration-test/postgres.spec.ts b/packages/server/src/integration-test/postgres.spec.ts index 3e34ce097b..f2e0382deb 100644 --- a/packages/server/src/integration-test/postgres.spec.ts +++ b/packages/server/src/integration-test/postgres.spec.ts @@ -12,13 +12,12 @@ import { Knex } from "knex" const config = setup.getConfig()! describe("postgres integrations", () => { - let rawDatasource: Datasource let datasource: Datasource let client: Knex beforeAll(async () => { await config.init() - rawDatasource = await getDatasource(DatabaseName.POSTGRES) + const rawDatasource = await getDatasource(DatabaseName.POSTGRES) datasource = await config.api.datasource.create(rawDatasource) client = await knexClient(rawDatasource) }) @@ -91,17 +90,16 @@ describe("postgres integrations", () => { }) describe("Integration compatibility with postgres search_path", () => { - let rawDatasource: Datasource, - datasource: Datasource, - client: Knex, - schema1: string, - schema2: string + let datasource: Datasource + let client: Knex + let schema1: string + let schema2: string beforeEach(async () => { schema1 = generator.guid().replaceAll("-", "") schema2 = generator.guid().replaceAll("-", "") - rawDatasource = await getDatasource(DatabaseName.POSTGRES) + const rawDatasource = await getDatasource(DatabaseName.POSTGRES) client = await knexClient(rawDatasource) await client.schema.createSchema(schema1) diff --git a/packages/server/src/integrations/tests/utils/index.ts b/packages/server/src/integrations/tests/utils/index.ts index fd7d2373bb..b888f1adc1 100644 --- a/packages/server/src/integrations/tests/utils/index.ts +++ b/packages/server/src/integrations/tests/utils/index.ts @@ -48,23 +48,6 @@ export async function getDatasources( return Promise.all(sourceNames.map(sourceName => providers[sourceName]())) } -export async function rawQuery(ds: Datasource, sql: string): Promise { - switch (ds.source) { - case SourceName.POSTGRES: { - return postgres.rawQuery(ds, sql) - } - case SourceName.MYSQL: { - return mysql.rawQuery(ds, sql) - } - case SourceName.SQL_SERVER: { - return mssql.rawQuery(ds, sql) - } - default: { - throw new Error(`Unsupported source: ${ds.source}`) - } - } -} - export async function knexClient(ds: Datasource) { switch (ds.source) { case SourceName.POSTGRES: { diff --git a/packages/server/src/integrations/tests/utils/mariadb.ts b/packages/server/src/integrations/tests/utils/mariadb.ts index c4dd4cf43b..3a90b554ee 100644 --- a/packages/server/src/integrations/tests/utils/mariadb.ts +++ b/packages/server/src/integrations/tests/utils/mariadb.ts @@ -1,9 +1,9 @@ import { Datasource, SourceName } from "@budibase/types" import { GenericContainer, Wait } from "testcontainers" import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy" -import { rawQuery } from "./mysql" import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { startContainer } from "." +import { knexClient } from "./mysql" let ports: Promise @@ -55,7 +55,8 @@ export async function getDatasource(): Promise { } const database = generator.guid().replaceAll("-", "") - await rawQuery(datasource, `CREATE DATABASE \`${database}\``) + const client = await knexClient(datasource) + await client.raw(`CREATE DATABASE \`${database}\``) datasource.config.database = database return datasource } diff --git a/packages/server/src/integrations/tests/utils/mssql.ts b/packages/server/src/integrations/tests/utils/mssql.ts index 3f661f4914..a4bd5448f4 100644 --- a/packages/server/src/integrations/tests/utils/mssql.ts +++ b/packages/server/src/integrations/tests/utils/mssql.ts @@ -1,13 +1,12 @@ import { Datasource, SourceName } from "@budibase/types" import { GenericContainer, Wait } from "testcontainers" -import mssql from "mssql" import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { startContainer } from "." import knex from "knex" let ports: Promise -export async function GetDatasource(): Promise { +export async function getDatasource(): Promise { if (!ports) { ports = startContainer( new GenericContainer("mcr.microsoft.com/mssql/server:2022-latest") @@ -50,30 +49,13 @@ export async function GetDatasource(): Promise { } const database = generator.guid().replaceAll("-", "") - await rawQuery(datasource, `CREATE DATABASE "${database}"`) + const client = await knexClient(datasource) + await client.raw(`CREATE DATABASE "${database}"`) datasource.config!.database = database return datasource } -export async function rawQuery(ds: Datasource, sql: string) { - if (!ds.config) { - throw new Error("Datasource config is missing") - } - if (ds.source !== SourceName.SQL_SERVER) { - throw new Error("Datasource source is not SQL Server") - } - - const pool = new mssql.ConnectionPool(ds.config! as mssql.config) - const client = await pool.connect() - try { - const { recordset } = await client.query(sql) - return recordset - } finally { - await pool.close() - } -} - export async function knexClient(ds: Datasource) { if (!ds.config) { throw new Error("Datasource config is missing") diff --git a/packages/server/src/integrations/tests/utils/mysql.ts b/packages/server/src/integrations/tests/utils/mysql.ts index 1975e07730..c35be0689e 100644 --- a/packages/server/src/integrations/tests/utils/mysql.ts +++ b/packages/server/src/integrations/tests/utils/mysql.ts @@ -1,7 +1,6 @@ import { Datasource, SourceName } from "@budibase/types" import { GenericContainer, Wait } from "testcontainers" import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy" -import mysql from "mysql2/promise" import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { startContainer } from "." import knex from "knex" @@ -57,28 +56,12 @@ export async function getDatasource(): Promise { } const database = generator.guid().replaceAll("-", "") - await rawQuery(datasource, `CREATE DATABASE \`${database}\``) + const client = await knexClient(datasource) + await client.raw(`CREATE DATABASE \`${database}\``) datasource.config!.database = database return datasource } -export async function rawQuery(ds: Datasource, sql: string) { - if (!ds.config) { - throw new Error("Datasource config is missing") - } - if (ds.source !== SourceName.MYSQL) { - throw new Error("Datasource source is not MySQL") - } - - const connection = await mysql.createConnection(ds.config) - try { - const [rows] = await connection.query(sql) - return rows - } finally { - connection.end() - } -} - export async function knexClient(ds: Datasource) { if (!ds.config) { throw new Error("Datasource config is missing") diff --git a/packages/server/src/integrations/tests/utils/postgres.ts b/packages/server/src/integrations/tests/utils/postgres.ts index 20b56331c1..74f5722737 100644 --- a/packages/server/src/integrations/tests/utils/postgres.ts +++ b/packages/server/src/integrations/tests/utils/postgres.ts @@ -1,6 +1,5 @@ import { Datasource, SourceName } from "@budibase/types" import { GenericContainer, Wait } from "testcontainers" -import pg from "pg" import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { startContainer } from "." import knex from "knex" @@ -44,30 +43,13 @@ export async function getDatasource(): Promise { } const database = generator.guid().replaceAll("-", "") - await rawQuery(datasource, `CREATE DATABASE "${database}"`) + const client = await knexClient(datasource) + await client.raw(`CREATE DATABASE "${database}"`) datasource.config!.database = database return datasource } -export async function rawQuery(ds: Datasource, sql: string) { - if (!ds.config) { - throw new Error("Datasource config is missing") - } - if (ds.source !== SourceName.POSTGRES) { - throw new Error("Datasource source is not Postgres") - } - - const client = new pg.Client(ds.config) - await client.connect() - try { - const { rows } = await client.query(sql) - return rows - } finally { - await client.end() - } -} - export async function knexClient(ds: Datasource) { if (!ds.config) { throw new Error("Datasource config is missing")