Skip to content

Commit 677f5f9

Browse files
NathanFlurryclaude
andcommitted
feat: US-025 - Add pg-prepared e2e-docker fixture for prepared statements
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d0fdaa2 commit 677f5f9

4 files changed

Lines changed: 122 additions & 2 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"entry": "src/index.js",
3+
"expectation": "pass",
4+
"services": ["postgres"]
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "e2e-docker-pg-prepared",
3+
"private": true,
4+
"type": "commonjs",
5+
"dependencies": {
6+
"pg": "8.13.1"
7+
}
8+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
const { Client } = require("pg");
2+
3+
async function main() {
4+
const client = new Client({
5+
host: process.env.PG_HOST,
6+
port: Number(process.env.PG_PORT),
7+
user: "testuser",
8+
password: "testpass",
9+
database: "testdb",
10+
});
11+
12+
await client.connect();
13+
14+
// Setup table
15+
await client.query(
16+
"CREATE TABLE IF NOT EXISTS test_prepared (id SERIAL PRIMARY KEY, value TEXT, num INTEGER)",
17+
);
18+
19+
// Named prepared statement: insert
20+
await client.query({
21+
name: "insert-row",
22+
text: "INSERT INTO test_prepared (value, num) VALUES ($1, $2)",
23+
values: ["alpha", 1],
24+
});
25+
26+
// Reuse same named prepared statement (exercises prepared statement cache)
27+
await client.query({
28+
name: "insert-row",
29+
text: "INSERT INTO test_prepared (value, num) VALUES ($1, $2)",
30+
values: ["beta", 2],
31+
});
32+
33+
await client.query({
34+
name: "insert-row",
35+
text: "INSERT INTO test_prepared (value, num) VALUES ($1, $2)",
36+
values: ["gamma", 3],
37+
});
38+
39+
// Named prepared statement: select
40+
const res1 = await client.query({
41+
name: "select-by-value",
42+
text: "SELECT id, value, num FROM test_prepared WHERE value = $1",
43+
values: ["beta"],
44+
});
45+
46+
// Reuse named select
47+
const res2 = await client.query({
48+
name: "select-by-value",
49+
text: "SELECT id, value, num FROM test_prepared WHERE value = $1",
50+
values: ["gamma"],
51+
});
52+
53+
// Named prepared statement: select all ordered
54+
const resAll = await client.query({
55+
name: "select-all-ordered",
56+
text: "SELECT value, num FROM test_prepared ORDER BY num ASC",
57+
values: [],
58+
});
59+
60+
// Named prepared statement: update
61+
await client.query({
62+
name: "update-num",
63+
text: "UPDATE test_prepared SET num = $1 WHERE value = $2",
64+
values: [99, "alpha"],
65+
});
66+
67+
// Reuse named select to verify update
68+
const resUpdated = await client.query({
69+
name: "select-by-value",
70+
text: "SELECT id, value, num FROM test_prepared WHERE value = $1",
71+
values: ["alpha"],
72+
});
73+
74+
// Named prepared statement: delete
75+
await client.query({
76+
name: "delete-by-value",
77+
text: "DELETE FROM test_prepared WHERE value = $1",
78+
values: ["gamma"],
79+
});
80+
81+
// Verify deletion with reused select-all
82+
const resAfterDelete = await client.query({
83+
name: "select-all-ordered",
84+
text: "SELECT value, num FROM test_prepared ORDER BY num ASC",
85+
values: [],
86+
});
87+
88+
// Cleanup
89+
await client.query("DROP TABLE test_prepared");
90+
await client.end();
91+
92+
console.log(
93+
JSON.stringify({
94+
inserted: 3,
95+
selectBeta: { rowCount: res1.rowCount, value: res1.rows[0].value, num: res1.rows[0].num },
96+
selectGamma: { rowCount: res2.rowCount, value: res2.rows[0].value, num: res2.rows[0].num },
97+
selectAll: resAll.rows.map((r) => ({ value: r.value, num: r.num })),
98+
updated: { value: resUpdated.rows[0].value, num: resUpdated.rows[0].num },
99+
afterDelete: resAfterDelete.rows.map((r) => ({ value: r.value, num: r.num })),
100+
}),
101+
);
102+
}
103+
104+
main().catch((err) => {
105+
console.error(err.message);
106+
process.exit(1);
107+
});

scripts/ralph/prd.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@
448448
"Tests pass"
449449
],
450450
"priority": 25,
451-
"passes": false,
452-
"notes": "Named prepared statements use different wire protocol messages (Parse/Bind/Execute vs SimpleQuery). The current fixture only uses unnamed parameterized queries. Prepared statement caching and reuse is a production-critical path."
451+
"passes": true,
452+
"notes": "Completed. Fixture pg-prepared tests named prepared statements with insert (reused 3x), select (reused 2x), update, and delete. Exercises Parse/Bind/Execute wire protocol and prepared statement cache. Host and sandbox produce identical output."
453453
},
454454
{
455455
"id": "US-026",

0 commit comments

Comments
 (0)