Skip to content

Commit 7beb653

Browse files
authored
Fix and improve index.sql regression test coverage (#2300)
NOTE: This PR was created with AI tools and a human. - Remove unused copy command (leftover from deleted agload_test_graph test) - Replace broken Section 4 that referenced non-existent graph with comprehensive WHERE clause tests covering string, int, bool, and float properties with AND/OR/NOT operators - Add EXPLAIN tests to verify index usage: - Section 3: Validate GIN indices (load_city_gin_idx, load_country_gin_idx) show Bitmap Index Scan for property matching - Section 4: Validate all expression indices (city_country_code_idx, city_id_idx, city_west_coast_idx, country_life_exp_idx) show Index Scan for WHERE clause filtering All indices now have EXPLAIN verification confirming they are used as expected. modified: regress/expected/index.out modified: regress/sql/index.sql
1 parent 2e8f7ab commit 7beb653

File tree

2 files changed

+436
-28
lines changed

2 files changed

+436
-28
lines changed

regress/expected/index.out

Lines changed: 273 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19-
\! cp -r regress/age_load/data regress/instance/data/age_load
2019
LOAD 'age';
2120
SET search_path TO ag_catalog;
2221
SET enable_mergejoin = ON;
@@ -385,6 +384,19 @@ CREATE INDEX load_city_gin_idx
385384
ON cypher_index."City" USING gin (properties);
386385
CREATE INDEX load_country_gin_idx
387386
ON cypher_index."Country" USING gin (properties);
387+
-- Verify GIN index is used for City property match
388+
SELECT * FROM cypher('cypher_index', $$
389+
EXPLAIN (costs off) MATCH (c:City {city_id: 1})
390+
RETURN c
391+
$$) as (plan agtype);
392+
QUERY PLAN
393+
--------------------------------------------------------------
394+
Bitmap Heap Scan on "City" c
395+
Recheck Cond: (properties @> '{"city_id": 1}'::agtype)
396+
-> Bitmap Index Scan on load_city_gin_idx
397+
Index Cond: (properties @> '{"city_id": 1}'::agtype)
398+
(4 rows)
399+
388400
SELECT * FROM cypher('cypher_index', $$
389401
MATCH (c:City {city_id: 1})
390402
RETURN c
@@ -418,6 +430,19 @@ $$) as (n agtype);
418430
{"id": 1970324836974597, "label": "City", "properties": {"name": "Vancouver", "city_id": 5, "west_coast": true, "country_code": "CA"}}::vertex
419431
(4 rows)
420432

433+
-- Verify GIN index is used for Country property match
434+
SELECT * FROM cypher('cypher_index', $$
435+
EXPLAIN (costs off) MATCH (c:Country {life_expectancy: 82.05})
436+
RETURN c
437+
$$) as (plan agtype);
438+
QUERY PLAN
439+
--------------------------------------------------------------------------
440+
Bitmap Heap Scan on "Country" c
441+
Recheck Cond: (properties @> '{"life_expectancy": 82.05}'::agtype)
442+
-> Bitmap Index Scan on load_country_gin_idx
443+
Index Cond: (properties @> '{"life_expectancy": 82.05}'::agtype)
444+
(4 rows)
445+
421446
SELECT * FROM cypher('cypher_index', $$
422447
MATCH (c:Country {life_expectancy: 82.05})
423448
RETURN c
@@ -441,26 +466,259 @@ DROP INDEX cypher_index.load_country_gin_idx;
441466
--
442467
-- Section 4: Index use with WHERE clause
443468
--
444-
SELECT COUNT(*) FROM cypher('cypher_index', $$
469+
-- Create expression index on country_code property
470+
CREATE INDEX city_country_code_idx ON cypher_index."City"
471+
(ag_catalog.agtype_access_operator(properties, '"country_code"'::agtype));
472+
-- Verify index is used with EXPLAIN (should show Index Scan on city_country_code_idx)
473+
SELECT * FROM cypher('cypher_index', $$
474+
EXPLAIN (costs off) MATCH (a:City)
475+
WHERE a.country_code = 'US'
476+
RETURN a
477+
$$) as (plan agtype);
478+
QUERY PLAN
479+
---------------------------------------------------------------------------------------------------------------
480+
Index Scan using city_country_code_idx on "City" a
481+
Index Cond: (agtype_access_operator(VARIADIC ARRAY[properties, '"country_code"'::agtype]) = '"US"'::agtype)
482+
(2 rows)
483+
484+
-- Test WHERE with indexed string property
485+
SELECT * FROM cypher('cypher_index', $$
445486
MATCH (a:City)
446-
WHERE a.country_code = 'RS'
487+
WHERE a.country_code = 'US'
488+
RETURN a.name
489+
ORDER BY a.city_id
490+
$$) as (name agtype);
491+
name
492+
-----------------
493+
"New York"
494+
"San Fransisco"
495+
"Los Angeles"
496+
"Seattle"
497+
(4 rows)
498+
499+
SELECT * FROM cypher('cypher_index', $$
500+
MATCH (a:City)
501+
WHERE a.country_code = 'CA'
502+
RETURN a.name
503+
ORDER BY a.city_id
504+
$$) as (name agtype);
505+
name
506+
-------------
507+
"Vancouver"
508+
"Toronto"
509+
"Montreal"
510+
(3 rows)
511+
512+
-- Test WHERE with no matching results
513+
SELECT * FROM cypher('cypher_index', $$
514+
MATCH (a:City)
515+
WHERE a.country_code = 'XX'
516+
RETURN a.name
517+
$$) as (name agtype);
518+
name
519+
------
520+
(0 rows)
521+
522+
-- Create expression index on city_id property
523+
CREATE INDEX city_id_idx ON cypher_index."City"
524+
(ag_catalog.agtype_access_operator(properties, '"city_id"'::agtype));
525+
-- Verify index is used with EXPLAIN for integer property
526+
SELECT * FROM cypher('cypher_index', $$
527+
EXPLAIN (costs off) MATCH (a:City)
528+
WHERE a.city_id = 1
447529
RETURN a
448-
$$) as (n agtype);
449-
count
450-
-------
451-
0
530+
$$) as (plan agtype);
531+
QUERY PLAN
532+
-------------------------------------------------------------------------------------------------------
533+
Index Scan using city_id_idx on "City" a
534+
Index Cond: (agtype_access_operator(VARIADIC ARRAY[properties, '"city_id"'::agtype]) = '1'::agtype)
535+
(2 rows)
536+
537+
-- Test WHERE with indexed integer property
538+
SELECT * FROM cypher('cypher_index', $$
539+
MATCH (a:City)
540+
WHERE a.city_id = 1
541+
RETURN a.name
542+
$$) as (name agtype);
543+
name
544+
------------
545+
"New York"
452546
(1 row)
453547

454-
CREATE INDEX CONCURRENTLY cntry_ode_idx ON cypher_index."City"
455-
(ag_catalog.agtype_access_operator(properties, '"country_code"'::agtype));
456-
SELECT COUNT(*) FROM cypher('agload_test_graph', $$
548+
SELECT * FROM cypher('cypher_index', $$
457549
MATCH (a:City)
458-
WHERE a.country_code = 'RS'
550+
WHERE a.city_id = 5
551+
RETURN a.name
552+
$$) as (name agtype);
553+
name
554+
-------------
555+
"Vancouver"
556+
(1 row)
557+
558+
-- Test WHERE with comparison operators on indexed property
559+
SELECT * FROM cypher('cypher_index', $$
560+
MATCH (a:City)
561+
WHERE a.city_id < 3
562+
RETURN a.name
563+
ORDER BY a.city_id
564+
$$) as (name agtype);
565+
name
566+
-----------------
567+
"New York"
568+
"San Fransisco"
569+
(2 rows)
570+
571+
SELECT * FROM cypher('cypher_index', $$
572+
MATCH (a:City)
573+
WHERE a.city_id >= 8
574+
RETURN a.name
575+
ORDER BY a.city_id
576+
$$) as (name agtype);
577+
name
578+
-------------
579+
"Monterrey"
580+
"Tijuana"
581+
(2 rows)
582+
583+
-- Create expression index on west_coast boolean property
584+
CREATE INDEX city_west_coast_idx ON cypher_index."City"
585+
(ag_catalog.agtype_access_operator(properties, '"west_coast"'::agtype));
586+
-- Verify index is used with EXPLAIN for boolean property
587+
SELECT * FROM cypher('cypher_index', $$
588+
EXPLAIN (costs off) MATCH (a:City)
589+
WHERE a.west_coast = true
459590
RETURN a
460-
$$) as (n agtype);
461-
ERROR: graph "agload_test_graph" does not exist
462-
LINE 1: SELECT COUNT(*) FROM cypher('agload_test_graph', $$
463-
^
591+
$$) as (plan agtype);
592+
QUERY PLAN
593+
-------------------------------------------------------------------------------------------------------------
594+
Index Scan using city_west_coast_idx on "City" a
595+
Index Cond: (agtype_access_operator(VARIADIC ARRAY[properties, '"west_coast"'::agtype]) = 'true'::agtype)
596+
(2 rows)
597+
598+
-- Test WHERE with indexed boolean property
599+
SELECT * FROM cypher('cypher_index', $$
600+
MATCH (a:City)
601+
WHERE a.west_coast = true
602+
RETURN a.name
603+
ORDER BY a.city_id
604+
$$) as (name agtype);
605+
name
606+
-----------------
607+
"San Fransisco"
608+
"Los Angeles"
609+
"Seattle"
610+
"Vancouver"
611+
(4 rows)
612+
613+
SELECT * FROM cypher('cypher_index', $$
614+
MATCH (a:City)
615+
WHERE a.west_coast = false
616+
RETURN a.name
617+
ORDER BY a.city_id
618+
$$) as (name agtype);
619+
name
620+
---------------
621+
"New York"
622+
"Toronto"
623+
"Montreal"
624+
"Mexico City"
625+
"Monterrey"
626+
"Tijuana"
627+
(6 rows)
628+
629+
-- Test WHERE with multiple conditions (AND)
630+
SELECT * FROM cypher('cypher_index', $$
631+
MATCH (a:City)
632+
WHERE a.country_code = 'US' AND a.west_coast = true
633+
RETURN a.name
634+
ORDER BY a.city_id
635+
$$) as (name agtype);
636+
name
637+
-----------------
638+
"San Fransisco"
639+
"Los Angeles"
640+
"Seattle"
641+
(3 rows)
642+
643+
-- Test WHERE with OR conditions
644+
SELECT * FROM cypher('cypher_index', $$
645+
MATCH (a:City)
646+
WHERE a.city_id = 1 OR a.city_id = 5
647+
RETURN a.name
648+
ORDER BY a.city_id
649+
$$) as (name agtype);
650+
name
651+
-------------
652+
"New York"
653+
"Vancouver"
654+
(2 rows)
655+
656+
-- Test WHERE with NOT
657+
SELECT * FROM cypher('cypher_index', $$
658+
MATCH (a:City)
659+
WHERE NOT a.west_coast = true AND a.country_code = 'US'
660+
RETURN a.name
661+
$$) as (name agtype);
662+
name
663+
------------
664+
"New York"
665+
(1 row)
666+
667+
-- Create expression index on life_expectancy for Country
668+
CREATE INDEX country_life_exp_idx ON cypher_index."Country"
669+
(ag_catalog.agtype_access_operator(properties, '"life_expectancy"'::agtype));
670+
-- Verify index is used with EXPLAIN for float property
671+
SELECT * FROM cypher('cypher_index', $$
672+
EXPLAIN (costs off) MATCH (c:Country)
673+
WHERE c.life_expectancy > 80.0
674+
RETURN c
675+
$$) as (plan agtype);
676+
QUERY PLAN
677+
------------------------------------------------------------------------------------------------------------------
678+
Index Scan using country_life_exp_idx on "Country" c
679+
Index Cond: (agtype_access_operator(VARIADIC ARRAY[properties, '"life_expectancy"'::agtype]) > '80.0'::agtype)
680+
(2 rows)
681+
682+
-- Test WHERE with float property
683+
SELECT * FROM cypher('cypher_index', $$
684+
MATCH (c:Country)
685+
WHERE c.life_expectancy > 80.0
686+
RETURN c.name
687+
$$) as (name agtype);
688+
name
689+
----------
690+
"Canada"
691+
(1 row)
692+
693+
SELECT * FROM cypher('cypher_index', $$
694+
MATCH (c:Country)
695+
WHERE c.life_expectancy < 76.0
696+
RETURN c.name
697+
$$) as (name agtype);
698+
name
699+
----------
700+
"Mexico"
701+
(1 row)
702+
703+
-- Test WHERE in combination with pattern matching
704+
SELECT * FROM cypher('cypher_index', $$
705+
MATCH (country:Country)<-[:has_city]-(city:City)
706+
WHERE country.country_code = 'CA'
707+
RETURN city.name
708+
ORDER BY city.city_id
709+
$$) as (name agtype);
710+
name
711+
-------------
712+
"Vancouver"
713+
"Toronto"
714+
"Montreal"
715+
(3 rows)
716+
717+
-- Clean up indices
718+
DROP INDEX cypher_index.city_country_code_idx;
719+
DROP INDEX cypher_index.city_id_idx;
720+
DROP INDEX cypher_index.city_west_coast_idx;
721+
DROP INDEX cypher_index.country_life_exp_idx;
464722
--
465723
-- General Cleanup
466724
--
@@ -478,5 +736,3 @@ NOTICE: graph "cypher_index" has been dropped
478736

479737
(1 row)
480738

481-
SELECT drop_graph('agload_test_graph', true);
482-
ERROR: graph "agload_test_graph" does not exist

0 commit comments

Comments
 (0)