Skip to content

Commit

Permalink
prohibit collisions in column / table names
Browse files Browse the repository at this point in the history
  • Loading branch information
darkgnotic committed Feb 1, 2025
1 parent 6026940 commit fdbd187
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
64 changes: 64 additions & 0 deletions packages/zero-schema/src/builder/schema-builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,4 +504,68 @@ test('alternate upstream names', () => {
],
}
`);

const foo = table('foo')
.from('fooz')
.columns({
bar: string().from('baz'),
baz: string().from('boo'),
boo: number().from('bar'),
})
.primaryKey('bar');

expect(foo.build()).toMatchInlineSnapshot(`
{
"columns": {
"bar": {
"customType": null,
"from": "baz",
"optional": false,
"type": "string",
},
"baz": {
"customType": null,
"from": "boo",
"optional": false,
"type": "string",
},
"boo": {
"customType": null,
"from": "bar",
"optional": false,
"type": "number",
},
},
"from": "fooz",
"name": "foo",
"primaryKey": [
"bar",
],
}
`);
});

test('conflicting column names', () => {
const user = table('user')
.from('users')
.columns({
a: string().from('b'),
b: string().from('c'),
c: string(),
recruiterId: number().from('user_recruiter_id'),
})
.primaryKey('a');

expect(() => user.build()).toThrowErrorMatchingInlineSnapshot(
`[Error: Table "user" has multiple columns referencing "c"]`,
);
});

test('schema with conflicting table names', () => {
const foo = table('foo').from('bar').columns({a: string()}).primaryKey('a');
const bar = table('bar').columns({a: string()}).primaryKey('a');

expect(() =>
createSchema(1, {tables: [foo, bar]}),
).toThrowErrorMatchingInlineSnapshot(`[Error: Multiple tables reference the name "bar"]`);
});
6 changes: 6 additions & 0 deletions packages/zero-schema/src/builder/schema-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,14 @@ export function createSchema<
} {
const retTables: Record<string, TableSchema> = {};
const retRelationships: Record<string, Record<string, Relationship>> = {};
const tableNames = new Set<string>();

options.tables.forEach(table => {
const name = table.schema.from ?? table.schema.name;
if (tableNames.has(name)) {
throw new Error(`Multiple tables reference the name "${name}"`);
}
tableNames.add(name);
if (retTables[table.schema.name]) {
throw new Error(
`Table "${table.schema.name}" is defined more than once in the schema`,
Expand Down
12 changes: 12 additions & 0 deletions packages/zero-schema/src/builder/table-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ export class TableBuilderWithColumns<const TShape extends TableSchema> {
if (this.#schema.primaryKey.length === 0) {
throw new Error(`Table "${this.#schema.name}" is missing a primary key`);
}
const columnNames = new Set<string>();
for (const [col, {from}] of Object.entries(this.#schema.columns)) {
const name = from ?? col;
if (columnNames.has(name)) {
throw new Error(
`Table "${
this.#schema.name
}" has multiple columns referencing "${name}"`,
);
}
columnNames.add(name);
}
return this.#schema;
}
}
Expand Down

0 comments on commit fdbd187

Please sign in to comment.