Skip to content

Commit e13743d

Browse files
anth-volkclaude
andcommitted
Fix dataset param missing from query in set_user_policy
When dataset is truthy, the query builds "AND dataset = ?" (7 placeholders) but the params tuple only contained 6 values — the dataset value was never appended. This caused a parameter binding crash when saving a policy with a custom dataset. Build the params list conditionally so dataset is included when present. Fixes #3310 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8cad222 commit e13743d

2 files changed

Lines changed: 103 additions & 1 deletion

File tree

policyengine_api/endpoints/policy.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,13 @@ def set_user_policy(country_id: str) -> dict:
228228
f"AND dataset {dataset_select_str}"
229229
)
230230

231+
params = [country_id, reform_id, baseline_id, user_id, year, geography]
232+
if dataset:
233+
params.append(dataset)
234+
231235
row = database.query(
232236
query,
233-
(country_id, reform_id, baseline_id, user_id, year, geography),
237+
tuple(params),
234238
).fetchone()
235239

236240
except Exception as e:
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""Regression test for issue #3310.
2+
3+
When dataset is truthy in set_user_policy (policy.py:224-237), the query
4+
builds "AND dataset = ?" (7 placeholders) but the params must include
5+
the dataset value. Previously, the dataset was never appended, causing
6+
a parameter binding crash.
7+
"""
8+
9+
import time
10+
11+
12+
def test_set_user_policy_dataset_param_included(test_db):
13+
"""Verify that the SELECT after INSERT in set_user_policy correctly
14+
includes the dataset value in params when dataset is truthy.
15+
16+
Reproduces the exact code path from policy.py:224-237.
17+
"""
18+
now = int(time.time())
19+
20+
country_id = "us"
21+
reform_id = 2
22+
baseline_id = 1
23+
user_id = "user1"
24+
year = "2025"
25+
geography = "us"
26+
dataset = "cps"
27+
28+
# Insert a user_policy with a non-null dataset
29+
test_db.query(
30+
"INSERT INTO user_policies (country_id, reform_label, reform_id, "
31+
"baseline_label, baseline_id, user_id, year, geography, dataset, "
32+
"number_of_provisions, api_version, added_date, updated_date) "
33+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
34+
(
35+
country_id, None, reform_id, None, baseline_id, user_id,
36+
year, geography, dataset, 3, "1.0.0", now, now,
37+
),
38+
)
39+
40+
# Reproduce the exact code from policy.py:224-237
41+
dataset_select_str = "IS NULL" if not dataset else "= ?"
42+
query = (
43+
"SELECT * FROM user_policies WHERE country_id = ? AND reform_id = ? "
44+
"AND baseline_id = ? AND user_id = ? AND year = ? AND geography = ? "
45+
f"AND dataset {dataset_select_str}"
46+
)
47+
48+
params = [country_id, reform_id, baseline_id, user_id, year, geography]
49+
if dataset:
50+
params.append(dataset)
51+
52+
# This must not crash — 7 placeholders, 7 params
53+
row = test_db.query(query, tuple(params)).fetchone()
54+
55+
assert row is not None
56+
assert row["dataset"] == "cps"
57+
assert row["reform_id"] == reform_id
58+
assert row["user_id"] == user_id
59+
60+
61+
def test_set_user_policy_dataset_null_still_works(test_db):
62+
"""When dataset is None/falsy, the query uses IS NULL with 6 params."""
63+
now = int(time.time())
64+
65+
country_id = "us"
66+
reform_id = 2
67+
baseline_id = 1
68+
user_id = "user1"
69+
year = "2025"
70+
geography = "us"
71+
dataset = None
72+
73+
test_db.query(
74+
"INSERT INTO user_policies (country_id, reform_label, reform_id, "
75+
"baseline_label, baseline_id, user_id, year, geography, dataset, "
76+
"number_of_provisions, api_version, added_date, updated_date) "
77+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
78+
(
79+
country_id, None, reform_id, None, baseline_id, user_id,
80+
year, geography, dataset, 3, "1.0.0", now, now,
81+
),
82+
)
83+
84+
dataset_select_str = "IS NULL" if not dataset else "= ?"
85+
query = (
86+
"SELECT * FROM user_policies WHERE country_id = ? AND reform_id = ? "
87+
"AND baseline_id = ? AND user_id = ? AND year = ? AND geography = ? "
88+
f"AND dataset {dataset_select_str}"
89+
)
90+
91+
params = [country_id, reform_id, baseline_id, user_id, year, geography]
92+
if dataset:
93+
params.append(dataset)
94+
95+
row = test_db.query(query, tuple(params)).fetchone()
96+
97+
assert row is not None
98+
assert row["dataset"] is None

0 commit comments

Comments
 (0)