@@ -584,6 +584,12 @@ UpdateIndexRelation(Oid indexoid,
584
584
Relation pg_index ;
585
585
HeapTuple tuple ;
586
586
int i ;
587
+ int2vector * indgenkey ;
588
+ int16 * colgenerated ;
589
+
590
+ colgenerated = palloc_array (int16 , indexInfo -> ii_NumIndexAttrs );
591
+ for (i = 0 ; i < indexInfo -> ii_NumIndexAttrs ; i ++ )
592
+ colgenerated [i ] = indexInfo -> ii_IndexAttrGeneratedNumbers [i ];
587
593
588
594
/*
589
595
* Copy the index key, opclass, and indoption info into arrays (should we
@@ -596,6 +602,7 @@ UpdateIndexRelation(Oid indexoid,
596
602
indclass = buildoidvector (opclassOids , indexInfo -> ii_NumIndexKeyAttrs );
597
603
indoption = buildint2vector (coloptions , indexInfo -> ii_NumIndexKeyAttrs );
598
604
605
+ indgenkey = buildint2vector (colgenerated , indexInfo -> ii_NumIndexAttrs );
599
606
/*
600
607
* Convert the index expressions (if any) to a text datum
601
608
*/
@@ -653,6 +660,7 @@ UpdateIndexRelation(Oid indexoid,
653
660
values [Anum_pg_index_indcollation - 1 ] = PointerGetDatum (indcollation );
654
661
values [Anum_pg_index_indclass - 1 ] = PointerGetDatum (indclass );
655
662
values [Anum_pg_index_indoption - 1 ] = PointerGetDatum (indoption );
663
+ values [Anum_pg_index_indattrgenerated - 1 ] = PointerGetDatum (indgenkey );
656
664
values [Anum_pg_index_indexprs - 1 ] = exprsDatum ;
657
665
if (exprsDatum == (Datum ) 0 )
658
666
nulls [Anum_pg_index_indexprs - 1 ] = true;
@@ -1134,6 +1142,28 @@ index_create(Relation heapRelation,
1134
1142
}
1135
1143
}
1136
1144
1145
+ /*
1146
+ * Internally, we convert index of virtual generation column into an
1147
+ * expression index. For example, if column 'b' is defined as (b INT
1148
+ * GENERATED ALWAYS AS (a * 2) VIRTUAL) then index over 'b' would
1149
+ * transformed into an expression index as ((a * 2)). As a result,
1150
+ * the pg_depend refobjsubid does not retain the original attribute
1151
+ * number of the virtual generated column. But we need rebuild any
1152
+ * index that was build on virtual generated column. so we need auto
1153
+ * dependencies on referenced virtual generated columns.
1154
+ */
1155
+ for (i = 0 ; i < indexInfo -> ii_NumIndexAttrs ; i ++ )
1156
+ {
1157
+ if (indexInfo -> ii_IndexAttrGeneratedNumbers [i ] != 0 )
1158
+ {
1159
+ ObjectAddressSubSet (referenced , RelationRelationId ,
1160
+ heapRelationId ,
1161
+ indexInfo -> ii_IndexAttrGeneratedNumbers [i ]);
1162
+ add_exact_object_address (& referenced , addrs );
1163
+ have_simple_col = false;
1164
+ }
1165
+ }
1166
+
1137
1167
/*
1138
1168
* If there are no simply-referenced columns, give the index an
1139
1169
* auto dependency on the whole table. In most cases, this will
@@ -2428,9 +2458,12 @@ IndexInfo *
2428
2458
BuildIndexInfo (Relation index )
2429
2459
{
2430
2460
IndexInfo * ii ;
2461
+ HeapTuple ht_idx ;
2431
2462
Form_pg_index indexStruct = index -> rd_index ;
2432
2463
int i ;
2433
2464
int numAtts ;
2465
+ Datum indgenkeyDatum ;
2466
+ int2vector * indgenkey ;
2434
2467
2435
2468
/* check the number of keys, and copy attr numbers into the IndexInfo */
2436
2469
numAtts = indexStruct -> indnatts ;
@@ -2454,9 +2487,19 @@ BuildIndexInfo(Relation index)
2454
2487
index -> rd_indam -> amsummarizing ,
2455
2488
indexStruct -> indisexclusion && indexStruct -> indisunique );
2456
2489
2490
+ ht_idx = SearchSysCache1 (INDEXRELID , ObjectIdGetDatum (indexStruct -> indexrelid ));
2491
+ indgenkeyDatum = SysCacheGetAttrNotNull (INDEXRELID , ht_idx ,
2492
+ Anum_pg_index_indattrgenerated );
2493
+ indgenkey = (int2vector * ) DatumGetPointer (indgenkeyDatum );
2494
+
2457
2495
/* fill in attribute numbers */
2458
2496
for (i = 0 ; i < numAtts ; i ++ )
2497
+ {
2459
2498
ii -> ii_IndexAttrNumbers [i ] = indexStruct -> indkey .values [i ];
2499
+ ii -> ii_IndexAttrGeneratedNumbers [i ] = indgenkey -> values [i ];
2500
+ }
2501
+
2502
+ ReleaseSysCache (ht_idx );
2460
2503
2461
2504
/* fetch exclusion constraint info if any */
2462
2505
if (indexStruct -> indisexclusion )
@@ -2523,6 +2566,23 @@ BuildDummyIndexInfo(Relation index)
2523
2566
return ii ;
2524
2567
}
2525
2568
2569
+ /*
2570
+ * IndexOverVirtualGenerated
2571
+ * Return whether this index is built on virtual generated column.
2572
+ */
2573
+ bool
2574
+ IsIndexOverVirtualGenerated (const IndexInfo * info )
2575
+ {
2576
+ int i ;
2577
+
2578
+ for (i = 0 ; i < info -> ii_NumIndexAttrs ; i ++ )
2579
+ {
2580
+ if (AttributeNumberIsValid (info -> ii_IndexAttrGeneratedNumbers [i ]))
2581
+ return true;
2582
+ }
2583
+ return false;
2584
+ }
2585
+
2526
2586
/*
2527
2587
* CompareIndexInfo
2528
2588
* Return whether the properties of two indexes (in different tables)
@@ -2585,6 +2645,15 @@ CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2,
2585
2645
return false;
2586
2646
}
2587
2647
2648
+ if (AttributeNumberIsValid (info1 -> ii_IndexAttrGeneratedNumbers [i ]) ||
2649
+ AttributeNumberIsValid (info2 -> ii_IndexAttrGeneratedNumbers [i ]))
2650
+ {
2651
+ /* fail if index over virtual generated column attribute does not match */
2652
+ if (attmap -> attnums [info2 -> ii_IndexAttrGeneratedNumbers [i ] - 1 ] !=
2653
+ info1 -> ii_IndexAttrGeneratedNumbers [i ])
2654
+ return false;
2655
+ }
2656
+
2588
2657
/* collation and opfamily are not valid for included columns */
2589
2658
if (i >= info1 -> ii_NumIndexKeyAttrs )
2590
2659
continue ;
0 commit comments