1
0
Fork 0
mirror of synced 2024-09-30 00:57:16 +13:00

Merge pull request #12727 from Budibase/feature/postgresql-multiple-schema

Search path support for Postgres
This commit is contained in:
Michael Drury 2024-01-08 16:06:27 +00:00 committed by GitHub
commit 127392db86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 3 deletions

View file

@ -1118,4 +1118,76 @@ describe("postgres integrations", () => {
})
})
})
describe("Integration compatibility with postgres search_path", () => {
let client: Client, pathDatasource: Datasource
const schema1 = "test1",
schema2 = "test-2"
beforeAll(async () => {
const dsConfig = await databaseTestProviders.postgres.getDsConfig()
const dbConfig = dsConfig.config!
client = new Client(dbConfig)
await client.connect()
await client.query(`CREATE SCHEMA "${schema1}";`)
await client.query(`CREATE SCHEMA "${schema2}";`)
const pathConfig: any = {
...dsConfig,
config: {
...dbConfig,
schema: `${schema1}, ${schema2}`,
},
}
pathDatasource = await config.api.datasource.create(pathConfig)
})
afterAll(async () => {
await client.query(`DROP SCHEMA "${schema1}" CASCADE;`)
await client.query(`DROP SCHEMA "${schema2}" CASCADE;`)
await client.end()
})
it("discovers tables from any schema in search path", async () => {
await client.query(
`CREATE TABLE "${schema1}".table1 (id1 SERIAL PRIMARY KEY);`
)
await client.query(
`CREATE TABLE "${schema2}".table2 (id2 SERIAL PRIMARY KEY);`
)
const response = await makeRequest("post", "/api/datasources/info", {
datasource: pathDatasource,
})
expect(response.status).toBe(200)
expect(response.body.tableNames).toBeDefined()
expect(response.body.tableNames).toEqual(
expect.arrayContaining(["table1", "table2"])
)
})
it("does not mix columns from different tables", async () => {
const repeated_table_name = "table_same_name"
await client.query(
`CREATE TABLE "${schema1}".${repeated_table_name} (id SERIAL PRIMARY KEY, val1 TEXT);`
)
await client.query(
`CREATE TABLE "${schema2}".${repeated_table_name} (id2 SERIAL PRIMARY KEY, val2 TEXT);`
)
const response = await makeRequest(
"post",
`/api/datasources/${pathDatasource._id}/schema`,
{
tablesFilter: [repeated_table_name],
}
)
expect(response.status).toBe(200)
expect(
response.body.datasource.entities[repeated_table_name].schema
).toBeDefined()
const schema =
response.body.datasource.entities[repeated_table_name].schema
expect(Object.keys(schema).sort()).toEqual(["id", "val1"])
})
})
})

View file

@ -159,7 +159,8 @@ class PostgresIntegration extends Sql implements DatasourcePlus {
JOIN pg_index ON pg_class.oid = pg_index.indrelid AND pg_index.indisprimary
JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid AND pg_attribute.attnum = ANY(pg_index.indkey)
JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE pg_namespace.nspname = '${this.config.schema}';
WHERE pg_namespace.nspname = ANY(current_schemas(false))
AND pg_table_is_visible(pg_class.oid);
`
ENUM_VALUES = () => `
@ -219,8 +220,12 @@ class PostgresIntegration extends Sql implements DatasourcePlus {
if (!this.config.schema) {
this.config.schema = "public"
}
await this.client.query(`SET search_path TO "${this.config.schema}"`)
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'`
const search_path = this.config.schema
.split(",")
.map(item => `"${item.trim()}"`)
await this.client.query(`SET search_path TO ${search_path.join(",")};`)
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = ANY(current_schemas(false))
AND pg_table_is_visible(to_regclass(table_schema || '.' || table_name));`
this.open = true
}