diff --git a/doc/src/sgml/ref/create_index.sgmlin b/doc/src/sgml/ref/create_index.sgmlin index e023227c1..9ff7b1fa5 100644 --- a/doc/src/sgml/ref/create_index.sgmlin +++ b/doc/src/sgml/ref/create_index.sgmlin @@ -17,7 +17,7 @@ CREATE [ UNIQUE ] INDEX [ [schema_name.] index_name ] ON table_name [ USING meth [ WHERE predicate ]; CREATE [ UNIQUE ] INDEX [ [schema_name.] index_name ] ON table_name [ USING method ] ( {{ column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS LAST ] }[, ...] ) -LOCAL [ ( { PARTITION index_partition_name [ TABLESPACE index_partition_tablespace ] } [, ...] ) ] +[ LOCAL [ ( { PARTITION index_partition_name [ TABLESPACE index_partition_tablespace ] } [, ...] ) ] | GLOBAL ] [ WITH ( { storage_parameter = value } [, ...] ) ] [ TABLESPACE tablespace_name ]; diff --git a/src/bin/psql/describe.cpp b/src/bin/psql/describe.cpp index aafe3109a..2b6060b4b 100755 --- a/src/bin/psql/describe.cpp +++ b/src/bin/psql/describe.cpp @@ -3042,7 +3042,7 @@ bool listTables(const char* tabtypes, const char* pattern, bool verbose, bool sh gettext_noop("view"), gettext_noop("materialized view"), gettext_noop("index"), - gettext_noop("index"), + gettext_noop("global partition index"), gettext_noop("sequence"), gettext_noop("special"), gettext_noop("foreign table"), diff --git a/src/common/backend/catalog/heap.cpp b/src/common/backend/catalog/heap.cpp index 463248791..95c700468 100755 --- a/src/common/backend/catalog/heap.cpp +++ b/src/common/backend/catalog/heap.cpp @@ -2970,8 +2970,8 @@ static void StoreRelCheck( is_validated, RelationGetRelid(rel), /* relation */ attNos, /* attrs in the constraint */ - keycount, /* # key attrs in the constraint */ - keycount, /* # total attrs in the constraint */ + keycount, /* # key attrs in the constraint */ + keycount, /* # total attrs in the constraint */ InvalidOid, /* not a domain constraint */ InvalidOid, /* no associated index */ InvalidOid, /* Foreign key fields */ @@ -5513,11 +5513,9 @@ void heap_truncate_one_part(Relation rel, Oid partOid) parentIndId = (((Form_pg_partition)GETSTRUCT(partIndexTuple)))->parentid; partIndId = HeapTupleGetOid(partIndexTuple); parentIndex = index_open(parentIndId, AccessShareLock); - if (!RelationIsGlobalIndex(parentIndex)) { - indexPart = partitionOpen(parentIndex, partIndId, AccessExclusiveLock); - reindex_partIndex(rel, p, parentIndex, indexPart); - partitionClose(parentIndex, indexPart, NoLock); - } + indexPart = partitionOpen(parentIndex, partIndId, AccessExclusiveLock); + reindex_partIndex(rel, p, parentIndex, indexPart); + partitionClose(parentIndex, indexPart, NoLock); index_close(parentIndex, NoLock); } } @@ -5883,8 +5881,8 @@ List* AddRelClusterConstraints(Relation rel, List* clusterKeys) true, /* Is Validated */ RelationGetRelid(rel), /* relation */ attNums, /* attrs in the constraint */ - colNum, /* # attrs in the constraint */ - colNum, /* # attrs in the constraint */ + colNum, /* # key attrs in the constraint */ + colNum, /* total # attrs (include attrs and key attrs) in the constraint */ InvalidOid, /* not a domain constraint */ InvalidOid, /* no associated index */ InvalidOid, /* Foreign key fields */ @@ -6130,3 +6128,25 @@ static void LockSeqConstraints(Relation rel, List* Constraints) return; } + +/* Get index's indnkeyatts value with indexTuple */ +int GetIndexKeyAttsByTuple(Relation relation, HeapTuple indexTuple) +{ + bool isnull = false; + Datum indkeyDatum; + TupleDesc tupleDesc = RelationIsValid(relation) ? RelationGetDescr(relation) : GetDefaultPgIndexDesc(); + Form_pg_index index = (Form_pg_index)GETSTRUCT(indexTuple); + + /* + * This scenario will only occur after the upgrade, This scenario means that + * the indnatts and Indnkeyatts of all current indexes are equal + */ + if (heap_attisnull(indexTuple, Anum_pg_index_indnkeyatts, NULL)) { + return index->indnatts; + } + + indkeyDatum = fastgetattr(indexTuple, Anum_pg_index_indnkeyatts, tupleDesc, &isnull); + Assert(!isnull); + + return DatumGetInt16(indkeyDatum); +} diff --git a/src/common/backend/catalog/index.cpp b/src/common/backend/catalog/index.cpp index 6e2e829b4..9a4f922ae 100755 --- a/src/common/backend/catalog/index.cpp +++ b/src/common/backend/catalog/index.cpp @@ -426,8 +426,9 @@ static TupleDesc ConstructTupleDescriptor(Relation heapRelation, IndexInfo* inde errmsg("cache lookup failed for opclass %u", classObjectId[i]))); } opclassTup = (Form_pg_opclass)GETSTRUCT(tuple); - if (OidIsValid(opclassTup->opckeytype)) + if (OidIsValid(opclassTup->opckeytype)) { keyType = opclassTup->opckeytype; + } /* * If keytype is specified as ANYELEMENT, and opcintype is @@ -593,7 +594,6 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid, IndexInfo* indexInfo, values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid); values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid); values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs); - values[Anum_pg_index_indnkeyatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs); values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique); values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary); values[Anum_pg_index_indisexclusion - 1] = BoolGetDatum(isexclusion); @@ -616,6 +616,7 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid, IndexInfo* indexInfo, nulls[Anum_pg_index_indpred - 1] = true; values[Anum_pg_index_indisreplident - 1] = BoolGetDatum(false); + values[Anum_pg_index_indnkeyatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs); tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls); /* @@ -859,9 +860,18 @@ Oid index_create(Relation heapRelation, const char* indexRelationName, Oid index } char relKind = RELKIND_INDEX; + bool isLocalPart = false; + if (extra->isGlobalPartitionedIndex) { relKind = RELKIND_GLOBAL_INDEX; } + /* + * for normal relation index and global partition index, isLocalPart should be false. + * more description refers to defination of IndexCreateExtraArgs; + */ + if (extra->isPartitionedIndex && !extra->isGlobalPartitionedIndex) { + isLocalPart = true; + } /* * create the index relation's relcache entry and physical disk file. (If * we fail further down, it's the smgr's responsibility to remove the disk @@ -876,7 +886,7 @@ Oid index_create(Relation heapRelation, const char* indexRelationName, Oid index indexTupDesc, relKind, relpersistence, - extra->isPartitionedIndex != extra->isGlobalPartitionedIndex ? true : false, + isLocalPart, false, shared_relation, mapped_relation, @@ -1118,7 +1128,7 @@ Oid index_create(Relation heapRelation, const char* indexRelationName, Oid index else Assert(indexRelation->rd_indexcxt != NULL); - indexRelation->rd_index->indnkeyatts = (int2)indexInfo->ii_NumIndexKeyAttrs; + indexRelation->rd_indnkeyatts = indexInfo->ii_NumIndexKeyAttrs; /* * If this is bootstrap (initdb) time, then we don't actually fill in the * index yet. We'll be creating more indexes and classes later, so we @@ -1830,31 +1840,29 @@ void index_drop(Oid indexId, bool concurrent) */ IndexInfo* BuildIndexInfo(Relation index) { - IndexInfo* ii; Form_pg_index indexStruct = index->rd_index; - int i; - int numAtts; - ii = makeIndexInfo(indexStruct->indnatts, - RelationGetIndexExpressions(index), - RelationGetIndexPredicate(index), - indexStruct->indisunique, - IndexIsReady(indexStruct), - false); + IndexInfo* ii = makeIndexInfo(indexStruct->indnatts, + RelationGetIndexExpressions(index), + RelationGetIndexPredicate(index), + indexStruct->indisunique, + IndexIsReady(indexStruct), + false); /* check the number of keys, and copy attr numbers into the IndexInfo */ - numAtts = indexStruct->indnatts; - if (numAtts < 1 || numAtts > INDEX_MAX_KEYS) + int numAtts = indexStruct->indnatts; + if (numAtts < 1 || numAtts > INDEX_MAX_KEYS) { ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("invalid indnatts %d for index %u", numAtts, RelationGetRelid(index)))); + } ii->ii_NumIndexAttrs = numAtts; - ii->ii_NumIndexKeyAttrs = indexStruct->indnkeyatts; + ii->ii_NumIndexKeyAttrs = IndexRelationGetNumberOfKeyAttributes(index); Assert(ii->ii_NumIndexKeyAttrs != 0); Assert(ii->ii_NumIndexKeyAttrs <= ii->ii_NumIndexAttrs); /* fill in attribute numbers */ - for (i = 0; i < numAtts; i++) { + for (int i = 0; i < numAtts; i++) { ii->ii_KeyAttrNumbers[i] = indexStruct->indkey.values[i]; } /* fetch exclusion constraint info if any */ @@ -2156,10 +2164,11 @@ void index_update_stats( BlockNumber relpages = RelationGetNumberOfBlocks(rel); BlockNumber relallvisible; - if (rd_rel->relkind != RELKIND_INDEX && rd_rel->relkind != RELKIND_GLOBAL_INDEX) + if (rd_rel->relkind != RELKIND_INDEX && rd_rel->relkind != RELKIND_GLOBAL_INDEX) { relallvisible = visibilitymap_count(rel, NULL); - else /* don't bother for indexes */ + } else { /* don't bother for indexes */ relallvisible = 0; + } if (is_gtt) { rel->rd_rel->relpages = static_cast(relpages); @@ -2395,39 +2404,39 @@ static IndexBuildResult* index_build_storage_for_bucket(Relation heapRelation, R stats->index_tuples += results->index_tuples; stats->heap_tuples += results->heap_tuples; - pfree(results); + pfree_ext(results); } return stats; } void UpdateStatsForGlobalIndex( - Relation heapRelation, Relation indexRelation, IndexBuildResult* stats, bool isprimary, Oid cudesc_idx_oid) + Relation heapRelation, Relation indexRelation, IndexBuildResult* stats, bool isPrimary, Oid cudescIdxOid) { - ListCell* partitioncell = NULL; - Oid partitionid; + ListCell* partitionCell = NULL; + Oid partitionOid; Partition partition = NULL; - List* partitionidlist = NIL; - partitionidlist = relationGetPartitionOidList(heapRelation); - int partitionidx = 0; + List* partitionOidList = NIL; + partitionOidList = relationGetPartitionOidList(heapRelation); + int partitionIdx = 0; - Assert(PointerIsValid(stats->global_index_tuples)); + Assert(PointerIsValid(stats->all_part_tuples)); - foreach (partitioncell, partitionidlist) { - partitionid = lfirst_oid(partitioncell); - partition = partitionOpen(heapRelation, partitionid, ShareLock); + foreach (partitionCell, partitionOidList) { + partitionOid = lfirst_oid(partitionCell); + partition = partitionOpen(heapRelation, partitionOid, ShareLock); partition_index_update_stats(partition, true, - isprimary, + isPrimary, (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ? RelationGetRelid(indexRelation) : InvalidOid, - cudesc_idx_oid, - stats->global_index_tuples[partitionidx]); + cudescIdxOid, + stats->all_part_tuples[partitionIdx]); partitionClose(heapRelation, partition, NoLock); - partitionidx++; + partitionIdx++; } - + releasePartitionOidList(&partitionOidList); index_update_stats(heapRelation, true, - isprimary, + isPrimary, (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ? RelationGetRelid(indexRelation) : InvalidOid, InvalidOid, -1); @@ -2444,10 +2453,10 @@ void UpdateStatsForGlobalIndex( * entries of the index and heap relation as needed, using statistics * returned by ambuild as well as data passed by the caller. * - * isprimary tells whether to mark the index as a primary-key index. + * isPrimary tells whether to mark the index as a primary-key index. * isreindex indicates we are recreating a previously-existing index. * - * Note: when reindexing an existing index, isprimary can be false even if + * Note: when reindexing an existing index, isPrimary can be false even if * the index is a PK; it's already properly marked and need not be re-marked. * * Note: before Postgres 8.2, the passed-in heap and index Relations @@ -2455,7 +2464,7 @@ void UpdateStatsForGlobalIndex( * The caller opened 'em, and the caller should close 'em. */ void index_build(Relation heapRelation, Partition heapPartition, Relation indexRelation, Partition indexPartition, - IndexInfo* indexInfo, bool isprimary, bool isreindex, IndexCreatePartitionType partitionType) + IndexInfo* indexInfo, bool isPrimary, bool isreindex, IndexCreatePartitionType partitionType) { RegProcedure procedure; double indextuples; @@ -2544,7 +2553,7 @@ void index_build(Relation heapRelation, Partition heapPartition, Relation indexR (partitionType != INDEX_CREATE_NONE_PARTITION && RELATION_OWN_BUCKETKEY(heapRelation)); IndexBuildResult* stats = NULL; - if (hasbucket == true) { + if (hasbucket) { stats = index_build_storage_for_bucket(heapRelation, indexRelation, heapPartition, @@ -2605,10 +2614,10 @@ void index_build(Relation heapRelation, Partition heapPartition, Relation indexR heap_close(pg_index, RowExclusiveLock); } - Oid cudesc_idx_oid = InvalidOid; + Oid cudescIdxOid = InvalidOid; switch (indexInfo->ii_PgClassAttrId) { case Anum_pg_class_relcudescidx: { - cudesc_idx_oid = RelationGetRelid(indexRelation); + cudescIdxOid = RelationGetRelid(indexRelation); break; } default: @@ -2621,9 +2630,9 @@ void index_build(Relation heapRelation, Partition heapPartition, Relation indexR if (partitionType == INDEX_CREATE_NONE_PARTITION) { index_update_stats(heapRelation, true, - isprimary, + isPrimary, (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ? RelationGetRelid(indexRelation) : InvalidOid, - cudesc_idx_oid, + cudescIdxOid, heaptuples); index_update_stats(indexRelation, false, false, InvalidOid, InvalidOid, indextuples); @@ -2634,15 +2643,15 @@ void index_build(Relation heapRelation, Partition heapPartition, Relation indexR */ partition_index_update_stats(heapPartition, true, - isprimary, + isPrimary, (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ? RelationGetRelid(indexRelation) : InvalidOid, - cudesc_idx_oid, + cudescIdxOid, heaptuples); - partition_index_update_stats(indexPartition, false, false, InvalidOid, cudesc_idx_oid, indextuples); + partition_index_update_stats(indexPartition, false, false, InvalidOid, cudescIdxOid, indextuples); } else if (partitionType == INDEX_CREATE_GLOBAL_PARTITION) { - UpdateStatsForGlobalIndex(heapRelation, indexRelation, stats, isprimary, cudesc_idx_oid); - pfree(stats->global_index_tuples); + UpdateStatsForGlobalIndex(heapRelation, indexRelation, stats, isPrimary, cudescIdxOid); + pfree(stats->all_part_tuples); } pfree(stats); @@ -3085,6 +3094,7 @@ double* GlobalIndexBuildHeapScan(Relation heapRelation, Relation indexRelation, partitionClose(heapRelation, partition, NoLock); partitionIdx++; } + releasePartitionOidList(&partitionIdList); return globalIndexTuples; } @@ -4467,10 +4477,6 @@ bool reindexPartition(Oid relid, Oid partOid, int flags, int reindexType) foreach (indexId, indexIds) { Oid indexOid = lfirst_oid(indexId); Relation indexRel = index_open(indexOid, AccessShareLock); - if (RelationIsGlobalIndex(indexRel)) { - index_close(indexRel, AccessShareLock); - continue; - } if ((((uint32)reindexType) & REINDEX_ALL_INDEX) || ((((uint32)reindexType) & REINDEX_BTREE_INDEX) && (indexRel->rd_rel->relam == BTREE_AM_OID)) || @@ -4885,8 +4891,8 @@ Oid psort_create(const char* indexRelationName, Relation indexRelation, Oid tabl true, /* Is Validated */ psortRelationId, /* relation */ attrNums, /* attrs in the constraint */ - natts, /* # attrs in the constraint */ - natts, /* # attrs in the constraint */ + natts, /* # key attrs in the constraint */ + natts, /* total # attrs (include attrs and key attrs) in the constraint */ InvalidOid, /* not a domain constraint */ InvalidOid, /* no associated index */ InvalidOid, /* Foreign key fields */ @@ -5110,10 +5116,7 @@ static Oid bupgrade_get_next_psort_array_pg_type_oid() } /* - * Parameter isPartitionedIndex indicates whether the index is a partition index. - * Parameter isGlobalPartitionedIndex indicates whether the index is a global partition index. - * - * Notes: isGlobalPartitionedIndex as means isPartitionedIndex is true. + * set IndexCreateExtraArgs, more info refer to defination of IndexCreateExtraArgs */ void SetIndexCreateExtraArgs(IndexCreateExtraArgs* extra, Oid psortOid, bool isPartition, bool isGlobal) { diff --git a/src/common/backend/catalog/pg_constraint.cpp b/src/common/backend/catalog/pg_constraint.cpp index 492230518..27af27d2a 100755 --- a/src/common/backend/catalog/pg_constraint.cpp +++ b/src/common/backend/catalog/pg_constraint.cpp @@ -85,15 +85,17 @@ Oid CreateConstraintEntry(const char* constraintName, Oid constraintNamespace, c conkeyArray = NULL; } + // index attrs have key attrs and include attrs, the num of include attrs maybe 0 if (constraintNTotalKeys > constraintNKeys) { - Datum* conincluding; int j = 0; int constraintNIncludedKeys = constraintNTotalKeys - constraintNKeys; - conincluding = (Datum*)palloc(constraintNIncludedKeys * sizeof(Datum)); - for (i = constraintNKeys; i < constraintNTotalKeys; i++) + Datum* conincluding = (Datum*)palloc(constraintNIncludedKeys * sizeof(Datum)); + for (i = constraintNKeys; i < constraintNTotalKeys; i++) { conincluding[j++] = Int16GetDatum(constraintKey[i]); + } conincludingArray = construct_array(conincluding, constraintNIncludedKeys, INT2OID, 2, true, 's'); + pfree_ext(conincluding); } else { conincludingArray = NULL; } @@ -167,10 +169,11 @@ Oid CreateConstraintEntry(const char* constraintName, Oid constraintNamespace, c else nulls[Anum_pg_constraint_conkey - 1] = true; - if (conincludingArray) + if (conincludingArray) { values[Anum_pg_constraint_conincluding - 1] = PointerGetDatum(conincludingArray); - else + } else { nulls[Anum_pg_constraint_conincluding - 1] = true; + } if (confkeyArray != NULL) values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray); diff --git a/src/common/backend/nodes/readfuncs.cpp b/src/common/backend/nodes/readfuncs.cpp index 26493109e..44b614579 100644 --- a/src/common/backend/nodes/readfuncs.cpp +++ b/src/common/backend/nodes/readfuncs.cpp @@ -4619,6 +4619,7 @@ static IndexStmt* _readIndexStmt() READ_STRING_FIELD(accessMethod); READ_STRING_FIELD(tableSpace); READ_NODE_FIELD(indexParams); + READ_NODE_FIELD(indexIncludingParams); READ_NODE_FIELD(options); READ_NODE_FIELD(whereClause); READ_NODE_FIELD(excludeOpNames); diff --git a/src/common/backend/parser/parse_utilcmd.cpp b/src/common/backend/parser/parse_utilcmd.cpp index e3ee1d1cf..9b3dd39c8 100644 --- a/src/common/backend/parser/parse_utilcmd.cpp +++ b/src/common/backend/parser/parse_utilcmd.cpp @@ -1996,6 +1996,7 @@ static IndexStmt* generateClonedIndexStmt( Datum datum; bool isnull = false; bool isResize = false; + int indnkeyatts; /* * Fetch pg_class tuple of source index. We can't use the copy in the @@ -2011,6 +2012,7 @@ static IndexStmt* generateClonedIndexStmt( htIdx = source_idx->rd_indextuple; idxrec = (Form_pg_index)GETSTRUCT(htIdx); indrelid = idxrec->indrelid; + indnkeyatts = IndexRelationGetNumberOfKeyAttributes(source_idx); /* Fetch pg_am tuple for source index from relcache entry */ amrec = source_idx->rd_am; @@ -2152,7 +2154,7 @@ static IndexStmt* generateClonedIndexStmt( index->indexIncludingParams = NIL; indexprItem = list_head(indexprs); - for (keyno = 0; keyno < idxrec->indnkeyatts; keyno++) { + for (keyno = 0; keyno < indnkeyatts; keyno++) { IndexElem* iparam = NULL; AttrNumber attnum = idxrec->indkey.values[keyno]; uint16 opt = (uint16)source_idx->rd_indoption[keyno]; @@ -2242,7 +2244,7 @@ static IndexStmt* generateClonedIndexStmt( } /* Handle included columns separately */ - if (idxrec->indnkeyatts != idxrec->indnatts) { + if (indnkeyatts != idxrec->indnatts) { /* Only global-partition-index would satisfy this condition in the current code */ index->isGlobal = true; } @@ -2678,6 +2680,7 @@ static IndexStmt* transformIndexConstraint(Constraint* constraint, CreateStmtCon Datum indclassDatum; bool isnull = true; int i; + int indnkeyatts; /* Grammar should not allow this with explicit column list */ AssertEreport(constraint->keys == NIL, MOD_OPT, ""); @@ -2703,6 +2706,7 @@ static IndexStmt* transformIndexConstraint(Constraint* constraint, CreateStmtCon /* Open the index (this will throw an error if it is not an index) */ indexRel = index_open(indexOid, AccessShareLock); indexForm = indexRel->rd_index; + indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRel); /* check the conditons for this function, * and verify the index is usable @@ -2733,7 +2737,7 @@ static IndexStmt* transformIndexConstraint(Constraint* constraint, CreateStmtCon RELATION_HAS_BUCKET(heapRel)); attname = pstrdup(NameStr(attform->attname)); - if (i < indexForm->indnkeyatts) { + if (i < indnkeyatts) { /* * Insist on default opclass and sort options. While the * index would still work as a constraint with non-default @@ -2948,11 +2952,11 @@ static IndexStmt* transformIndexConstraint(Constraint* constraint, CreateStmtCon rel = heap_openrv(inh, AccessShareLock); /* check user requested inheritance from valid relkind */ - if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE && - rel->rd_rel->relkind != PARTTYPE_PARTITIONED_RELATION) + if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE) { ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("inherited relation \"%s\" is not a table or foreign table", inh->relname))); + } for (count = 0; count < rel->rd_att->natts; count++) { Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att, count); char* inhname = NameStr(inhattr->attname); diff --git a/src/common/backend/utils/adt/ruleutils.cpp b/src/common/backend/utils/adt/ruleutils.cpp index de8925675..7d23b9ebd 100755 --- a/src/common/backend/utils/adt/ruleutils.cpp +++ b/src/common/backend/utils/adt/ruleutils.cpp @@ -45,6 +45,7 @@ #include "catalog/pg_synonym.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type.h" +#include "catalog/heap.h" #include "commands/comment.h" #include "commands/defrem.h" #include "commands/tablespace.h" @@ -2225,6 +2226,7 @@ static char* pg_get_indexdef_worker( StringInfoData buf; char* str = NULL; char* sep = NULL; + int indnkeyatts; /* * Fetch the pg_index tuple by the Oid of the index @@ -2237,6 +2239,7 @@ static char* pg_get_indexdef_worker( indrelid = idxrec->indrelid; Assert(indexrelid == idxrec->indexrelid); + indnkeyatts = GetIndexKeyAttsByTuple(NULL, ht_idx); /* Must get indcollation, indclass, and indoption the hard way */ indcoll_datum = SysCacheGetAttr(INDEXRELID, ht_idx, Anum_pg_index_indcollation, &isnull); @@ -2326,9 +2329,9 @@ static char* pg_get_indexdef_worker( /* * Ignore non-key attributes if told to. */ - if (keyno >= idxrec->indnkeyatts) + if (keyno >= indnkeyatts) { break; - + } if (!colno) { appendStringInfoString(&buf, sep); } @@ -2370,7 +2373,7 @@ static char* pg_get_indexdef_worker( if (!attrs_only && (!colno || colno == keyno + 1)) { Oid indcoll; - if (keyno >= idxrec->indnkeyatts) { + if (keyno >= indnkeyatts) { continue; } @@ -2670,9 +2673,7 @@ static char* pg_get_constraintdef_worker(Oid constraint_id, bool full_command, i val = SysCacheGetAttr(CONSTROID, tup, Anum_pg_constraint_conincluding, &isnull); if (!isnull) { appendStringInfoString(&buf, " INCLUDE ("); - decompile_column_index_array(val, con_form->conrelid, &buf); - appendStringInfoChar(&buf, ')'); } diff --git a/src/common/backend/utils/adt/selfuncs.cpp b/src/common/backend/utils/adt/selfuncs.cpp index b48e05a1d..57d0261f9 100644 --- a/src/common/backend/utils/adt/selfuncs.cpp +++ b/src/common/backend/utils/adt/selfuncs.cpp @@ -7198,7 +7198,6 @@ static bool gincost_pattern(IndexOptInfo* index, int indexcol, Oid clause_op, Da int32 search_mode = GIN_SEARCH_MODE_DEFAULT; int32 i; - Assert(indexcol < index->nkeycolumns); /* * Get the operator's strategy number and declared input data types within * the index opfamily. (We don't need the latter, but we use diff --git a/src/common/backend/utils/cache/partcache.cpp b/src/common/backend/utils/cache/partcache.cpp index 7275bb056..1484067d4 100755 --- a/src/common/backend/utils/cache/partcache.cpp +++ b/src/common/backend/utils/cache/partcache.cpp @@ -1189,16 +1189,17 @@ Relation partitionGetRelation(Relation rel, Partition part) relation->rd_rel->relcudescidx = part->pd_part->relcudescidx; relation->rd_rel->reldeltarelid = part->pd_part->reldeltarelid; relation->rd_rel->reldeltaidx = part->pd_part->reldeltaidx; - relation->rd_bucketoid = rel->rd_bucketoid; + relation->rd_bucketoid = rel->rd_bucketoid; if (REALTION_BUCKETKEY_INITED(rel)) relation->rd_bucketkey = rel->rd_bucketkey; else relation->rd_bucketkey = NULL; relation->rd_att = rel->rd_att; - relation->rd_partHeapOid = part->pd_part->indextblid; + relation->rd_partHeapOid = part->pd_part->indextblid; relation->rd_index = rel->rd_index; relation->rd_indextuple = rel->rd_indextuple; relation->rd_am = rel->rd_am; + relation->rd_indnkeyatts = rel->rd_indnkeyatts; if (!OidIsValid(rel->rd_rel->relam)) { relation->rd_indexcxt = NULL; @@ -1541,7 +1542,7 @@ static bool PartitionStatusIsLive(Oid partOid, Bitmapset** liveParts) return false; } -/* Check one invisible partition whether enable clean, and save in Bitmapset enableCleanParts */ +/* Check one invisible partition whether enable clean */ static bool InvisblePartEnableClean(HeapTuple partTuple, TupleDesc tupleDesc) { Datum partOptions; @@ -1555,7 +1556,7 @@ static bool InvisblePartEnableClean(HeapTuple partTuple, TupleDesc tupleDesc) return false; } -/* Just for lazy vacuum check one partition's status */ +/* Just for lazy vacuum get one partition's status */ static PartStatus PartTupleStatusForVacuum(HeapTuple partTuple, Buffer buffer, TransactionId oldestXmin) { PartStatus partStatus = PART_METADATA_NOEXIST; @@ -1671,7 +1672,7 @@ PartStatus PartitionGetMetadataStatus(Oid partOid, bool vacuumFlag) return PART_METADATA_NOEXIST; } -/* Set reloptions walt_clean_gpi, Just for pg_partition's tuple */ +/* Set reloptions wait_clean_gpi, Just for pg_partition's tuple */ Datum SetWaitCleanGpiRelOptions(Datum oldOptions, bool enable) { Datum newOptions; @@ -1972,7 +1973,7 @@ void PartitionGetAllInvisibleParts(Oid parentOid, Bitmapset** invisibleParts) /* * Check whether contain a tuple in pg_partition, which includes - * wait_clean_gpi=y in the reloPTIONS of the tuple + * wait_clean_gpi=y in the reloptions of the tuple * * Notes: this function is called only when vacuum full pg_partition */ diff --git a/src/common/backend/utils/cache/relcache.cpp b/src/common/backend/utils/cache/relcache.cpp index d7c7199e7..3be4cf835 100644 --- a/src/common/backend/utils/cache/relcache.cpp +++ b/src/common/backend/utils/cache/relcache.cpp @@ -1258,8 +1258,9 @@ static void relation_build_tuple_desc(Relation relation, bool onlyLoadInitDefVal { int i; - for (i = 0; i < RelationGetNumberOfAttributes(relation); i++) + for (i = 0; i < RelationGetNumberOfAttributes(relation); i++) { Assert(relation->rd_att->attrs[i]->attcacheoff == -1); + } } #endif @@ -1268,8 +1269,9 @@ static void relation_build_tuple_desc(Relation relation, bool onlyLoadInitDefVal * attribute: it must be zero. This eliminates the need for special cases * for attnum=1 that used to exist in fastgetattr() and index_getattr(). */ - if (RelationGetNumberOfAttributes(relation) > 0) + if (RelationGetNumberOfAttributes(relation) > 0) { relation->rd_att->attrs[0]->attcacheoff = 0; + } /* * Set up constraint/default info @@ -2004,6 +2006,27 @@ static void relation_init_physical_addr(Relation relation) relation->rd_node.bucketNode = InvalidBktId; } +/* + * Initialize index key number for an index relation + */ +static void IndexRelationInitKeyNums(Relation relation) +{ + int indnkeyatts; + bool isnull = false; + + if (heap_attisnull(relation->rd_indextuple, Anum_pg_index_indnkeyatts, NULL)) { + /* This scenario will only occur after the upgrade */ + indnkeyatts = RelationGetNumberOfAttributes(relation); + } else { + Datum indkeyDatum = + heap_getattr(relation->rd_indextuple, Anum_pg_index_indnkeyatts, get_pg_index_descriptor(), &isnull); + Assert(!isnull); + indnkeyatts = DatumGetInt16(indkeyDatum); + } + + relation->rd_indnkeyatts = indnkeyatts; +} + /* * Initialize index-access-method support data for an index relation */ @@ -2063,6 +2086,8 @@ void RelationInitIndexAccessInfo(Relation relation) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("relnatts disagrees with indnatts for index %u", RelationGetRelid(relation)))); + + IndexRelationInitKeyNums(relation); indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation); amsupport = aform->amsupport; @@ -4524,6 +4549,17 @@ static TupleDesc get_pg_index_descriptor(void) return u_sess->relcache_cxt.pgindexdesc; } +/* + * Replace with get_pg_index_descriptor + * + * Ban to release return value since it is a static value, and it is used + * frequently in relation operation + */ +TupleDesc GetDefaultPgIndexDesc(void) +{ + return get_pg_index_descriptor(); +} + /* * Load any default attribute value definitions for the relation. */ @@ -4662,7 +4698,6 @@ void SaveCopyList(Relation relation, List* result, int oidIndex) /* * RelationGetSpecificKindIndexList -- get a list of OIDs of global indexes on this relation or not - * if isGlobal is true get list of global indexes ;if isGlobal is false get list of index without global */ List* RelationGetSpecificKindIndexList(Relation relation, bool isGlobal) { @@ -5827,6 +5862,7 @@ static bool load_relcache_init_file(bool shared) /* Fix up internal pointers in the tuple -- see heap_copytuple */ rel->rd_indextuple->t_data = (HeapTupleHeader)((char*)rel->rd_indextuple + HEAPTUPLESIZE); rel->rd_index = (Form_pg_index)GETSTRUCT(rel->rd_indextuple); + IndexRelationInitKeyNums(rel); /* next, read the access method tuple form */ if (fread(&len, 1, sizeof(len), fp) != sizeof(len)) diff --git a/src/gausskernel/bootstrap/bootparse.y b/src/gausskernel/bootstrap/bootparse.y index 8c3f84c41..9fd1043d7 100755 --- a/src/gausskernel/bootstrap/bootparse.y +++ b/src/gausskernel/bootstrap/bootparse.y @@ -314,7 +314,7 @@ Boot_DeclareIndexStmt: stmt->accessMethod = $8; stmt->tableSpace = NULL; stmt->indexParams = $10; - stmt->indexIncludingParams = NIL; + stmt->indexIncludingParams = NIL; stmt->options = NIL; stmt->whereClause = NULL; stmt->excludeOpNames = NIL; @@ -355,7 +355,7 @@ Boot_DeclareUniqueIndexStmt: stmt->accessMethod = $9; stmt->tableSpace = NULL; stmt->indexParams = $11; - stmt->indexIncludingParams = NIL; + stmt->indexIncludingParams = NIL; stmt->options = NIL; stmt->whereClause = NULL; stmt->excludeOpNames = NIL; diff --git a/src/gausskernel/optimizer/commands/indexcmds.cpp b/src/gausskernel/optimizer/commands/indexcmds.cpp index 24ddb4824..581522229 100755 --- a/src/gausskernel/optimizer/commands/indexcmds.cpp +++ b/src/gausskernel/optimizer/commands/indexcmds.cpp @@ -92,8 +92,9 @@ static Oid buildInformationalConstraint( IndexStmt* stmt, Oid indexRelationId, const char* indexRelationName, Relation rel, IndexInfo* indexInfo, Oid namespaceId); static bool CheckGlobalIndexCompatible(Oid relOid, bool isGlobal, const IndexInfo* indexInfo, Oid methodOid); static bool CheckIndexMethodConsistency(HeapTuple indexTuple, Relation indexRelation, Oid currMethodOid); -static bool CheckSimpleAttrsConsistency(Form_pg_index indexTuple, const int16* currAttrsArray, int currKeyNum); +static bool CheckSimpleAttrsConsistency(HeapTuple tarTuple, const int16* currAttrsArray, int currKeyNum); static int AttrComparator(const void* a, const void* b); +static void AddIndexColumnForGpi(IndexStmt* stmt); /* * CheckIndexCompatible @@ -232,7 +233,7 @@ bool CheckIndexCompatible(Oid oldId, char* accessMethodName, List* attributeList } /* Any change in operator class or collation breaks compatibility. */ - old_natts = indexForm->indnkeyatts; + old_natts = GetIndexKeyAttsByTuple(NULL, tuple); Assert(old_natts == numberOfAttributes); d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indcollation, &isnull); @@ -432,14 +433,9 @@ Oid DefineIndex(Oid relationId, IndexStmt* stmt, Oid indexRelationId, bool is_al ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot create concurrent partitioned indexes "))); } + /* Add special index columns tableoid to global partition index */ if (stmt->isGlobal) { - IndexElem* iparam = makeNode(IndexElem); - iparam->name = pstrdup("tableoid"); - iparam->expr = NULL; - iparam->indexcolname = NULL; - iparam->collation = NIL; - iparam->opclass = NIL; - stmt->indexIncludingParams = lappend(stmt->indexIncludingParams, iparam); + AddIndexColumnForGpi(stmt); } if (list_intersection(stmt->indexParams, stmt->indexIncludingParams) != NIL) { @@ -448,6 +444,14 @@ Oid DefineIndex(Oid relationId, IndexStmt* stmt, Oid indexRelationId, bool is_al errmsg("included columns must not intersect with key columns"))); } + if (list_length(stmt->indexParams) <= 0) { + ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("must specify at least one column"))); + } + if (list_length(stmt->indexParams) > INDEX_MAX_KEYS) { + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_COLUMNS), errmsg("cannot use more than %d columns in an index", INDEX_MAX_KEYS))); + } + /* * count key attributes in index */ @@ -581,7 +585,7 @@ Oid DefineIndex(Oid relationId, IndexStmt* stmt, Oid indexRelationId, bool is_al AclResult aclresult; ListCell* tspcell = NULL; - if (!stmt->isGlobal) { // LOCAL partition index check + if (!stmt->isGlobal) { // LOCAL partition index check foreach (tspcell, partitiontspList) { tablespaceOid = lfirst_oid(tspcell); if (OidIsValid(tablespaceOid) && tablespaceOid != u_sess->proc_cxt.MyDatabaseTableSpace) { @@ -597,6 +601,15 @@ Oid DefineIndex(Oid relationId, IndexStmt* stmt, Oid indexRelationId, bool is_al errmsg("only shared relations can be placed in pg_global tablespace"))); } } + } else { + if (OidIsValid(tablespaceId) && tablespaceId != u_sess->proc_cxt.MyDatabaseTableSpace) { + AclResult aclresult; + + aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) { + aclcheck_error(aclresult, ACL_KIND_TABLESPACE, get_tablespace_name(tablespaceId)); + } + } } /* @@ -688,12 +701,6 @@ Oid DefineIndex(Oid relationId, IndexStmt* stmt, Oid indexRelationId, bool is_al (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support unique indexes", accessMethodName))); - if (list_length(stmt->indexIncludingParams) > 0 && !accessMethodForm->amcaninclude) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("access method \"%s\" does not support for global partition index", accessMethodName))); - } - if (numberOfAttributes > 1 && !accessMethodForm->amcanmulticol) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -2700,7 +2707,7 @@ void addIndexForPartition(Relation partitionedRelation, Oid partOid) } /* get oid list of indexRel */ - indelist = RelationGetIndexList(partitionedRelation); + indelist = RelationGetSpecificKindIndexList(partitionedRelation, false); if (!PointerIsValid(indelist)) { return; } @@ -2714,12 +2721,6 @@ void addIndexForPartition(Relation partitionedRelation, Oid partOid) indexElemList = NIL; indexRelOid = lfirst_oid(cell); indexRel = relation_open(indexRelOid, AccessShareLock); - - /* Ignore global partition index */ - if (RelationIsGlobalIndex(indexRel)) { - relation_close(indexRel, AccessShareLock); - continue; - } indexInfo = BuildIndexInfo(indexRel); indexTuple = SearchSysCacheCopy1(INDEXRELID, ObjectIdGetDatum(indexRel->rd_id)); @@ -3035,7 +3036,7 @@ static Oid buildInformationalConstraint( /* * Index constraint: Local partition index could not be on same column with global partition index - * This function check all exist index on table of 'relOid', compare index attr column wiht new index of 'indexInfo', + * This function check all exist index on table of 'relOid', compare index attr column with new index of 'indexInfo', * return true indicate new index is compatible with all existing index, otherwise, return false. */ static bool CheckGlobalIndexCompatible(Oid relOid, bool isGlobal, const IndexInfo* indexInfo, Oid currMethodOid) @@ -3046,19 +3047,19 @@ static bool CheckGlobalIndexCompatible(Oid relOid, bool isGlobal, const IndexInf Relation indexRelation; bool ret = true; errno_t rc; - bool isNull; + bool isNull = false; char currIdxKind = isGlobal ? RELKIND_GLOBAL_INDEX : RELKIND_INDEX; - int currSize = sizeof(int16) * indexInfo->ii_NumIndexKeyAttrs; + int currSize = sizeof(AttrNumber) * indexInfo->ii_NumIndexKeyAttrs; int currKeyNum = indexInfo->ii_NumIndexKeyAttrs; ScanKeyInit(&skey[0], Anum_pg_index_indrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(relOid)); indexRelation = heap_open(IndexRelationId, AccessShareLock); sysScan = systable_beginscan(indexRelation, IndexIndrelidIndexId, true, SnapshotNow, 1, skey); - int16* currAttrsArray = (int16*)palloc0(currSize); + AttrNumber* currAttrsArray = (AttrNumber*)palloc0(currSize); rc = memcpy_s(currAttrsArray, currSize, indexInfo->ii_KeyAttrNumbers, currSize); securec_check(rc, "\0", "\0"); - qsort(currAttrsArray, currKeyNum, sizeof(int16), AttrComparator); + qsort(currAttrsArray, currKeyNum, sizeof(AttrNumber), AttrComparator); while (HeapTupleIsValid(tarTuple = systable_getnext(sysScan))) { Form_pg_index indexTuple = (Form_pg_index)GETSTRUCT(tarTuple); @@ -3069,15 +3070,17 @@ static bool CheckGlobalIndexCompatible(Oid relOid, bool isGlobal, const IndexInf ret = false; break; } - /* - * check expressions: GPI is not support expression, thus, if there is expression on LPI - * we assume it as compatible and check next index; - */ + heap_getattr(tarTuple, Anum_pg_index_indexprs, RelationGetDescr(indexRelation), &isNull); + /* + * check expressions: This condition looks confused, here we judge whether tow index has expressions, + * like XOR operation. if two indexes both have expression or not, we continue to + * check next condition, otherwise, two index could be treated as compatible. + */ if ((indexInfo->ii_Expressions != NIL) != (!isNull)) { continue; } - if (!CheckSimpleAttrsConsistency(indexTuple, currAttrsArray, currKeyNum)) { + if (!CheckSimpleAttrsConsistency(tarTuple, currAttrsArray, currKeyNum)) { ret = false; break; } @@ -3096,8 +3099,8 @@ static bool CheckIndexMethodConsistency(HeapTuple indexTuple, Relation indexRela { bool isNull = false; bool ret = true; - oidvector* opClass = - (oidvector*)heap_getattr(indexTuple, Anum_pg_index_indclass, RelationGetDescr(indexRelation), &isNull); + oidvector* opClass = + (oidvector*)DatumGetPointer(heap_getattr(indexTuple, Anum_pg_index_indclass, RelationGetDescr(indexRelation), &isNull)); Assert(!isNull); Oid opClassOid = opClass->values[0]; HeapTuple opClassTuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opClassOid)); @@ -3117,9 +3120,10 @@ static bool CheckIndexMethodConsistency(HeapTuple indexTuple, Relation indexRela * check column consistency: if run here, then compare two indexes' simple index col, * if index col array is totally same, it means not compatible situation. */ -static bool CheckSimpleAttrsConsistency(Form_pg_index indexTuple, const int16* currAttrsArray, int currKeyNum) +static bool CheckSimpleAttrsConsistency(HeapTuple tarTuple, const int16* currAttrsArray, int currKeyNum) { - int tarKeyNum = indexTuple->indnkeyatts; + Form_pg_index indexTuple = (Form_pg_index)GETSTRUCT(tarTuple); + int tarKeyNum = GetIndexKeyAttsByTuple(NULL, tarTuple); bool ret = true; int i; if (tarKeyNum == currKeyNum) { @@ -3138,5 +3142,17 @@ static bool CheckSimpleAttrsConsistency(Form_pg_index indexTuple, const int16* c static int AttrComparator(const void* a, const void* b) { - return *(int16*)a - *(int16*)b; + return *(AttrNumber*)a - *(AttrNumber*)b; +} + +/* Set the internal index column partoid for global partition index */ +static void AddIndexColumnForGpi(IndexStmt* stmt) +{ + IndexElem* iparam = makeNode(IndexElem); + iparam->name = pstrdup("tableoid"); + iparam->expr = NULL; + iparam->indexcolname = NULL; + iparam->collation = NIL; + iparam->opclass = NIL; + stmt->indexIncludingParams = lappend(stmt->indexIncludingParams, iparam); } diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index 6cdf1f1f6..a2fe4f5b7 100644 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -2797,14 +2797,13 @@ static void RangeVarCallbackForDropRelation( return; /* concurrently dropped, so nothing to do */ classform = (Form_pg_class)GETSTRUCT(tuple); - char expected_relkind = relkind; + char expected_relkind = classform->relkind; if (classform->relkind == RELKIND_GLOBAL_INDEX) { - expected_relkind = RELKIND_GLOBAL_INDEX; + expected_relkind = RELKIND_INDEX; } - if ((classform->relkind != expected_relkind) && - !(u_sess->attr.attr_common.IsInplaceUpgrade && - expected_relkind == RELKIND_RELATION && - classform->relkind == RELKIND_TOASTVALUE)) { + + if ((expected_relkind != relkind) && !(u_sess->attr.attr_common.IsInplaceUpgrade && + relkind == RELKIND_RELATION && expected_relkind == RELKIND_TOASTVALUE)) { DropErrorMsgWrongType(rel->relname, classform->relkind, relkind); } @@ -8150,6 +8149,7 @@ static void ATExecDropNotNull(Relation rel, const char* colName, LOCKMODE lockmo HeapTuple indexTuple; Form_pg_index indexStruct; int i; + int indnkeyatts; indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid)); if (!HeapTupleIsValid(indexTuple)) { @@ -8157,6 +8157,7 @@ static void ATExecDropNotNull(Relation rel, const char* colName, LOCKMODE lockmo ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for index %u", indexoid))); } indexStruct = (Form_pg_index)GETSTRUCT(indexTuple); + indnkeyatts = GetIndexKeyAttsByTuple(NULL, indexTuple); /* If the index is not a primary key, skip the check */ if (indexStruct->indisprimary) { @@ -8164,7 +8165,7 @@ static void ATExecDropNotNull(Relation rel, const char* colName, LOCKMODE lockmo * Loop over each attribute in the primary key and see if it * matches the to-be-altered attribute */ - for (i = 0; i < indexStruct->indnkeyatts; i++) { + for (i = 0; i < indnkeyatts; i++) { if (indexStruct->indkey.values[i] == attnum) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), @@ -9833,6 +9834,7 @@ static int transformFkeyGetPrimaryKey( Datum indclassDatum; bool isnull = false; oidvector* indclass = NULL; + int indnkeyatts = 0; int i; /* @@ -9854,6 +9856,7 @@ static int transformFkeyGetPrimaryKey( } indexStruct = (Form_pg_index)GETSTRUCT(indexTuple); + indnkeyatts = GetIndexKeyAttsByTuple(NULL, indexTuple); if (indexStruct->indisprimary && IndexIsValid(indexStruct)) { /* * Refuse to use a deferrable primary key. This is per SQL spec, @@ -9892,7 +9895,7 @@ static int transformFkeyGetPrimaryKey( * assume a primary key cannot have expressional elements) */ *attnamelist = NIL; - for (i = 0; i < indexStruct->indnkeyatts; i++) { + for (i = 0; i < indnkeyatts; i++) { int pkattno = indexStruct->indkey.values[i]; attnums[i] = pkattno; @@ -9932,6 +9935,7 @@ static Oid transformFkeyCheckAttrs(Relation pkrel, int numattrs, int16* attnums, foreach (indexoidscan, indexoidlist) { HeapTuple indexTuple; Form_pg_index indexStruct; + int indnkeyatts; int i, j; indexoid = lfirst_oid(indexoidscan); @@ -9941,13 +9945,14 @@ static Oid transformFkeyCheckAttrs(Relation pkrel, int numattrs, int16* attnums, ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("cache lookup failed for index %u", indexoid))); } indexStruct = (Form_pg_index)GETSTRUCT(indexTuple); + indnkeyatts = GetIndexKeyAttsByTuple(NULL, indexTuple); /* * Must have the right number of columns; must be unique and not a * partial index; forget it if there are any expressions, too. Invalid * indexes are out as well. */ - if (indexStruct->indnkeyatts == numattrs && indexStruct->indisunique && IndexIsValid(indexStruct) && + if (indnkeyatts == numattrs && indexStruct->indisunique && IndexIsValid(indexStruct) && heap_attisnull(indexTuple, Anum_pg_index_indpred, NULL) && heap_attisnull(indexTuple, Anum_pg_index_indexprs, NULL)) { /* Must get indclass the hard way */ diff --git a/src/gausskernel/optimizer/commands/vacuum.cpp b/src/gausskernel/optimizer/commands/vacuum.cpp index b8676c7dc..bf9d553fd 100755 --- a/src/gausskernel/optimizer/commands/vacuum.cpp +++ b/src/gausskernel/optimizer/commands/vacuum.cpp @@ -2382,7 +2382,7 @@ void vac_update_partstats(Partition part, BlockNumber num_pages, double num_tupl heap_close(rd, RowExclusiveLock); } -void vac_open_part_indexes(VacuumStmt* vacstmt, LOCKMODE lockmode, int* nindexes, int* nindexes_global, Relation** Irel, +void vac_open_part_indexes(VacuumStmt* vacstmt, LOCKMODE lockmode, int* nindexes, int* nindexesGlobal, Relation** Irel, Relation** indexrel, Partition** indexpart) { List* localIndOidList = NIL; @@ -2458,7 +2458,7 @@ void vac_open_part_indexes(VacuumStmt* vacstmt, LOCKMODE lockmode, int* nindexes index_close(indrel, lockmode); } } - *nindexes_global = j; + *nindexesGlobal = j; *nindexes += j; list_free(localIndOidList); @@ -2466,13 +2466,13 @@ void vac_open_part_indexes(VacuumStmt* vacstmt, LOCKMODE lockmode, int* nindexes } void vac_close_part_indexes( - int nindexes, int nindexes_global, Relation* Irel, Relation* indexrel, Partition* indexpart, LOCKMODE lockmode) + int nindexes, int nindexesGlobal, Relation* Irel, Relation* indexrel, Partition* indexpart, LOCKMODE lockmode) { if (Irel == NULL) { return; } - int nindexes_local = nindexes - nindexes_global; + int nindexes_local = nindexes - nindexesGlobal; while (nindexes--) { Relation rel = Irel[nindexes]; if (nindexes < nindexes_local) { @@ -3557,11 +3557,10 @@ static bool GPIIsInvisibleTuple(ItemPointer itemptr, void* state, Oid partOid) if (partStat == PART_METADATA_INVISIBLE) { pvacStates->invisMap = bms_add_member(pvacStates->invisMap, partOid); return true; - } else { - // visible include EXIST and NOEXIST - pvacStates->visMap = bms_add_member(pvacStates->visMap, partOid); - return false; } + // visible include EXIST and NOEXIST + pvacStates->visMap = bms_add_member(pvacStates->visMap, partOid); + return false; } // clean invisible tuples for global partition index diff --git a/src/gausskernel/optimizer/commands/vacuumlazy.cpp b/src/gausskernel/optimizer/commands/vacuumlazy.cpp index b23998120..469a2d374 100644 --- a/src/gausskernel/optimizer/commands/vacuumlazy.cpp +++ b/src/gausskernel/optimizer/commands/vacuumlazy.cpp @@ -166,7 +166,7 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy LVRelStats* vacrelstats = NULL; Relation* Irel = NULL; int nindexes; - int nindexes_global; + int nindexesGlobal; PGRUsage ru0; TimestampTz starttime = 0; long secs; @@ -385,7 +385,7 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy /* Open all indexes of the relation */ if (RelationIsPartition(onerel)) { - vac_open_part_indexes(vacstmt, RowExclusiveLock, &nindexes, &nindexes_global, &Irel, &indexrel, &indexpart); + vac_open_part_indexes(vacstmt, RowExclusiveLock, &nindexes, &nindexesGlobal, &Irel, &indexrel, &indexpart); } else { vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel); } @@ -449,7 +449,7 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy vacstmt->onepartrel, vacstmt->onepartrel->rd_rel->relhasindex, new_frozen_xid); // update stats of local partition indexes - for (int idx = 0; idx < nindexes - nindexes_global; idx++) { + for (int idx = 0; idx < nindexes - nindexesGlobal; idx++) { if (vacrelstats->idx_estimated[idx]) { continue; } @@ -464,9 +464,9 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy } // update stats of global partition indexes - Assert((nindexes - nindexes_global) >= 0); + Assert((nindexes - nindexesGlobal) >= 0); Relation classRel = heap_open(RelationRelationId, RowExclusiveLock); - for (int idx = nindexes - nindexes_global; idx < nindexes; idx++) { + for (int idx = nindexes - nindexesGlobal; idx < nindexes; idx++) { if (vacrelstats->idx_estimated[idx]) { continue; } @@ -504,7 +504,7 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy /* Done with indexes */ if (RelationIsPartition(onerel)) { - vac_close_part_indexes(nindexes, nindexes_global, Irel, indexrel, indexpart, NoLock); + vac_close_part_indexes(nindexes, nindexesGlobal, Irel, indexrel, indexpart, NoLock); } else { vac_close_indexes(nindexes, Irel, NoLock); } diff --git a/src/gausskernel/optimizer/path/indxpath.cpp b/src/gausskernel/optimizer/path/indxpath.cpp index ff22b4f63..cc8d8456b 100755 --- a/src/gausskernel/optimizer/path/indxpath.cpp +++ b/src/gausskernel/optimizer/path/indxpath.cpp @@ -971,7 +971,10 @@ static List* build_paths_for_OR( if (!index->amhasgetbitmap) continue; - /* Ignore global partition index if caller don't set use global part index flag */ + /* + * Ignore global partition index if caller don't set use global part index flag + * Ignore local partition or normal index if caller set use global part index flag + */ if (index->isGlobal != justUseGloalPartIndex) { continue; } @@ -1415,11 +1418,11 @@ static Path* choose_bitmap_and(PlannerInfo* root, RelOptInfo* rel, List* paths, List* bestpaths = NIL; Cost bestcost = 0; int i; - int globalPartPaths = list_length(globalPartIndexPaths); + int gpinPaths = list_length(globalPartIndexPaths); PathClauseUsage** globalPathinfoarray; AssertEreport(npaths > 0, MOD_OPT, "Path number is incorrect"); - if (npaths == 1 && globalPartPaths == 0) + if (npaths == 1 && gpinPaths == 0) return (Path*)linitial(paths); /* easy case */ /* @@ -1478,18 +1481,18 @@ static Path* choose_bitmap_and(PlannerInfo* root, RelOptInfo* rel, List* paths, pathinfoarray = GetPathClauseUsage(paths, clauselist, &npaths); /* Global part index path and local part index path use same clauselist */ - globalPathinfoarray = GetPathClauseUsage(globalPartIndexPaths, clauselist, &globalPartPaths); + globalPathinfoarray = GetPathClauseUsage(globalPartIndexPaths, clauselist, &gpinPaths); /* If only one surviving path, we're done */ - if (npaths == 1 && globalPartPaths == 0) + if (npaths == 1 && gpinPaths == 0) return pathinfoarray[0]->path; /* Sort the surviving paths by index access cost */ qsort(pathinfoarray, (size_t)npaths, sizeof(PathClauseUsage*), path_usage_comparator); /* Sort the surviving paths by index access cost for global partition index paths */ - if (globalPartPaths > 1) { - qsort(globalPathinfoarray, (size_t)globalPartPaths, sizeof(PathClauseUsage*), path_usage_comparator); + if (gpinPaths > 1) { + qsort(globalPathinfoarray, (size_t)gpinPaths, sizeof(PathClauseUsage*), path_usage_comparator); } /* @@ -1516,9 +1519,9 @@ static Path* choose_bitmap_and(PlannerInfo* root, RelOptInfo* rel, List* paths, * * Notes: For global partition index, the start judgment point is 0. */ - if (globalPartPaths > 0) { + if (gpinPaths > 0) { chooseInfo.startPath = 0; - ChooseBitmapAndWithMultiIndex(root, rel, &chooseInfo, globalPathinfoarray, globalPartPaths); + ChooseBitmapAndWithMultiIndex(root, rel, &chooseInfo, globalPathinfoarray, gpinPaths); } /* Keep the cheapest AND-group (or singleton) */ diff --git a/src/gausskernel/optimizer/util/plancat.cpp b/src/gausskernel/optimizer/util/plancat.cpp index 83777a4b6..6dc7f12bd 100644 --- a/src/gausskernel/optimizer/util/plancat.cpp +++ b/src/gausskernel/optimizer/util/plancat.cpp @@ -258,7 +258,7 @@ void get_relation_info(PlannerInfo* root, Oid relationObjectId, bool inhparent, info->reltablespace = RelationGetForm(indexRelation)->reltablespace; info->rel = rel; info->ncolumns = ncolumns = index->indnatts; - info->nkeycolumns = nkeycolumns = index->indnkeyatts; + info->nkeycolumns = nkeycolumns = IndexRelationGetNumberOfKeyAttributes(indexRelation); info->indexkeys = (int*)palloc(sizeof(int) * ncolumns); info->indexcollations = (Oid*)palloc(sizeof(Oid) * nkeycolumns); info->opfamily = (Oid*)palloc(sizeof(Oid) * nkeycolumns); diff --git a/src/gausskernel/runtime/executor/execUtils.cpp b/src/gausskernel/runtime/executor/execUtils.cpp index 9a8d234e4..8736d3354 100755 --- a/src/gausskernel/runtime/executor/execUtils.cpp +++ b/src/gausskernel/runtime/executor/execUtils.cpp @@ -1483,7 +1483,7 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e if (ispartitionedtable && !RelationIsGlobalIndex(indexRelation)) { /* The GPI index insertion is the same as that of a common table */ if (RelationIsGlobalIndex(indexRelation)) { - if (indexRelation->rd_index->indisusable == false) { + if (!indexRelation->rd_index->indisusable) { continue; } actualindex = indexRelation; @@ -1507,7 +1507,7 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e indexpartition, RowExclusiveLock); // skip unusable index - if (false == indexpartition->pd_part->indisusable) { + if (!indexpartition->pd_part->indisusable) { continue; } } diff --git a/src/gausskernel/runtime/executor/nodeBitmapHeapscan.cpp b/src/gausskernel/runtime/executor/nodeBitmapHeapscan.cpp index cc680b4f8..7c8753634 100755 --- a/src/gausskernel/runtime/executor/nodeBitmapHeapscan.cpp +++ b/src/gausskernel/runtime/executor/nodeBitmapHeapscan.cpp @@ -189,10 +189,9 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node) /* If the current partition is invalid, the next page is directly processed */ tbmres = NULL; continue; - } else { - scan->rs_rd = node->gpi_scan->fakePartRelation; - scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd); } + scan->rs_rd = node->gpi_scan->fakePartRelation; + scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd); } #ifdef USE_PREFETCH diff --git a/src/gausskernel/storage/access/index/genam.cpp b/src/gausskernel/storage/access/index/genam.cpp index e85be151e..1c49f1347 100755 --- a/src/gausskernel/storage/access/index/genam.cpp +++ b/src/gausskernel/storage/access/index/genam.cpp @@ -23,6 +23,7 @@ #include "access/relscan.h" #include "access/transam.h" #include "catalog/index.h" +#include "catalog/heap.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "utils/acl.h" @@ -207,6 +208,7 @@ char* BuildIndexValueDescription(Relation index_relation, Datum* values, const b indrelid = idxrec->indrelid; Assert(indexrelid == idxrec->indexrelid); + int tuplekeyatts = GetIndexKeyAttsByTuple(NULL, ht_idx); /* Table-level SELECT is enough, if the user has it */ aclresult = pg_class_aclcheck(indrelid, GetUserId(), ACL_SELECT); if (aclresult != ACLCHECK_OK) { @@ -214,7 +216,7 @@ char* BuildIndexValueDescription(Relation index_relation, Datum* values, const b * No table-level access, so step through the columns in the * index and make sure the user has SELECT rights on all of them. */ - for (keyno = 0; keyno < idxrec->indnkeyatts; keyno++) { + for (keyno = 0; keyno < tuplekeyatts; keyno++) { AttrNumber attnum = idxrec->indkey.values[keyno]; aclresult = pg_attribute_aclcheck(indrelid, attnum, GetUserId(), ACL_SELECT); if (aclresult != ACLCHECK_OK) { @@ -551,8 +553,7 @@ HeapTuple systable_getnext_back(SysScanDesc sysscan) static void GPIInitFakeRelTable(GPIScanDesc gpiScan, MemoryContext cxt) { HASHCTL ctl; - errno_t errorno; - errorno = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); + errno_t errorno = memset_s(&ctl, sizeof(ctl), 0, sizeof(ctl)); securec_check_c(errorno, "\0", "\0"); ctl.keysize = sizeof(PartRelIdCacheKey); ctl.entrysize = sizeof(PartRelIdCacheEnt); diff --git a/src/gausskernel/storage/access/index/indexam.cpp b/src/gausskernel/storage/access/index/indexam.cpp index d3ecef944..e6be3876c 100755 --- a/src/gausskernel/storage/access/index/indexam.cpp +++ b/src/gausskernel/storage/access/index/indexam.cpp @@ -177,9 +177,10 @@ Relation index_open(Oid relation_id, LOCKMODE lockmode, int2 bucket_id) Relation r; r = relation_open(relation_id, lockmode, bucket_id); - if (r->rd_rel->relkind != RELKIND_INDEX && r->rd_rel->relkind != RELKIND_GLOBAL_INDEX) + if (!RelationIsIndex(r)) { ereport( ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not an index", RelationGetRelationName(r)))); + } return r; } @@ -627,7 +628,6 @@ HeapTuple index_getnext(IndexScanDesc scan, ScanDirection direction) } scan->heapRelation = scan->xs_gpi_scan->fakePartRelation; } - } else { /* * We are resuming scan of a HOT chain after having returned an diff --git a/src/gausskernel/storage/access/nbtree/nbtinsert.cpp b/src/gausskernel/storage/access/nbtree/nbtinsert.cpp index e50f0665f..6f4d4cfad 100644 --- a/src/gausskernel/storage/access/nbtree/nbtinsert.cpp +++ b/src/gausskernel/storage/access/nbtree/nbtinsert.cpp @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------- * * nbtinsert.cpp - * Item insertion in Lehman and Yao btrees for Postgres. + * Item insertion in Lehman and Yao btrees for Postgres. * * Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd. * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group @@ -235,7 +235,6 @@ static TransactionId _bt_check_unique(Relation rel, IndexTuple itup, Relation he ItemId curitemid; IndexTuple curitup; BlockNumber nblkno; - bool isNull; /* * make sure the offset points to an actual item before trying to @@ -273,8 +272,9 @@ static TransactionId _bt_check_unique(Relation rel, IndexTuple itup, Relation he /* okay, we gotta fetch the heap tuple ... */ curitup = (IndexTuple)PageGetItem(page, curitemid); htid = curitup->t_tid; - Oid curPartOid; + Oid curPartOid = InvalidOid; Datum datum; + bool isNull = false; if (RelationIsGlobalIndex(rel)) { datum = index_getattr(curitup, IndexRelationGetNumberOfAttributes(rel), RelationGetDescr(rel), &isNull); @@ -305,12 +305,10 @@ static TransactionId _bt_check_unique(Relation rel, IndexTuple itup, Relation he * abnormal condition. */ if (checkUnique == UNIQUE_CHECK_EXISTING && ItemPointerCompare(&htid, &itup->t_tid) == 0) { - if (RelationIsGlobalIndex(rel)) { - if (curPartOid != heapRel->rd_id) { - ereport(ERROR, - (errcode(ERRCODE_INDEX_CORRUPTED), - errmsg("failed to re-find tuple within GPI \"%s\"", RelationGetRelationName(rel)))); - } + if (RelationIsGlobalIndex(rel) && curPartOid != heapRel->rd_id) { + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("failed to re-find tuple within GPI \"%s\"", RelationGetRelationName(rel)))); } found = true; } else if (heap_hot_search(&htid, tarRel, &SnapshotDirty, &all_dead)) { @@ -414,7 +412,6 @@ static TransactionId _bt_check_unique(Relation rel, IndexTuple itup, Relation he * killed. */ /* okay, we gotta fetch the heap tuple ... */ - curitup = (IndexTuple)PageGetItem(page, curitemid); ItemIdMarkDead(curitemid); opaque->btpo_flags |= BTP_HAS_GARBAGE; @@ -2022,10 +2019,6 @@ static bool _bt_isequal(Relation idxrel, Page page, OffsetNumber offnum, int key * for regular non-truncated leaf tuples and P_HIKEY tuple on * rightmost leaf page. */ - Assert((P_RIGHTMOST((BTPageOpaqueInternal)PageGetSpecialPointer(page)) || offnum != P_HIKEY) - ? BTreeTupleGetNAtts(itup, idxrel) == itupdesc->natts - : true); - for (i = 1; i <= keysz; i++) { AttrNumber attno; Datum datum; diff --git a/src/gausskernel/storage/access/nbtree/nbtree.cpp b/src/gausskernel/storage/access/nbtree/nbtree.cpp index 77fc1ccb8..6d3add9bd 100755 --- a/src/gausskernel/storage/access/nbtree/nbtree.cpp +++ b/src/gausskernel/storage/access/nbtree/nbtree.cpp @@ -97,9 +97,9 @@ Datum btbuild(PG_FUNCTION_ARGS) buildstate.spool = _bt_spoolinit(index, indexInfo->ii_Unique, false, &indexInfo->ii_desc); /* do the heap scan */ - double* globalIndexTuples = NULL; + double* allPartTuples = NULL; if (RelationIsGlobalIndex(index)) { - globalIndexTuples = GlobalIndexBuildHeapScan(heap, index, indexInfo, btbuildCallback, (void*)&buildstate); + allPartTuples = GlobalIndexBuildHeapScan(heap, index, indexInfo, btbuildCallback, (void*)&buildstate); } else { reltuples = IndexBuildHeapScan(heap, index, indexInfo, true, btbuildCallback, (void*)&buildstate); } @@ -134,7 +134,7 @@ Datum btbuild(PG_FUNCTION_ARGS) result->heap_tuples = reltuples; result->index_tuples = buildstate.indtuples; - result->global_index_tuples = globalIndexTuples; + result->all_part_tuples = allPartTuples; PG_RETURN_POINTER(result); } @@ -969,7 +969,7 @@ restart: Oid partOid = InvalidOid; if (RelationIsGlobalIndex(rel)) { bool isnull = false; - partOid = index_getattr(itup, partitionOidAttr, tupdesc, &isnull); + partOid = DatumGetUInt32(index_getattr(itup, partitionOidAttr, tupdesc, &isnull)); Assert(!isnull); } if (callback(htup, callback_state, partOid)) { diff --git a/src/gausskernel/storage/access/nbtree/nbtsort.cpp b/src/gausskernel/storage/access/nbtree/nbtsort.cpp index f8a34d4c2..92e7f7c3f 100755 --- a/src/gausskernel/storage/access/nbtree/nbtsort.cpp +++ b/src/gausskernel/storage/access/nbtree/nbtsort.cpp @@ -456,9 +456,6 @@ void _bt_buildadd(BTWriteState* wstate, BTPageState* state, IndexTuple itup) OffsetNumber last_off; Size pgspc; Size itupsz; - BTPageOpaqueInternal pageop; - int indnatts = IndexRelationGetNumberOfAttributes(wstate->index); - int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(wstate->index); /* * This is a handy place to check for cancel interrupts during the btree @@ -538,6 +535,8 @@ void _bt_buildadd(BTWriteState* wstate, BTPageState* state, IndexTuple itup) *hii = *ii; ItemIdSetUnused(ii); /* redundant */ ((PageHeader)opage)->pd_lower -= sizeof(ItemIdData); + int indnatts = IndexRelationGetNumberOfAttributes(wstate->index); + int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(wstate->index); if (indnkeyatts != indnatts && P_ISLEAF(opageop)) { /* @@ -612,7 +611,6 @@ void _bt_buildadd(BTWriteState* wstate, BTPageState* state, IndexTuple itup) last_off = P_FIRSTKEY; } - pageop = (BTPageOpaqueInternal) PageGetSpecialPointer(npage); /* * If the new item is the first for its page, stash a copy for later. Note * this will only happen for the first item on a level; on later pages, diff --git a/src/include/access/genam.h b/src/include/access/genam.h index 82e78688c..e76a38bb0 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -28,7 +28,7 @@ typedef struct IndexBuildResult { double heap_tuples; /* # of tuples seen in parent table */ double index_tuples; /* # of tuples inserted into index */ - double* global_index_tuples; + double* all_part_tuples; } IndexBuildResult; /* diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index cdec5dd25..ae32a3a82 100755 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -431,11 +431,11 @@ typedef struct xl_btree_newroot { ItemPointerGetOffsetNumberNoCheck(&(itup)->t_tid) & BT_N_KEYS_OFFSET_MASK) \ : IndexRelationGetNumberOfAttributes(rel)) -#define BTreeTupleSetNAtts(itup, n) \ - do { \ - (itup)->t_info |= INDEX_ALT_TID_MASK; \ - Assert(((n) & BT_RESERVED_OFFSET_MASK) == 0); \ - ItemPointerSetOffsetNumber(&(itup)->t_tid, (n) & BT_N_KEYS_OFFSET_MASK); \ +#define BTreeTupleSetNAtts(itup, n) \ + do { \ + (itup)->t_info |= INDEX_ALT_TID_MASK; \ + Assert(((n) & BT_RESERVED_OFFSET_MASK) == 0); \ + ItemPointerSetOffsetNumber(&(itup)->t_tid, (n) & BT_N_KEYS_OFFSET_MASK); \ } while (0) /* diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index 93b7fbc39..a88a34e56 100755 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -126,7 +126,7 @@ typedef struct IndexScanDescData { /* scan parameters */ Relation heapRelation; /* heap relation descriptor, or NULL */ Relation indexRelation; /* index relation descriptor */ - GPIScanDesc xs_gpi_scan; /* global partition index scan use information */ + GPIScanDesc xs_gpi_scan; /* global partition index scan use information */ Snapshot xs_snapshot; /* snapshot to see */ int numberOfKeys; /* number of index qualifier conditions */ int numberOfOrderBys; /* number of ordering operators */ diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index a0df9b3b5..06ffd8373 100755 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -146,4 +146,6 @@ extern bool* check_partkey_has_timestampwithzone(Relation partTableRel); extern Oid AddNewIntervalPartition(Relation rel, HeapTuple insertTuple); +extern int GetIndexKeyAttsByTuple(Relation relation, HeapTuple indexTuple); + #endif /* HEAP_H */ diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 6bb39bda1..ddff7eb72 100755 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -56,7 +56,23 @@ typedef enum CheckWaitMode extern void index_check_primary_key(Relation heapRel, IndexInfo *indexInfo, bool is_alter_table); -typedef struct { +/* + * Parameter isPartitionedIndex indicates whether the index is a partition index. + * Parameter isGlobalPartitionedIndex indicates whether the index is a global partition index + * ------------------------------------------------------------------------- + * | isPartitionedIndex | isGlobalPartitionedIndex | Description | + * ------------------------------------------------------------------------- + * | false | false | normal relation index | + * ------------------------------------------------------------------------- + * | true | false | local partition index | + * ------------------------------------------------------------------------- + * | false | true | can not happen | + * ------------------------------------------------------------------------- + * | true | true | global partition index | + * ------------------------------------------------------------------------- + */ +typedef struct +{ Oid existingPSortOid; bool isPartitionedIndex; bool isGlobalPartitionedIndex; diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index dd81c306c..e96e396b5 100755 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -52,7 +52,6 @@ CATALOG(pg_am,2601) BKI_SCHEMA_MACRO bool amstorage; /* can storage type differ from column type? */ bool amclusterable; /* does AM support cluster command? */ bool ampredlocks; /* does AM handle predicate locks? */ - bool amcaninclude; /* does AM support create index xxx include? */ Oid amkeytype; /* type of data in index, or InvalidOid */ regproc aminsert; /* "insert this tuple" function */ regproc ambeginscan; /* "prepare for index scan" function */ @@ -83,7 +82,7 @@ typedef FormData_pg_am *Form_pg_am; * compiler constants for pg_am * ---------------- */ -#define Natts_pg_am 32 +#define Natts_pg_am 31 #define Anum_pg_am_amname 1 #define Anum_pg_am_amstrategies 2 #define Anum_pg_am_amsupport 3 @@ -98,55 +97,54 @@ typedef FormData_pg_am *Form_pg_am; #define Anum_pg_am_amstorage 12 #define Anum_pg_am_amclusterable 13 #define Anum_pg_am_ampredlocks 14 -#define Anum_pg_am_amcaninclude 15 -#define Anum_pg_am_amkeytype 16 -#define Anum_pg_am_aminsert 17 -#define Anum_pg_am_ambeginscan 18 -#define Anum_pg_am_amgettuple 19 -#define Anum_pg_am_amgetbitmap 20 -#define Anum_pg_am_amrescan 21 -#define Anum_pg_am_amendscan 22 -#define Anum_pg_am_ammarkpos 23 -#define Anum_pg_am_amrestrpos 24 -#define Anum_pg_am_ammerge 25 -#define Anum_pg_am_ambuild 26 -#define Anum_pg_am_ambuildempty 27 -#define Anum_pg_am_ambulkdelete 28 -#define Anum_pg_am_amvacuumcleanup 29 -#define Anum_pg_am_amcanreturn 30 -#define Anum_pg_am_amcostestimate 31 -#define Anum_pg_am_amoptions 32 +#define Anum_pg_am_amkeytype 15 +#define Anum_pg_am_aminsert 16 +#define Anum_pg_am_ambeginscan 17 +#define Anum_pg_am_amgettuple 18 +#define Anum_pg_am_amgetbitmap 19 +#define Anum_pg_am_amrescan 20 +#define Anum_pg_am_amendscan 21 +#define Anum_pg_am_ammarkpos 22 +#define Anum_pg_am_amrestrpos 23 +#define Anum_pg_am_ammerge 24 +#define Anum_pg_am_ambuild 25 +#define Anum_pg_am_ambuildempty 26 +#define Anum_pg_am_ambulkdelete 27 +#define Anum_pg_am_amvacuumcleanup 28 +#define Anum_pg_am_amcanreturn 29 +#define Anum_pg_am_amcostestimate 30 +#define Anum_pg_am_amoptions 31 /* ---------------- * initial contents of pg_am * ---------------- */ -DATA(insert OID = 403 ( btree 5 2 t f t t t t t t f t t t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btmerge btbuild btbuildempty btbulkdelete btvacuumcleanup btcanreturn btcostestimate btoptions )); +DATA(insert OID = 403 ( btree 5 2 t f t t t t t t f t t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btmerge btbuild btbuildempty btbulkdelete btvacuumcleanup btcanreturn btcostestimate btoptions )); DESCR("b-tree index access method"); #define BTREE_AM_OID 403 -DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashmerge hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup - hashcostestimate hashoptions )); +DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashmerge hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup - hashcostestimate hashoptions )); DESCR("hash index access method"); #define HASH_AM_OID 405 -DATA(insert OID = 783 ( gist 0 8 f t f f t t f t t t f f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistmerge gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup - gistcostestimate gistoptions )); +DATA(insert OID = 783 ( gist 0 8 f t f f t t f t t t f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistmerge gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup - gistcostestimate gistoptions )); DESCR("GiST index access method"); #define GIST_AM_OID 783 -DATA(insert OID = 2742 ( gin 0 6 f f f f t t f f t f f f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginmerge ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions )); +DATA(insert OID = 2742 ( gin 0 6 f f f f t t f f t f f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginmerge ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions )); DESCR("GIN index access method"); #define GIN_AM_OID 2742 -DATA(insert OID = 4000 ( spgist 0 5 f f f f f t f t f f f f 0 spginsert spgbeginscan spggettuple spggetbitmap spgrescan spgendscan spgmarkpos spgrestrpos spgmerge spgbuild spgbuildempty spgbulkdelete spgvacuumcleanup spgcanreturn spgcostestimate spgoptions )); +DATA(insert OID = 4000 ( spgist 0 5 f f f f f t f t f f f 0 spginsert spgbeginscan spggettuple spggetbitmap spgrescan spgendscan spgmarkpos spgrestrpos spgmerge spgbuild spgbuildempty spgbulkdelete spgvacuumcleanup spgcanreturn spgcostestimate spgoptions )); DESCR("SP-GiST index access method"); #define SPGIST_AM_OID 4000 -DATA(insert OID = 4039 ( psort 5 1 f f f f t t f t f f f f 0 - - psortgettuple psortgetbitmap - - - - - psortbuild - - - psortcanreturn psortcostestimate psortoptions )); +DATA(insert OID = 4039 ( psort 5 1 f f f f t t f t f f f 0 - - psortgettuple psortgetbitmap - - - - - psortbuild - - - psortcanreturn psortcostestimate psortoptions )); DESCR("psort index access method"); #define PSORT_AM_OID 4039 -DATA(insert OID = 4239 ( cbtree 5 1 f f f f t t f t f f t f 0 btinsert btbeginscan cbtreegettuple cbtreegetbitmap btrescan btendscan - - - cbtreebuild btbuildempty - - cbtreecanreturn cbtreecostestimate cbtreeoptions )); +DATA(insert OID = 4239 ( cbtree 5 1 f f f f t t f t f f t 0 btinsert btbeginscan cbtreegettuple cbtreegetbitmap btrescan btendscan - - - cbtreebuild btbuildempty - - cbtreecanreturn cbtreecostestimate cbtreeoptions )); DESCR("cstore btree index access method"); #define CBTREE_AM_OID 4239 -DATA(insert OID = 4444 ( cgin 0 6 f f f f t t f f t f f f 0 gininsert ginbeginscan - cgingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginmerge cginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions )); +DATA(insert OID = 4444 ( cgin 0 6 f f f f t t f f t f f 0 gininsert ginbeginscan - cgingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginmerge cginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions )); DESCR("cstore GIN index access method"); #define CGIN_AM_OID 4444 diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h index ea639dc69..305779598 100755 --- a/src/include/catalog/pg_constraint.h +++ b/src/include/catalog/pg_constraint.h @@ -104,13 +104,6 @@ CATALOG(pg_constraint,2606) BKI_SCHEMA_MACRO */ int2 conkey[1]; - /* - * Columns of conrelid that the constraint does not apply to, but included - * into the same index with key columns. - */ - int2 conincluding[1]; - - /* * If a foreign key, the referenced columns of confrelid */ @@ -149,6 +142,12 @@ CATALOG(pg_constraint,2606) BKI_SCHEMA_MACRO * If a check constraint, source-text representation of expression */ text consrc; + + /* + * Columns of conrelid that the constraint does not apply to, but included + * into the same index with key columns. + */ + int2 conincluding[1]; #endif } FormData_pg_constraint; @@ -183,14 +182,14 @@ typedef FormData_pg_constraint *Form_pg_constraint; #define Anum_pg_constraint_consoft 17 #define Anum_pg_constraint_conopt 18 #define Anum_pg_constraint_conkey 19 -#define Anum_pg_constraint_conincluding 20 -#define Anum_pg_constraint_confkey 21 -#define Anum_pg_constraint_conpfeqop 22 -#define Anum_pg_constraint_conppeqop 23 -#define Anum_pg_constraint_conffeqop 24 -#define Anum_pg_constraint_conexclop 25 -#define Anum_pg_constraint_conbin 26 -#define Anum_pg_constraint_consrc 27 +#define Anum_pg_constraint_confkey 20 +#define Anum_pg_constraint_conpfeqop 21 +#define Anum_pg_constraint_conppeqop 22 +#define Anum_pg_constraint_conffeqop 23 +#define Anum_pg_constraint_conexclop 24 +#define Anum_pg_constraint_conbin 25 +#define Anum_pg_constraint_consrc 26 +#define Anum_pg_constraint_conincluding 27 /* Valid values for contype */ diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h index d65456556..ae552667e 100644 --- a/src/include/catalog/pg_index.h +++ b/src/include/catalog/pg_index.h @@ -34,7 +34,6 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO Oid indexrelid; /* OID of the index */ Oid indrelid; /* OID of the relation it indexes */ int2 indnatts; /* total number of columns in index */ - int2 indnkeyatts; /* number of key columns in index */ bool indisunique; /* is this a unique index? */ bool indisprimary; /* is this index for primary key? */ bool indisexclusion; /* is this index for exclusion constraint? */ @@ -59,6 +58,7 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO pg_node_tree indpred; /* expression tree for predicate, if a partial * index; else NULL */ bool indisreplident; /* is this index the identity for replication? */ + int2 indnkeyatts; /* number of key columns in index */ #endif } FormData_pg_index; @@ -77,23 +77,24 @@ typedef FormData_pg_index *Form_pg_index; #define Anum_pg_index_indexrelid 1 #define Anum_pg_index_indrelid 2 #define Anum_pg_index_indnatts 3 -#define Anum_pg_index_indnkeyatts 4 -#define Anum_pg_index_indisunique 5 -#define Anum_pg_index_indisprimary 6 -#define Anum_pg_index_indisexclusion 7 -#define Anum_pg_index_indimmediate 8 -#define Anum_pg_index_indisclustered 9 -#define Anum_pg_index_indisusable 10 -#define Anum_pg_index_indisvalid 11 -#define Anum_pg_index_indcheckxmin 12 -#define Anum_pg_index_indisready 13 -#define Anum_pg_index_indkey 14 -#define Anum_pg_index_indcollation 15 -#define Anum_pg_index_indclass 16 -#define Anum_pg_index_indoption 17 -#define Anum_pg_index_indexprs 18 -#define Anum_pg_index_indpred 19 -#define Anum_pg_index_indisreplident 20 +#define Anum_pg_index_indisunique 4 +#define Anum_pg_index_indisprimary 5 +#define Anum_pg_index_indisexclusion 6 +#define Anum_pg_index_indimmediate 7 +#define Anum_pg_index_indisclustered 8 +#define Anum_pg_index_indisusable 9 +#define Anum_pg_index_indisvalid 10 +#define Anum_pg_index_indcheckxmin 11 +#define Anum_pg_index_indisready 12 +#define Anum_pg_index_indkey 13 +#define Anum_pg_index_indcollation 14 +#define Anum_pg_index_indclass 15 +#define Anum_pg_index_indoption 16 +#define Anum_pg_index_indexprs 17 +#define Anum_pg_index_indpred 18 +#define Anum_pg_index_indisreplident 19 +#define Anum_pg_index_indnkeyatts 20 + /* * Index AMs that support ordered scans must support these two indoption * bits. Otherwise, the content of the per-column indoption fields is diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 151062c31..5a79a6407 100755 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -386,10 +386,10 @@ extern int compute_attr_target(Form_pg_attribute attr); extern void vac_update_partstats(Partition part, BlockNumber num_pages, double num_tuples, BlockNumber num_all_visible_pages, TransactionId frozenxid); -extern void vac_open_part_indexes(VacuumStmt* vacstmt, LOCKMODE lockmode, int* nindexes, int* nindexes_global, +extern void vac_open_part_indexes(VacuumStmt* vacstmt, LOCKMODE lockmode, int* nindexes, int* nindexesGlobal, Relation** Irel, Relation** indexrel, Partition** indexpart); extern void vac_close_part_indexes( - int nindexes, int nindexes_global, Relation* Irel, Relation* indexrel, Partition* indexpart, LOCKMODE lockmode); + int nindexes, int nindexesGlobal, Relation* Irel, Relation* indexrel, Partition* indexpart, LOCKMODE lockmode); extern void vac_update_pgclass_partitioned_table(Relation partitionRel, bool hasIndex, TransactionId newFrozenXid); extern void CStoreVacUpdateNormalRelStats(Oid relid, TransactionId frozenxid, Relation pgclassRel); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index ea851cd97..e04ffd1d3 100755 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -159,6 +159,7 @@ typedef struct RelationData { /* use "struct" here to avoid needing to include htup.h: */ struct HeapTupleData* rd_indextuple; /* all of pg_index tuple */ Form_pg_am rd_am; /* pg_am tuple for index's AM */ + int rd_indnkeyatts; /* index relation's indexkey nums */ /* * index access support info (used only for an index relation) @@ -404,7 +405,8 @@ typedef struct StdRdOptions { * IndexRelationGetNumberOfKeyAttributes * Returns the number of key attributes in an index. */ -#define IndexRelationGetNumberOfKeyAttributes(relation) ((relation)->rd_index->indnkeyatts) +#define IndexRelationGetNumberOfKeyAttributes(relation) \ + (AssertMacro((relation)->rd_indnkeyatts != 0), ((relation)->rd_indnkeyatts)) /* * RelationGetDescr diff --git a/src/include/utils/rel_gs.h b/src/include/utils/rel_gs.h index 8caf1cabf..d9fff410e 100755 --- a/src/include/utils/rel_gs.h +++ b/src/include/utils/rel_gs.h @@ -586,10 +586,9 @@ static inline bool IsCompressedByCmprsInPgclass(const RelCompressType cmprInPgcl /* Partition get reloptions whether have wait_clean_gpi for parition */ static inline bool PartitionEnableWaitCleanGpi(Partition partition) { - if (PointerIsValid(partition) && partition->rd_options != NULL) { - if (pg_strcasecmp(OptEnabledWaitCleanGpi, ParitionGetWaitCleanGpi(partition)) == 0) { - return true; - } + if (PointerIsValid(partition) && partition->rd_options != NULL && + pg_strcasecmp(OptEnabledWaitCleanGpi, ParitionGetWaitCleanGpi(partition)) == 0) { + return true; } return false; @@ -598,10 +597,9 @@ static inline bool PartitionEnableWaitCleanGpi(Partition partition) /* Relation get reloptions whether have wait_clean_gpi for relation */ static inline bool RelationEnableWaitCleanGpi(Relation relation) { - if (PointerIsValid(relation) && relation->rd_options != NULL) { - if (pg_strcasecmp(OptEnabledWaitCleanGpi, RelationGetWaitCleanGpi(relation)) == 0) { - return true; - } + if (PointerIsValid(relation) && relation->rd_options != NULL && + pg_strcasecmp(OptEnabledWaitCleanGpi, RelationGetWaitCleanGpi(relation)) == 0) { + return true; } return false; diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 5846a5094..f0dd4085a 100755 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -58,7 +58,6 @@ extern int RelationGetIndexNum(Relation relation); extern Oid RelationGetOidIndex(Relation relation); extern Oid RelationGetReplicaIndex(Relation relation); extern List* RelationGetIndexExpressions(Relation relation); -extern List* RelationGetIndexExpressions(Relation relation); extern List* RelationGetDummyIndexExpressions(Relation relation); extern List* RelationGetIndexPredicate(Relation relation); @@ -132,6 +131,7 @@ extern void RelationCacheInitFileRemove(void); extern TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute* attrs, bool hasoids); extern TupleDesc GetDefaultPgClassDesc(void); +extern TupleDesc GetDefaultPgIndexDesc(void); extern bool CheckRelationInRedistribution(Oid rel_oid); diff --git a/src/test/regress/expected/gpi_bitmapscan.out b/src/test/regress/expected/gpi_bitmapscan.out index 9228fe61a..309eb2d5c 100644 --- a/src/test/regress/expected/gpi_bitmapscan.out +++ b/src/test/regress/expected/gpi_bitmapscan.out @@ -220,6 +220,10 @@ SELECT * FROM gpi_bitmap_table2 WHERE c1 = 10000 OR c2 = 30000; (2 rows) DROP TABLE idx1_gpi_bitmap_table1; +ERROR: "idx1_gpi_bitmap_table1" is not a table +HINT: Use DROP INDEX to remove an global partition index. DROP TABLE idx1_gpi_bitmap_table2; +ERROR: "idx1_gpi_bitmap_table2" is not a table +HINT: Use DROP INDEX to remove an global partition index. SET enable_seqscan=on; SET enable_indexscan=on; diff --git a/src/test/regress/expected/gpi_build_index.out b/src/test/regress/expected/gpi_build_index.out index 5befdf23f..fcf4f2a1f 100644 --- a/src/test/regress/expected/gpi_build_index.out +++ b/src/test/regress/expected/gpi_build_index.out @@ -242,3 +242,25 @@ select * from test_gpi_create_like where c1 = 0; (1 row) drop table test_gpi_create_like; +drop table if exists gpi_multi_cols; +NOTICE: table "gpi_multi_cols" does not exist, skipping +create table gpi_multi_cols(a0 int,a1 int,a2 int,a3 int,a4 int,a5 int,a6 int,a7 int,a8 int,a9 int,a10 int,a11 int,a12 int,a13 int,a14 int,a15 int,a16 int,a17 int,a18 int,a19 int,a20 int,a21 int,a22 int,a23 int,a24 int,a25 int,a26 int,a27 int,a28 int,a29 int,a30 int,a31 int,a32 int, a33 int) partition by range(a0) (partition p1 values less than (1001), partition p2 values less than (2001), partition p3 values less than (3001)); +-- success +create index gpi_multi_cols_index on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30) global; +--failed +create index gpi_multi_cols_index on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30, a31) global; +ERROR: cannot use more than 32 columns in an index +--success +create index gpi_multi_cols_index_local on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30, a31) local; +insert into gpi_multi_cols select r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r from generate_series(1,3000) as r; +vacuum analyze gpi_multi_cols; +set enable_seqscan = off; +select * from gpi_multi_cols where a1 = 200; + a0 | a1 | a2 | a3 | a4 | a5 | a6 | a7 | a8 | a9 | a10 | a11 | a12 | a13 | a14 | a15 | a16 | a17 | a18 | a19 | a20 | a21 | a22 | a23 | a24 | a25 | a26 | a27 | a28 | a29 | a30 | a31 | a32 | a33 +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----- + 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | 200 | +(1 row) + +reset enable_seqscan; +--clean data +drop table gpi_multi_cols; diff --git a/src/test/regress/expected/gpi_clean_wait.out b/src/test/regress/expected/gpi_clean_wait.out index 04b6fad4c..4e5f9564f 100644 --- a/src/test/regress/expected/gpi_clean_wait.out +++ b/src/test/regress/expected/gpi_clean_wait.out @@ -13,11 +13,11 @@ vacuum analyze test_gpi_more_invalid; start transaction; alter table test_gpi_more_invalid add partition p6 values less than (4001); update test_gpi_more_invalid set a = 3000 + a where a <= 100; -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions -----------------------+----------+--------------------------------------------------- - test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} p6 | p | {orientation=row,compression=no,wait_clean_gpi=y} + test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} (2 rows) explain (costs off) select * from test_gpi_more_invalid where a >= 3000; @@ -78,7 +78,7 @@ select count(*) from test_gpi_more_invalid where a >= 3000; (1 row) -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions -----------------------+----------+--------------------------------------------------- test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} @@ -86,7 +86,7 @@ select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a vacuum analyze test_gpi_more_invalid; -- test_gpi_more_invalid have wait_clean_gpi=n -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions ---------+----------+------------ (0 rows) @@ -187,7 +187,7 @@ ERROR: duplicate key value violates unique constraint "global_index_gpi_more_in DETAIL: Key (b)=(1001) already exists. commit; -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions -----------------------+----------+--------------------------------------------------- test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} @@ -340,11 +340,11 @@ select count(*) from test_gpi_more_invalid where c = 100 and b = 2000; (1 row) -- test_gpi_more_invalid/p5 have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions -----------------------+----------+--------------------------------------------------- - test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} p5 | p | {orientation=row,compression=no,wait_clean_gpi=y} + test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} (2 rows) abort; @@ -353,7 +353,7 @@ vacuum full pg_partition; WARNING: system table pg_partition contain relation test_gpi_more_invalid have reloptions wait_clean_gpi=y,must run the vacuum (full) test_gpi_more_invalid first WARNING: skipping "pg_partition" --- only table or database can vacuum it -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions -----------------------+----------+--------------------------------------------------- test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} @@ -361,7 +361,7 @@ select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a vacuum analyze test_gpi_more_invalid; -- test_gpi_more_invalid have wait_clean_gpi=n -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions ---------+----------+------------ (0 rows) @@ -432,7 +432,7 @@ select c.relname, i.indisusable from pg_index i join pg_class c on i.indexrelid (5 rows) -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions -----------------------+----------+--------------------------------------------------- test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} @@ -451,7 +451,7 @@ select c.relname, i.indisusable from pg_index i join pg_class c on i.indexrelid (5 rows) -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions -----------------------+----------+--------------------------------------------------- test_gpi_more_invalid | r | {orientation=row,compression=no,wait_clean_gpi=y} @@ -515,7 +515,7 @@ explain (costs off) select count(*) from interval_normal_date where b <= 500; Index Cond: (b <= 500) (5 rows) -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions ----------------------+----------+--------------------------------------------------- interval_normal_date | r | {orientation=row,compression=no,wait_clean_gpi=y} @@ -524,14 +524,14 @@ select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a alter table interval_normal_date drop partition sys_p2; commit; -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions ----------------------+----------+--------------------------------------------------- interval_normal_date | r | {orientation=row,compression=no,wait_clean_gpi=y} (1 row) vacuum analyze interval_normal_date; -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; relname | parttype | reloptions ---------+----------+------------ (0 rows) @@ -560,8 +560,7 @@ vacuum interval_partition_table_vacuum; vacuum interval_partition_table_vacuum; vacuum analyze interval_partition_table_vacuum; \parallel off -set enable_bitmascan = off; -ERROR: unrecognized configuration parameter "enable_bitmascan" +set enable_bitmapscan = off; explain (costs off) select count(*) from interval_partition_table_vacuum where c1 = 1; QUERY PLAN --------------------------------------------------------------------------------------------------------------- @@ -592,8 +591,7 @@ select count(*) from pg_partition a, pg_class b where a.parentid = b.oid and b.r 0 (1 row) -reset enable_bitmascan; -ERROR: unrecognized configuration parameter "enable_bitmascan" +reset enable_bitmapscan; -- clean table drop table interval_partition_table_vacuum; drop table interval_normal_date; diff --git a/src/test/regress/expected/gpi_interval.out b/src/test/regress/expected/gpi_interval.out index ae9939ad8..010edba83 100644 --- a/src/test/regress/expected/gpi_interval.out +++ b/src/test/regress/expected/gpi_interval.out @@ -463,6 +463,7 @@ SELECT COUNT(*) FROM interval_partition_table_004 where c1 <= 7; (1 row) VACUUM full interval_partition_table_004; +set enable_seqscan = off; explain (costs off, nodes off) SELECT COUNT(*) FROM interval_partition_table_004 where c1 <= 7; QUERY PLAN ------------------------------------------------------------------------ @@ -479,6 +480,7 @@ SELECT COUNT(*) FROM interval_partition_table_004 where c1 <= 7; 11293 (1 row) +reset enable_seqscan; --drop table and index drop index if exists ip_index_global; drop index if exists ip_index_local; diff --git a/src/test/regress/sql/gpi_build_index.sql b/src/test/regress/sql/gpi_build_index.sql index 9204d1968..d3f8ee7a4 100644 --- a/src/test/regress/sql/gpi_build_index.sql +++ b/src/test/regress/sql/gpi_build_index.sql @@ -218,3 +218,23 @@ explain (costs off) select * from test_gpi_create_like where c1 = 0; select * from test_gpi_create_like where c1 = 0; drop table test_gpi_create_like; + +drop table if exists gpi_multi_cols; +create table gpi_multi_cols(a0 int,a1 int,a2 int,a3 int,a4 int,a5 int,a6 int,a7 int,a8 int,a9 int,a10 int,a11 int,a12 int,a13 int,a14 int,a15 int,a16 int,a17 int,a18 int,a19 int,a20 int,a21 int,a22 int,a23 int,a24 int,a25 int,a26 int,a27 int,a28 int,a29 int,a30 int,a31 int,a32 int, a33 int) partition by range(a0) (partition p1 values less than (1001), partition p2 values less than (2001), partition p3 values less than (3001)); + +-- success +create index gpi_multi_cols_index on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30) global; +--failed +create index gpi_multi_cols_index on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30, a31) global; +--success +create index gpi_multi_cols_index_local on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30, a31) local; + +insert into gpi_multi_cols select r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r from generate_series(1,3000) as r; + +vacuum analyze gpi_multi_cols; +set enable_seqscan = off; +select * from gpi_multi_cols where a1 = 200; +reset enable_seqscan; + +--clean data +drop table gpi_multi_cols; diff --git a/src/test/regress/sql/gpi_clean_wait.sql b/src/test/regress/sql/gpi_clean_wait.sql index 7802af372..2b854eacd 100644 --- a/src/test/regress/sql/gpi_clean_wait.sql +++ b/src/test/regress/sql/gpi_clean_wait.sql @@ -14,7 +14,7 @@ vacuum analyze test_gpi_more_invalid; start transaction; alter table test_gpi_more_invalid add partition p6 values less than (4001); update test_gpi_more_invalid set a = 3000 + a where a <= 100; -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; explain (costs off) select * from test_gpi_more_invalid where a >= 3000; --100 rows select count(*) from test_gpi_more_invalid where a > 3000; @@ -39,10 +39,10 @@ select count(*) from test_gpi_more_invalid where a <= 100 and b = 100000; -- 0 rows select count(*) from test_gpi_more_invalid where a >= 3000; -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; vacuum analyze test_gpi_more_invalid; -- test_gpi_more_invalid have wait_clean_gpi=n -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; explain (costs off) select count(*) from test_gpi_more_invalid where a <= 100; explain (costs off) select count(*) from test_gpi_more_invalid where a >= 4000; @@ -72,7 +72,7 @@ update test_gpi_more_invalid set b = 1001 where c = 200; commit; -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; set enable_seqscan = off; -- rows 100 @@ -121,17 +121,17 @@ select * from test_gpi_more_invalid where b = 300000 and c = 700 for update; update test_gpi_more_invalid set a = a + 1000 where a > 1000 or a < 500; select count(*) from test_gpi_more_invalid where c = 100 and b = 2000; -- test_gpi_more_invalid/p5 have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; abort; --failed vacuum full pg_partition; -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; vacuum analyze test_gpi_more_invalid; -- test_gpi_more_invalid have wait_clean_gpi=n -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; -- success vacuum full pg_partition; @@ -159,14 +159,14 @@ commit; -- all global index unusuable select c.relname, i.indisusable from pg_index i join pg_class c on i.indexrelid = c.oid where i.indrelid = 'test_gpi_more_invalid'::regclass ORDER BY c.relname; -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; vacuum full test_gpi_more_invalid; -- all global index unusuable select c.relname, i.indisusable from pg_index i join pg_class c on i.indexrelid = c.oid where i.indrelid = 'test_gpi_more_invalid'::regclass ORDER BY c.relname; -- test_gpi_more_invalid have wait_clean_gpi=y -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'test_gpi_more_invalid' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; alter index local_index_gpi_more_invalid_a_b unusable; @@ -200,12 +200,12 @@ vacuum interval_normal_date; start transaction; insert into interval_normal_date select '2020-6-02', r,r from generate_series(0,500) as r; explain (costs off) select count(*) from interval_normal_date where b <= 500; -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; alter table interval_normal_date drop partition sys_p2; commit; -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; vacuum analyze interval_normal_date; -select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by b.relname; +select a.relname,a.parttype,a.reloptions from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_normal_date' and a.reloptions[3] like '%wait_clean_gpi=y%' order by 1,2,3; drop table if exists interval_partition_table_vacuum; create table interval_partition_table_vacuum @@ -232,7 +232,7 @@ vacuum interval_partition_table_vacuum; vacuum analyze interval_partition_table_vacuum; \parallel off -set enable_bitmascan = off; +set enable_bitmapscan = off; explain (costs off) select count(*) from interval_partition_table_vacuum where c1 = 1; -- 11293 rows select count(*) from interval_partition_table_vacuum where c1 = 1; @@ -242,7 +242,7 @@ select true from (select count(*) as count from pg_partition a, pg_class b where vacuum analyze interval_partition_table_vacuum; -- 0 rows select count(*) from pg_partition a, pg_class b where a.parentid = b.oid and b.relname = 'interval_partition_table_vacuum' and a.reloptions[3] like '%wait_clean_gpi=y%'; -reset enable_bitmascan; +reset enable_bitmapscan; -- clean table drop table interval_partition_table_vacuum; diff --git a/src/test/regress/sql/gpi_interval.sql b/src/test/regress/sql/gpi_interval.sql index ce42f035a..382be75ea 100644 --- a/src/test/regress/sql/gpi_interval.sql +++ b/src/test/regress/sql/gpi_interval.sql @@ -272,8 +272,10 @@ ANALYZE interval_partition_table_004; explain (costs off, nodes off) SELECT COUNT(*) FROM interval_partition_table_004 where c1 <= 7; SELECT COUNT(*) FROM interval_partition_table_004 where c1 <= 7; VACUUM full interval_partition_table_004; +set enable_seqscan = off; explain (costs off, nodes off) SELECT COUNT(*) FROM interval_partition_table_004 where c1 <= 7; SELECT COUNT(*) FROM interval_partition_table_004 where c1 <= 7; +reset enable_seqscan; --drop table and index drop index if exists ip_index_global;