Remove rawQuery entirely.

This commit is contained in:
Sam Rose 2024-06-17 16:15:51 +01:00
parent 16cacb3de7
commit c107ab937d
No known key found for this signature in database
8 changed files with 57 additions and 145 deletions

View File

@ -10,37 +10,11 @@ import * as setup from "../utilities"
import { import {
DatabaseName, DatabaseName,
getDatasource, getDatasource,
rawQuery, knexClient,
} from "../../../../integrations/tests/utils" } from "../../../../integrations/tests/utils"
import { Expectations } from "src/tests/utilities/api/base" import { Expectations } from "src/tests/utilities/api/base"
import { events } from "@budibase/backend-core" import { events } from "@budibase/backend-core"
import { Knex } from "knex"
const createTableSQL: Record<string, string> = {
[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;`
describe.each( describe.each(
[ [
@ -53,6 +27,7 @@ describe.each(
const config = setup.getConfig() const config = setup.getConfig()
let rawDatasource: Datasource let rawDatasource: Datasource
let datasource: Datasource let datasource: Datasource
let client: Knex
async function createQuery( async function createQuery(
query: Partial<Query>, query: Partial<Query>,
@ -82,21 +57,34 @@ describe.each(
rawDatasource = await dsProvider rawDatasource = await dsProvider
datasource = await config.api.datasource.create(rawDatasource) datasource = await config.api.datasource.create(rawDatasource)
// The Datasource API does not return the password, but we need // The Datasource API doesn ot return the password, but we need it later to
// it later to connect to the underlying database, so we fill it // connect to the underlying database, so we fill it back in here.
// back in here.
datasource.config!.password = rawDatasource.config!.password datasource.config!.password = rawDatasource.config!.password
await rawQuery(datasource, createTableSQL[datasource.source]) client = await knexClient(rawDatasource)
await rawQuery(datasource, insertSQL)
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() jest.clearAllMocks()
}) })
afterEach(async () => { afterEach(async () => {
const ds = await config.api.datasource.get(datasource._id!) const ds = await config.api.datasource.get(datasource._id!)
config.api.datasource.delete(ds) await config.api.datasource.delete(ds)
await rawQuery(datasource, dropTableSQL) await client.schema.dropTable("test_table")
}) })
afterAll(async () => { 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!) const prodQuery = await config.api.query.getProd(query._id!)
expect(prodQuery._id).toEqual(query._id) expect(prodQuery._id).toEqual(query._id)
@ -429,11 +417,11 @@ describe.each(
}, },
]) ])
const rows = await rawQuery( const rows = await client("test_table").where({ name: "baz" }).select()
datasource,
"SELECT * FROM test_table WHERE name = 'baz'"
)
expect(rows).toHaveLength(1) expect(rows).toHaveLength(1)
for (const row of rows) {
expect(row).toMatchObject({ name: "baz" })
}
}) })
it("should not allow handlebars as parameters", async () => { it("should not allow handlebars as parameters", async () => {
@ -490,11 +478,14 @@ describe.each(
expect(result.data).toEqual([{ created: true }]) expect(result.data).toEqual([{ created: true }])
const rows = await rawQuery( const rows = await client("test_table")
datasource, .where({ birthday: datetimeStr })
`SELECT * FROM test_table WHERE birthday = '${date.toISOString()}'` .select()
)
expect(rows).toHaveLength(1) 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 }]) expect(result.data).toEqual([{ created: true }])
const rows = await rawQuery( const rows = await client("test_table")
datasource, .where({ name: notDateStr })
`SELECT * FROM test_table WHERE name = '${notDateStr}'` .select()
)
expect(rows).toHaveLength(1) expect(rows).toHaveLength(1)
} }
) )
@ -660,10 +650,7 @@ describe.each(
}, },
]) ])
const rows = await rawQuery( const rows = await client("test_table").where({ id: 1 }).select()
datasource,
"SELECT * FROM test_table WHERE id = 1"
)
expect(rows).toEqual([ expect(rows).toEqual([
{ id: 1, name: "foo", birthday: null, number: null }, { id: 1, name: "foo", birthday: null, number: null },
]) ])
@ -731,10 +718,7 @@ describe.each(
}, },
]) ])
const rows = await rawQuery( const rows = await client("test_table").where({ id: 1 }).select()
datasource,
"SELECT * FROM test_table WHERE id = 1"
)
expect(rows).toHaveLength(0) expect(rows).toHaveLength(0)
}) })
}) })

View File

@ -18,13 +18,12 @@ function uniqueTableName(length?: number): string {
const config = setup.getConfig()! const config = setup.getConfig()!
describe("mysql integrations", () => { describe("mysql integrations", () => {
let rawDatasource: Datasource
let datasource: Datasource let datasource: Datasource
let client: Knex let client: Knex
beforeAll(async () => { beforeAll(async () => {
await config.init() await config.init()
rawDatasource = await getDatasource(DatabaseName.MYSQL) const rawDatasource = await getDatasource(DatabaseName.MYSQL)
datasource = await config.api.datasource.create(rawDatasource) datasource = await config.api.datasource.create(rawDatasource)
client = await knexClient(rawDatasource) client = await knexClient(rawDatasource)
}) })

View File

@ -12,13 +12,12 @@ import { Knex } from "knex"
const config = setup.getConfig()! const config = setup.getConfig()!
describe("postgres integrations", () => { describe("postgres integrations", () => {
let rawDatasource: Datasource
let datasource: Datasource let datasource: Datasource
let client: Knex let client: Knex
beforeAll(async () => { beforeAll(async () => {
await config.init() await config.init()
rawDatasource = await getDatasource(DatabaseName.POSTGRES) const rawDatasource = await getDatasource(DatabaseName.POSTGRES)
datasource = await config.api.datasource.create(rawDatasource) datasource = await config.api.datasource.create(rawDatasource)
client = await knexClient(rawDatasource) client = await knexClient(rawDatasource)
}) })
@ -91,17 +90,16 @@ describe("postgres integrations", () => {
}) })
describe("Integration compatibility with postgres search_path", () => { describe("Integration compatibility with postgres search_path", () => {
let rawDatasource: Datasource, let datasource: Datasource
datasource: Datasource, let client: Knex
client: Knex, let schema1: string
schema1: string, let schema2: string
schema2: string
beforeEach(async () => { beforeEach(async () => {
schema1 = generator.guid().replaceAll("-", "") schema1 = generator.guid().replaceAll("-", "")
schema2 = generator.guid().replaceAll("-", "") schema2 = generator.guid().replaceAll("-", "")
rawDatasource = await getDatasource(DatabaseName.POSTGRES) const rawDatasource = await getDatasource(DatabaseName.POSTGRES)
client = await knexClient(rawDatasource) client = await knexClient(rawDatasource)
await client.schema.createSchema(schema1) await client.schema.createSchema(schema1)

View File

@ -48,23 +48,6 @@ export async function getDatasources(
return Promise.all(sourceNames.map(sourceName => providers[sourceName]())) return Promise.all(sourceNames.map(sourceName => providers[sourceName]()))
} }
export async function rawQuery(ds: Datasource, sql: string): Promise<any> {
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) { export async function knexClient(ds: Datasource) {
switch (ds.source) { switch (ds.source) {
case SourceName.POSTGRES: { case SourceName.POSTGRES: {

View File

@ -1,9 +1,9 @@
import { Datasource, SourceName } from "@budibase/types" import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait } from "testcontainers" import { GenericContainer, Wait } from "testcontainers"
import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy" import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy"
import { rawQuery } from "./mysql"
import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { generator, testContainerUtils } from "@budibase/backend-core/tests"
import { startContainer } from "." import { startContainer } from "."
import { knexClient } from "./mysql"
let ports: Promise<testContainerUtils.Port[]> let ports: Promise<testContainerUtils.Port[]>
@ -55,7 +55,8 @@ export async function getDatasource(): Promise<Datasource> {
} }
const database = generator.guid().replaceAll("-", "") 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 datasource.config.database = database
return datasource return datasource
} }

View File

@ -1,13 +1,12 @@
import { Datasource, SourceName } from "@budibase/types" import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait } from "testcontainers" import { GenericContainer, Wait } from "testcontainers"
import mssql from "mssql"
import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { generator, testContainerUtils } from "@budibase/backend-core/tests"
import { startContainer } from "." import { startContainer } from "."
import knex from "knex" import knex from "knex"
let ports: Promise<testContainerUtils.Port[]> let ports: Promise<testContainerUtils.Port[]>
export async function GetDatasource(): Promise<Datasource> { export async function getDatasource(): Promise<Datasource> {
if (!ports) { if (!ports) {
ports = startContainer( ports = startContainer(
new GenericContainer("mcr.microsoft.com/mssql/server:2022-latest") new GenericContainer("mcr.microsoft.com/mssql/server:2022-latest")
@ -50,30 +49,13 @@ export async function GetDatasource(): Promise<Datasource> {
} }
const database = generator.guid().replaceAll("-", "") 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 datasource.config!.database = database
return datasource 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) { export async function knexClient(ds: Datasource) {
if (!ds.config) { if (!ds.config) {
throw new Error("Datasource config is missing") throw new Error("Datasource config is missing")

View File

@ -1,7 +1,6 @@
import { Datasource, SourceName } from "@budibase/types" import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait } from "testcontainers" import { GenericContainer, Wait } from "testcontainers"
import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy" import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy"
import mysql from "mysql2/promise"
import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { generator, testContainerUtils } from "@budibase/backend-core/tests"
import { startContainer } from "." import { startContainer } from "."
import knex from "knex" import knex from "knex"
@ -57,28 +56,12 @@ export async function getDatasource(): Promise<Datasource> {
} }
const database = generator.guid().replaceAll("-", "") 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 datasource.config!.database = database
return datasource 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) { export async function knexClient(ds: Datasource) {
if (!ds.config) { if (!ds.config) {
throw new Error("Datasource config is missing") throw new Error("Datasource config is missing")

View File

@ -1,6 +1,5 @@
import { Datasource, SourceName } from "@budibase/types" import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait } from "testcontainers" import { GenericContainer, Wait } from "testcontainers"
import pg from "pg"
import { generator, testContainerUtils } from "@budibase/backend-core/tests" import { generator, testContainerUtils } from "@budibase/backend-core/tests"
import { startContainer } from "." import { startContainer } from "."
import knex from "knex" import knex from "knex"
@ -44,30 +43,13 @@ export async function getDatasource(): Promise<Datasource> {
} }
const database = generator.guid().replaceAll("-", "") 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 datasource.config!.database = database
return datasource 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) { export async function knexClient(ds: Datasource) {
if (!ds.config) { if (!ds.config) {
throw new Error("Datasource config is missing") throw new Error("Datasource config is missing")