SQL server relationship fix for tables in schema (#9103)

* Add schema to LEFT JOIN

* lint
This commit is contained in:
melohagan 2022-12-19 18:12:05 +00:00 committed by GitHub
parent 221f9e3813
commit 033094cf30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 5 deletions

View File

@ -313,7 +313,8 @@ class InternalBuilder {
addRelationships( addRelationships(
query: KnexQuery, query: KnexQuery,
fromTable: string, fromTable: string,
relationships: RelationshipsJson[] | undefined relationships: RelationshipsJson[] | undefined,
schema: string | undefined
): KnexQuery { ): KnexQuery {
if (!relationships) { if (!relationships) {
return query return query
@ -337,9 +338,13 @@ class InternalBuilder {
} }
for (let [key, relationships] of Object.entries(tableSets)) { for (let [key, relationships] of Object.entries(tableSets)) {
const { toTable, throughTable } = JSON.parse(key) const { toTable, throughTable } = JSON.parse(key)
const toTableWithSchema = schema ? `${schema}.${toTable}` : toTable
const throughTableWithSchema = schema
? `${schema}.${throughTable}`
: throughTable
if (!throughTable) { if (!throughTable) {
// @ts-ignore // @ts-ignore
query = query.leftJoin(toTable, function () { query = query.leftJoin(toTableWithSchema, function () {
for (let relationship of relationships) { for (let relationship of relationships) {
const from = relationship.from, const from = relationship.from,
to = relationship.to to = relationship.to
@ -350,7 +355,7 @@ class InternalBuilder {
} else { } else {
query = query query = query
// @ts-ignore // @ts-ignore
.leftJoin(throughTable, function () { .leftJoin(throughTableWithSchema, function () {
for (let relationship of relationships) { for (let relationship of relationships) {
const fromPrimary = relationship.fromPrimary const fromPrimary = relationship.fromPrimary
const from = relationship.from const from = relationship.from
@ -362,7 +367,7 @@ class InternalBuilder {
) )
} }
}) })
.leftJoin(toTable, function () { .leftJoin(toTableWithSchema, function () {
for (let relationship of relationships) { for (let relationship of relationships) {
const toPrimary = relationship.toPrimary const toPrimary = relationship.toPrimary
const to = relationship.to const to = relationship.to
@ -456,7 +461,12 @@ class InternalBuilder {
preQuery = this.addSorting(preQuery, json) preQuery = this.addSorting(preQuery, json)
} }
// handle joins // handle joins
query = this.addRelationships(preQuery, tableName, relationships) query = this.addRelationships(
preQuery,
tableName,
relationships,
endpoint.schema
)
return this.addFilters(query, filters, { relationship: true }) return this.addFilters(query, filters, { relationship: true })
} }

View File

@ -51,6 +51,72 @@ function generateDeleteJson(table = TABLE_NAME, filters = {}) {
} }
} }
function generateRelationshipJson(config: { schema?: string } = {}) {
return {
endpoint: {
datasourceId: "Postgres",
entityId: "brands",
operation: "READ",
schema: config.schema,
},
resource: {
fields: [
"brands.brand_id",
"brands.brand_name",
"products.product_id",
"products.product_name",
"products.brand_id",
],
},
filters: {},
sort: {},
paginate: {},
relationships: [
{
from: "brand_id",
to: "brand_id",
tableName: "products",
column: "products",
},
],
extra: { idFilter: {} },
}
}
function generateManyRelationshipJson(config: { schema?: string } = {}) {
return {
endpoint: {
datasourceId: "Postgres",
entityId: "stores",
operation: "READ",
schema: config.schema,
},
resource: {
fields: [
"stores.store_id",
"stores.store_name",
"products.product_id",
"products.product_name",
],
},
filters: {},
sort: {},
paginate: {},
relationships: [
{
from: "store_id",
to: "product_id",
tableName: "products",
column: "products",
through: "stocks",
fromPrimary: "store_id",
toPrimary: "product_id",
},
],
extra: { idFilter: {} },
}
}
describe("SQL query builder", () => { describe("SQL query builder", () => {
const limit = 500 const limit = 500
const client = SqlClient.POSTGRES const client = SqlClient.POSTGRES
@ -425,4 +491,30 @@ describe("SQL query builder", () => {
sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb ?| array [20,25] and \"${TABLE_NAME}\".\"name\"::jsonb ?| array ['John','Mary'] limit $1) as \"${TABLE_NAME}\"`, sql: `select * from (select * from \"${TABLE_NAME}\" where \"${TABLE_NAME}\".\"age\"::jsonb ?| array [20,25] and \"${TABLE_NAME}\".\"name\"::jsonb ?| array ['John','Mary'] limit $1) as \"${TABLE_NAME}\"`,
}) })
}) })
it("should add the schema to the LEFT JOIN", () => {
const query = sql._query(generateRelationshipJson({ schema: "production" }))
expect(query).toEqual({
bindings: [500, 5000],
sql: `select "brands"."brand_id" as "brands.brand_id", "brands"."brand_name" as "brands.brand_name", "products"."product_id" as "products.product_id", "products"."product_name" as "products.product_name", "products"."brand_id" as "products.brand_id" from (select * from "production"."brands" limit $1) as "brands" left join "production"."products" on "brands"."brand_id" = "products"."brand_id" limit $2`,
})
})
it("should handle if the schema is not present when doing a LEFT JOIN", () => {
const query = sql._query(generateRelationshipJson())
expect(query).toEqual({
bindings: [500, 5000],
sql: `select "brands"."brand_id" as "brands.brand_id", "brands"."brand_name" as "brands.brand_name", "products"."product_id" as "products.product_id", "products"."product_name" as "products.product_name", "products"."brand_id" as "products.brand_id" from (select * from "brands" limit $1) as "brands" left join "products" on "brands"."brand_id" = "products"."brand_id" limit $2`,
})
})
it("should add the schema to both the toTable and throughTable in many-to-many join", () => {
const query = sql._query(
generateManyRelationshipJson({ schema: "production" })
)
expect(query).toEqual({
bindings: [500, 5000],
sql: `select "stores"."store_id" as "stores.store_id", "stores"."store_name" as "stores.store_name", "products"."product_id" as "products.product_id", "products"."product_name" as "products.product_name" from (select * from "production"."stores" limit $1) as "stores" left join "production"."stocks" on "stores"."store_id" = "stocks"."store_id" left join "production"."products" on "products"."product_id" = "stocks"."product_id" limit $2`,
})
})
}) })