Skip to content

Commit 6ba6e17

Browse files
Enhance constraint pretty printing formatting
- Place FOREIGN KEY and REFERENCES clauses on separate lines with indentation - Improve CHECK constraint formatting for multi-line expressions with proper parentheses - Fix MATCH clause spacing to prevent 'REFERENCESfooMATCH FULL' parsing errors - Add proper indentation for NOT VALID clause in pretty printing mode - Maintain existing behavior for non-pretty mode - Follow existing pretty printing patterns in codebase Fixes kitchen-sink test failures in: - original-tables-custom.test.ts - original-upstream-foreign_key.test.ts - original-upstream-alter_table.test.ts Co-Authored-By: Dan Lynch <[email protected]>
1 parent f456654 commit 6ba6e17

File tree

4 files changed

+93
-28
lines changed

4 files changed

+93
-28
lines changed

packages/deparser/__tests__/pretty/__snapshots__/constraints-pretty.test.ts.snap

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ exports[`pretty: pretty/constraints-3.sql 1`] = `
5151

5252
exports[`pretty: pretty/constraints-4.sql 1`] = `
5353
"ALTER TABLE "Orders"."OrderLines"
54-
ADD CONSTRAINT "FK_Order_Ref" FOREIGN KEY (order_id) REFERENCES "Orders"."Order" ("OrderID")"
54+
ADD CONSTRAINT "FK_Order_Ref" FOREIGN KEY (order_id)
55+
REFERENCES "Orders"."Order" ("OrderID")"
5556
`;
5657

5758
exports[`pretty: pretty/constraints-5.sql 1`] = `
@@ -66,7 +67,8 @@ exports[`pretty: pretty/constraints-6.sql 1`] = `
6667

6768
exports[`pretty: pretty/constraints-7.sql 1`] = `
6869
"ALTER TABLE "Billing"."Invoices"
69-
ADD CONSTRAINT "FK_Client_ID" FOREIGN KEY ("Client ID") REFERENCES "Clients"."ClientBase" ("Client ID")"
70+
ADD CONSTRAINT "FK_Client_ID" FOREIGN KEY ("Client ID")
71+
REFERENCES "Clients"."ClientBase" ("Client ID")"
7072
`;
7173

7274
exports[`pretty: pretty/constraints-8.sql 1`] = `
@@ -76,13 +78,16 @@ exports[`pretty: pretty/constraints-8.sql 1`] = `
7678

7779
exports[`pretty: pretty/constraints-9.sql 1`] = `
7880
"ALTER TABLE finance.transactions
79-
ADD CONSTRAINT tax_rate_range CHECK (tax_rate >= 0
80-
AND tax_rate <= 1)"
81+
ADD CONSTRAINT tax_rate_range CHECK (
82+
tax_rate >= 0
83+
AND tax_rate <= 1
84+
)"
8185
`;
8286

8387
exports[`pretty: pretty/constraints-10.sql 1`] = `
8488
"ALTER TABLE school.enrollments
85-
ADD CONSTRAINT fk_student_course FOREIGN KEY (student_id, course_id) REFERENCES school.courses_students (student_id, course_id)"
89+
ADD CONSTRAINT fk_student_course FOREIGN KEY (student_id, course_id)
90+
REFERENCES school.courses_students (student_id, course_id)"
8691
`;
8792

8893
exports[`pretty: pretty/constraints-11.sql 1`] = `
@@ -92,7 +97,8 @@ exports[`pretty: pretty/constraints-11.sql 1`] = `
9297
total numeric(10, 2) CHECK (total > 0),
9398
status varchar(20) DEFAULT 'pending',
9499
created_at pg_catalog.timestamp DEFAULT now(),
95-
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users (id)
100+
CONSTRAINT fk_user FOREIGN KEY (user_id)
101+
REFERENCES users (id)
96102
ON DELETE CASCADE,
97103
CONSTRAINT unique_user_date UNIQUE (user_id, created_at),
98104
CONSTRAINT check_status CHECK (status IN ('pending', 'completed', 'cancelled'))
@@ -101,7 +107,8 @@ exports[`pretty: pretty/constraints-11.sql 1`] = `
101107

102108
exports[`pretty: pretty/constraints-12.sql 1`] = `
103109
"ALTER TABLE products
104-
ADD CONSTRAINT fk_category FOREIGN KEY (category_id) REFERENCES categories (id)
110+
ADD CONSTRAINT fk_category FOREIGN KEY (category_id)
111+
REFERENCES categories (id)
105112
ON UPDATE CASCADE
106113
ON DELETE SET NULL
107114
DEFERRABLE
@@ -120,13 +127,16 @@ exports[`pretty: pretty/constraints-14.sql 1`] = `
120127

121128
exports[`pretty: pretty/constraints-15.sql 1`] = `
122129
"ALTER TABLE school.enrollments
123-
ADD CONSTRAINT fk_student_course FOREIGN KEY (student_id, course_id) REFERENCES school.courses_students (student_id, course_id)"
130+
ADD CONSTRAINT fk_student_course FOREIGN KEY (student_id, course_id)
131+
REFERENCES school.courses_students (student_id, course_id)"
124132
`;
125133

126134
exports[`pretty: pretty/constraints-16.sql 1`] = `
127135
"ALTER TABLE school.enrollments
128-
ADD CONSTRAINT chk_enrollment_date CHECK (enrollment_date <= CURRENT_DATE
129-
AND status IN ('active', 'completed', 'withdrawn'))"
136+
ADD CONSTRAINT chk_enrollment_date CHECK (
137+
enrollment_date <= CURRENT_DATE
138+
AND status IN ('active', 'completed', 'withdrawn')
139+
)"
130140
`;
131141

132142
exports[`pretty: pretty/constraints-17.sql 1`] = `

packages/deparser/__tests__/pretty/__snapshots__/create-table-pretty.test.ts.snap

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ exports[`pretty: pretty/create_table-2.sql 1`] = `
3030
created_at pg_catalog.timestamp DEFAULT now(),
3131
updated_at pg_catalog.timestamp,
3232
UNIQUE (name, category_id),
33-
FOREIGN KEY (category_id) REFERENCES categories (id)
33+
FOREIGN KEY (category_id)
34+
REFERENCES categories (id)
3435
)"
3536
`;
3637

@@ -68,6 +69,7 @@ exports[`pretty: pretty/create_table-6.sql 1`] = `
6869
total numeric(10, 2) CHECK (total > 0),
6970
status varchar(20) DEFAULT 'pending',
7071
created_at pg_catalog.timestamp DEFAULT now(),
71-
FOREIGN KEY (user_id) REFERENCES users (id)
72+
FOREIGN KEY (user_id)
73+
REFERENCES users (id)
7274
)"
7375
`;

packages/deparser/__tests__/pretty/__snapshots__/tables-pretty.test.ts.snap

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ exports[`pretty: pretty/tables-5.sql 1`] = `
7373
"CREATE TABLE "Orders"."OrderLines" (
7474
id serial PRIMARY KEY,
7575
order_id int,
76-
CONSTRAINT "FK Order Reference" FOREIGN KEY (order_id) REFERENCES "Orders"."Order" ("OrderID")
76+
CONSTRAINT "FK Order Reference" FOREIGN KEY (order_id)
77+
REFERENCES "Orders"."Order" ("OrderID")
7778
)"
7879
`;
7980

@@ -126,7 +127,8 @@ exports[`pretty: pretty/tables-12.sql 1`] = `
126127
"CREATE TABLE secure.sessions (
127128
session_id uuid PRIMARY KEY,
128129
user_id uuid,
129-
CONSTRAINT "fk-user->session" FOREIGN KEY (user_id) REFERENCES users (id)
130+
CONSTRAINT "fk-user->session" FOREIGN KEY (user_id)
131+
REFERENCES users (id)
130132
)"
131133
`;
132134

@@ -150,7 +152,8 @@ exports[`pretty: pretty/tables-15.sql 1`] = `
150152
"CREATE TABLE "Billing"."Invoices" (
151153
invoice_id uuid PRIMARY KEY,
152154
"Client ID" uuid,
153-
CONSTRAINT "FK_Client" FOREIGN KEY ("Client ID") REFERENCES "Clients"."ClientBase" ("Client ID")
155+
CONSTRAINT "FK_Client" FOREIGN KEY ("Client ID")
156+
REFERENCES "Clients"."ClientBase" ("Client ID")
154157
)"
155158
`;
156159

packages/deparser/src/deparser.ts

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,7 +2619,16 @@ export class Deparser implements DeparserVisitor {
26192619
case 'CONSTR_CHECK':
26202620
output.push('CHECK');
26212621
if (node.raw_expr) {
2622-
output.push(this.formatter.parens(this.visit(node.raw_expr, context)));
2622+
if (this.formatter.isPretty()) {
2623+
const checkExpr = this.visit(node.raw_expr, context);
2624+
if (checkExpr.includes('\n')) {
2625+
output.push('(\n' + this.formatter.indent(checkExpr) + '\n)');
2626+
} else {
2627+
output.push(`(${checkExpr})`);
2628+
}
2629+
} else {
2630+
output.push(this.formatter.parens(this.visit(node.raw_expr, context)));
2631+
}
26232632
}
26242633
// Handle NOT VALID for check constraints
26252634
if (node.skip_validation) {
@@ -2709,33 +2718,70 @@ export class Deparser implements DeparserVisitor {
27092718
case 'CONSTR_FOREIGN':
27102719
// Only add "FOREIGN KEY" for table-level constraints, not column-level constraints
27112720
if (!context.isColumnConstraint) {
2712-
output.push('FOREIGN KEY');
2713-
if (node.fk_attrs && node.fk_attrs.length > 0) {
2714-
const fkAttrs = ListUtils.unwrapList(node.fk_attrs)
2715-
.map(attr => this.visit(attr, context))
2716-
.join(', ');
2717-
output.push(`(${fkAttrs})`);
2721+
if (this.formatter.isPretty()) {
2722+
output.push('FOREIGN KEY');
2723+
if (node.fk_attrs && node.fk_attrs.length > 0) {
2724+
const fkAttrs = ListUtils.unwrapList(node.fk_attrs)
2725+
.map(attr => this.visit(attr, context))
2726+
.join(', ');
2727+
output.push(`(${fkAttrs})`);
2728+
}
2729+
output.push('\n' + this.formatter.indent('REFERENCES'));
2730+
} else {
2731+
output.push('FOREIGN KEY');
2732+
if (node.fk_attrs && node.fk_attrs.length > 0) {
2733+
const fkAttrs = ListUtils.unwrapList(node.fk_attrs)
2734+
.map(attr => this.visit(attr, context))
2735+
.join(', ');
2736+
output.push(`(${fkAttrs})`);
2737+
}
2738+
output.push('REFERENCES');
27182739
}
2740+
} else {
2741+
output.push('REFERENCES');
27192742
}
2720-
output.push('REFERENCES');
27212743
if (node.pktable) {
2722-
output.push(this.RangeVar(node.pktable, context));
2744+
if (this.formatter.isPretty() && !context.isColumnConstraint) {
2745+
const lastIndex = output.length - 1;
2746+
if (lastIndex >= 0 && output[lastIndex].includes('REFERENCES')) {
2747+
output[lastIndex] += ' ' + this.RangeVar(node.pktable, context);
2748+
} else {
2749+
output.push(this.RangeVar(node.pktable, context));
2750+
}
2751+
} else {
2752+
output.push(this.RangeVar(node.pktable, context));
2753+
}
27232754
}
27242755
if (node.pk_attrs && node.pk_attrs.length > 0) {
27252756
const pkAttrs = ListUtils.unwrapList(node.pk_attrs)
27262757
.map(attr => this.visit(attr, context))
27272758
.join(', ');
2728-
output.push(`(${pkAttrs})`);
2759+
if (this.formatter.isPretty() && !context.isColumnConstraint) {
2760+
const lastIndex = output.length - 1;
2761+
if (lastIndex >= 0) {
2762+
output[lastIndex] += ` (${pkAttrs})`;
2763+
} else {
2764+
output.push(`(${pkAttrs})`);
2765+
}
2766+
} else {
2767+
output.push(`(${pkAttrs})`);
2768+
}
27292769
}
27302770
if (node.fk_matchtype && node.fk_matchtype !== 's') {
2771+
let matchClause = '';
27312772
switch (node.fk_matchtype) {
27322773
case 'f':
2733-
output.push('MATCH FULL');
2774+
matchClause = 'MATCH FULL';
27342775
break;
27352776
case 'p':
2736-
output.push('MATCH PARTIAL');
2777+
matchClause = 'MATCH PARTIAL';
27372778
break;
27382779
}
2780+
if (this.formatter.isPretty() && !context.isColumnConstraint) {
2781+
output.push('\n' + this.formatter.indent(matchClause));
2782+
} else {
2783+
output.push(matchClause);
2784+
}
27392785
}
27402786
if (node.fk_upd_action && node.fk_upd_action !== 'a') {
27412787
let updateClause = 'ON UPDATE ';
@@ -2785,7 +2831,11 @@ export class Deparser implements DeparserVisitor {
27852831
}
27862832
// Handle NOT VALID for foreign key constraints - only for table constraints, not domain constraints
27872833
if (node.skip_validation && !context.isDomainConstraint) {
2788-
output.push('NOT VALID');
2834+
if (this.formatter.isPretty() && !context.isColumnConstraint) {
2835+
output.push('\n' + this.formatter.indent('NOT VALID'));
2836+
} else {
2837+
output.push('NOT VALID');
2838+
}
27892839
}
27902840
break;
27912841
case 'CONSTR_ATTR_DEFERRABLE':

0 commit comments

Comments
 (0)