diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 5d7493e1949..df5ceacc90f 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -1204,7 +1204,7 @@ brin_summarize_range_internal(PG_FUNCTION_ARGS) /* Must be a BRIN index */ if (indexRel->rd_rel->relkind != RELKIND_INDEX || - indexRel->rd_rel->relam != BRIN_AM_OID) + !IsIndexAccessMethod(indexRel->rd_rel->relam, BRIN_AM_OID)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a BRIN index", @@ -1290,7 +1290,7 @@ brin_desummarize_range(PG_FUNCTION_ARGS) /* Must be a BRIN index */ if (indexRel->rd_rel->relkind != RELKIND_INDEX || - indexRel->rd_rel->relam != BRIN_AM_OID) + !IsIndexAccessMethod(indexRel->rd_rel->relam, BRIN_AM_OID)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a BRIN index", diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index 02d2d6cf4e7..88d2d9a7182 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -1042,7 +1042,7 @@ gin_clean_pending_list(PG_FUNCTION_ARGS) /* Must be a GIN index */ if (indexRel->rd_rel->relkind != RELKIND_INDEX || - indexRel->rd_rel->relam != GIN_AM_OID) + !IsIndexAccessMethod(indexRel->rd_rel->relam, GIN_AM_OID)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a GIN index", diff --git a/src/backend/access/index/amapi.c b/src/backend/access/index/amapi.c index d30bc435146..028b8e9999e 100644 --- a/src/backend/access/index/amapi.c +++ b/src/backend/access/index/amapi.c @@ -20,7 +20,18 @@ #include "utils/builtins.h" #include "utils/syscache.h" +is_index_access_method_hook_type is_index_access_method_hook = NULL; +bool +IsIndexAccessMethod(Oid relam, Oid indexAccessMethod) +{ + if ((is_index_access_method_hook && (*is_index_access_method_hook)(relam, indexAccessMethod)) || + (!is_index_access_method_hook && relam == indexAccessMethod)) + { + return true; + } + return false; +} /* * GetIndexAmRoutine - call the specified access method handler routine to get * its IndexAmRoutine struct, which will be palloc'd in the caller's context. diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 095d4f84e63..ebacc2bfcb5 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -988,3 +988,54 @@ index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, return build_local_reloptions(&relopts, attoptions, validate); } + +/* check_hook: validate new default_index_access_method */ +bool +check_default_index_access_method(char **newval, void **extra, GucSource source) +{ + if (**newval == '\0') + { + GUC_check_errdetail("%s cannot be empty.", + "check_default_index_access_method"); + return false; + } + + if (strlen(*newval) >= NAMEDATALEN) + { + GUC_check_errdetail("%s is too long (maximum %d characters).", + "check_default_index_access_method", NAMEDATALEN - 1); + return false; + } + + /* + * If we aren't inside a transaction, or not connected to a database, we + * cannot do the catalog access necessary to verify the method. Must + * accept the value on faith. + */ + if (IsTransactionState() && MyDatabaseId != InvalidOid) + { + if (!OidIsValid(get_index_am_oid(*newval, true))) + { + /* + * When source == PGC_S_TEST, don't throw a hard error for a + * nonexistent index access method, only a NOTICE. See comments in + * guc.h. + */ + if (source == PGC_S_TEST) + { + ereport(NOTICE, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("index access method \"%s\" does not exist", + *newval))); + } + else + { + GUC_check_errdetail("index access method \"%s\" does not exist.", + *newval); + return false; + } + } + } + + return true; +} diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 5e3a2b7aa47..7c3563024db 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -41,7 +41,6 @@ #include "catalog/indexing.h" #include "catalog/pg_namespace.h" - /* * BTPARALLEL_NOT_INITIALIZED indicates that the scan has not started. * diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index 4484805192c..e3e663a006e 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -35,7 +35,6 @@ #include "utils/lsyscache.h" #include "utils/syscache.h" - /* * SP-GiST handler function: return IndexAmRoutine with access method parameters * and callbacks. diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 917a541c6c0..4438ca40e33 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -99,6 +99,8 @@ #include "cdb/cdboidsync.h" #include "utils/faultinjector.h" +/* GUC variables */ +char *default_index_access_method = DEFAULT_INDEX_TYPE; /* Potentially set by pg_upgrade_support functions */ Oid binary_upgrade_next_index_pg_class_oid = InvalidOid; @@ -2808,7 +2810,7 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii) */ Assert(ii->ii_Unique); - if (index->rd_rel->relam != BTREE_AM_OID) + if (!IsIndexAccessMethod(index->rd_rel->relam, BTREE_AM_OID)) elog(ERROR, "unexpected non-btree speculative unique index"); ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * indnkeyatts); @@ -3129,7 +3131,7 @@ index_build(Relation heapRelation, * to introduce parallelism to singlenode mode. */ if (parallel && !IS_SINGLENODE() && IsNormalProcessingMode() && - indexRelation->rd_rel->relam == BTREE_AM_OID) + IsIndexAccessMethod(indexRelation->rd_rel->relam, BTREE_AM_OID)) indexInfo->ii_ParallelWorkers = plan_create_index_workers(RelationGetRelid(heapRelation), RelationGetRelid(indexRelation)); diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 12ad9fa2af0..ed0762fd42b 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -962,7 +962,7 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, * tells us it's cheaper. Otherwise, always indexscan if an index is * provided, else plain seqscan. */ - if (OldIndex != NULL && OldIndex->rd_rel->relam == BTREE_AM_OID) + if (OldIndex != NULL && IsIndexAccessMethod(OldIndex->rd_rel->relam, BTREE_AM_OID)) use_sort = plan_cluster_use_sort(OIDOldHeap, OIDOldIndex); else use_sort = false; diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 51e30960223..cfbbebdf2be 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1021,6 +1021,10 @@ DefineIndex(Oid relationId, * look up the access method, verify it can handle the requested features */ accessMethodName = stmt->accessMethod; + if (accessMethodName == NULL) + { + accessMethodName = default_index_access_method; + } tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName)); if (!HeapTupleIsValid(tuple)) { @@ -1268,7 +1272,7 @@ DefineIndex(Oid relationId, * btree opclasses; if there are ever any other index types that * support unique indexes, this logic will need extension. */ - if (accessMethodId == BTREE_AM_OID) + if (IsIndexAccessMethod(accessMethodId, BTREE_AM_OID)) eq_strategy = BTEqualStrategyNumber; else ereport(ERROR, diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index b1f6306f681..124f764c15f 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -15,6 +15,7 @@ */ #include "postgres.h" +#include "access/amapi.h" #include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" @@ -908,7 +909,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, if (!HeapTupleIsValid(cla_ht)) elog(ERROR, "cache lookup failed for opclass %u", opclass); cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht); - Assert(cla_tup->opcmethod == BTREE_AM_OID); + Assert(IsIndexAccessMethod(cla_tup->opcmethod, BTREE_AM_OID)); opfamily = cla_tup->opcfamily; opcintype = cla_tup->opcintype; ReleaseSysCache(cla_ht); @@ -1068,7 +1069,7 @@ is_usable_unique_index(Relation indexRel) */ if (indexStruct->indisunique && indexStruct->indimmediate && - indexRel->rd_rel->relam == BTREE_AM_OID && + IsIndexAccessMethod(indexRel->rd_rel->relam, BTREE_AM_OID) && indexStruct->indisvalid && RelationGetIndexPredicate(indexRel) == NIL && indexStruct->indnatts > 0) diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index ab9008ca9cd..4bd2716baea 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -595,7 +595,7 @@ DefineOpClass(CreateOpClassStmt *stmt) if (OidIsValid(storageoid)) { /* Just drop the spec if same as column datatype */ - if (storageoid == typeoid) + if (storageoid == typeoid && !amstorage) storageoid = InvalidOid; else if (!amstorage) ereport(ERROR, @@ -1289,7 +1289,7 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, * returning int4, while proc 2 must be a 2-arg proc returning int8. * Otherwise we don't know. */ - else if (amoid == BTREE_AM_OID) + else if (IsIndexAccessMethod(amoid, BTREE_AM_OID)) { if (member->number == BTORDER_PROC) { @@ -1372,7 +1372,7 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, errmsg("btree equal image functions must not be cross-type"))); } } - else if (amoid == HASH_AM_OID) + else if (IsIndexAccessMethod(amoid, HASH_AM_OID)) { if (member->number == HASHSTANDARD_PROC) { diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 63e1ee76d87..77adf685ddf 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -10751,7 +10751,7 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * strategy number is equality. (Is it reasonable to insist that * every such index AM use btree's number for equality?) */ - if (amid != BTREE_AM_OID) + if (!IsIndexAccessMethod(amid, BTREE_AM_OID)) elog(ERROR, "only b-tree indexes are supported for foreign keys"); eqstrategy = BTEqualStrategyNumber; diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index a083e13d6b2..4c5d3b587e0 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -1378,7 +1378,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, * We have to look up the operator's associated btree support * function */ - if (index->rd_rel->relam != BTREE_AM_OID || + if (!IsIndexAccessMethod(index->rd_rel->relam, BTREE_AM_OID) || varattno < 1 || varattno > indnkeyatts) elog(ERROR, "bogus RowCompare index qualification"); opfamily = index->rd_opfamily[varattno - 1]; diff --git a/src/backend/mock.mk b/src/backend/mock.mk index 11b02242aab..c72c2dca2b0 100644 --- a/src/backend/mock.mk +++ b/src/backend/mock.mk @@ -37,9 +37,6 @@ EXCL_OBJS=\ # of the test programs. Feel free to link them back (i.e. remove them from # this exclusion list) as needed. EXCL_OBJS+=\ - src/backend/access/hash/hash.o \ - src/backend/access/hash/hashsearch.o \ - \ src/backend/utils/adt/cash.o \ src/backend/utils/adt/char.o \ src/backend/utils/adt/complex_type.o \ diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 421ff7bb9ba..d1c7c631a13 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -2830,7 +2830,7 @@ match_rowcompare_to_indexcol(PlannerInfo *root, Oid expr_coll; /* Forget it if we're not dealing with a btree index */ - if (index->relam != BTREE_AM_OID) + if (!IsIndexAccessMethod(index->relam, BTREE_AM_OID)) return NULL; index_relid = index->rel->relid; @@ -3529,7 +3529,7 @@ ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel, * generate_implied_equalities_for_column; see * match_eclass_clauses_to_index. */ - if (index->relam == BTREE_AM_OID && + if (IsIndexAccessMethod(index->relam, BTREE_AM_OID) && !list_member_oid(ec->ec_opfamilies, curFamily)) return false; diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 918c554579e..2371df4eacc 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -19,6 +19,7 @@ #include +#include "access/amapi.h" #include "foreign/fdwapi.h" #include "miscadmin.h" #include "nodes/extensible.h" @@ -1124,7 +1125,7 @@ create_index_path(PlannerInfo *root, required_outer); pathnode->path.parallel_aware = false; /* GPDB_12_MERGE_FEATURE_NOT_SUPPORTED: the parallel StreamBitmap scan is not implemented */ - pathnode->path.parallel_safe = rel->consider_parallel && (index->relam != BITMAP_AM_OID); + pathnode->path.parallel_safe = rel->consider_parallel && !IsIndexAccessMethod(index->relam, BITMAP_AM_OID); pathnode->path.parallel_workers = 0; pathnode->path.pathkeys = pathkeys; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 2281294422c..832635cb981 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -311,7 +311,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, /* * Fetch the ordering information for the index, if any. */ - if (info->relam == BTREE_AM_OID) + if (IsIndexAccessMethod(info->relam, BTREE_AM_OID)) { /* * If it's a btree index, we can use its opfamily OIDs @@ -436,7 +436,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->tuples > rel->tuples) info->tuples = rel->tuples; - if (info->relam == BTREE_AM_OID) + if (IsIndexAccessMethod(info->relam, BTREE_AM_OID)) { /* For btrees, get tree height while we have the index open */ info->tree_height = _bt_getrootheight(indexRelation); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c9a49579eef..300f7da3505 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10165,7 +10165,7 @@ opt_index_name: access_method_clause: USING name { $$ = $2; } - | /*EMPTY*/ { $$ = DEFAULT_INDEX_TYPE; } + | /*EMPTY*/ { $$ = NULL; } ; index_params: index_elem { $$ = list_make1($1); } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index dd07b4075be..e0c8423d45c 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -3289,7 +3289,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) index->idxname = NULL; /* DefineIndex will choose name */ index->relation = cxt->relation; - index->accessMethod = constraint->access_method ? constraint->access_method : DEFAULT_INDEX_TYPE; + index->accessMethod = constraint->access_method ? constraint->access_method : default_index_access_method; index->options = constraint->options; index->tableSpace = constraint->indexspace; index->whereClause = constraint->where_clause; @@ -3413,7 +3413,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) * else dump and reload will produce a different index (breaking * pg_upgrade in particular). */ - if (index_rel->rd_rel->relam != get_index_am_oid(DEFAULT_INDEX_TYPE, false)) + if (!IsIndexAccessMethod(index_rel->rd_rel->relam, BTREE_AM_OID)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("index \"%s\" is not a btree", index_name), diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 221099b03f4..086d627d4d2 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -6229,7 +6229,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, ScanDirection indexscandir; /* Ignore non-btree indexes */ - if (index->relam != BTREE_AM_OID) + if (!IsIndexAccessMethod(index->relam, BTREE_AM_OID)) continue; /* diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index fe6b8c56a56..e57e41b10ec 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -866,8 +866,8 @@ equality_ops_are_compatible(Oid opno1, Oid opno2) Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); /* must be btree or hash */ - if (op_form->amopmethod == BTREE_AM_OID || - op_form->amopmethod == HASH_AM_OID) + if (IsIndexAccessMethod(op_form->amopmethod, BTREE_AM_OID) || + IsIndexAccessMethod(op_form->amopmethod, HASH_AM_OID)) { if (op_in_opfamily(opno2, op_form->amopfamily)) { diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 5cc58b4f5d6..d4df12d2ebd 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -48,6 +48,7 @@ #include "catalog/pg_authid.h" #include "catalog/pg_profile.h" #include "catalog/storage.h" +#include "catalog/index.h" #include "commands/async.h" #include "commands/prepare.h" #include "commands/trigger.h" diff --git a/src/backend/utils/misc/guc_gp.c b/src/backend/utils/misc/guc_gp.c index e19ebd0e951..a25db7f796a 100644 --- a/src/backend/utils/misc/guc_gp.c +++ b/src/backend/utils/misc/guc_gp.c @@ -58,6 +58,7 @@ #include "utils/resource_manager.h" #include "utils/varlena.h" #include "utils/vmem_tracker.h" +#include "catalog/index.h" /* * These constants are copied from guc.c. They should not bitrot when we @@ -4572,6 +4573,17 @@ struct config_string ConfigureNamesString_gp[] = GP_VERSION, NULL, NULL, NULL }, + + { + {"default_index_access_method", PGC_USERSET, CLIENT_CONN_STATEMENT, + gettext_noop("Sets the default index access method."), + NULL, + GUC_IS_NAME + }, + &default_index_access_method, + DEFAULT_INDEX_TYPE, + check_default_index_access_method, NULL, NULL + }, #ifndef USE_INTERNAL_FTS { {"gp_etcd_account_id", PGC_BACKEND, CUSTOM_OPTIONS, diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c index 6a889ec189f..97d8c580d64 100644 --- a/src/backend/utils/sort/sortsupport.c +++ b/src/backend/utils/sort/sortsupport.c @@ -167,7 +167,7 @@ PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy, Assert(ssup->comparator == NULL); - if (indexRel->rd_rel->relam != BTREE_AM_OID) + if (!IsIndexAccessMethod(indexRel->rd_rel->relam, BTREE_AM_OID)) elog(ERROR, "unexpected non-btree AM: %u", indexRel->rd_rel->relam); if (strategy != BTGreaterStrategyNumber && strategy != BTLessStrategyNumber) @@ -194,7 +194,7 @@ PrepareSortSupportFromGistIndexRel(Relation indexRel, SortSupport ssup) Assert(ssup->comparator == NULL); - if (indexRel->rd_rel->relam != GIST_AM_OID) + if (!IsIndexAccessMethod(indexRel->rd_rel->relam, GIST_AM_OID)) elog(ERROR, "unexpected non-gist AM: %u", indexRel->rd_rel->relam); ssup->ssup_reverse = false; diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 8d2bdc3df94..0b9c16f9417 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -985,7 +985,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc, MemoryContext oldcontext; int i; - Assert(indexRel->rd_rel->relam == BTREE_AM_OID); + Assert(IsIndexAccessMethod(indexRel->rd_rel->relam, BTREE_AM_OID)); oldcontext = MemoryContextSwitchTo(state->maincontext); diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h index 02be79c3663..a30f4bb6a63 100644 --- a/src/include/access/amapi.h +++ b/src/include/access/amapi.h @@ -14,6 +14,7 @@ #define AMAPI_H #include "access/genam.h" +#include "catalog/pg_index.h" /* * We don't wish to include planner header files here, since most of an index @@ -285,6 +286,7 @@ typedef struct IndexAmRoutine /* Functions in access/index/amapi.c */ +extern bool IsIndexAccessMethod(Oid relam, Oid indexAccessMethod); extern IndexAmRoutine *GetIndexAmRoutine(Oid amhandler); extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror); diff --git a/src/include/access/brin.h b/src/include/access/brin.h index 4e2be13cd61..5c80a6ae611 100644 --- a/src/include/access/brin.h +++ b/src/include/access/brin.h @@ -38,13 +38,13 @@ typedef struct BrinStatsData #define BRIN_DEFAULT_PAGES_PER_RANGE 128 #define BrinGetPagesPerRange(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == BRIN_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, BRIN_AM_OID)), \ (relation)->rd_options ? \ ((BrinOptions *) (relation)->rd_options)->pagesPerRange : \ BRIN_DEFAULT_PAGES_PER_RANGE) #define BrinGetAutoSummarize(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == BRIN_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, BRIN_AM_OID)), \ (relation)->rd_options ? \ ((BrinOptions *) (relation)->rd_options)->autosummarize : \ false) diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index b24112ff96a..74c9b70dc32 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -32,12 +32,12 @@ typedef struct GinOptions #define GIN_DEFAULT_USE_FASTUPDATE true #define GinGetUseFastUpdate(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == GIN_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, GIN_AM_OID)), \ (relation)->rd_options ? \ ((GinOptions *) (relation)->rd_options)->useFastUpdate : GIN_DEFAULT_USE_FASTUPDATE) #define GinGetPendingListCleanupSize(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == GIN_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, GIN_AM_OID)), \ (relation)->rd_options && \ ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize != -1 ? \ ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize : \ diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 6de41944a9c..f29cd3db35e 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -272,7 +272,7 @@ typedef struct HashOptions #define HashGetFillFactor(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == HASH_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, HASH_AM_OID)), \ (relation)->rd_options ? \ ((HashOptions *) (relation)->rd_options)->fillfactor : \ HASH_DEFAULT_FILLFACTOR) diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 28d360d058f..816a0fe761d 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -1092,7 +1092,7 @@ typedef struct BTOptions #define BTGetFillFactor(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == BTREE_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, BTREE_AM_OID)), \ (relation)->rd_options ? \ ((BTOptions *) (relation)->rd_options)->fillfactor : \ BTREE_DEFAULT_FILLFACTOR) @@ -1100,7 +1100,7 @@ typedef struct BTOptions (BLCKSZ * (100 - BTGetFillFactor(relation)) / 100) #define BTGetDeduplicateItems(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == BTREE_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, BTREE_AM_OID)), \ ((relation)->rd_options ? \ ((BTOptions *) (relation)->rd_options)->deduplicate_items : true)) diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h index 40d3b71b89e..cc7f0922556 100644 --- a/src/include/access/spgist_private.h +++ b/src/include/access/spgist_private.h @@ -31,7 +31,7 @@ typedef struct SpGistOptions #define SpGistGetFillFactor(relation) \ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == SPGIST_AM_OID), \ + IsIndexAccessMethod(relation->rd_rel->relam, SPGIST_AM_OID)), \ (relation)->rd_options ? \ ((SpGistOptions *) (relation)->rd_options)->fillfactor : \ SPGIST_DEFAULT_FILLFACTOR) diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 8e0ee2349b2..28985171776 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -20,10 +20,13 @@ #include "catalog/objectaddress.h" #include "executor/tuptable.h" /* TupTableSlot */ #include "nodes/execnodes.h" +#include "utils/guc.h" struct EState; /* #include "nodes/execnodes.h" */ #define DEFAULT_INDEX_TYPE "btree" +/* GUCs */ +extern char *default_index_access_method; /* Action code for index_set_state_flags */ typedef enum @@ -225,6 +228,8 @@ extern void SerializeReindexState(Size maxsize, char *start_address); extern void RestoreReindexState(void *reindexstate); extern void IndexSetParentIndex(Relation idx, Oid parentOid); +extern bool check_default_index_access_method(char **newval, void **extra, + GucSource source); /* diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h index 38b5bfc42c2..15794cb50ef 100644 --- a/src/include/catalog/pg_index.h +++ b/src/include/catalog/pg_index.h @@ -73,6 +73,8 @@ FOREIGN_KEY(indrelid REFERENCES pg_class(oid)); * ---------------- */ typedef FormData_pg_index *Form_pg_index; +typedef bool (*is_index_access_method_hook_type)(Oid id, Oid expected_oid); +extern PGDLLIMPORT is_index_access_method_hook_type is_index_access_method_hook; DECLARE_INDEX(pg_index_indrelid_index, 2678, on pg_index using btree(indrelid oid_ops)); #define IndexIndrelidIndexId 2678 diff --git a/src/include/utils/sync_guc_name.h b/src/include/utils/sync_guc_name.h index 1b4c8a040c4..aefc91e8716 100644 --- a/src/include/utils/sync_guc_name.h +++ b/src/include/utils/sync_guc_name.h @@ -17,6 +17,7 @@ "DateStyle", "debug_discard_caches", "default_table_access_method", + "default_index_access_method", "default_tablespace", "default_toast_compression", "dml_ignore_target_partition_check", diff --git a/src/test/regress/expected/brin.out b/src/test/regress/expected/brin.out index 73a68af6b51..bdc3dad0569 100644 --- a/src/test/regress/expected/brin.out +++ b/src/test/regress/expected/brin.out @@ -560,7 +560,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM brin_test WHERE b = 1; (4 rows) -- make sure data are properly de-toasted in BRIN index -CREATE TABLE brintest_3 (a text, b text, c text, d text); +CREATE TABLE brintest_3 (a text, b text, c text, d text, e varchar); -- long random strings (~2000 chars each, so ~6kB for min/max on two -- columns) to trigger toasting WITH rand_value AS (SELECT string_agg(md5(i::text),'') AS val FROM generate_series(1,60) s(i)) @@ -573,6 +573,9 @@ DELETE FROM brintest_3; -- is a one way to achieve that, because it does exactly such wait. CREATE INDEX brin_test_temp_idx ON brintest_3(a); DROP INDEX brin_test_temp_idx; +-- make sure varchar to text implicitly +CREATE INDEX brin_test_varchar_to_text_idx on brintest_3(e); +DROP INDEX brin_test_varchar_to_text_idx; -- vacuum the table, to discard TOAST data VACUUM brintest_3; -- retry insert with a different random-looking (but deterministic) value @@ -596,8 +599,8 @@ SELECT * FROM brintest_3 WHERE b < '0'; (6 rows) SELECT * FROM brintest_3 WHERE b < '0'; - a | b | c | d ----+---+---+--- + a | b | c | d | e +---+---+---+---+--- (0 rows) DROP TABLE brintest_3; diff --git a/src/test/regress/expected/brin_optimizer.out b/src/test/regress/expected/brin_optimizer.out index 3dd5ff30598..a95155d8344 100644 --- a/src/test/regress/expected/brin_optimizer.out +++ b/src/test/regress/expected/brin_optimizer.out @@ -584,7 +584,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM brin_test WHERE b = 1; (6 rows) -- make sure data are properly de-toasted in BRIN index -CREATE TABLE brintest_3 (a text, b text, c text, d text); +CREATE TABLE brintest_3 (a text, b text, c text, d text, e varchar); NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Cloudberry Database data distribution key for this table. HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. -- long random strings (~2000 chars each, so ~6kB for min/max on two @@ -601,6 +601,9 @@ HINT: For non-partitioned tables, run analyze (). For -- is a one way to achieve that, because it does exactly such wait. CREATE INDEX brin_test_temp_idx ON brintest_3(a); DROP INDEX brin_test_temp_idx; +-- make sure varchar to text implicitly +CREATE INDEX brin_test_varchar_to_text_idx on brintest_3(e); +DROP INDEX brin_test_varchar_to_text_idx; -- vacuum the table, to discard TOAST data VACUUM brintest_3; -- retry insert with a different random-looking (but deterministic) value @@ -624,8 +627,8 @@ SELECT * FROM brintest_3 WHERE b < '0'; (6 rows) SELECT * FROM brintest_3 WHERE b < '0'; - a | b | c | d ----+---+---+--- + a | b | c | d | e +---+---+---+---+--- (0 rows) DROP TABLE brintest_3; diff --git a/src/test/regress/sql/brin.sql b/src/test/regress/sql/brin.sql index c8879599a5f..e9704aaa0d7 100644 --- a/src/test/regress/sql/brin.sql +++ b/src/test/regress/sql/brin.sql @@ -511,7 +511,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM brin_test WHERE a = 1; EXPLAIN (COSTS OFF) SELECT * FROM brin_test WHERE b = 1; -- make sure data are properly de-toasted in BRIN index -CREATE TABLE brintest_3 (a text, b text, c text, d text); +CREATE TABLE brintest_3 (a text, b text, c text, d text, e varchar); -- long random strings (~2000 chars each, so ~6kB for min/max on two -- columns) to trigger toasting @@ -528,6 +528,10 @@ DELETE FROM brintest_3; CREATE INDEX brin_test_temp_idx ON brintest_3(a); DROP INDEX brin_test_temp_idx; +-- make sure varchar to text implicitly +CREATE INDEX brin_test_varchar_to_text_idx on brintest_3(e); +DROP INDEX brin_test_varchar_to_text_idx; + -- vacuum the table, to discard TOAST data VACUUM brintest_3;