1
0
Fork 0
mirror of synced 2024-07-03 13:30:46 +12:00

Merge pull request #13432 from Budibase/budi-7659-sqs-investigate-handle-more-complex-types

[BUDI-7659] First end-to-end test for SQS functionality.
This commit is contained in:
Sam Rose 2024-04-09 17:05:16 +01:00 committed by GitHub
commit c753ffede9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 117 additions and 11 deletions

View file

@ -109,7 +109,7 @@ jobs:
- name: Pull testcontainers images - name: Pull testcontainers images
run: | run: |
docker pull testcontainers/ryuk:0.5.1 & docker pull testcontainers/ryuk:0.5.1 &
docker pull budibase/couchdb & docker pull budibase/couchdb:v3.2.1-sql &
docker pull redis & docker pull redis &
wait $(jobs -p) wait $(jobs -p)
@ -173,7 +173,7 @@ jobs:
docker pull mongo:7.0-jammy & docker pull mongo:7.0-jammy &
docker pull mariadb:lts & docker pull mariadb:lts &
docker pull testcontainers/ryuk:0.5.1 & docker pull testcontainers/ryuk:0.5.1 &
docker pull budibase/couchdb & docker pull budibase/couchdb:v3.2.1-sql &
docker pull redis & docker pull redis &
wait $(jobs -p) wait $(jobs -p)

View file

@ -13,8 +13,8 @@ export default async function setup() {
} }
try { try {
let couchdb = new GenericContainer("budibase/couchdb") let couchdb = new GenericContainer("budibase/couchdb:v3.2.1-sqs")
.withExposedPorts(5984) .withExposedPorts(5984, 4984)
.withEnvironment({ .withEnvironment({
COUCHDB_PASSWORD: "budibase", COUCHDB_PASSWORD: "budibase",
COUCHDB_USER: "budibase", COUCHDB_USER: "budibase",

View file

@ -77,9 +77,15 @@ export function setupEnv(...envs: any[]) {
throw new Error("CouchDB port not found") throw new Error("CouchDB port not found")
} }
const couchSqlPort = getExposedV4Port(couch, 4984)
if (!couchSqlPort) {
throw new Error("CouchDB SQL port not found")
}
const configs = [ const configs = [
{ key: "COUCH_DB_PORT", value: `${couchPort}` }, { key: "COUCH_DB_PORT", value: `${couchPort}` },
{ key: "COUCH_DB_URL", value: `http://127.0.0.1:${couchPort}` }, { key: "COUCH_DB_URL", value: `http://127.0.0.1:${couchPort}` },
{ key: "COUCH_DB_SQL_URL", value: `http://127.0.0.1:${couchSqlPort}` },
] ]
for (const config of configs.filter(x => !!x.value)) { for (const config of configs.filter(x => !!x.value)) {

View file

@ -1,6 +1,7 @@
// need to handle table name + field or just field, depending on if relationships used // need to handle table name + field or just field, depending on if relationships used
import { FieldType, Row, Table } from "@budibase/types" import { FieldType, Row, Table } from "@budibase/types"
import { generateRowIdField } from "../../../../integrations/utils" import { generateRowIdField } from "../../../../integrations/utils"
import { CONSTANT_INTERNAL_ROW_COLS } from "../../../../db/utils"
function extractFieldValue({ function extractFieldValue({
row, row,
@ -20,6 +21,15 @@ function extractFieldValue({
return value return value
} }
export function getInternalRowId(row: Row, table: Table): string {
return extractFieldValue({
row,
tableName: table._id!,
fieldName: "_id",
isLinked: false,
})
}
export function generateIdForRow( export function generateIdForRow(
row: Row | undefined, row: Row | undefined,
table: Table, table: Table,
@ -78,6 +88,15 @@ export function basicProcessing({
thisRow._id = generateIdForRow(row, table, isLinked) thisRow._id = generateIdForRow(row, table, isLinked)
thisRow.tableId = table._id thisRow.tableId = table._id
thisRow._rev = "rev" thisRow._rev = "rev"
} else {
for (let internalColumn of CONSTANT_INTERNAL_ROW_COLS) {
thisRow[internalColumn] = extractFieldValue({
row,
tableName: table._id!,
fieldName: internalColumn,
isLinked: false,
})
}
} }
return thisRow return thisRow
} }

View file

@ -32,7 +32,7 @@ export async function updateRelationshipColumns(
row: Row, row: Row,
rows: { [key: string]: Row }, rows: { [key: string]: Row },
relationships: RelationshipsJson[], relationships: RelationshipsJson[],
opts?: { internal?: boolean } opts?: { sqs?: boolean }
) { ) {
const columns: { [key: string]: any } = {} const columns: { [key: string]: any } = {}
for (let relationship of relationships) { for (let relationship of relationships) {
@ -55,7 +55,7 @@ export async function updateRelationshipColumns(
row, row,
table: linkedTable, table: linkedTable,
isLinked: true, isLinked: true,
internal: opts?.internal, internal: opts?.sqs,
}) })
if (!linked._id) { if (!linked._id) {
continue continue

View file

@ -15,7 +15,12 @@ import {
processFormulas, processFormulas,
} from "../../../../utilities/rowProcessor" } from "../../../../utilities/rowProcessor"
import { updateRelationshipColumns } from "./sqlUtils" import { updateRelationshipColumns } from "./sqlUtils"
import { basicProcessing, generateIdForRow, fixArrayTypes } from "./basic" import {
basicProcessing,
generateIdForRow,
fixArrayTypes,
getInternalRowId,
} from "./basic"
import sdk from "../../../../sdk" import sdk from "../../../../sdk"
import validateJs from "validate.js" import validateJs from "validate.js"
@ -117,7 +122,7 @@ export async function sqlOutputProcessing(
table: Table, table: Table,
tables: Record<string, Table>, tables: Record<string, Table>,
relationships: RelationshipsJson[], relationships: RelationshipsJson[],
opts?: { internal?: boolean } opts?: { sqs?: boolean }
): Promise<Row[]> { ): Promise<Row[]> {
if (!Array.isArray(rows) || rows.length === 0 || rows[0].read === true) { if (!Array.isArray(rows) || rows.length === 0 || rows[0].read === true) {
return [] return []
@ -125,7 +130,9 @@ export async function sqlOutputProcessing(
let finalRows: { [key: string]: Row } = {} let finalRows: { [key: string]: Row } = {}
for (let row of rows as Row[]) { for (let row of rows as Row[]) {
let rowId = row._id let rowId = row._id
if (!rowId) { if (opts?.sqs) {
rowId = getInternalRowId(row, table)
} else if (!rowId) {
rowId = generateIdForRow(row, table) rowId = generateIdForRow(row, table)
row._id = rowId row._id = rowId
} }
@ -146,7 +153,7 @@ export async function sqlOutputProcessing(
row, row,
table, table,
isLinked: false, isLinked: false,
internal: opts?.internal, internal: opts?.sqs,
}), }),
table table
) )

View file

@ -0,0 +1,74 @@
import { tableForDatasource } from "../../../tests/utilities/structures"
import { DatabaseName, getDatasource } from "../../../integrations/tests/utils"
import * as setup from "./utilities"
import { Datasource, FieldType, Table } from "@budibase/types"
jest.unmock("mssql")
describe.each([
["internal", undefined],
["internal-sqs", undefined],
[DatabaseName.POSTGRES, getDatasource(DatabaseName.POSTGRES)],
[DatabaseName.MYSQL, getDatasource(DatabaseName.MYSQL)],
[DatabaseName.SQL_SERVER, getDatasource(DatabaseName.SQL_SERVER)],
[DatabaseName.MARIADB, getDatasource(DatabaseName.MARIADB)],
])("/api/:sourceId/search (%s)", (name, dsProvider) => {
const isSqs = name === "internal-sqs"
const config = setup.getConfig()
let envCleanup: (() => void) | undefined
let table: Table
let datasource: Datasource | undefined
beforeAll(async () => {
if (isSqs) {
envCleanup = config.setEnv({ SQS_SEARCH_ENABLE: "true" })
}
await config.init()
if (dsProvider) {
datasource = await config.createDatasource({
datasource: await dsProvider,
})
}
})
afterAll(async () => {
setup.afterAll()
if (envCleanup) {
envCleanup()
}
})
beforeEach(async () => {
table = await config.api.table.save(
tableForDatasource(datasource, {
schema: {
name: {
name: "name",
type: FieldType.STRING,
},
},
})
)
})
it("should return rows", async () => {
const rows = await Promise.all([
config.api.row.save(table._id!, { name: "foo" }),
config.api.row.save(table._id!, { name: "bar" }),
])
const result = await config.api.row.search(table._id!, {
tableId: table._id!,
query: {},
})
expect(result.rows).toEqual(
expect.arrayContaining([
expect.objectContaining({ _id: rows[0]._id }),
expect.objectContaining({ _id: rows[1]._id }),
])
)
})
})

View file

@ -179,7 +179,7 @@ export async function search(
allTablesMap, allTablesMap,
relationships, relationships,
{ {
internal: true, sqs: true,
} }
), ),
} }