|
3 | 3 | //! Converted from src/operators/=_test.sql |
4 | 4 | //! Tests EQL equality operators with encrypted data (HMAC and Blake3 indexes) |
5 | 5 |
|
| 6 | +use anyhow::{Context, Result}; |
6 | 7 | use eql_tests::QueryAssertion; |
7 | 8 | use sqlx::{PgPool, Row}; |
8 | 9 |
|
9 | 10 | /// Helper to execute create_encrypted_json SQL function with specific indexes |
10 | 11 | /// Uses variadic form: create_encrypted_json(id, index1, index2, ...) |
11 | | -async fn create_encrypted_json_with_index(pool: &PgPool, id: i32, index_type: &str) -> String { |
| 12 | +async fn create_encrypted_json_with_index( |
| 13 | + pool: &PgPool, |
| 14 | + id: i32, |
| 15 | + index_type: &str, |
| 16 | +) -> Result<String> { |
12 | 17 | let sql = format!( |
13 | 18 | "SELECT create_encrypted_json({}, '{}')::text", |
14 | 19 | id, index_type |
15 | 20 | ); |
16 | 21 |
|
17 | | - let row = sqlx::query(&sql).fetch_one(pool).await.unwrap_or_else(|e| { |
18 | | - panic!( |
19 | | - "Failed to create encrypted JSON with id={}, index_type='{}': {}", |
20 | | - id, index_type, e |
21 | | - ) |
22 | | - }); |
| 22 | + let row = sqlx::query(&sql) |
| 23 | + .fetch_one(pool) |
| 24 | + .await |
| 25 | + .with_context(|| format!("fetching create_encrypted_json({}, '{}')", id, index_type))?; |
23 | 26 |
|
24 | | - let result: Option<String> = row.try_get(0).unwrap_or_else(|e| { |
25 | | - panic!( |
26 | | - "Failed to get result from create_encrypted_json(id={}, index_type='{}'): {}", |
27 | | - id, index_type, e |
| 27 | + let result: Option<String> = row.try_get(0).with_context(|| { |
| 28 | + format!( |
| 29 | + "extracting text column for id={}, index_type='{}'", |
| 30 | + id, index_type |
28 | 31 | ) |
29 | | - }); |
| 32 | + })?; |
30 | 33 |
|
31 | | - result.unwrap_or_else(|| { |
32 | | - panic!( |
| 34 | + result.with_context(|| { |
| 35 | + format!( |
33 | 36 | "create_encrypted_json returned NULL for id={}, index_type='{}'", |
34 | 37 | id, index_type |
35 | 38 | ) |
36 | 39 | }) |
37 | 40 | } |
38 | 41 |
|
| 42 | +async fn fetch_text_column(pool: &PgPool, sql: &str) -> Result<String> { |
| 43 | + let row = sqlx::query(sql).fetch_one(pool).await.with_context(|| { |
| 44 | + format!("executing query for text result: {}", sql) |
| 45 | + })?; |
| 46 | + |
| 47 | + row.try_get(0).with_context(|| format!("extracting text column for query: {}", sql)) |
| 48 | +} |
| 49 | + |
39 | 50 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
40 | | -async fn equality_operator_finds_matching_record_hmac(pool: PgPool) { |
| 51 | +async fn equality_operator_finds_matching_record_hmac(pool: PgPool) -> Result<()> { |
41 | 52 | // Test: eql_v2_encrypted = eql_v2_encrypted with HMAC index |
42 | 53 | // Original SQL line 10-32 in src/operators/=_test.sql |
43 | 54 |
|
44 | | - let encrypted = create_encrypted_json_with_index(&pool, 1, "hm").await; |
| 55 | + let encrypted = create_encrypted_json_with_index(&pool, 1, "hm").await?; |
45 | 56 |
|
46 | 57 | let sql = format!( |
47 | 58 | "SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted", |
48 | 59 | encrypted |
49 | 60 | ); |
50 | 61 |
|
51 | 62 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 63 | + |
| 64 | + Ok(()) |
52 | 65 | } |
53 | 66 |
|
54 | 67 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
55 | | -async fn equality_operator_returns_empty_for_no_match_hmac(pool: PgPool) { |
| 68 | +async fn equality_operator_returns_empty_for_no_match_hmac(pool: PgPool) -> Result<()> { |
56 | 69 | // Test: equality returns no results for non-existent record |
57 | 70 | // Original SQL line 25-29 in src/operators/=_test.sql |
58 | 71 | // Note: Using id=4 instead of 91347 to ensure ore data exists (start=40 is within ore range 1-99) |
59 | 72 | // The important part is that id=4 doesn't exist in the fixture data (only 1, 2, 3) |
60 | 73 |
|
61 | | - let encrypted = create_encrypted_json_with_index(&pool, 4, "hm").await; |
| 74 | + let encrypted = create_encrypted_json_with_index(&pool, 4, "hm").await?; |
62 | 75 |
|
63 | 76 | let sql = format!( |
64 | 77 | "SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted", |
65 | 78 | encrypted |
66 | 79 | ); |
67 | 80 |
|
68 | 81 | QueryAssertion::new(&pool, &sql).count(0).await; |
| 82 | + |
| 83 | + Ok(()) |
69 | 84 | } |
70 | 85 |
|
71 | 86 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
72 | | -async fn equality_operator_finds_matching_record_blake3(pool: PgPool) { |
| 87 | +async fn equality_operator_finds_matching_record_blake3(pool: PgPool) -> Result<()> { |
73 | 88 | // Test: eql_v2_encrypted = eql_v2_encrypted with Blake3 index |
74 | 89 | // Original SQL line 105-127 in src/operators/=_test.sql |
75 | 90 |
|
76 | | - let encrypted = create_encrypted_json_with_index(&pool, 1, "b3").await; |
| 91 | + let encrypted = create_encrypted_json_with_index(&pool, 1, "b3").await?; |
77 | 92 |
|
78 | 93 | let sql = format!( |
79 | 94 | "SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted", |
80 | 95 | encrypted |
81 | 96 | ); |
82 | 97 |
|
83 | 98 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 99 | + |
| 100 | + Ok(()) |
84 | 101 | } |
85 | 102 |
|
86 | 103 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
87 | | -async fn equality_operator_returns_empty_for_no_match_blake3(pool: PgPool) { |
| 104 | +async fn equality_operator_returns_empty_for_no_match_blake3(pool: PgPool) -> Result<()> { |
88 | 105 | // Test: equality returns no results for non-existent record with Blake3 |
89 | 106 | // Original SQL line 120-124 in src/operators/=_test.sql |
90 | 107 | // Note: Using id=4 instead of 91347 to ensure ore data exists |
91 | 108 | // The important part is that id=4 doesn't exist in the fixture data (only 1, 2, 3) |
92 | 109 |
|
93 | | - let encrypted = create_encrypted_json_with_index(&pool, 4, "b3").await; |
| 110 | + let encrypted = create_encrypted_json_with_index(&pool, 4, "b3").await?; |
94 | 111 |
|
95 | 112 | let sql = format!( |
96 | 113 | "SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted", |
97 | 114 | encrypted |
98 | 115 | ); |
99 | 116 |
|
100 | 117 | QueryAssertion::new(&pool, &sql).count(0).await; |
| 118 | + |
| 119 | + Ok(()) |
101 | 120 | } |
102 | 121 |
|
103 | 122 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
104 | | -async fn eq_function_finds_matching_record_hmac(pool: PgPool) { |
| 123 | +async fn eq_function_finds_matching_record_hmac(pool: PgPool) -> Result<()> { |
105 | 124 | // Test: eql_v2.eq() function with HMAC index |
106 | 125 | // Original SQL line 38-59 in src/operators/=_test.sql |
107 | 126 | // Uses create_encrypted_json(id)::jsonb-'ob' to get encrypted data without ORE field |
108 | 127 |
|
109 | 128 | // Call SQL function to create encrypted JSON and remove 'ob' field |
110 | 129 | // Cast to eql_v2_encrypted first, then to text to get tuple format |
111 | 130 | let sql_create = "SELECT ((create_encrypted_json(1)::jsonb - 'ob')::eql_v2_encrypted)::text"; |
112 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
113 | | - let encrypted: String = row.try_get(0).unwrap(); |
| 131 | + let encrypted = fetch_text_column(&pool, sql_create).await?; |
114 | 132 |
|
115 | 133 | let sql = format!( |
116 | 134 | "SELECT e FROM encrypted WHERE eql_v2.eq(e, '{}'::eql_v2_encrypted)", |
117 | 135 | encrypted |
118 | 136 | ); |
119 | 137 |
|
120 | 138 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 139 | + |
| 140 | + Ok(()) |
121 | 141 | } |
122 | 142 |
|
123 | 143 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
124 | | -async fn eq_function_finds_matching_record_blake3(pool: PgPool) { |
| 144 | +async fn eq_function_finds_matching_record_blake3(pool: PgPool) -> Result<()> { |
125 | 145 | // Test: eql_v2.eq() function with Blake3 index |
126 | 146 | // Original SQL line 135-156 in src/operators/=_test.sql |
127 | 147 |
|
128 | 148 | // Call SQL function to create encrypted JSON with Blake3 and remove 'ob' field |
129 | 149 | let sql_create = "SELECT ((create_encrypted_json(1, 'b3')::jsonb - 'ob')::eql_v2_encrypted)::text"; |
130 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
131 | | - let encrypted: String = row.try_get(0).unwrap(); |
| 150 | + let encrypted = fetch_text_column(&pool, sql_create).await?; |
132 | 151 |
|
133 | 152 | let sql = format!( |
134 | 153 | "SELECT e FROM encrypted WHERE eql_v2.eq(e, '{}'::eql_v2_encrypted)", |
135 | 154 | encrypted |
136 | 155 | ); |
137 | 156 |
|
138 | 157 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 158 | + |
| 159 | + Ok(()) |
139 | 160 | } |
140 | 161 |
|
141 | 162 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
142 | | -async fn eq_function_returns_empty_for_no_match_blake3(pool: PgPool) { |
| 163 | +async fn eq_function_returns_empty_for_no_match_blake3(pool: PgPool) -> Result<()> { |
143 | 164 | // Test: eql_v2.eq() returns no results for non-existent record with Blake3 |
144 | 165 | // Original SQL line 148-153 in src/operators/=_test.sql |
145 | 166 |
|
146 | 167 | let sql_create = "SELECT ((create_encrypted_json(4, 'b3')::jsonb - 'ob')::eql_v2_encrypted)::text"; |
147 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
148 | | - let encrypted: String = row.try_get(0).unwrap(); |
| 168 | + let encrypted = fetch_text_column(&pool, sql_create).await?; |
149 | 169 |
|
150 | 170 | let sql = format!( |
151 | 171 | "SELECT e FROM encrypted WHERE eql_v2.eq(e, '{}'::eql_v2_encrypted)", |
152 | 172 | encrypted |
153 | 173 | ); |
154 | 174 |
|
155 | 175 | QueryAssertion::new(&pool, &sql).count(0).await; |
| 176 | + |
| 177 | + Ok(()) |
156 | 178 | } |
157 | 179 |
|
158 | 180 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
159 | | -async fn equality_operator_encrypted_equals_jsonb_hmac(pool: PgPool) { |
| 181 | +async fn equality_operator_encrypted_equals_jsonb_hmac(pool: PgPool) -> Result<()> { |
160 | 182 | // Test: eql_v2_encrypted = jsonb with HMAC index |
161 | 183 | // Original SQL line 65-94 in src/operators/=_test.sql |
162 | 184 |
|
163 | 185 | // Create encrypted JSON with HMAC, remove 'ob' field for comparison |
164 | 186 | let sql_create = "SELECT (create_encrypted_json(1)::jsonb - 'ob')::text"; |
165 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
166 | | - let json_value: String = row.try_get(0).unwrap(); |
| 187 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
167 | 188 |
|
168 | 189 | let sql = format!( |
169 | 190 | "SELECT e FROM encrypted WHERE e = '{}'::jsonb", |
170 | 191 | json_value |
171 | 192 | ); |
172 | 193 |
|
173 | 194 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 195 | + |
| 196 | + Ok(()) |
174 | 197 | } |
175 | 198 |
|
176 | 199 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
177 | | -async fn equality_operator_jsonb_equals_encrypted_hmac(pool: PgPool) { |
| 200 | +async fn equality_operator_jsonb_equals_encrypted_hmac(pool: PgPool) -> Result<()> { |
178 | 201 | // Test: jsonb = eql_v2_encrypted with HMAC index (reverse direction) |
179 | 202 | // Original SQL line 78-81 in src/operators/=_test.sql |
180 | 203 |
|
181 | 204 | let sql_create = "SELECT (create_encrypted_json(1)::jsonb - 'ob')::text"; |
182 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
183 | | - let json_value: String = row.try_get(0).unwrap(); |
| 205 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
184 | 206 |
|
185 | 207 | let sql = format!( |
186 | 208 | "SELECT e FROM encrypted WHERE '{}'::jsonb = e", |
187 | 209 | json_value |
188 | 210 | ); |
189 | 211 |
|
190 | 212 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 213 | + |
| 214 | + Ok(()) |
191 | 215 | } |
192 | 216 |
|
193 | 217 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
194 | | -async fn equality_operator_encrypted_equals_jsonb_no_match_hmac(pool: PgPool) { |
| 218 | +async fn equality_operator_encrypted_equals_jsonb_no_match_hmac(pool: PgPool) -> Result<()> { |
195 | 219 | // Test: eql_v2_encrypted = jsonb with no matching record |
196 | 220 | // Original SQL line 83-87 in src/operators/=_test.sql |
197 | 221 |
|
198 | 222 | let sql_create = "SELECT (create_encrypted_json(4)::jsonb - 'ob')::text"; |
199 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
200 | | - let json_value: String = row.try_get(0).unwrap(); |
| 223 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
201 | 224 |
|
202 | 225 | let sql = format!( |
203 | 226 | "SELECT e FROM encrypted WHERE e = '{}'::jsonb", |
204 | 227 | json_value |
205 | 228 | ); |
206 | 229 |
|
207 | 230 | QueryAssertion::new(&pool, &sql).count(0).await; |
| 231 | + |
| 232 | + Ok(()) |
208 | 233 | } |
209 | 234 |
|
210 | 235 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
211 | | -async fn equality_operator_jsonb_equals_encrypted_no_match_hmac(pool: PgPool) { |
| 236 | +async fn equality_operator_jsonb_equals_encrypted_no_match_hmac(pool: PgPool) -> Result<()> { |
212 | 237 | // Test: jsonb = eql_v2_encrypted with no matching record |
213 | 238 | // Original SQL line 89-91 in src/operators/=_test.sql |
214 | 239 |
|
215 | 240 | let sql_create = "SELECT (create_encrypted_json(4)::jsonb - 'ob')::text"; |
216 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
217 | | - let json_value: String = row.try_get(0).unwrap(); |
| 241 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
218 | 242 |
|
219 | 243 | let sql = format!( |
220 | 244 | "SELECT e FROM encrypted WHERE '{}'::jsonb = e", |
221 | 245 | json_value |
222 | 246 | ); |
223 | 247 |
|
224 | 248 | QueryAssertion::new(&pool, &sql).count(0).await; |
| 249 | + |
| 250 | + Ok(()) |
225 | 251 | } |
226 | 252 |
|
227 | 253 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
228 | | -async fn equality_operator_encrypted_equals_jsonb_blake3(pool: PgPool) { |
| 254 | +async fn equality_operator_encrypted_equals_jsonb_blake3(pool: PgPool) -> Result<()> { |
229 | 255 | // Test: eql_v2_encrypted = jsonb with Blake3 index |
230 | 256 | // Original SQL line 164-193 in src/operators/=_test.sql |
231 | 257 |
|
232 | 258 | let sql_create = "SELECT create_encrypted_json(1, 'b3')::jsonb::text"; |
233 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
234 | | - let json_value: String = row.try_get(0).unwrap(); |
| 259 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
235 | 260 |
|
236 | 261 | let sql = format!( |
237 | 262 | "SELECT e FROM encrypted WHERE e = '{}'::jsonb", |
238 | 263 | json_value |
239 | 264 | ); |
240 | 265 |
|
241 | 266 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 267 | + |
| 268 | + Ok(()) |
242 | 269 | } |
243 | 270 |
|
244 | 271 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
245 | | -async fn equality_operator_jsonb_equals_encrypted_blake3(pool: PgPool) { |
| 272 | +async fn equality_operator_jsonb_equals_encrypted_blake3(pool: PgPool) -> Result<()> { |
246 | 273 | // Test: jsonb = eql_v2_encrypted with Blake3 index (reverse direction) |
247 | 274 | // Original SQL line 177-180 in src/operators/=_test.sql |
248 | 275 |
|
249 | 276 | let sql_create = "SELECT create_encrypted_json(1, 'b3')::jsonb::text"; |
250 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
251 | | - let json_value: String = row.try_get(0).unwrap(); |
| 277 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
252 | 278 |
|
253 | 279 | let sql = format!( |
254 | 280 | "SELECT e FROM encrypted WHERE '{}'::jsonb = e", |
255 | 281 | json_value |
256 | 282 | ); |
257 | 283 |
|
258 | 284 | QueryAssertion::new(&pool, &sql).returns_rows().await; |
| 285 | + |
| 286 | + Ok(()) |
259 | 287 | } |
260 | 288 |
|
261 | 289 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
262 | | -async fn equality_operator_encrypted_equals_jsonb_no_match_blake3(pool: PgPool) { |
| 290 | +async fn equality_operator_encrypted_equals_jsonb_no_match_blake3(pool: PgPool) -> Result<()> { |
263 | 291 | // Test: eql_v2_encrypted = jsonb with no matching record (Blake3) |
264 | 292 | // Original SQL line 184-187 in src/operators/=_test.sql |
265 | 293 |
|
266 | 294 | let sql_create = "SELECT create_encrypted_json(4, 'b3')::jsonb::text"; |
267 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
268 | | - let json_value: String = row.try_get(0).unwrap(); |
| 295 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
269 | 296 |
|
270 | 297 | let sql = format!( |
271 | 298 | "SELECT e FROM encrypted WHERE e = '{}'::jsonb", |
272 | 299 | json_value |
273 | 300 | ); |
274 | 301 |
|
275 | 302 | QueryAssertion::new(&pool, &sql).count(0).await; |
| 303 | + |
| 304 | + Ok(()) |
276 | 305 | } |
277 | 306 |
|
278 | 307 | #[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))] |
279 | | -async fn equality_operator_jsonb_equals_encrypted_no_match_blake3(pool: PgPool) { |
| 308 | +async fn equality_operator_jsonb_equals_encrypted_no_match_blake3(pool: PgPool) -> Result<()> { |
280 | 309 | // Test: jsonb = eql_v2_encrypted with no matching record (Blake3) |
281 | 310 | // Original SQL line 188-191 in src/operators/=_test.sql |
282 | 311 |
|
283 | 312 | let sql_create = "SELECT create_encrypted_json(4, 'b3')::jsonb::text"; |
284 | | - let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap(); |
285 | | - let json_value: String = row.try_get(0).unwrap(); |
| 313 | + let json_value = fetch_text_column(&pool, sql_create).await?; |
286 | 314 |
|
287 | 315 | let sql = format!( |
288 | 316 | "SELECT e FROM encrypted WHERE '{}'::jsonb = e", |
289 | 317 | json_value |
290 | 318 | ); |
291 | 319 |
|
292 | 320 | QueryAssertion::new(&pool, &sql).count(0).await; |
| 321 | + |
| 322 | + Ok(()) |
293 | 323 | } |
0 commit comments