test('composite FK column order follows constraint ordinality rather than physical column order', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create table parent (
x int,
y int,
primary key (y, x)
);
create table child (
a int,
b int,
constraint child_parent_fk
foreign key (b, a) references parent (y, x)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const childTable = result.tables.find(
(t: { name: string }) => t.name === 'public.child'
);
expect(childTable).toBeDefined();
const constraints = childTable.foreign_key_constraints ?? [];
expect(constraints).toHaveLength(1);
expect(constraints).toEqual([
{
name: 'child_parent_fk',
source_table: 'public.child',
source_columns: ['b', 'a'],
target_table: 'public.parent',
target_columns: ['y', 'x'],
},
]);
});test('target table includes incoming foreign key constraint with source_table', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create table parent (
id int primary key
);
create table child (
parent_id int,
constraint child_parent_fk
foreign key (parent_id) references parent (id)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const parentTable = result.tables.find(
(t: { name: string }) => t.name === 'public.parent'
);
expect(parentTable).toBeDefined();
const constraints = parentTable.foreign_key_constraints ?? [];
expect(constraints).toHaveLength(1);
expect(constraints).toEqual([
{
name: 'child_parent_fk',
source_table: 'public.child',
source_columns: ['parent_id'],
target_table: 'public.parent',
target_columns: ['id'],
},
]);
});test('multiple independent FKs between same tables are separate constraints', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create table parent (
id int primary key
);
create table child (
primary_parent_id int,
backup_parent_id int,
constraint child_primary_parent_fk
foreign key (primary_parent_id) references parent (id),
constraint child_backup_parent_fk
foreign key (backup_parent_id) references parent (id)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const childTable = result.tables.find(
(t: { name: string }) => t.name === 'public.child'
);
expect(childTable).toBeDefined();
const constraints = [...(childTable.foreign_key_constraints ?? [])].sort(
(a, b) => a.name.localeCompare(b.name)
);
expect(constraints).toHaveLength(2);
expect(constraints).toEqual([
{
name: 'child_backup_parent_fk',
source_table: 'public.child',
source_columns: ['backup_parent_id'],
target_table: 'public.parent',
target_columns: ['id'],
},
{
name: 'child_primary_parent_fk',
source_table: 'public.child',
source_columns: ['primary_parent_id'],
target_table: 'public.parent',
target_columns: ['id'],
},
]);
});test('cross-schema foreign keys use schema-qualified source and target tables', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create schema app;
create table public.accounts (
id int primary key
);
create table app.orders (
account_id int,
constraint orders_account_fk
foreign key (account_id) references public.accounts (id)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public', 'app'],
verbose: true,
},
});
const orderTable = result.tables.find(
(t: { name: string }) => t.name === 'app.orders'
);
expect(orderTable).toBeDefined();
const constraints = orderTable.foreign_key_constraints ?? [];
expect(constraints).toHaveLength(1);
expect(constraints).toEqual([
{
name: 'orders_account_fk',
source_table: 'app.orders',
source_columns: ['account_id'],
target_table: 'public.accounts',
target_columns: ['id'],
},
]);
});test('foreign key referencing a unique constraint is listed', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create table parent (
id int primary key,
code text unique
);
create table child (
parent_code text,
constraint child_parent_code_fk
foreign key (parent_code) references parent (code)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const childTable = result.tables.find(
(t: { name: string }) => t.name === 'public.child'
);
expect(childTable).toBeDefined();
const constraints = childTable.foreign_key_constraints ?? [];
expect(constraints).toHaveLength(1);
expect(constraints).toEqual([
{
name: 'child_parent_code_fk',
source_table: 'public.child',
source_columns: ['parent_code'],
target_table: 'public.parent',
target_columns: ['code'],
},
]);
});test('self-referential foreign key is represented once', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create table employee (
id int primary key,
manager_id int,
constraint employee_manager_fk
foreign key (manager_id) references employee (id)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const employeeTable = result.tables.find(
(t: { name: string }) => t.name === 'public.employee'
);
expect(employeeTable).toBeDefined();
const constraints = employeeTable.foreign_key_constraints ?? [];
expect(constraints).toHaveLength(1);
expect(constraints).toEqual([
{
name: 'employee_manager_fk',
source_table: 'public.employee',
source_columns: ['manager_id'],
target_table: 'public.employee',
target_columns: ['id'],
},
]);
});test('table with no foreign keys has no foreign key constraints', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create table standalone (
id int primary key
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const standaloneTable = result.tables.find(
(t: { name: string }) => t.name === 'public.standalone'
);
expect(standaloneTable).toBeDefined();
const constraints = standaloneTable.foreign_key_constraints ?? [];
expect(constraints).toHaveLength(0);
expect(constraints).toEqual([]);
});test('composite FK verbose output is stable across repeated list_tables calls', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(`
create table parent (
x int,
y int,
primary key (y, x)
);
create table child (
a int,
b int,
constraint child_parent_fk
foreign key (b, a) references parent (y, x)
);
`);
const firstResult = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const secondResult = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const firstChildTable = firstResult.tables.find(
(t: { name: string }) => t.name === 'public.child'
);
const secondChildTable = secondResult.tables.find(
(t: { name: string }) => t.name === 'public.child'
);
expect(firstChildTable).toBeDefined();
expect(secondChildTable).toBeDefined();
const firstConstraints = firstChildTable.foreign_key_constraints ?? [];
const secondConstraints = secondChildTable.foreign_key_constraints ?? [];
expect(firstConstraints).toHaveLength(1);
expect(secondConstraints).toHaveLength(1);
expect(firstConstraints).toEqual([
{
name: 'child_parent_fk',
source_table: 'public.child',
source_columns: ['b', 'a'],
target_table: 'public.parent',
target_columns: ['y', 'x'],
},
]);
expect(secondConstraints).toEqual(firstConstraints);
});test('list_tables verbose preserves composite target column order when it differs from target table order', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(codeBlock`
create table public.parent_target_order (
parent_a integer not null,
parent_b integer not null,
constraint parent_target_order_key unique (parent_b, parent_a)
);
create table public.child_target_order (
child_a integer not null,
child_b integer not null,
constraint child_parent_target_order_fkey
foreign key (child_b, child_a)
references public.parent_target_order (parent_b, parent_a)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const tables = [...result.tables].sort((a, b) => a.name.localeCompare(b.name));
const tableNames = tables.map(({ name }) => name);
expect(tableNames).toHaveLength(2);
expect(tableNames).toEqual([
'public.child_target_order',
'public.parent_target_order',
]);
const [child, parent] = tables;
const expectedForeignKeys = [
{
name: 'child_parent_target_order_fkey',
source_table: 'public.child_target_order',
source_columns: ['child_b', 'child_a'],
target_table: 'public.parent_target_order',
target_columns: ['parent_b', 'parent_a'],
},
];
const childForeignKeys = [...(child.foreign_key_constraints ?? [])].sort((a, b) =>
`${a.source_table}|${a.name}`.localeCompare(`${b.source_table}|${b.name}`)
);
expect(childForeignKeys).toHaveLength(1);
expect(childForeignKeys).toEqual(expectedForeignKeys);
const parentForeignKeys = [...(parent.foreign_key_constraints ?? [])].sort((a, b) =>
`${a.source_table}|${a.name}`.localeCompare(`${b.source_table}|${b.name}`)
);
expect(parentForeignKeys).toHaveLength(1);
expect(parentForeignKeys).toEqual(expectedForeignKeys);
});test('list_tables verbose keeps same-named foreign keys on different tables separate', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(codeBlock`
create table public.same_name_parent (
tenant_id integer not null,
code integer not null,
primary key (tenant_id, code)
);
create table public.same_name_child_one (
id integer primary key,
tenant_id integer not null,
code integer not null,
constraint same_named_parent_fkey
foreign key (tenant_id, code)
references public.same_name_parent (tenant_id, code)
);
create table public.same_name_child_two (
id integer primary key,
tenant_id integer not null,
code integer not null,
constraint same_named_parent_fkey
foreign key (tenant_id, code)
references public.same_name_parent (tenant_id, code)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const tables = [...result.tables].sort((a, b) => a.name.localeCompare(b.name));
const tableNames = tables.map(({ name }) => name);
expect(tableNames).toHaveLength(3);
expect(tableNames).toEqual([
'public.same_name_child_one',
'public.same_name_child_two',
'public.same_name_parent',
]);
const [childOne, childTwo, parent] = tables;
const childOneForeignKeys = [...(childOne.foreign_key_constraints ?? [])].sort((a, b) =>
`${a.source_table}|${a.name}`.localeCompare(`${b.source_table}|${b.name}`)
);
expect(childOneForeignKeys).toHaveLength(1);
expect(childOneForeignKeys).toEqual([
{
name: 'same_named_parent_fkey',
source_table: 'public.same_name_child_one',
source_columns: ['tenant_id', 'code'],
target_table: 'public.same_name_parent',
target_columns: ['tenant_id', 'code'],
},
]);
const childTwoForeignKeys = [...(childTwo.foreign_key_constraints ?? [])].sort((a, b) =>
`${a.source_table}|${a.name}`.localeCompare(`${b.source_table}|${b.name}`)
);
expect(childTwoForeignKeys).toHaveLength(1);
expect(childTwoForeignKeys).toEqual([
{
name: 'same_named_parent_fkey',
source_table: 'public.same_name_child_two',
source_columns: ['tenant_id', 'code'],
target_table: 'public.same_name_parent',
target_columns: ['tenant_id', 'code'],
},
]);
const parentForeignKeys = [...(parent.foreign_key_constraints ?? [])].sort((a, b) =>
`${a.source_table}|${a.name}`.localeCompare(`${b.source_table}|${b.name}`)
);
expect(parentForeignKeys).toHaveLength(2);
expect(parentForeignKeys).toEqual([
{
name: 'same_named_parent_fkey',
source_table: 'public.same_name_child_one',
source_columns: ['tenant_id', 'code'],
target_table: 'public.same_name_parent',
target_columns: ['tenant_id', 'code'],
},
{
name: 'same_named_parent_fkey',
source_table: 'public.same_name_child_two',
source_columns: ['tenant_id', 'code'],
target_table: 'public.same_name_parent',
target_columns: ['tenant_id', 'code'],
},
]);
});test('list_tables verbose includes incoming foreign keys from schemas outside the requested schema list', async () => {
const { callTool } = await setup();
const org = await createOrganization({
name: 'My Org',
plan: 'free',
allowed_release_channels: ['ga'],
});
const project = await createProject({
name: 'Project 1',
region: 'us-east-1',
organization_id: org.id,
});
project.status = 'ACTIVE_HEALTHY';
await project.db.exec(codeBlock`
create schema hidden_fk_source;
create table public.incoming_parent (
tenant_id integer not null,
sku text not null,
primary key (tenant_id, sku)
);
create table hidden_fk_source.incoming_child (
id integer primary key,
tenant_id integer not null,
sku text not null,
constraint hidden_child_parent_fkey
foreign key (tenant_id, sku)
references public.incoming_parent (tenant_id, sku)
);
`);
const result = await callTool({
name: 'list_tables',
arguments: {
project_id: project.id,
schemas: ['public'],
verbose: true,
},
});
const tables = [...result.tables].sort((a, b) => a.name.localeCompare(b.name));
const tableNames = tables.map(({ name }) => name);
expect(tableNames).toHaveLength(1);
expect(tableNames).toEqual(['public.incoming_parent']);
const [parent] = tables;
const parentForeignKeys = [...(parent.foreign_key_constraints ?? [])].sort((a, b) =>
`${a.source_table}|${a.name}`.localeCompare(`${b.source_table}|${b.name}`)
);
expect(parentForeignKeys).toHaveLength(1);
expect(parentForeignKeys).toEqual([
{
name: 'hidden_child_parent_fkey',
source_table: 'hidden_fk_source.incoming_child',
source_columns: ['tenant_id', 'sku'],
target_table: 'public.incoming_parent',
target_columns: ['tenant_id', 'sku'],
},
]);
});