Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit52ccd00

Browse files
alubennikovavbwagner
authored andcommitted
including_columns_2.0. Clear patch.
1 parent747aa24 commit52ccd00

File tree

17 files changed

+135
-110
lines changed

17 files changed

+135
-110
lines changed

‎doc/src/sgml/catalogs.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@
645645
</row>
646646

647647
<row>
648-
<entry><structfield>amcanincluding</structfield></entry>
648+
<entry><structfield>amcaninclude</structfield></entry>
649649
<entry><type>bool</type></entry>
650650
<entry></entry>
651651
<entry>Does the access method support included columns?</entry>

‎doc/src/sgml/indexam.sgml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -765,10 +765,10 @@ amrestrpos (IndexScanDesc scan);
765765
<para>
766766
<productname>&productname;</productname> enforces SQL uniqueness constraints
767767
using <firstterm>unique indexes</>, which are indexes that disallow
768-
multiple entries with identical keys. An access method that supports this
768+
multiple entries with identical keys.An access method that supports this
769769
feature sets <structname>pg_am</>.<structfield>amcanunique</> true.
770-
Columns included with clause INCLUDING aren't used to enforce uniqueness.
771-
(At present, only b-tree supports them.)
770+
(At present, only b-tree supports it.) Columns which are present in the
771+
<literal>INCLUDING</> clause are not used to enforce uniqueness.
772772
</para>
773773

774774
<para>

‎doc/src/sgml/indices.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,8 @@ CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</repla
644644
indexed values are not allowed. Null values are not considered
645645
equal. A multicolumn unique index will only reject cases where all
646646
indexed columns are equal in multiple rows. Columns included with clause
647-
<literal>INCLUDING</literal> aren't used to enforce constraints (UNIQUE, PRIMARY KEY, etc).
647+
<literal>INCLUDING</literal> aren't used to enforce constraints (UNIQUE,
648+
PRIMARY KEY, etc).
648649
</para>
649650

650651
<para>

‎doc/src/sgml/ref/create_index.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] <replaceable class=
157157
<literal>INCLUDING</> clause, on which the uniqueness is not enforced upon.
158158
It's the same with other constraints (PRIMARY KEY and EXCLUDE). This can
159159
also can be used for non-unique indexes as any columns which are not required
160-
for the searching or ordering of records candefined in the
160+
for the searching or ordering of records canbe included in the
161161
<literal>INCLUDING</> clause, which can slightly reduce the size of the index,
162162
due to storing included attributes only in leaf index pages.
163163
Currently, only the B-tree access method supports this feature.

‎src/backend/access/index/genam.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ BuildIndexValueDescription(Relation indexRelation,
175175
Form_pg_indexidxrec;
176176
HeapTupleht_idx;
177177
intnatts=indexRelation->rd_rel->relnatts;
178+
intnkeyatts;
178179
inti;
179180
intkeyno;
180181
Oidindexrelid=RelationGetRelid(indexRelation);
@@ -244,6 +245,7 @@ BuildIndexValueDescription(Relation indexRelation,
244245
appendStringInfo(&buf,"(%s)=(",
245246
pg_get_indexdef_columns(indexrelid, true));
246247

248+
nkeyatts=IndexRelationGetNumberOfKeyAttributes(indexRelation);
247249
for (i=0;i<natts;i++)
248250
{
249251
char*val;
@@ -254,20 +256,31 @@ BuildIndexValueDescription(Relation indexRelation,
254256
{
255257
Oidfoutoid;
256258
booltypisvarlena;
257-
259+
TupleDesctupdesc=RelationGetDescr(indexRelation);
258260
/*
259-
*Theprovided data is not necessarily of the type stored in the
260-
* index; rather it is of the index opclass's input type. So look
261-
* at rd_opcintype not the index tupdesc.
261+
*For key attributes theprovided data is not necessarily of the
262+
*type stored in theindex; rather it is of the index opclass's
263+
*input type. So lookat rd_opcintype not the index tupdesc.
262264
*
263265
* Note: this is a bit shaky for opclasses that have pseudotype
264266
* input types such as ANYARRAY or RECORD. Currently, the
265267
* typoutput functions associated with the pseudotypes will work
266268
* okay, but we might have to try harder in future.
269+
*
270+
* For included attributes just use info stored in the index
271+
* tupdesc.
267272
*/
268-
getTypeOutputInfo(indexRelation->rd_opcintype[i],
269-
&foutoid,&typisvarlena);
270-
val=OidOutputFunctionCall(foutoid,values[i]);
273+
if (i<nkeyatts)
274+
{
275+
getTypeOutputInfo(indexRelation->rd_opcintype[i],
276+
&foutoid,&typisvarlena);
277+
val=OidOutputFunctionCall(foutoid,values[i]);
278+
}
279+
else
280+
{
281+
getTypeOutputInfo(tupdesc->attrs[i]->atttypid,&foutoid,&typisvarlena);
282+
val=OidOutputFunctionCall(foutoid,values[i]);
283+
}
271284
}
272285

273286
if (i>0)

‎src/backend/access/nbtree/nbtinsert.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ bool
107107
_bt_doinsert(Relationrel,IndexTupleitup,
108108
IndexUniqueCheckcheckUnique,RelationheapRel)
109109
{
110-
boolis_unique;
110+
boolis_unique= false;
111111
intnkeyatts;
112112
ScanKeyitup_scankey;
113113
BTStackstack;
@@ -117,7 +117,6 @@ _bt_doinsert(Relation rel, IndexTuple itup,
117117
Assert(rel->rd_index->indnatts!=0);
118118
Assert(rel->rd_index->indnkeyatts!=0);
119119
nkeyatts=IndexRelationGetNumberOfKeyAttributes(rel);
120-
is_unique= false;
121120

122121
/* we need an insertion scan key to do our search, so build one */
123122
itup_scankey=_bt_mkscankey(rel,itup);
@@ -255,9 +254,6 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
255254
Buffernbuf=InvalidBuffer;
256255
boolfound= false;
257256

258-
Assert(rel->rd_index->indnatts!=0);
259-
Assert(rel->rd_index->indnkeyatts!=0);
260-
261257
/* Assume unique until we find a duplicate */
262258
*is_unique= true;
263259

@@ -1977,8 +1973,11 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
19771973
itemid=PageGetItemId(lpage,P_HIKEY);
19781974
right_item_sz=ItemIdGetLength(itemid);
19791975
item= (IndexTuple)PageGetItem(lpage,itemid);
1980-
right_item=CopyIndexTuple(item);
1981-
right_item=index_reform_tuple(rel,right_item,rel->rd_index->indnatts,rel->rd_index->indnkeyatts);
1976+
1977+
if (rel->rd_index->indnatts!=rel->rd_index->indnkeyatts)
1978+
right_item=index_reform_tuple(rel,item,rel->rd_index->indnatts,rel->rd_index->indnkeyatts);
1979+
else
1980+
right_item=CopyIndexTuple(item);
19821981
ItemPointerSet(&(right_item->t_tid),rbkno,P_HIKEY);
19831982

19841983
/* NO EREPORT(ERROR) from here till newroot op is logged */

‎src/backend/access/nbtree/nbtutils.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,16 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
6464
ScanKeyskey;
6565
TupleDescitupdesc;
6666
intnkeyatts;
67-
int16*indoption=rel->rd_indoption;
67+
int16*indoption;
6868
inti;
69+
6970
itupdesc=RelationGetDescr(rel);
71+
nkeyatts=rel->rd_index->indnkeyatts;
72+
indoption=rel->rd_indoption;
7073

7174
Assert(rel->rd_index->indnkeyatts!=0);
7275
Assert(rel->rd_index->indnkeyatts <=rel->rd_index->indnatts);
7376

74-
nkeyatts=rel->rd_index->indnkeyatts;
75-
7677
/*
7778
* We'll execute search using ScanKey constructed on key columns.
7879
* Non key (included) columns must be omitted.
@@ -121,16 +122,16 @@ ScanKey
121122
_bt_mkscankey_nodata(Relationrel)
122123
{
123124
ScanKeyskey;
124-
intnatts;
125+
intnkeyatts;
125126
int16*indoption;
126127
inti;
127128

128-
natts=RelationGetNumberOfAttributes(rel);
129+
nkeyatts=IndexRelationGetNumberOfKeyAttributes(rel);
129130
indoption=rel->rd_indoption;
130131

131-
skey= (ScanKey)palloc(natts*sizeof(ScanKeyData));
132+
skey= (ScanKey)palloc(nkeyatts*sizeof(ScanKeyData));
132133

133-
for (i=0;i<natts;i++)
134+
for (i=0;i<nkeyatts;i++)
134135
{
135136
FmgrInfo*procinfo;
136137
intflags;

‎src/backend/catalog/index.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,9 @@ ConstructTupleDescriptor(Relation heapRelation,
425425
namestrcpy(&to->attname, (constchar*)lfirst(colnames_item));
426426
colnames_item=lnext(colnames_item);
427427

428+
if (i >=indexInfo->ii_NumIndexKeyAttrs)
429+
continue;
430+
428431
/*
429432
* Check the opclass and index AM to see if either provides a keytype
430433
* (overriding the attribute type). Opclass takes precedence.
@@ -1012,7 +1015,7 @@ index_create(Relation heapRelation,
10121015
}
10131016

10141017
/* Store dependency on operator classes */
1015-
for (i=0;i<indexInfo->ii_NumIndexAttrs;i++)
1018+
for (i=0;i<indexInfo->ii_NumIndexKeyAttrs;i++)
10161019
{
10171020
referenced.classId=OperatorClassRelationId;
10181021
referenced.objectId=classObjectId[i];
@@ -1632,19 +1635,19 @@ BuildIndexInfo(Relation index)
16321635
IndexInfo*ii=makeNode(IndexInfo);
16331636
Form_pg_indexindexStruct=index->rd_index;
16341637
inti;
1635-
intnumKeys;
1638+
intnumAtts;
16361639

16371640
/* check the number of keys, and copy attr numbers into the IndexInfo */
1638-
numKeys=indexStruct->indnatts;
1639-
if (numKeys<1||numKeys>INDEX_MAX_KEYS)
1641+
numAtts=indexStruct->indnatts;
1642+
if (numAtts<1||numAtts>INDEX_MAX_KEYS)
16401643
elog(ERROR,"invalid indnatts %d for index %u",
1641-
numKeys,RelationGetRelid(index));
1642-
ii->ii_NumIndexAttrs=numKeys;
1644+
numAtts,RelationGetRelid(index));
1645+
ii->ii_NumIndexAttrs=numAtts;
16431646
ii->ii_NumIndexKeyAttrs=indexStruct->indnkeyatts;
16441647
Assert(ii->ii_NumIndexKeyAttrs!=0);
16451648
Assert(ii->ii_NumIndexKeyAttrs <=ii->ii_NumIndexAttrs);
16461649

1647-
for (i=0;i<numKeys;i++)
1650+
for (i=0;i<numAtts;i++)
16481651
ii->ii_KeyAttrNumbers[i]=indexStruct->indkey.values[i];
16491652

16501653
/* fetch any expressions needed for expressional indexes */
@@ -1700,9 +1703,11 @@ BuildIndexInfo(Relation index)
17001703
void
17011704
BuildSpeculativeIndexInfo(Relationindex,IndexInfo*ii)
17021705
{
1703-
intncols=index->rd_rel->relnatts;
1706+
intnkeycols;
17041707
inti;
17051708

1709+
nkeycols=IndexRelationGetNumberOfKeyAttributes(index);
1710+
17061711
/*
17071712
* fetch info for checking unique indexes
17081713
*/
@@ -1711,16 +1716,16 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
17111716
if (index->rd_rel->relam!=BTREE_AM_OID)
17121717
elog(ERROR,"unexpected non-btree speculative unique index");
17131718

1714-
ii->ii_UniqueOps= (Oid*)palloc(sizeof(Oid)*ncols);
1715-
ii->ii_UniqueProcs= (Oid*)palloc(sizeof(Oid)*ncols);
1716-
ii->ii_UniqueStrats= (uint16*)palloc(sizeof(uint16)*ncols);
1719+
ii->ii_UniqueOps= (Oid*)palloc(sizeof(Oid)*nkeycols);
1720+
ii->ii_UniqueProcs= (Oid*)palloc(sizeof(Oid)*nkeycols);
1721+
ii->ii_UniqueStrats= (uint16*)palloc(sizeof(uint16)*nkeycols);
17171722

17181723
/*
17191724
* We have to look up the operator's strategy number. This provides a
17201725
* cross-check that the operator does match the index.
17211726
*/
17221727
/* We need the func OIDs and strategy numbers too */
1723-
for (i=0;i<ncols;i++)
1728+
for (i=0;i<nkeycols;i++)
17241729
{
17251730
ii->ii_UniqueStrats[i]=BTEqualStrategyNumber;
17261731
ii->ii_UniqueOps[i]=

‎src/backend/commands/indexcmds.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,8 @@ DefineIndex(Oid relationId,
320320
Datumreloptions;
321321
int16*coloptions;
322322
IndexInfo*indexInfo;
323-
intnumberOfAttributes,
324-
numberOfKeyAttributes;
323+
intnumberOfAttributes;
324+
intnumberOfKeyAttributes;
325325
TransactionIdlimitXmin;
326326
VirtualTransactionId*old_snapshots;
327327
ObjectAddressaddress;
@@ -336,7 +336,6 @@ DefineIndex(Oid relationId,
336336
ereport(ERROR,
337337
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
338338
errmsg("included columns must not intersect with key columns")));
339-
340339
/*
341340
* count attributes in index
342341
*/
@@ -351,7 +350,7 @@ DefineIndex(Oid relationId,
351350
* we have one list with all columns. Later we can determine which of these
352351
* are key columns, and which are just part of the INCLUDING list by check the list
353352
* position. A list item in a position less than ii_NumIndexKeyAttrs is part of
354-
* theindexed columns, and anything equal to and over is part of the
353+
* thekey columns, and anything equal to and over is part of the
355354
* INCLUDING columns.
356355
*/
357356
stmt->indexParams=list_concat(stmt->indexParams,stmt->indexIncludingParams);
@@ -488,7 +487,6 @@ DefineIndex(Oid relationId,
488487
* look up the access method, verify it can handle the requested features
489488
*/
490489
accessMethodName=stmt->accessMethod;
491-
492490
tuple=SearchSysCache1(AMNAME,PointerGetDatum(accessMethodName));
493491
if (!HeapTupleIsValid(tuple))
494492
{
@@ -523,6 +521,11 @@ DefineIndex(Oid relationId,
523521
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
524522
errmsg("access method \"%s\" does not support unique indexes",
525523
accessMethodName)));
524+
if (list_length(stmt->indexIncludingParams)>0&& !accessMethodForm->amcaninclude)
525+
ereport(ERROR,
526+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
527+
errmsg("access method \"%s\" does not support included columns",
528+
accessMethodName)));
526529
if (numberOfAttributes>1&& !accessMethodForm->amcanmulticol)
527530
ereport(ERROR,
528531
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -534,12 +537,6 @@ DefineIndex(Oid relationId,
534537
errmsg("access method \"%s\" does not support exclusion constraints",
535538
accessMethodName)));
536539

537-
if (list_length(stmt->indexIncludingParams)>0&& !accessMethodForm->amcanincluding)
538-
ereport(ERROR,
539-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
540-
errmsg("access method \"%s\" does not support included columns",
541-
accessMethodName)));
542-
543540
amcanorder=accessMethodForm->amcanorder;
544541
amoptions=accessMethodForm->amoptions;
545542

@@ -988,16 +985,15 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
988985
ListCell*nextExclOp;
989986
ListCell*lc;
990987
intattn;
988+
intnkeycols=indexInfo->ii_NumIndexKeyAttrs;
991989

992990
/* Allocate space for exclusion operator info, if needed */
993991
if (exclusionOpNames)
994992
{
995-
intncols=list_length(attList);
996-
997-
Assert(list_length(exclusionOpNames)==ncols);
998-
indexInfo->ii_ExclusionOps= (Oid*)palloc(sizeof(Oid)*ncols);
999-
indexInfo->ii_ExclusionProcs= (Oid*)palloc(sizeof(Oid)*ncols);
1000-
indexInfo->ii_ExclusionStrats= (uint16*)palloc(sizeof(uint16)*ncols);
993+
Assert(list_length(exclusionOpNames)==nkeycols);
994+
indexInfo->ii_ExclusionOps= (Oid*)palloc(sizeof(Oid)*nkeycols);
995+
indexInfo->ii_ExclusionProcs= (Oid*)palloc(sizeof(Oid)*nkeycols);
996+
indexInfo->ii_ExclusionStrats= (uint16*)palloc(sizeof(uint16)*nkeycols);
1001997
nextExclOp=list_head(exclusionOpNames);
1002998
}
1003999
else
@@ -1050,6 +1046,11 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
10501046
Node*expr=attribute->expr;
10511047

10521048
Assert(expr!=NULL);
1049+
1050+
if (attn >=nkeycols)
1051+
ereport(ERROR,
1052+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1053+
errmsg("Expressions in INCLUDING clause are not supported")));
10531054
atttype=exprType(expr);
10541055
attcollation=exprCollation(expr);
10551056

@@ -1130,6 +1131,11 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
11301131
/*
11311132
* Identify the opclass to use.
11321133
*/
1134+
if (attn >=nkeycols)
1135+
{
1136+
attn++;
1137+
continue;
1138+
}
11331139
classOidP[attn]=GetIndexOpClass(attribute->opclass,
11341140
atttype,
11351141
accessMethodName,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp