Skip to content

Commit f889aea

Browse files
committed
test(sqlx): add ORDER BY NULL handling and helper function tests
Add test coverage for ORDER BY edge cases and helper function: - NULLS FIRST/LAST behavior in ASC and DESC ordering - eql_v2.order_by() helper function with filtered result sets Tests verify correct NULL positioning in ordered results and proper functioning of the order_by helper across different sort directions.
1 parent 9ec9f2d commit f889aea

File tree

1 file changed

+269
-0
lines changed

1 file changed

+269
-0
lines changed

tests/sqlx/tests/order_by_tests.rs

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,272 @@ async fn order_by_asc_with_greater_than_returns_lowest(pool: PgPool) -> Result<(
118118

119119
Ok(())
120120
}
121+
122+
// NULL ordering tests - replicating SQL test cases from order_by_test.sql lines 93-116
123+
124+
#[sqlx::test]
125+
async fn order_by_asc_nulls_first_returns_null_record_first(pool: PgPool) -> Result<()> {
126+
// Test: ORDER BY e ASC NULLS FIRST returns NULL values first
127+
// Setup: Create table with NULLs and encrypted values
128+
// - ID=1: NULL
129+
// - ID=2: 42
130+
// - ID=3: 3
131+
// - ID=4: NULL
132+
// Expected: ORDER BY e ASC NULLS FIRST returns id=1 first
133+
134+
// Create test table
135+
sqlx::query("CREATE TABLE encrypted(id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, e eql_v2_encrypted)")
136+
.execute(&pool)
137+
.await?;
138+
139+
// Insert NULL
140+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
141+
.execute(&pool)
142+
.await?;
143+
144+
// Insert id=42 from ore table
145+
let ore_42 = get_ore_encrypted(&pool, 42).await?;
146+
sqlx::query(&format!(
147+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
148+
ore_42
149+
))
150+
.execute(&pool)
151+
.await?;
152+
153+
// Insert id=3 from ore table
154+
let ore_3 = get_ore_encrypted(&pool, 3).await?;
155+
sqlx::query(&format!(
156+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
157+
ore_3
158+
))
159+
.execute(&pool)
160+
.await?;
161+
162+
// Insert another NULL
163+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
164+
.execute(&pool)
165+
.await?;
166+
167+
// Test: NULLS FIRST should return id=1
168+
let sql = "SELECT id FROM encrypted ORDER BY e ASC NULLS FIRST";
169+
let row = sqlx::query(sql).fetch_one(&pool).await?;
170+
let first_id: i64 = row.try_get(0)?;
171+
assert_eq!(
172+
first_id, 1,
173+
"ORDER BY e ASC NULLS FIRST should return NULL value (id=1) first"
174+
);
175+
176+
Ok(())
177+
}
178+
179+
#[sqlx::test]
180+
async fn order_by_asc_nulls_last_returns_smallest_value_first(pool: PgPool) -> Result<()> {
181+
// Test: ORDER BY e ASC NULLS LAST returns smallest non-NULL value first
182+
// Setup: Same as previous test
183+
// Expected: ORDER BY e ASC NULLS LAST returns id=3 (value=3) first
184+
185+
// Create test table
186+
sqlx::query("CREATE TABLE encrypted(id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, e eql_v2_encrypted)")
187+
.execute(&pool)
188+
.await?;
189+
190+
// Insert NULL
191+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
192+
.execute(&pool)
193+
.await?;
194+
195+
// Insert id=42 from ore table
196+
let ore_42 = get_ore_encrypted(&pool, 42).await?;
197+
sqlx::query(&format!(
198+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
199+
ore_42
200+
))
201+
.execute(&pool)
202+
.await?;
203+
204+
// Insert id=3 from ore table
205+
let ore_3 = get_ore_encrypted(&pool, 3).await?;
206+
sqlx::query(&format!(
207+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
208+
ore_3
209+
))
210+
.execute(&pool)
211+
.await?;
212+
213+
// Insert another NULL
214+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
215+
.execute(&pool)
216+
.await?;
217+
218+
// Test: NULLS LAST should return id=3 (smallest value)
219+
let sql = "SELECT id FROM encrypted ORDER BY e ASC NULLS LAST";
220+
let row = sqlx::query(sql).fetch_one(&pool).await?;
221+
let first_id: i64 = row.try_get(0)?;
222+
assert_eq!(
223+
first_id, 3,
224+
"ORDER BY e ASC NULLS LAST should return smallest non-NULL value (id=3) first"
225+
);
226+
227+
Ok(())
228+
}
229+
230+
#[sqlx::test]
231+
async fn order_by_desc_nulls_first_returns_null_value_first(pool: PgPool) -> Result<()> {
232+
// Test: ORDER BY e DESC NULLS FIRST returns NULL values first
233+
// Expected: ORDER BY e DESC NULLS FIRST returns id=1 first
234+
235+
// Create test table
236+
sqlx::query("CREATE TABLE encrypted(id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, e eql_v2_encrypted)")
237+
.execute(&pool)
238+
.await?;
239+
240+
// Insert NULL
241+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
242+
.execute(&pool)
243+
.await?;
244+
245+
// Insert id=42 from ore table
246+
let ore_42 = get_ore_encrypted(&pool, 42).await?;
247+
sqlx::query(&format!(
248+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
249+
ore_42
250+
))
251+
.execute(&pool)
252+
.await?;
253+
254+
// Insert id=3 from ore table
255+
let ore_3 = get_ore_encrypted(&pool, 3).await?;
256+
sqlx::query(&format!(
257+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
258+
ore_3
259+
))
260+
.execute(&pool)
261+
.await?;
262+
263+
// Insert another NULL
264+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
265+
.execute(&pool)
266+
.await?;
267+
268+
// Test: DESC NULLS FIRST should return id=1
269+
let sql = "SELECT id FROM encrypted ORDER BY e DESC NULLS FIRST";
270+
let row = sqlx::query(sql).fetch_one(&pool).await?;
271+
let first_id: i64 = row.try_get(0)?;
272+
assert_eq!(
273+
first_id, 1,
274+
"ORDER BY e DESC NULLS FIRST should return NULL value (id=1) first"
275+
);
276+
277+
Ok(())
278+
}
279+
280+
#[sqlx::test]
281+
async fn order_by_desc_nulls_last_returns_largest_value_first(pool: PgPool) -> Result<()> {
282+
// Test: ORDER BY e DESC NULLS LAST returns largest non-NULL value first
283+
// Expected: ORDER BY e DESC NULLS LAST returns id=2 (value=42) first
284+
285+
// Create test table
286+
sqlx::query("CREATE TABLE encrypted(id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, e eql_v2_encrypted)")
287+
.execute(&pool)
288+
.await?;
289+
290+
// Insert NULL
291+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
292+
.execute(&pool)
293+
.await?;
294+
295+
// Insert id=42 from ore table
296+
let ore_42 = get_ore_encrypted(&pool, 42).await?;
297+
sqlx::query(&format!(
298+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
299+
ore_42
300+
))
301+
.execute(&pool)
302+
.await?;
303+
304+
// Insert id=3 from ore table
305+
let ore_3 = get_ore_encrypted(&pool, 3).await?;
306+
sqlx::query(&format!(
307+
"INSERT INTO encrypted(e) VALUES ('{}'::eql_v2_encrypted)",
308+
ore_3
309+
))
310+
.execute(&pool)
311+
.await?;
312+
313+
// Insert another NULL
314+
sqlx::query("INSERT INTO encrypted(e) VALUES (NULL::jsonb::eql_v2_encrypted)")
315+
.execute(&pool)
316+
.await?;
317+
318+
// Test: DESC NULLS LAST should return id=2 (largest value)
319+
let sql = "SELECT id FROM encrypted ORDER BY e DESC NULLS LAST";
320+
let row = sqlx::query(sql).fetch_one(&pool).await?;
321+
let first_id: i64 = row.try_get(0)?;
322+
assert_eq!(
323+
first_id, 2,
324+
"ORDER BY e DESC NULLS LAST should return largest non-NULL value (id=2) first"
325+
);
326+
327+
Ok(())
328+
}
329+
330+
// eql_v2.order_by() helper function tests - from order_by_test.sql lines 133-144
331+
332+
#[sqlx::test]
333+
async fn order_by_helper_function_desc_returns_correct_count(pool: PgPool) -> Result<()> {
334+
// Test: ORDER BY eql_v2.order_by(e) DESC with WHERE e < 42
335+
// Expected: Returns 41 records
336+
337+
let ore_term = get_ore_encrypted(&pool, 42).await?;
338+
339+
let sql = format!(
340+
"SELECT id FROM ore WHERE e < '{}'::eql_v2_encrypted ORDER BY eql_v2.order_by(e) DESC",
341+
ore_term
342+
);
343+
344+
QueryAssertion::new(&pool, &sql).count(41).await;
345+
346+
Ok(())
347+
}
348+
349+
#[sqlx::test]
350+
async fn order_by_helper_function_desc_returns_highest_value_first(pool: PgPool) -> Result<()> {
351+
// Test: ORDER BY eql_v2.order_by(e) DESC LIMIT 1 returns id=41
352+
353+
let ore_term = get_ore_encrypted(&pool, 42).await?;
354+
355+
let sql = format!(
356+
"SELECT id FROM ore WHERE e < '{}'::eql_v2_encrypted ORDER BY eql_v2.order_by(e) DESC LIMIT 1",
357+
ore_term
358+
);
359+
360+
let row = sqlx::query(&sql).fetch_one(&pool).await?;
361+
let id: i64 = row.try_get(0)?;
362+
assert_eq!(
363+
id, 41,
364+
"ORDER BY eql_v2.order_by(e) DESC should return id=41 (highest value < 42) first"
365+
);
366+
367+
Ok(())
368+
}
369+
370+
#[sqlx::test]
371+
async fn order_by_helper_function_asc_returns_lowest_value_first(pool: PgPool) -> Result<()> {
372+
// Test: ORDER BY eql_v2.order_by(e) ASC LIMIT 1 returns id=1
373+
374+
let ore_term = get_ore_encrypted(&pool, 42).await?;
375+
376+
let sql = format!(
377+
"SELECT id FROM ore WHERE e < '{}'::eql_v2_encrypted ORDER BY eql_v2.order_by(e) ASC LIMIT 1",
378+
ore_term
379+
);
380+
381+
let row = sqlx::query(&sql).fetch_one(&pool).await?;
382+
let id: i64 = row.try_get(0)?;
383+
assert_eq!(
384+
id, 1,
385+
"ORDER BY eql_v2.order_by(e) ASC should return id=1 (lowest value < 42) first"
386+
);
387+
388+
Ok(())
389+
}

0 commit comments

Comments
 (0)