@@ -19,8 +19,14 @@ defmodule Ecto.RTreeTest do
1919 # Start the test repo
2020 { :ok , _ } = TestRepo . start_link ( database: @ test_db )
2121
22- # Clean up after all tests complete
22+ # Clean up after all tests complete - stop GenServer and remove db files
2323 on_exit ( fn ->
24+ try do
25+ GenServer . stop ( TestRepo )
26+ catch
27+ _ , _ -> nil
28+ end
29+
2430 File . rm ( @ test_db )
2531 File . rm ( @ test_db <> "-shm" )
2632 File . rm ( @ test_db <> "-wal" )
@@ -264,7 +270,8 @@ defmodule Ecto.RTreeTest do
264270 end
265271 end
266272
267- describe "R*Tree queries" do
273+ describe "R*Tree queries and operations" do
274+ # Each test gets its own fresh data to avoid order dependencies
268275 setup do
269276 # Create R*Tree table
270277 Ecto.Adapters.SQL . query! ( TestRepo , """
@@ -378,4 +385,223 @@ defmodule Ecto.RTreeTest do
378385 assert result . rows == [ [ 1 ] , [ 3 ] ]
379386 end
380387 end
388+
389+ describe "R*Tree edge cases and advanced scenarios" do
390+ test "handles empty R*Tree table" do
391+ # Create and query empty R*Tree table
392+ Ecto.Adapters.SQL . query! ( TestRepo , """
393+ DROP TABLE IF EXISTS empty_rtree
394+ """ )
395+
396+ Ecto.Adapters.SQL . query! ( TestRepo , """
397+ CREATE VIRTUAL TABLE empty_rtree USING rtree(
398+ id,
399+ min_lat, max_lat,
400+ min_lng, max_lng
401+ )
402+ """ )
403+
404+ result =
405+ Ecto.Adapters.SQL . query! (
406+ TestRepo ,
407+ "SELECT COUNT(*) FROM empty_rtree"
408+ )
409+
410+ assert result . rows == [ [ 0 ] ]
411+ end
412+
413+ test "handles boundary condition with min=max coordinates" do
414+ Ecto.Adapters.SQL . query! ( TestRepo , """
415+ DROP TABLE IF EXISTS point_rtree
416+ """ )
417+
418+ Ecto.Adapters.SQL . query! ( TestRepo , """
419+ CREATE VIRTUAL TABLE point_rtree USING rtree(
420+ id,
421+ min_x, max_x,
422+ min_y, max_y
423+ )
424+ """ )
425+
426+ # Insert a point (min=max for both dimensions)
427+ Ecto.Adapters.SQL . query! (
428+ TestRepo ,
429+ "INSERT INTO point_rtree VALUES (1, 0.0, 0.0, 0.0, 0.0)"
430+ )
431+
432+ # Query for exact point
433+ result =
434+ Ecto.Adapters.SQL . query! (
435+ TestRepo ,
436+ """
437+ SELECT id FROM point_rtree
438+ WHERE min_x <= 0.0 AND max_x >= 0.0
439+ AND min_y <= 0.0 AND max_y >= 0.0
440+ """
441+ )
442+
443+ assert result . rows == [ [ 1 ] ]
444+ end
445+
446+ test "handles bulk inserts with many regions" do
447+ Ecto.Adapters.SQL . query! ( TestRepo , """
448+ DROP TABLE IF EXISTS bulk_rtree
449+ """ )
450+
451+ Ecto.Adapters.SQL . query! ( TestRepo , """
452+ CREATE VIRTUAL TABLE bulk_rtree USING rtree(
453+ id,
454+ min_x, max_x,
455+ min_y, max_y
456+ )
457+ """ )
458+
459+ # Bulk insert 100 regions
460+ Enum . each ( 1 .. 100 , fn i ->
461+ Ecto.Adapters.SQL . query! (
462+ TestRepo ,
463+ "INSERT INTO bulk_rtree VALUES (#{ i } , #{ i } .0, #{ i + 1 } .0, #{ i } .0, #{ i + 1 } .0)"
464+ )
465+ end )
466+
467+ result =
468+ Ecto.Adapters.SQL . query! (
469+ TestRepo ,
470+ "SELECT COUNT(*) FROM bulk_rtree"
471+ )
472+
473+ assert result . rows == [ [ 100 ] ]
474+
475+ # Verify we can query in the bulk data
476+ result =
477+ Ecto.Adapters.SQL . query! (
478+ TestRepo ,
479+ """
480+ SELECT COUNT(*) FROM bulk_rtree
481+ WHERE max_x >= 50.0 AND min_x <= 51.0
482+ """
483+ )
484+
485+ assert [ [ count ] ] = result . rows
486+ assert count >= 1
487+ end
488+
489+ test "handles R*Tree operations within transaction rollback" do
490+ Ecto.Adapters.SQL . query! ( TestRepo , """
491+ DROP TABLE IF EXISTS txn_rtree
492+ """ )
493+
494+ Ecto.Adapters.SQL . query! ( TestRepo , """
495+ CREATE VIRTUAL TABLE txn_rtree USING rtree(
496+ id,
497+ min_x, max_x,
498+ min_y, max_y
499+ )
500+ """ )
501+
502+ # Insert initial data
503+ Ecto.Adapters.SQL . query! (
504+ TestRepo ,
505+ "INSERT INTO txn_rtree VALUES (1, 0.0, 1.0, 0.0, 1.0)"
506+ )
507+
508+ # Begin transaction and insert, then rollback
509+ case EctoLibSql . connect ( database: @ test_db ) do
510+ { :ok , state } ->
511+ { :ok , :begin , state } = EctoLibSql . handle_begin ( [ ] , state )
512+
513+ # Insert within transaction
514+ { :ok , _query , _result , state } =
515+ EctoLibSql . handle_execute (
516+ "INSERT INTO txn_rtree VALUES (2, 2.0, 3.0, 2.0, 3.0)" ,
517+ [ ] ,
518+ [ ] ,
519+ state
520+ )
521+
522+ # Rollback the transaction
523+ { :ok , _rollback_result , _final_state } = EctoLibSql . handle_rollback ( [ ] , state )
524+
525+ # Verify only original data exists
526+ result =
527+ Ecto.Adapters.SQL . query! (
528+ TestRepo ,
529+ "SELECT COUNT(*) FROM txn_rtree"
530+ )
531+
532+ assert result . rows == [ [ 1 ] ]
533+
534+ { :error , _reason } ->
535+ # Skip if connection fails
536+ :ok
537+ end
538+ end
539+
540+ test "handles different coordinate types (integer vs float)" do
541+ Ecto.Adapters.SQL . query! ( TestRepo , """
542+ DROP TABLE IF EXISTS mixed_coords
543+ """ )
544+
545+ Ecto.Adapters.SQL . query! ( TestRepo , """
546+ CREATE VIRTUAL TABLE mixed_coords USING rtree(
547+ id,
548+ min_x, max_x,
549+ min_y, max_y
550+ )
551+ """ )
552+
553+ # Insert with integer coordinates (SQLite converts to float internally)
554+ Ecto.Adapters.SQL . query! (
555+ TestRepo ,
556+ "INSERT INTO mixed_coords VALUES (1, 1, 2, 1, 2)"
557+ )
558+
559+ # Insert with float coordinates
560+ Ecto.Adapters.SQL . query! (
561+ TestRepo ,
562+ "INSERT INTO mixed_coords VALUES (2, 2.5, 3.5, 2.5, 3.5)"
563+ )
564+
565+ # Both should be queryable
566+ result =
567+ Ecto.Adapters.SQL . query! (
568+ TestRepo ,
569+ "SELECT COUNT(*) FROM mixed_coords"
570+ )
571+
572+ assert result . rows == [ [ 2 ] ]
573+ end
574+
575+ test "handles large coordinate values" do
576+ Ecto.Adapters.SQL . query! ( TestRepo , """
577+ DROP TABLE IF EXISTS large_coords
578+ """ )
579+
580+ Ecto.Adapters.SQL . query! ( TestRepo , """
581+ CREATE VIRTUAL TABLE large_coords USING rtree(
582+ id,
583+ min_x, max_x,
584+ min_y, max_y
585+ )
586+ """ )
587+
588+ # Insert with very large coordinate values
589+ Ecto.Adapters.SQL . query! (
590+ TestRepo ,
591+ "INSERT INTO large_coords VALUES (1, -180.0, 180.0, -90.0, 90.0)"
592+ )
593+
594+ result =
595+ Ecto.Adapters.SQL . query! (
596+ TestRepo ,
597+ """
598+ SELECT id FROM large_coords
599+ WHERE max_x >= 0.0 AND min_x <= 0.0
600+ AND max_y >= 0.0 AND min_y <= 0.0
601+ """
602+ )
603+
604+ assert result . rows == [ [ 1 ] ]
605+ end
606+ end
381607end
0 commit comments