From 26fa0222a18d70978f7cf51404974d0b1fdfd791 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 26 Nov 2024 12:00:30 +0000 Subject: [PATCH] Get all bigint tests passing. --- packages/backend-core/src/sql/sql.ts | 46 +++++++++++-------- .../server/src/api/routes/tests/row.spec.ts | 42 ++++++++++++----- .../src/integrations/microsoftSqlServer.ts | 3 +- 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/packages/backend-core/src/sql/sql.ts b/packages/backend-core/src/sql/sql.ts index d7d7235f3a..e97e31869c 100644 --- a/packages/backend-core/src/sql/sql.ts +++ b/packages/backend-core/src/sql/sql.ts @@ -1191,7 +1191,7 @@ class InternalBuilder { return withSchema } - private buildJsonField(table: Table, field: string): string { + private buildJsonField(table: Table, field: string): [string, Knex.Raw] { const parts = field.split(".") const baseName = parts[parts.length - 1] let unaliased: string @@ -1208,18 +1208,11 @@ class InternalBuilder { const schema = table.schema[baseName] - const separator = this.client === SqlClient.ORACLE ? " VALUE " : "," let identifier = this.rawQuotedIdentifier(tableField) - // if (schema.type === FieldType.BIGINT) { - // identifier = this.castIntToString(identifier) - // } else if (schema.type === FieldType.LINK) { - // const otherTable = this.query.meta.tables![schema.tableId] - // const otherField = otherTable.schema[schema.fieldName] - // if (otherField.type === FieldType.BIGINT) { - // identifier = this.castIntToString(identifier) - // } - // } - return this.knex.raw(`?${separator}??`, [unaliased, identifier]).toString() + if (schema.type === FieldType.BIGINT) { + identifier = this.castIntToString(identifier) + } + return [unaliased, identifier] } maxFunctionParameters() { @@ -1282,8 +1275,14 @@ class InternalBuilder { 0, Math.floor(this.maxFunctionParameters() / 2) ) - const fieldList: string = relationshipFields - .map(field => this.buildJsonField(relatedTable!, field)) + const fieldList = relationshipFields.map(field => + this.buildJsonField(relatedTable!, field) + ) + const fieldListFormatted = fieldList + .map(f => { + const separator = this.client === SqlClient.ORACLE ? " VALUE " : "," + return this.knex.raw(`?${separator}??`, [f[0], f[1]]).toString() + }) .join(",") // SQL Server uses TOP - which performs a little differently to the normal LIMIT syntax // it reduces the result set rather than limiting how much data it filters over @@ -1331,35 +1330,42 @@ class InternalBuilder { // need to check the junction table document is to the right column, this is just for SQS subQuery = this.addJoinFieldCheck(subQuery, relationship) wrapperQuery = standardWrap( - this.knex.raw(`json_group_array(json_object(${fieldList}))`) + this.knex.raw( + `json_group_array(json_object(${fieldListFormatted}))` + ) ) break case SqlClient.POSTGRES: wrapperQuery = standardWrap( - this.knex.raw(`json_agg(json_build_object(${fieldList}))`) + this.knex.raw(`json_agg(json_build_object(${fieldListFormatted}))`) ) break case SqlClient.MARIADB: // can't use the standard wrap due to correlated sub-query limitations in MariaDB wrapperQuery = subQuery.select( knex.raw( - `json_arrayagg(json_object(${fieldList}) LIMIT ${getRelationshipLimit()})` + `json_arrayagg(json_object(${fieldListFormatted}) LIMIT ${getRelationshipLimit()})` ) ) break case SqlClient.MY_SQL: case SqlClient.ORACLE: wrapperQuery = standardWrap( - this.knex.raw(`json_arrayagg(json_object(${fieldList}))`) + this.knex.raw(`json_arrayagg(json_object(${fieldListFormatted}))`) ) break case SqlClient.MS_SQL: { const comparatorQuery = knex - .select(`${fromAlias}.*`) + .select(`*`) // @ts-ignore - from alias syntax not TS supported .from({ [fromAlias]: subQuery - .select(`${toAlias}.*`) + .select( + fieldList.map(f => { + // @ts-expect-error raw is fine here, knex types are wrong + return knex.ref(f[1]).as(f[0]) + }) + ) .limit(getRelationshipLimit()), }) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 8809ae5cbc..3b1b151f1f 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -3496,7 +3496,7 @@ if (descriptions.length) { }) }) - if (!isInternal) { + if (!isInternal && !isOracle) { describe("bigint ids", () => { let table1: Table, table2: Table let table1Name: string, table2Name: string @@ -3504,15 +3504,14 @@ if (descriptions.length) { beforeAll(async () => { table1Name = `table1-${generator.guid().substring(0, 5)}` await client!.schema.createTable(table1Name, table => { - table.bigIncrements("table1Id").primary() + table.bigInteger("table1Id").primary() }) table2Name = `table2-${generator.guid().substring(0, 5)}` await client!.schema.createTable(table2Name, table => { - table.increments("table2Id").primary() + table.bigInteger("table2Id").primary() table .bigInteger("table1Ref") - .unsigned() .references("table1Id") .inTable(table1Name) }) @@ -3540,21 +3539,42 @@ if (descriptions.length) { }) it.only("should be able to fetch rows with related bigint ids", async () => { - const row = await config.api.row.save(table1._id!, {}) - await config.api.row.save(table2._id!, { table1Ref: row.table1Id }) + const row = await config.api.row.save(table1._id!, { + table1Id: "1", + }) + await config.api.row.save(table2._id!, { + table2Id: "2", + table1Ref: row.table1Id, + }) - const { rows } = await config.api.row.search(table1._id!) - expect(rows).toEqual([ + let resp = await config.api.row.search(table1._id!) + expect(resp.rows).toEqual([ expect.objectContaining({ _id: "%5B'1'%5D", - _rev: "rev", table1Id: "1", many: [ { - _id: "%5B'1'%5D", - primaryDisplay: 1, + _id: "%5B'2'%5D", + primaryDisplay: "2", }, ], + tableId: table1._id, + }), + ]) + + resp = await config.api.row.search(table2._id!) + expect(resp.rows).toEqual([ + expect.objectContaining({ + _id: "%5B'2'%5D", + table2Id: "2", + table1Ref: "1", + one: [ + { + _id: "%5B'1'%5D", + primaryDisplay: "1", + }, + ], + tableId: table2._id, }), ]) }) diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index 1c74e6b1ff..4997f3256d 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -342,7 +342,8 @@ class SqlServerIntegration extends Sql implements DatasourcePlus { ? `${query.sql}; SELECT SCOPE_IDENTITY() AS id;` : query.sql this.log(sql, query.bindings) - return await request.query(sql) + const resp = await request.query(sql) + return resp } catch (err: any) { let readableMessage = getReadableErrorMessage( SourceName.SQL_SERVER,