@@ -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
@@ -595,6 +601,7 @@ UpdateIndexRelation(Oid indexoid,
595
601
indcollation = buildoidvector (collationOids , indexInfo -> ii_NumIndexKeyAttrs );
596
602
indclass = buildoidvector (opclassOids , indexInfo -> ii_NumIndexKeyAttrs );
597
603
indoption = buildint2vector (coloptions , indexInfo -> ii_NumIndexKeyAttrs );
604
+ indgenkey = buildint2vector (colgenerated , indexInfo -> ii_NumIndexAttrs );
598
605
599
606
/*
600
607
* Convert the index expressions (if any) to a text datum
@@ -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
@@ -1411,6 +1441,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
1411
1441
1412
1442
indexColNames = lappend (indexColNames , NameStr (att -> attname ));
1413
1443
newInfo -> ii_IndexAttrNumbers [i ] = oldInfo -> ii_IndexAttrNumbers [i ];
1444
+ newInfo -> ii_IndexAttrGeneratedNumbers [i ] = oldInfo -> ii_IndexAttrGeneratedNumbers [i ];
1414
1445
}
1415
1446
1416
1447
/* Extract opclass options for each attribute */
@@ -2428,9 +2459,12 @@ IndexInfo *
2428
2459
BuildIndexInfo (Relation index )
2429
2460
{
2430
2461
IndexInfo * ii ;
2462
+ HeapTuple ht_idx ;
2431
2463
Form_pg_index indexStruct = index -> rd_index ;
2432
2464
int i ;
2433
2465
int numAtts ;
2466
+ Datum indgenkeyDatum ;
2467
+ int2vector * indgenkey ;
2434
2468
2435
2469
/* check the number of keys, and copy attr numbers into the IndexInfo */
2436
2470
numAtts = indexStruct -> indnatts ;
@@ -2454,9 +2488,19 @@ BuildIndexInfo(Relation index)
2454
2488
index -> rd_indam -> amsummarizing ,
2455
2489
indexStruct -> indisexclusion && indexStruct -> indisunique );
2456
2490
2491
+ ht_idx = SearchSysCache1 (INDEXRELID , ObjectIdGetDatum (indexStruct -> indexrelid ));
2492
+ indgenkeyDatum = SysCacheGetAttrNotNull (INDEXRELID , ht_idx ,
2493
+ Anum_pg_index_indattrgenerated );
2494
+ indgenkey = (int2vector * ) DatumGetPointer (indgenkeyDatum );
2495
+
2457
2496
/* fill in attribute numbers */
2458
2497
for (i = 0 ; i < numAtts ; i ++ )
2498
+ {
2459
2499
ii -> ii_IndexAttrNumbers [i ] = indexStruct -> indkey .values [i ];
2500
+ ii -> ii_IndexAttrGeneratedNumbers [i ] = indgenkey -> values [i ];
2501
+ }
2502
+
2503
+ ReleaseSysCache (ht_idx );
2460
2504
2461
2505
/* fetch exclusion constraint info if any */
2462
2506
if (indexStruct -> indisexclusion )
@@ -2518,11 +2562,35 @@ BuildDummyIndexInfo(Relation index)
2518
2562
for (i = 0 ; i < numAtts ; i ++ )
2519
2563
ii -> ii_IndexAttrNumbers [i ] = indexStruct -> indkey .values [i ];
2520
2564
2565
+ /*
2566
+ * Index expressions or predicates are skipped here, see above comments. If
2567
+ * virtual generated columns references another column, ii_IndexAttrNumbers
2568
+ * will set to that referenced column. So do nothing for
2569
+ * ii_IndexAttrGeneratedNumbers here.
2570
+ */
2571
+
2521
2572
/* We ignore the exclusion constraint if any */
2522
2573
2523
2574
return ii ;
2524
2575
}
2525
2576
2577
+ /*
2578
+ * IndexOverVirtualGenerated
2579
+ * Return whether this index was built on virtual generated column.
2580
+ */
2581
+ bool
2582
+ IsIndexOverVirtualGenerated (const IndexInfo * info )
2583
+ {
2584
+ int i ;
2585
+
2586
+ for (i = 0 ; i < info -> ii_NumIndexAttrs ; i ++ )
2587
+ {
2588
+ if (AttributeNumberIsValid (info -> ii_IndexAttrGeneratedNumbers [i ]))
2589
+ return true;
2590
+ }
2591
+ return false;
2592
+ }
2593
+
2526
2594
/*
2527
2595
* CompareIndexInfo
2528
2596
* Return whether the properties of two indexes (in different tables)
@@ -2585,6 +2653,15 @@ CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2,
2585
2653
return false;
2586
2654
}
2587
2655
2656
+ if (AttributeNumberIsValid (info1 -> ii_IndexAttrGeneratedNumbers [i ]) ||
2657
+ AttributeNumberIsValid (info2 -> ii_IndexAttrGeneratedNumbers [i ]))
2658
+ {
2659
+ /* fail if index over virtual generated column does not match */
2660
+ if (attmap -> attnums [info2 -> ii_IndexAttrGeneratedNumbers [i ] - 1 ] !=
2661
+ info1 -> ii_IndexAttrGeneratedNumbers [i ])
2662
+ return false;
2663
+ }
2664
+
2588
2665
/* collation and opfamily are not valid for included columns */
2589
2666
if (i >= info1 -> ii_NumIndexKeyAttrs )
2590
2667
continue ;
0 commit comments