Skip to content

Commit dd86a90

Browse files
committed
fix(plpgsql-parse): comment reinjection fixes — pad stitched body with newlines, skip DECLARE sections during statement matching
1 parent ac04253 commit dd86a90

2 files changed

Lines changed: 67 additions & 37 deletions

File tree

packages/plpgsql-parse/__tests__/__snapshots__/roundtrip.test.ts.snap

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ EXCEPTION
1717
-- Log the error and return null
1818
RAISE NOTICE 'Division by zero: % / %', a, b;
1919
RETURN NULL;
20-
END;
20+
END
2121
$$;"
2222
`;
2323

@@ -31,15 +31,18 @@ DECLARE
3131
r RECORD;
3232
BEGIN
3333
-- Process items in batches
34-
FOR r IN SELECT id, data FROM pending_items LIMIT p_batch_size LOOP
35-
-- Process each item
36-
PERFORM process_item(r.id, r.data);
37-
v_processed := v_processed + 1;
34+
FOR r IN SELECT
35+
id,
36+
data
37+
FROM pending_items
38+
LIMIT p_batch_size LOOP
39+
-- Process each item
40+
PERFORM process_item(r.id, r.data);
41+
v_processed := v_processed + 1;
3842
END LOOP;
39-
4043
-- Return the count of processed items
4144
RETURN v_processed;
42-
END;
45+
END
4346
$$;"
4447
`;
4548

@@ -54,7 +57,7 @@ CREATE FUNCTION add_numbers(
5457
BEGIN
5558
-- Simple addition
5659
RETURN a + b;
57-
END;
60+
END
5861
$$;
5962
6063
-- Second function with its own body comments
@@ -65,7 +68,7 @@ CREATE FUNCTION multiply_numbers(
6568
BEGIN
6669
-- Multiply the inputs
6770
RETURN a * b;
68-
END;
71+
END
6972
$$;"
7073
`;
7174

@@ -79,19 +82,20 @@ DECLARE
7982
v_status text;
8083
BEGIN
8184
-- First, calculate the order total
82-
SELECT sum(amount) INTO v_total FROM order_items WHERE order_id = p_order_id;
83-
85+
SELECT sum(amount) INTO v_total
86+
FROM order_items
87+
WHERE
88+
order_id = p_order_id;
8489
-- Then update the order status
8590
-- based on the total amount
8691
IF v_total > 1000 THEN
87-
v_status := 'premium';
92+
v_status := 'premium';
8893
ELSE
89-
v_status := 'standard';
94+
v_status := 'standard';
9095
END IF;
91-
9296
-- Finally, record the result
93-
UPDATE orders SET status = v_status, total = v_total WHERE id = p_order_id;
94-
END;
97+
UPDATE orders SET status = v_status,total = v_total WHERE id = p_order_id;
98+
END
9599
$$;"
96100
`;
97101

@@ -105,19 +109,20 @@ DECLARE
105109
BEGIN
106110
-- Initialize result
107111
v_result := 'unknown';
108-
109112
-- Try the main logic
110113
BEGIN
111-
-- Fetch and process
112-
SELECT status INTO v_result FROM items WHERE id = p_id;
114+
-- Fetch and process
115+
SELECT status INTO v_result
116+
FROM items
117+
WHERE
118+
id = p_id;
113119
EXCEPTION
114-
WHEN no_data_found THEN
115-
-- Handle missing item
116-
v_result := 'not_found';
120+
WHEN no_data_found THEN
121+
-- Handle missing item
122+
v_result := 'not_found';
117123
END;
118-
119124
RETURN v_result;
120-
END;
125+
END
121126
$$;"
122127
`;
123128

@@ -136,9 +141,12 @@ DECLARE
136141
v_count integer;
137142
BEGIN
138143
-- Count all active users
139-
SELECT count(*) INTO v_count FROM users WHERE is_active = true;
144+
SELECT count(*) INTO v_count
145+
FROM users
146+
WHERE
147+
is_active = true;
140148
RETURN v_count;
141-
END;
149+
END
142150
$$;"
143151
`;
144152

@@ -147,15 +155,18 @@ exports[`fixture round-trip tests trigger-function.sql deparsed output matches s
147155
CREATE FUNCTION audit_trigger() RETURNS trigger LANGUAGE plpgsql AS $$
148156
BEGIN
149157
-- Set the updated_at timestamp
150-
NEW.updated_at := now();
151-
158+
new.updated_at := now();
152159
-- Record the change in audit log
153-
IF TG_OP = 'UPDATE' THEN
154-
INSERT INTO audit_log (table_name, operation, old_data, new_data)
155-
VALUES (TG_TABLE_NAME, TG_OP, row_to_json(OLD), row_to_json(NEW));
160+
IF tg_op = 'UPDATE' THEN
161+
INSERT INTO audit_log (
162+
table_name,
163+
operation,
164+
old_data,
165+
new_data
166+
) VALUES
167+
(tg_table_name, tg_op, row_to_json(old), row_to_json(new));
156168
END IF;
157-
158-
RETURN NEW;
159-
END;
169+
RETURN new;
170+
END
160171
$$;"
161172
`;

packages/plpgsql-parse/src/deparse.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,23 @@ function reinjectBodyComments(
194194
let stmtKeyIdx = 0;
195195
const usedAnchors = new Set<number>();
196196

197+
// Track DECLARE sections: lines between DECLARE and the following BEGIN
198+
// are variable declarations, not statements, and must not consume
199+
// statement keyword matches (e.g. a declaration `v_x int;` would
200+
// otherwise match an assignment to `v_x`).
201+
let inDeclare = false;
202+
197203
for (const line of depLines) {
198204
const trimmed = line.trim().toUpperCase();
199205

206+
if (trimmed === 'DECLARE') {
207+
inDeclare = true;
208+
} else if (inDeclare && trimmed.startsWith('BEGIN')) {
209+
inDeclare = false;
210+
}
211+
200212
// Try to match this line to the next expected statement
201-
if (stmtKeyIdx < stmtKeywords.length) {
213+
if (!inDeclare && stmtKeyIdx < stmtKeywords.length) {
202214
const { lineno, keywords } = stmtKeywords[stmtKeyIdx];
203215

204216
if (lineMatchesKeywords(trimmed, keywords)) {
@@ -574,19 +586,26 @@ function findLastEndLine(lines: string[]): number {
574586

575587
/**
576588
* Replace the function body in a CREATE FUNCTION AST node.
589+
* The body is padded with newlines so it renders as
590+
* `AS $$\n<body>\n$$` rather than gluing onto the dollar quotes.
577591
*/
578592
function stitchBodyIntoAst(createFunctionStmt: any, newBody: string): void {
579593
if (!createFunctionStmt?.options) return;
580594

595+
const padded =
596+
(newBody.startsWith('\n') ? '' : '\n') +
597+
newBody +
598+
(newBody.endsWith('\n') ? '' : '\n');
599+
581600
for (const opt of createFunctionStmt.options) {
582601
if (opt?.DefElem?.defname === 'as') {
583602
const arg = opt.DefElem.arg;
584603
if (arg?.List?.items?.[0]?.String) {
585-
arg.List.items[0].String.sval = newBody;
604+
arg.List.items[0].String.sval = padded;
586605
return;
587606
}
588607
if (arg?.String) {
589-
arg.String.sval = newBody;
608+
arg.String.sval = padded;
590609
return;
591610
}
592611
}

0 commit comments

Comments
 (0)