@@ -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