@@ -559,6 +559,61 @@ local function build_index_parts_tree(indexes)
559
559
return roots
560
560
end
561
561
562
+ local function set_connection_index (c , c_name , c_type , collection_name ,
563
+ indexes , connection_indexes )
564
+ assert (type (c .index_name ) == ' string' ,
565
+ ' index_name must be a string, got ' .. type (c .index_name ))
566
+
567
+ -- validate index_name against 'indexes'
568
+ local index_meta = indexes [c .destination_collection ]
569
+ assert (type (index_meta ) == ' table' ,
570
+ ' index_meta must be a table, got ' .. type (index_meta ))
571
+
572
+ assert (type (collection_name ) == ' string' , ' collection_name expected to ' ..
573
+ ' be string, got ' .. type (collection_name ))
574
+
575
+ -- validate connection parts are match or being prefix of index
576
+ -- fields
577
+ local i = 1
578
+ local index_fields = index_meta [c .index_name ].fields
579
+ for _ , part in ipairs (c .parts ) do
580
+ assert (type (part .source_field ) == ' string' ,
581
+ ' part.source_field must be a string, got ' ..
582
+ type (part .source_field ))
583
+ assert (type (part .destination_field ) == ' string' ,
584
+ ' part.destination_field must be a string, got ' ..
585
+ type (part .destination_field ))
586
+ assert (part .destination_field == index_fields [i ],
587
+ (' connection "%s" of collection "%s" has destination parts that ' ..
588
+ ' is not prefix of the index "%s" parts ' ..
589
+ ' (destination collection - "%s")' ):format (c_name , collection_name ,
590
+ c .index_name , c .destination_collection ))
591
+ i = i + 1
592
+ end
593
+ local parts_cnt = i - 1
594
+
595
+ -- partial index of an unique index is not guaranteed to being
596
+ -- unique
597
+ assert (c_type == ' 1:N' or parts_cnt == # index_fields ,
598
+ (' 1:1 connection "%s" of collection "%s" ' ..
599
+ ' has less fields than the index of "%s" collection ' ..
600
+ ' (cannot prove uniqueness of the partial index)' ):format (c_name ,
601
+ collection_name , c .index_name , c .destination_collection ))
602
+
603
+ -- validate connection type against index uniqueness (if provided)
604
+ if index_meta .unique ~= nil then
605
+ assert (c_type == ' 1:N' or index_meta .unique == true ,
606
+ (' 1:1 connection ("%s") cannot be implemented ' ..
607
+ ' on top of non-unique index ("%s")' ):format (
608
+ c_name , c .index_name ))
609
+ end
610
+
611
+ return {
612
+ index_name = c .index_name ,
613
+ connection_type = c_type ,
614
+ }
615
+ end
616
+
562
617
--- Build `connection_indexes` table (part of `index_cache`) to use in the
563
618
--- @{get_index_name} function.
564
619
---
@@ -581,60 +636,28 @@ local function build_connection_indexes(indexes, collections)
581
636
assert (type (collections ) == ' table' , ' collections must be a table, got ' ..
582
637
type (collections ))
583
638
local connection_indexes = {}
584
- for _ , collection in pairs (collections ) do
639
+ for collection_name , collection in pairs (collections ) do
585
640
for _ , c in ipairs (collection .connections ) do
586
- if connection_indexes [c .destination_collection ] == nil then
587
- connection_indexes [c .destination_collection ] = {}
588
- end
589
- local index_name = c .index_name
590
- assert (type (index_name ) == ' string' ,
591
- ' index_name must be a string, got ' .. type (index_name ))
641
+ if c .destination_collection ~= nil then
642
+ if connection_indexes [c .destination_collection ] == nil then
643
+ connection_indexes [c .destination_collection ] = {}
644
+ end
592
645
593
- -- validate index_name against 'indexes'
594
- local index_meta = indexes [c .destination_collection ]
595
- assert (type (index_meta ) == ' table' ,
596
- ' index_meta must be a table, got ' .. type (index_meta ))
597
-
598
- -- validate connection parts are match or being prefix of index
599
- -- fields
600
- local i = 1
601
- local index_fields = index_meta [c .index_name ].fields
602
- for _ , part in ipairs (c .parts ) do
603
- assert (type (part .source_field ) == ' string' ,
604
- ' part.source_field must be a string, got ' ..
605
- type (part .source_field ))
606
- assert (type (part .destination_field ) == ' string' ,
607
- ' part.destination_field must be a string, got ' ..
608
- type (part .destination_field ))
609
- assert (part .destination_field == index_fields [i ],
610
- (' connection "%s" of collection "%s" ' ..
611
- ' has destination parts that is not prefix of the index ' ..
612
- ' "%s" parts' ):format (c .name , c .destination_collection ,
613
- c .index_name ))
614
- i = i + 1
615
- end
616
- local parts_cnt = i - 1
617
-
618
- -- partial index of an unique index is not guaranteed to being
619
- -- unique
620
- assert (c .type == ' 1:N' or parts_cnt == # index_fields ,
621
- (' 1:1 connection "%s" of collection "%s" ' ..
622
- ' has less fields than the index "%s" has (cannot prove ' ..
623
- ' uniqueness of the partial index)' ):format (c .name ,
624
- c .destination_collection , c .index_name ))
625
-
626
- -- validate connection type against index uniqueness (if provided)
627
- if index_meta .unique ~= nil then
628
- assert (c .type == ' 1:N' or index_meta .unique == true ,
629
- (' 1:1 connection ("%s") cannot be implemented ' ..
630
- ' on top of non-unique index ("%s")' ):format (
631
- c .name , index_name ))
646
+ connection_indexes [c .destination_collection ][c .name ] =
647
+ set_connection_index (c , c .name , c .type , collection_name ,
648
+ indexes , connection_indexes )
632
649
end
633
650
634
- connection_indexes [c .destination_collection ][c .name ] = {
635
- index_name = index_name ,
636
- connection_type = c .type ,
637
- }
651
+ if c .variants ~= nil then
652
+ for _ , v in ipairs (c .variants ) do
653
+ if connection_indexes [v .destination_collection ] == nil then
654
+ connection_indexes [v .destination_collection ] = {}
655
+ end
656
+ connection_indexes [v .destination_collection ][c .name ] =
657
+ set_connection_index (v , c .name , c .type , collection_name ,
658
+ indexes , connection_indexes )
659
+ end
660
+ end
638
661
end
639
662
end
640
663
return connection_indexes
@@ -678,7 +701,7 @@ local function validate_collections(collections, schemas)
678
701
type (schema_name ))
679
702
assert (schemas [schema_name ] ~= nil ,
680
703
(' cannot find schema "%s" for collection "%s"' ):format (
681
- schema_name , collection_name ))
704
+ schema_name , collection_name ))
682
705
local connections = collection .connections
683
706
assert (connections == nil or type (connections ) == ' table' ,
684
707
' collection.connections must be nil or table, got ' ..
@@ -688,16 +711,36 @@ local function validate_collections(collections, schemas)
688
711
' connection must be a table, got ' .. type (connection ))
689
712
assert (type (connection .name ) == ' string' ,
690
713
' connection.name must be a string, got ' ..
691
- type (connection .name ))
692
- assert (type (connection .destination_collection ) == ' string' ,
693
- ' connection.destination_collection must be a string, got ' ..
694
- type (connection .destination_collection ))
695
- assert (type (connection .parts ) == ' table' ,
696
- ' connection.parts must be a string, got ' ..
697
- type (connection .parts ))
698
- assert (type (connection .index_name ) == ' string' ,
699
- ' connection.index_name must be a string, got ' ..
700
- type (connection .index_name ))
714
+ type (connection .name ))
715
+ if connection .destination_collection then
716
+ assert (type (connection .destination_collection ) == ' string' ,
717
+ ' connection.destination_collection must be a string, got ' ..
718
+ type (connection .destination_collection ))
719
+ assert (type (connection .parts ) == ' table' ,
720
+ ' connection.parts must be a string, got ' ..
721
+ type (connection .parts ))
722
+ assert (type (connection .index_name ) == ' string' ,
723
+ ' connection.index_name must be a string, got ' ..
724
+ type (connection .index_name ))
725
+ elseif connection .variants then
726
+ for _ , v in pairs (connection .variants ) do
727
+ assert (type (v .determinant ) == ' table' , " variant's " ..
728
+ " determinant must be a table, got " ..
729
+ type (v .determinant ))
730
+ assert (type (v .destination_collection ) == ' string' ,
731
+ ' variant.destination_collection must be a string, ' ..
732
+ ' got ' .. type (v .destination_collection ))
733
+ assert (type (v .parts ) == ' table' ,
734
+ ' variant.parts must be a table, got ' .. type (v .parts ))
735
+ assert (type (v .index_name ) == ' string' ,
736
+ ' variant.index_name must be a string, got ' ..
737
+ type (v .index_name ))
738
+ end
739
+ else
740
+ assert (false , (' connection "%s" of collection "%s" does not ' ..
741
+ ' have neither destination collection nor variants field' ):
742
+ format (connection .name , collection_name ))
743
+ end
701
744
end
702
745
end
703
746
end
0 commit comments