Skip to content

Commit a1c6903

Browse files
committed
fix(typegen): schemas filtering
1 parent edc495d commit a1c6903

File tree

2 files changed

+84
-15
lines changed

2 files changed

+84
-15
lines changed

src/server/templates/python.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,18 @@ export const apply = ({
1717
types,
1818
}: GeneratorMetadata): string => {
1919
const ctx = new PythonContext(types, columns, schemas)
20-
const py_tables = tables
21-
.filter((table) => schemas.some((schema) => schema.name === table.schema))
22-
.flatMap((table) => {
23-
const py_class_and_methods = ctx.tableToClass(table)
24-
return py_class_and_methods
25-
})
20+
// Used for efficient lookup of types by schema name
21+
const schemasNames = new Set(schemas.map((schema) => schema.name))
22+
const py_tables = tables.flatMap((table) => {
23+
const py_class_and_methods = ctx.tableToClass(table)
24+
return py_class_and_methods
25+
})
2626
const composite_types = types
27-
.filter(
28-
(type) => type.attributes.length > 0 && schemas.some((schema) => type.schema == schema.name)
29-
)
27+
// We always include system schemas, so we need to filter out types that are not in the included schemas
28+
.filter((type) => type.attributes.length > 0 && schemasNames.has(type.schema))
3029
.map((type) => ctx.typeToClass(type))
31-
const py_views = views
32-
.filter((view) => schemas.some((schema) => schema.name === view.schema))
33-
.map((view) => ctx.viewToClass(view))
34-
const py_matviews = materializedViews
35-
.filter((matview) => schemas.some((schema) => schema.name === matview.schema))
36-
.map((matview) => ctx.matViewToClass(matview))
30+
const py_views = views.map((view) => ctx.viewToClass(view))
31+
const py_matviews = materializedViews.map((matview) => ctx.matViewToClass(matview))
3732

3833
let output = `
3934
from __future__ import annotations

test/server/typegen.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6501,3 +6501,77 @@ class PublicCompositeTypeWithRecordAttribute(BaseModel):
65016501
todo: PublicTodos = Field(alias="todo")"
65026502
`)
65036503
})
6504+
6505+
test('typegen: python w/ excluded/included schemas', async () => {
6506+
// Create a test schema with some tables
6507+
await app.inject({
6508+
method: 'POST',
6509+
path: '/query',
6510+
payload: {
6511+
query: `
6512+
CREATE SCHEMA IF NOT EXISTS test_schema;
6513+
CREATE TABLE IF NOT EXISTS test_schema.test_table (
6514+
id serial PRIMARY KEY,
6515+
name text
6516+
);
6517+
CREATE TABLE IF NOT EXISTS test_schema.another_table (
6518+
id serial PRIMARY KEY,
6519+
value text
6520+
);
6521+
`,
6522+
},
6523+
})
6524+
6525+
try {
6526+
// Test excluded_schemas - should exclude test_schema
6527+
const { body: excludedBody } = await app.inject({
6528+
method: 'GET',
6529+
path: '/generators/python',
6530+
query: { access_control: 'public', excluded_schemas: 'test_schema' },
6531+
})
6532+
expect(excludedBody).not.toContain('TestSchemaTestTable')
6533+
expect(excludedBody).not.toContain('TestSchemaAnotherTable')
6534+
expect(excludedBody).toContain('PublicUsers')
6535+
expect(excludedBody).toContain('PublicTodos')
6536+
6537+
// Test included_schemas - should only include test_schema
6538+
const { body: includedBody } = await app.inject({
6539+
method: 'GET',
6540+
path: '/generators/python',
6541+
query: { access_control: 'public', included_schemas: 'test_schema' },
6542+
})
6543+
expect(includedBody).toContain('TestSchemaTestTable')
6544+
expect(includedBody).toContain('TestSchemaAnotherTable')
6545+
expect(includedBody).not.toContain('PublicUsers')
6546+
expect(includedBody).not.toContain('PublicTodos')
6547+
6548+
// Test multiple excluded schemas
6549+
const { body: multipleExcludedBody } = await app.inject({
6550+
method: 'GET',
6551+
path: '/generators/python',
6552+
query: { access_control: 'public', excluded_schemas: 'test_schema,public' },
6553+
})
6554+
expect(multipleExcludedBody).not.toContain('TestSchemaTestTable')
6555+
expect(multipleExcludedBody).not.toContain('PublicUsers')
6556+
6557+
// // Test multiple included schemas
6558+
const { body: multipleIncludedBody } = await app.inject({
6559+
method: 'GET',
6560+
path: '/generators/python',
6561+
query: { access_control: 'public', included_schemas: 'public,test_schema' },
6562+
})
6563+
expect(multipleIncludedBody).toContain('TestSchemaTestTable')
6564+
expect(multipleIncludedBody).toContain('PublicUsers')
6565+
} finally {
6566+
// Clean up test schema
6567+
await app.inject({
6568+
method: 'POST',
6569+
path: '/query',
6570+
payload: {
6571+
query: `
6572+
DROP SCHEMA IF EXISTS test_schema CASCADE;
6573+
`,
6574+
},
6575+
})
6576+
}
6577+
})

0 commit comments

Comments
 (0)