Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 435a32b

Browse files
author
Commitfest Bot
committed
[CF 5667] v3 - support create index on virtual generated column.
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5667 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CACJufxFx2zmTnTrGaxfNpRpy3RbY9wpjBXqvfP5dWoxsW9f_FQ@mail.gmail.com Author(s): Jian He
2 parents 883339c + f57487f commit 435a32b

File tree

15 files changed

+788
-68
lines changed

15 files changed

+788
-68
lines changed

contrib/pageinspect/expected/btree.out

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,39 @@ tids |
183183

184184
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 2));
185185
ERROR: block number 2 is out of range for relation "test1_a_idx"
186+
---test index over virtual generated column
187+
CREATE TABLE test3 (a int8, b int4range, c int8 generated always as (a+1) virtual);
188+
INSERT INTO test3 VALUES (72057594037927936, '[0,1)');
189+
CREATE INDEX test3_a_idx ON test3 USING btree (c);
190+
SELECT * FROM bt_page_items('test3_a_idx', 1);
191+
-[ RECORD 1 ]-----------------------
192+
itemoffset | 1
193+
ctid | (0,1)
194+
itemlen | 16
195+
nulls | f
196+
vars | f
197+
data | 01 00 00 00 00 00 00 01
198+
dead | f
199+
htid | (0,1)
200+
tids |
201+
202+
--expect zero row.
203+
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 1))
204+
EXCEPT ALL
205+
SELECT * FROM bt_page_items(get_raw_page('test3_a_idx', 1));
206+
(0 rows)
207+
208+
CREATE TABLE test4(a int, b int GENERATED ALWAYS AS (a + 1), c text);
209+
INSERT INTO test4(a,c) VALUES (10,11), (10,11);
210+
CREATE INDEX test4_b ON test4 USING btree (b);
211+
CREATE INDEX test4_c ON test4 USING btree (c);
212+
ALTER TABLE test4 alter column b set data type text;
213+
---should return zero row.
214+
SELECT * FROM bt_page_items('test4_b', 1)
215+
EXCEPT ALL
216+
SELECT * FROM bt_page_items('test4_c', 1);
217+
(0 rows)
218+
186219
-- Failure when using a non-btree index.
187220
CREATE INDEX test1_a_hash ON test1 USING hash(a);
188221
SELECT bt_metap('test1_a_hash');

contrib/pageinspect/sql/btree.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,27 @@ SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 0));
3232
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 1));
3333
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 2));
3434

35+
---test index over virtual generated column
36+
CREATE TABLE test3 (a int8, b int4range, c int8 generated always as (a+1) virtual);
37+
INSERT INTO test3 VALUES (72057594037927936, '[0,1)');
38+
CREATE INDEX test3_a_idx ON test3 USING btree (c);
39+
SELECT * FROM bt_page_items('test3_a_idx', 1);
40+
41+
--expect zero row.
42+
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 1))
43+
EXCEPT ALL
44+
SELECT * FROM bt_page_items(get_raw_page('test3_a_idx', 1));
45+
46+
CREATE TABLE test4(a int, b int GENERATED ALWAYS AS (a + 1), c text);
47+
INSERT INTO test4(a,c) VALUES (10,11), (10,11);
48+
CREATE INDEX test4_b ON test4 USING btree (b);
49+
CREATE INDEX test4_c ON test4 USING btree (c);
50+
ALTER TABLE test4 alter column b set data type text;
51+
---should return zero row.
52+
SELECT * FROM bt_page_items('test4_b', 1)
53+
EXCEPT ALL
54+
SELECT * FROM bt_page_items('test4_c', 1);
55+
3556
-- Failure when using a non-btree index.
3657
CREATE INDEX test1_a_hash ON test1 USING hash(a);
3758
SELECT bt_metap('test1_a_hash');

doc/src/sgml/catalogs.sgml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4595,6 +4595,21 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
45954595
</para></entry>
45964596
</row>
45974597

4598+
<row>
4599+
<entry role="catalog_table_entry"><para role="column_definition">
4600+
<structfield>indattrgenerated</structfield> <type>int2vector</type>
4601+
(references <link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.<structfield>attnum</structfield>)
4602+
</para>
4603+
<para>
4604+
This is an array of <structfield>indnatts</structfield> values that
4605+
indicate which table virtual generated columns this index indexes.
4606+
For example, a value of <literal>1 3</literal> would mean that the first
4607+
and the third table columns of this index entries are virtual generated
4608+
column. A zero in this array indicates that the corresponding index
4609+
attribute is not virtual generated column reference.
4610+
</para></entry>
4611+
</row>
4612+
45984613
<row>
45994614
<entry role="catalog_table_entry"><para role="column_definition">
46004615
<structfield>indexprs</structfield> <type>pg_node_tree</type>

src/backend/catalog/index.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,12 @@ UpdateIndexRelation(Oid indexoid,
584584
Relation pg_index;
585585
HeapTuple tuple;
586586
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];
587593

588594
/*
589595
* Copy the index key, opclass, and indoption info into arrays (should we
@@ -596,6 +602,7 @@ UpdateIndexRelation(Oid indexoid,
596602
indclass = buildoidvector(opclassOids, indexInfo->ii_NumIndexKeyAttrs);
597603
indoption = buildint2vector(coloptions, indexInfo->ii_NumIndexKeyAttrs);
598604

605+
indgenkey = buildint2vector(colgenerated, indexInfo->ii_NumIndexAttrs);
599606
/*
600607
* Convert the index expressions (if any) to a text datum
601608
*/
@@ -653,6 +660,7 @@ UpdateIndexRelation(Oid indexoid,
653660
values[Anum_pg_index_indcollation - 1] = PointerGetDatum(indcollation);
654661
values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);
655662
values[Anum_pg_index_indoption - 1] = PointerGetDatum(indoption);
663+
values[Anum_pg_index_indattrgenerated - 1] = PointerGetDatum(indgenkey);
656664
values[Anum_pg_index_indexprs - 1] = exprsDatum;
657665
if (exprsDatum == (Datum) 0)
658666
nulls[Anum_pg_index_indexprs - 1] = true;
@@ -1134,6 +1142,28 @@ index_create(Relation heapRelation,
11341142
}
11351143
}
11361144

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+
11371167
/*
11381168
* If there are no simply-referenced columns, give the index an
11391169
* auto dependency on the whole table. In most cases, this will
@@ -2428,9 +2458,12 @@ IndexInfo *
24282458
BuildIndexInfo(Relation index)
24292459
{
24302460
IndexInfo *ii;
2461+
HeapTuple ht_idx;
24312462
Form_pg_index indexStruct = index->rd_index;
24322463
int i;
24332464
int numAtts;
2465+
Datum indgenkeyDatum;
2466+
int2vector *indgenkey;
24342467

24352468
/* check the number of keys, and copy attr numbers into the IndexInfo */
24362469
numAtts = indexStruct->indnatts;
@@ -2454,9 +2487,19 @@ BuildIndexInfo(Relation index)
24542487
index->rd_indam->amsummarizing,
24552488
indexStruct->indisexclusion && indexStruct->indisunique);
24562489

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+
24572495
/* fill in attribute numbers */
24582496
for (i = 0; i < numAtts; i++)
2497+
{
24592498
ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
2499+
ii->ii_IndexAttrGeneratedNumbers[i] = indgenkey->values[i];
2500+
}
2501+
2502+
ReleaseSysCache(ht_idx);
24602503

24612504
/* fetch exclusion constraint info if any */
24622505
if (indexStruct->indisexclusion)
@@ -2523,6 +2566,23 @@ BuildDummyIndexInfo(Relation index)
25232566
return ii;
25242567
}
25252568

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+
25262586
/*
25272587
* CompareIndexInfo
25282588
* Return whether the properties of two indexes (in different tables)
@@ -2585,6 +2645,15 @@ CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2,
25852645
return false;
25862646
}
25872647

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+
25882657
/* collation and opfamily are not valid for included columns */
25892658
if (i >= info1->ii_NumIndexKeyAttrs)
25902659
continue;

0 commit comments

Comments
 (0)