Merge pull request #12718 from warpcomdev/feature/postgresql-multiple-schema
Add support for full search path to postgres integration
This commit is contained in:
commit
5e040e42f1
|
@ -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"])
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -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_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_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
|
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 = () => `
|
ENUM_VALUES = () => `
|
||||||
|
@ -219,8 +220,12 @@ class PostgresIntegration extends Sql implements DatasourcePlus {
|
||||||
if (!this.config.schema) {
|
if (!this.config.schema) {
|
||||||
this.config.schema = "public"
|
this.config.schema = "public"
|
||||||
}
|
}
|
||||||
await this.client.query(`SET search_path TO "${this.config.schema}"`)
|
const search_path = this.config.schema
|
||||||
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${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
|
this.open = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue