mirror of
https://github.com/HypoPG/hypopg
synced 2026-05-23 17:18:44 +00:00
pgindent run and update changelog for last msvc commit.
Also update typedefs.list.
This commit is contained in:
parent
4a5dc56169
commit
acd87ef01a
9 changed files with 1389 additions and 610 deletions
|
|
@ -12,6 +12,7 @@ WIP version 2.0.0:
|
|||
**Miscellaneous**
|
||||
|
||||
- Use a dedicated MemoryContext to store hypothetical objects
|
||||
- Fix compatibility on Windows (Godwottery)
|
||||
|
||||
**Bug fixes:**
|
||||
|
||||
|
|
|
|||
146
hypopg.c
146
hypopg.c
|
|
@ -43,27 +43,27 @@ PG_MODULE_MAGIC;
|
|||
|
||||
typedef struct hypoWalkerContext
|
||||
{
|
||||
bool explain_found;
|
||||
bool explain_found;
|
||||
} hypoWalkerContext;
|
||||
|
||||
/*--- Variables exported ---*/
|
||||
|
||||
bool isExplain;
|
||||
bool hypo_is_enabled;
|
||||
bool isExplain;
|
||||
bool hypo_is_enabled;
|
||||
MemoryContext HypoMemoryContext;
|
||||
|
||||
/*--- Variables not exported ---*/
|
||||
|
||||
static List *pending_invals = NIL; /* List of interesting OID for which we
|
||||
received inval messages that need to be
|
||||
processed. */
|
||||
static List *pending_invals = NIL; /* List of interesting OID for which we
|
||||
* received inval messages that need to be
|
||||
* processed. */
|
||||
|
||||
/*--- Functions --- */
|
||||
|
||||
PGDLLEXPORT void _PG_init(void);
|
||||
PGDLLEXPORT void _PG_fini(void);
|
||||
PGDLLEXPORT void _PG_init(void);
|
||||
PGDLLEXPORT void _PG_fini(void);
|
||||
|
||||
PGDLLEXPORT Datum hypopg_reset(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_reset(PG_FUNCTION_ARGS);
|
||||
|
||||
PG_FUNCTION_INFO_V1(hypopg_reset);
|
||||
|
||||
|
|
@ -100,15 +100,15 @@ static void hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
static get_relation_info_hook_type prev_get_relation_info_hook = NULL;
|
||||
|
||||
static bool hypo_get_relation_stats_hook(PlannerInfo *root,
|
||||
RangeTblEntry *rte,
|
||||
AttrNumber attnum,
|
||||
VariableStatData *vardata);
|
||||
RangeTblEntry *rte,
|
||||
AttrNumber attnum,
|
||||
VariableStatData *vardata);
|
||||
static get_relation_stats_hook_type prev_get_relation_stats_hook = NULL;
|
||||
#if PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 110000
|
||||
static void hypo_set_rel_pathlist_hook(PlannerInfo *root,
|
||||
RelOptInfo *rel,
|
||||
Index rti,
|
||||
RangeTblEntry *rte);
|
||||
RelOptInfo *rel,
|
||||
Index rti,
|
||||
RangeTblEntry *rte);
|
||||
static set_rel_pathlist_hook_type prev_set_rel_pathlist_hook = NULL;
|
||||
#endif
|
||||
|
||||
|
|
@ -144,15 +144,15 @@ _PG_init(void)
|
|||
#endif
|
||||
|
||||
HypoMemoryContext = AllocSetContextCreate(TopMemoryContext,
|
||||
"HypoPG context",
|
||||
"HypoPG context",
|
||||
#if PG_VERSION_NUM >= 90600
|
||||
ALLOCSET_DEFAULT_SIZES
|
||||
ALLOCSET_DEFAULT_SIZES
|
||||
#else
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE
|
||||
#endif
|
||||
);
|
||||
);
|
||||
|
||||
DefineCustomBoolVariable("hypopg.enabled",
|
||||
"Enable / Disable hypopg",
|
||||
|
|
@ -240,15 +240,15 @@ hypo_utility_hook(
|
|||
DestReceiver *dest,
|
||||
char *completionTag)
|
||||
{
|
||||
hypoWalkerContext hypo_context = { 0 };
|
||||
hypoWalkerContext hypo_context = {0};
|
||||
|
||||
hypo_query_walker(
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
(Node *) pstmt,
|
||||
(Node *) pstmt,
|
||||
#else
|
||||
parsetree,
|
||||
parsetree,
|
||||
#endif
|
||||
&hypo_context);
|
||||
&hypo_context);
|
||||
|
||||
isExplain = hypo_context.explain_found;
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ hypo_utility_hook(
|
|||
#endif
|
||||
params,
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
queryEnv,
|
||||
queryEnv,
|
||||
#endif
|
||||
#if PG_VERSION_NUM < 90300
|
||||
isTopLevel,
|
||||
|
|
@ -313,9 +313,10 @@ hypo_query_walker(Node *node, hypoWalkerContext *context)
|
|||
{
|
||||
case T_PlannedStmt:
|
||||
{
|
||||
Node *stmt = ((PlannedStmt *) node)->utilityStmt;
|
||||
Node *stmt = ((PlannedStmt *) node)->utilityStmt;
|
||||
|
||||
return query_or_expression_tree_walker(stmt, hypo_query_walker,
|
||||
context, QTW_IGNORE_RANGE_TABLE);
|
||||
context, QTW_IGNORE_RANGE_TABLE);
|
||||
}
|
||||
case T_ExplainStmt:
|
||||
{
|
||||
|
|
@ -332,6 +333,7 @@ hypo_query_walker(Node *node, hypoWalkerContext *context)
|
|||
|
||||
context->explain_found = true;
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
|
||||
/*
|
||||
* No point in looking for unhandled command type if there are
|
||||
* no hypothetical partitions
|
||||
|
|
@ -348,35 +350,36 @@ hypo_query_walker(Node *node, hypoWalkerContext *context)
|
|||
#if PG_VERSION_NUM >= 100000
|
||||
case T_Query:
|
||||
{
|
||||
Query *query = (Query *) node;
|
||||
Query *query = (Query *) node;
|
||||
|
||||
Assert(context->explain_found);
|
||||
|
||||
if (context->explain_found &&
|
||||
(query->commandType == CMD_UPDATE ||
|
||||
query->commandType == CMD_DELETE)
|
||||
)
|
||||
(query->commandType == CMD_UPDATE ||
|
||||
query->commandType == CMD_DELETE)
|
||||
)
|
||||
{
|
||||
RangeTblEntry *rte = rt_fetch(query->resultRelation,
|
||||
query->rtable);
|
||||
query->rtable);
|
||||
|
||||
if (hypo_table_oid_is_hypothetical(rte->relid))
|
||||
elog(ERROR, "hypopg: UPDATE and DELETE on hypothetically"
|
||||
" partitioned tables are not supported");
|
||||
" partitioned tables are not supported");
|
||||
}
|
||||
|
||||
if (query->cteList)
|
||||
{
|
||||
ListCell *lc;
|
||||
ListCell *lc;
|
||||
|
||||
foreach(lc, query->cteList)
|
||||
{
|
||||
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
|
||||
|
||||
hypo_query_walker(cte->ctequery, context);
|
||||
}
|
||||
}
|
||||
return query_or_expression_tree_walker(node, hypo_query_walker,
|
||||
context, QTW_IGNORE_RANGE_TABLE);
|
||||
context, QTW_IGNORE_RANGE_TABLE);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
|
@ -385,7 +388,7 @@ hypo_query_walker(Node *node, hypoWalkerContext *context)
|
|||
}
|
||||
|
||||
return query_or_expression_tree_walker(node, hypo_query_walker, context,
|
||||
QTW_IGNORE_RANGE_TABLE);
|
||||
QTW_IGNORE_RANGE_TABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -403,7 +406,7 @@ static void
|
|||
hypo_CacheRelCallback(Datum arg, Oid relid)
|
||||
{
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
hypoTable *entry;
|
||||
hypoTable *entry;
|
||||
|
||||
entry = hypo_find_table(relid, true);
|
||||
if (entry)
|
||||
|
|
@ -428,7 +431,7 @@ void
|
|||
hypo_process_inval(void)
|
||||
{
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
ListCell *lc;
|
||||
ListCell *lc;
|
||||
|
||||
Assert(IsTransactionState());
|
||||
|
||||
|
|
@ -446,13 +449,13 @@ hypo_process_inval(void)
|
|||
{
|
||||
Oid relid = lfirst_oid(lc);
|
||||
hypoTable *entry = hypo_find_table(relid, false);
|
||||
char *relname = get_rel_name(relid);
|
||||
bool found = false;
|
||||
char *relname = get_rel_name(relid);
|
||||
bool found = false;
|
||||
|
||||
/*
|
||||
* The pending invalidations should be filtered and recorded after
|
||||
* removing an entry, and should always be processed before any attempt
|
||||
* to remove a hypothetical object, so we shoudl always find a
|
||||
* removing an entry, and should always be processed before any
|
||||
* attempt to remove a hypothetical object, so we shoudl always find a
|
||||
* hypoTable at this point.
|
||||
*/
|
||||
Assert(entry);
|
||||
|
|
@ -462,7 +465,7 @@ hypo_process_inval(void)
|
|||
|
||||
if (found)
|
||||
elog(DEBUG1, "hypopg: hypo_process_inval removed table %s (%d)",
|
||||
relname, relid);
|
||||
relname, relid);
|
||||
}
|
||||
|
||||
list_free(pending_invals);
|
||||
|
|
@ -502,14 +505,14 @@ hypo_executorEnd_hook(QueryDesc *queryDesc)
|
|||
*/
|
||||
static void
|
||||
hypo_get_relation_info_hook(PlannerInfo *root,
|
||||
Oid relationObjectId,
|
||||
bool inhparent,
|
||||
RelOptInfo *rel)
|
||||
Oid relationObjectId,
|
||||
bool inhparent,
|
||||
RelOptInfo *rel)
|
||||
{
|
||||
Relation relation;
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
RangeTblEntry *rte = planner_rt_fetch(rel->relid, root);
|
||||
bool hypopart = false;
|
||||
bool hypopart = false;
|
||||
#endif
|
||||
|
||||
if (HYPO_ENABLED())
|
||||
|
|
@ -517,9 +520,10 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
hypopart = hypo_table_oid_is_hypothetical(relationObjectId);
|
||||
|
||||
/*
|
||||
* If this relation is table we want to partition hypothetical,
|
||||
* inject hypothetical partitioning
|
||||
* If this relation is table we want to partition hypothetical, inject
|
||||
* hypothetical partitioning
|
||||
*/
|
||||
if (hypopart)
|
||||
hypo_injectHypotheticalPartitioning(root, relationObjectId, rel);
|
||||
|
|
@ -534,10 +538,11 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
#endif
|
||||
)
|
||||
{
|
||||
ListCell *lc;
|
||||
Oid parentId = relationObjectId;
|
||||
ListCell *lc;
|
||||
Oid parentId = relationObjectId;
|
||||
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
|
||||
/*
|
||||
* If this rel is a partition, get root table oid to look for
|
||||
* hypothetical indexes.
|
||||
|
|
@ -548,19 +553,20 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
{
|
||||
/*
|
||||
* when this is a real partition, we have to search root
|
||||
* table from PlannerInfo to get root table oid. when this
|
||||
* is a hypothetical partition, root table oid is equal to
|
||||
* relationObjectId, so nothing to do
|
||||
* table from PlannerInfo to get root table oid. when
|
||||
* this is a hypothetical partition, root table oid is
|
||||
* equal to relationObjectId, so nothing to do
|
||||
*/
|
||||
AppendRelInfo *appinfo;
|
||||
RelOptInfo *parentrel = rel;
|
||||
|
||||
do
|
||||
{
|
||||
#if PG_VERSION_NUM >= 110000
|
||||
appinfo = root->append_rel_array[parentrel->relid];
|
||||
#else
|
||||
appinfo = find_childrel_appendrelinfo(root, parentrel);
|
||||
#endif /* pg10 only */
|
||||
#endif /* pg10 only */
|
||||
parentrel = find_base_rel(root, appinfo->parent_relid);
|
||||
} while (parentrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
|
||||
parentId = appinfo->parent_reloid;
|
||||
|
|
@ -580,7 +586,7 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
#if PG_VERSION_NUM >= 110000
|
||||
&& !rel->part_scheme
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
oid = parentId;
|
||||
}
|
||||
|
|
@ -590,17 +596,19 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
{
|
||||
oid = relationObjectId;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for hypothetical index on hypothetical leaf partition
|
||||
*/
|
||||
else if (hypo_table_oid_is_hypothetical(relationObjectId) &&
|
||||
HYPO_TABLE_RTE_HAS_HYPOOID(rte) &&
|
||||
entry->relid == HYPO_TABLE_RTE_GET_HYPOOID(rte)
|
||||
)
|
||||
HYPO_TABLE_RTE_HAS_HYPOOID(rte) &&
|
||||
entry->relid == HYPO_TABLE_RTE_GET_HYPOOID(rte)
|
||||
)
|
||||
{
|
||||
oid = HYPO_TABLE_RTE_GET_HYPOOID(rte);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* hypothetical index found, add it to the relation's
|
||||
* indextlist
|
||||
|
|
@ -619,17 +627,17 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
|
||||
static bool
|
||||
hypo_get_relation_stats_hook(PlannerInfo *root,
|
||||
RangeTblEntry *rte,
|
||||
AttrNumber attnum,
|
||||
VariableStatData *vardata)
|
||||
RangeTblEntry *rte,
|
||||
AttrNumber attnum,
|
||||
VariableStatData *vardata)
|
||||
{
|
||||
#if PG_VERSION_NUM < 100000
|
||||
return false;
|
||||
#else
|
||||
Oid poid = InvalidOid;
|
||||
Oid poid = InvalidOid;
|
||||
hypoStatsKey key;
|
||||
hypoStatsEntry *entry;
|
||||
bool found;
|
||||
bool found;
|
||||
|
||||
/* Nothing to do if it's not a plain relation */
|
||||
if (rte->rtekind != RTE_RELATION)
|
||||
|
|
@ -638,8 +646,8 @@ hypo_get_relation_stats_hook(PlannerInfo *root,
|
|||
/*
|
||||
* If this is a root table hypothetically partitioned, we have to retrieve
|
||||
* the pg_statistic row ourselves, even if no hypopg_analyze has been
|
||||
* performed yet, because postgres will search for an entry with stainherit
|
||||
* = true, which won't exist.
|
||||
* performed yet, because postgres will search for an entry with
|
||||
* stainherit = true, which won't exist.
|
||||
*/
|
||||
if (HYPO_RTE_IS_TAGGED(rte) && (!HYPO_TABLE_RTE_HAS_HYPOOID(rte)))
|
||||
{
|
||||
|
|
@ -708,8 +716,8 @@ hypo_set_rel_pathlist_hook(PlannerInfo *root,
|
|||
Index rti,
|
||||
RangeTblEntry *rte)
|
||||
{
|
||||
if(HYPO_ENABLED() && hypo_table_oid_is_hypothetical(rte->relid) && rte->relkind == 'r')
|
||||
hypo_markDummyIfExcluded(root,rel,rti,rte);
|
||||
if (HYPO_ENABLED() && hypo_table_oid_is_hypothetical(rte->relid) && rte->relkind == 'r')
|
||||
hypo_markDummyIfExcluded(root, rel, rti, rte);
|
||||
|
||||
if (prev_set_rel_pathlist_hook)
|
||||
prev_set_rel_pathlist_hook(root, rel, rti, rte);
|
||||
|
|
|
|||
226
hypopg_index.c
226
hypopg_index.c
|
|
@ -75,7 +75,7 @@
|
|||
|
||||
#if PG_VERSION_NUM >= 90600
|
||||
/* this will be updated, when needed, by hypo_discover_am */
|
||||
static Oid BLOOM_AM_OID = InvalidOid;
|
||||
static Oid BLOOM_AM_OID = InvalidOid;
|
||||
#endif
|
||||
|
||||
/*--- Variables exported ---*/
|
||||
|
|
@ -99,10 +99,10 @@ static void hypo_discover_am(char *amname, Oid oid);
|
|||
static void hypo_estimate_index_simple(hypoIndex *entry,
|
||||
BlockNumber *pages, double *tuples);
|
||||
static void hypo_estimate_index(hypoIndex *entry, RelOptInfo *rel,
|
||||
PlannerInfo *root);
|
||||
static int hypo_estimate_index_colsize(hypoIndex *entry, int col);
|
||||
PlannerInfo *root);
|
||||
static int hypo_estimate_index_colsize(hypoIndex *entry, int col);
|
||||
static void hypo_index_check_uniqueness_compatibility(IndexStmt *stmt,
|
||||
Oid relid, hypoIndex *entry);
|
||||
Oid relid, hypoIndex *entry);
|
||||
static void hypo_index_pfree(hypoIndex *entry);
|
||||
static bool hypo_index_remove(Oid indexid);
|
||||
static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node,
|
||||
|
|
@ -120,7 +120,7 @@ static void hypo_set_indexname(hypoIndex *entry, char *indexname);
|
|||
*/
|
||||
static hypoIndex *
|
||||
hypo_newIndex(Oid relid, char *accessMethod, int nkeycolumns, int ninccolumns,
|
||||
List *options)
|
||||
List *options)
|
||||
{
|
||||
/* must be declared "volatile", because used in a PG_CATCH() */
|
||||
hypoIndex *volatile entry;
|
||||
|
|
@ -153,6 +153,7 @@ hypo_newIndex(Oid relid, char *accessMethod, int nkeycolumns, int ninccolumns,
|
|||
entry->relam = HeapTupleGetOid(tuple);
|
||||
|
||||
#if PG_VERSION_NUM >= 90600
|
||||
|
||||
/*
|
||||
* Since 9.6, AM informations are available through an amhandler function,
|
||||
* returning an IndexAmRoutine containing what's needed.
|
||||
|
|
@ -250,15 +251,15 @@ hypo_newIndex(Oid relid, char *accessMethod, int nkeycolumns, int ninccolumns,
|
|||
#if PG_VERSION_NUM >= 90600
|
||||
&& entry->relam != BLOOM_AM_OID
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
/*
|
||||
* do not store hypothetical indexes with access method not
|
||||
* supported
|
||||
*/
|
||||
elog(ERROR, "hypopg: access method \"%s\" is not supported",
|
||||
accessMethod);
|
||||
break;
|
||||
/*
|
||||
* do not store hypothetical indexes with access method not
|
||||
* supported
|
||||
*/
|
||||
elog(ERROR, "hypopg: access method \"%s\" is not supported",
|
||||
accessMethod);
|
||||
break;
|
||||
}
|
||||
|
||||
/* No more elog beyond this point. */
|
||||
|
|
@ -350,15 +351,15 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
|
||||
if (!table)
|
||||
elog(ERROR, "hypopg: table %s does not exists",
|
||||
quote_identifier(rv->relname));
|
||||
quote_identifier(rv->relname));
|
||||
|
||||
if (table->partkey)
|
||||
#if PG_VERSION_NUM < 110000
|
||||
elog(ERROR, "hypopg: cannot add hypothetical index on non-leaf "
|
||||
"hypothetical partition");
|
||||
"hypothetical partition");
|
||||
#else
|
||||
elog(ERROR, "hypopg: cannot add hypothetical index on non-leaf "
|
||||
"or non-root hypothetical partition");
|
||||
"or non-root hypothetical partition");
|
||||
#endif
|
||||
|
||||
relid = table->rootid;
|
||||
|
|
@ -382,7 +383,7 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
table = hypo_find_table(relid, true);
|
||||
if (table)
|
||||
elog(ERROR, "hypopg: cannot add hypothetical index on non-leaf "
|
||||
"hypothetical partition");
|
||||
"hypothetical partition");
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM >= 110000
|
||||
|
|
@ -392,11 +393,11 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
|
||||
if (!ok)
|
||||
elog(ERROR, "hypopg: cannot add hypothetical index on non-leaf "
|
||||
"or non-root partition");
|
||||
"or non-root partition");
|
||||
#endif
|
||||
if (!ok)
|
||||
elog(ERROR, "hypopg: cannot add hypothetical index on non-leaf "
|
||||
"partition");
|
||||
"partition");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -450,13 +451,13 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
if (node->unique && !entry->amcanunique)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("hypopg: access method \"%s\" does not support unique indexes",
|
||||
node->accessMethod)));
|
||||
errmsg("hypopg: access method \"%s\" does not support unique indexes",
|
||||
node->accessMethod)));
|
||||
if (nkeycolumns > 1 && !entry->amcanmulticol)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("hypopg: access method \"%s\" does not support multicolumn indexes",
|
||||
node->accessMethod)));
|
||||
errmsg("hypopg: access method \"%s\" does not support multicolumn indexes",
|
||||
node->accessMethod)));
|
||||
|
||||
entry->unique = node->unique;
|
||||
entry->ncolumns = nkeycolumns + ninccolumns;
|
||||
|
|
@ -532,8 +533,8 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
* they're only computed when a real index exists (selectivity
|
||||
* and average width).
|
||||
*/
|
||||
MemoryContext oldcontext;
|
||||
Node *expr = attribute->expr;
|
||||
MemoryContext oldcontext;
|
||||
Node *expr = attribute->expr;
|
||||
|
||||
Assert(expr != NULL);
|
||||
entry->indexcollations[attn] = exprCollation(attribute->expr);
|
||||
|
|
@ -556,7 +557,9 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
* Treat it like simple attribute anyway.
|
||||
*/
|
||||
entry->indexkeys[attn] = ((Var *) expr)->varattno;
|
||||
/* Generated index name will have _expr instead of attname
|
||||
|
||||
/*
|
||||
* Generated index name will have _expr instead of attname
|
||||
* in generated index name, and error message will also be
|
||||
* slighty different in case on unexisting column from a
|
||||
* simple attribute, but that's how ComputeIndexAttrs()
|
||||
|
|
@ -588,7 +591,7 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
|
||||
oldcontext = MemoryContextSwitchTo(HypoMemoryContext);
|
||||
entry->indexprs = lappend(entry->indexprs,
|
||||
(Node *) copyObject(attribute->expr));
|
||||
(Node *) copyObject(attribute->expr));
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
}
|
||||
}
|
||||
|
|
@ -651,7 +654,7 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
entry->nulls_first[attn] = true;
|
||||
}
|
||||
else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
|
||||
entry->nulls_first[attn] = true;
|
||||
entry->nulls_first[attn] = true;
|
||||
}
|
||||
|
||||
/* handle index-only scan info */
|
||||
|
|
@ -673,7 +676,7 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
#else
|
||||
/* per-column IOS information */
|
||||
entry->canreturn[attn] = hypo_can_return(entry, atttype, attn,
|
||||
node->accessMethod);
|
||||
node->accessMethod);
|
||||
#endif
|
||||
|
||||
attn++;
|
||||
|
|
@ -692,15 +695,16 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
if (attno < 0 && attno != ObjectIdAttributeNumber)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("hypopg: index creation on system columns is not supported")));
|
||||
errmsg("hypopg: index creation on system columns is not supported")));
|
||||
}
|
||||
|
||||
#if PG_VERSION_NUM >= 110000
|
||||
/*
|
||||
* check for uniqueness compatibility with (hypothetically) partitioned
|
||||
* tables
|
||||
*/
|
||||
hypo_index_check_uniqueness_compatibility(node, relid, entry);
|
||||
|
||||
/*
|
||||
* check for uniqueness compatibility with (hypothetically)
|
||||
* partitioned tables
|
||||
*/
|
||||
hypo_index_check_uniqueness_compatibility(node, relid, entry);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -767,19 +771,20 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
|
||||
/* per-column IOS information */
|
||||
entry->canreturn[attn] = hypo_can_return(entry, atttype, attn,
|
||||
node->accessMethod);
|
||||
node->accessMethod);
|
||||
|
||||
attn++;
|
||||
}
|
||||
Assert(attn == (nkeycolumns + ninccolumns));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Also check for system columns used in expressions or predicates.
|
||||
*/
|
||||
if (entry->indexprs || entry->indpred)
|
||||
{
|
||||
Bitmapset *indexattrs = NULL;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
pull_varattnos((Node *) entry->indexprs, 1, &indexattrs);
|
||||
pull_varattnos((Node *) entry->indpred, 1, &indexattrs);
|
||||
|
|
@ -791,7 +796,7 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
indexattrs))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("hypopg: index creation on system columns is not supported")));
|
||||
errmsg("hypopg: index creation on system columns is not supported")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -805,9 +810,9 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
"exceeds maximum %ld",
|
||||
ind_avg_width, HYPO_BTMaxItemSize),
|
||||
errhint("Values larger than 1/3 of a buffer page "
|
||||
"cannot be indexed.\nConsider a function index "
|
||||
" of an MD5 hash of the value, or use full text "
|
||||
"indexing\n(which is not yet supported by hypopg)."
|
||||
"cannot be indexed.\nConsider a function index "
|
||||
" of an MD5 hash of the value, or use full text "
|
||||
"indexing\n(which is not yet supported by hypopg)."
|
||||
)));
|
||||
/* Warn about posssible error with a 80% avg size */
|
||||
else if (ind_avg_width >= HYPO_BTMaxItemSize * .8)
|
||||
|
|
@ -817,9 +822,9 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
"is close to maximum %ld",
|
||||
ind_avg_width, HYPO_BTMaxItemSize),
|
||||
errhint("Values larger than 1/3 of a buffer page "
|
||||
"cannot be indexed.\nConsider a function index "
|
||||
" of an MD5 hash of the value, or use full text "
|
||||
"indexing\n(which is not yet supported by hypopg)."
|
||||
"cannot be indexed.\nConsider a function index "
|
||||
" of an MD5 hash of the value, or use full text "
|
||||
"indexing\n(which is not yet supported by hypopg)."
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -935,12 +940,12 @@ hypo_index_remove(Oid indexid)
|
|||
*/
|
||||
static void
|
||||
hypo_index_check_uniqueness_compatibility(IndexStmt *stmt, Oid relid,
|
||||
hypoIndex *entry)
|
||||
hypoIndex *entry)
|
||||
{
|
||||
PartitionKey key = NULL;
|
||||
Relation rel;
|
||||
const char *extra;
|
||||
int i;
|
||||
PartitionKey key = NULL;
|
||||
Relation rel;
|
||||
const char *extra;
|
||||
int i;
|
||||
|
||||
if (!stmt->unique)
|
||||
return;
|
||||
|
|
@ -949,7 +954,7 @@ hypo_index_check_uniqueness_compatibility(IndexStmt *stmt, Oid relid,
|
|||
|
||||
if (hypo_table_oid_is_hypothetical(relid))
|
||||
{
|
||||
hypoTable *table = hypo_find_table(relid, false);
|
||||
hypoTable *table = hypo_find_table(relid, false);
|
||||
|
||||
key = table->partkey;
|
||||
extra = "hypothetical ";
|
||||
|
|
@ -967,13 +972,13 @@ hypo_index_check_uniqueness_compatibility(IndexStmt *stmt, Oid relid,
|
|||
}
|
||||
|
||||
/*
|
||||
* A partitioned table can have unique indexes, as long as all the
|
||||
* columns in the partition key appear in the unique key. A
|
||||
* partition-local index can enforce global uniqueness iff the PK
|
||||
* value completely determines the partition that a row is in.
|
||||
* A partitioned table can have unique indexes, as long as all the columns
|
||||
* in the partition key appear in the unique key. A partition-local index
|
||||
* can enforce global uniqueness iff the PK value completely determines
|
||||
* the partition that a row is in.
|
||||
*
|
||||
* Thus, verify that all the columns in the partition key appear in
|
||||
* the unique key definition.
|
||||
* Thus, verify that all the columns in the partition key appear in the
|
||||
* unique key definition.
|
||||
*/
|
||||
for (i = 0; i < key->partnatts; i++)
|
||||
{
|
||||
|
|
@ -1072,11 +1077,11 @@ hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
{
|
||||
IndexOptInfo *index;
|
||||
int ncolumns,
|
||||
/*
|
||||
* For convenience and readability, use nkeycolumns even for
|
||||
* pg10- version. In this case, this var will be initialized
|
||||
* to ncolumns
|
||||
*/
|
||||
|
||||
/*
|
||||
* For convenience and readability, use nkeycolumns even for pg10-
|
||||
* version. In this case, this var will be initialized to ncolumns
|
||||
*/
|
||||
nkeycolumns,
|
||||
i;
|
||||
|
||||
|
|
@ -1191,7 +1196,8 @@ hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
index->amcanparallel = entry->amcanparallel;
|
||||
#endif
|
||||
|
||||
/* these has already been handled in hypo_index_store_parsetree() if any
|
||||
/*
|
||||
* these has already been handled in hypo_index_store_parsetree() if any
|
||||
*
|
||||
* We need deep copies since we will modify index->indexprs and
|
||||
* index->indpred later. So we should copy them from hypoIndex via
|
||||
|
|
@ -1318,7 +1324,7 @@ hypopg(PG_FUNCTION_ARGS)
|
|||
Datum values[HYPO_INDEX_NB_COLS];
|
||||
bool nulls[HYPO_INDEX_NB_COLS];
|
||||
ListCell *lc2;
|
||||
StringInfoData exprsString;
|
||||
StringInfoData exprsString;
|
||||
int i = 0;
|
||||
|
||||
memset(values, 0, sizeof(values));
|
||||
|
|
@ -1339,7 +1345,7 @@ hypopg(PG_FUNCTION_ARGS)
|
|||
initStringInfo(&exprsString);
|
||||
foreach(lc2, entry->indexprs)
|
||||
{
|
||||
Node *expr = lfirst(lc2);
|
||||
Node *expr = lfirst(lc2);
|
||||
|
||||
appendStringInfo(&exprsString, "%s", nodeToString(expr));
|
||||
}
|
||||
|
|
@ -1506,13 +1512,14 @@ hypopg_relation_size(PG_FUNCTION_ARGS)
|
|||
Datum
|
||||
hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid indexid = PG_GETARG_OID(0);
|
||||
ListCell *indexpr_item;
|
||||
StringInfoData buf;
|
||||
hypoIndex *entry = NULL;
|
||||
ListCell *lc;
|
||||
List *context;
|
||||
int keyno, cpt = 0;
|
||||
Oid indexid = PG_GETARG_OID(0);
|
||||
ListCell *indexpr_item;
|
||||
StringInfoData buf;
|
||||
hypoIndex *entry = NULL;
|
||||
ListCell *lc;
|
||||
List *context;
|
||||
int keyno,
|
||||
cpt = 0;
|
||||
|
||||
foreach(lc, hypoIndexes)
|
||||
{
|
||||
|
|
@ -1527,16 +1534,16 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
|
||||
initStringInfo(&buf);
|
||||
appendStringInfo(&buf, "CREATE %s ON %s.%s USING %s (",
|
||||
(entry->unique ? "UNIQUE INDEX" : "INDEX"),
|
||||
quote_identifier(get_namespace_name(get_rel_namespace(entry->relid))),
|
||||
quote_identifier(get_rel_name(entry->relid)),
|
||||
get_am_name(entry->relam));
|
||||
(entry->unique ? "UNIQUE INDEX" : "INDEX"),
|
||||
quote_identifier(get_namespace_name(get_rel_namespace(entry->relid))),
|
||||
quote_identifier(get_rel_name(entry->relid)),
|
||||
get_am_name(entry->relam));
|
||||
|
||||
indexpr_item = list_head(entry->indexprs);
|
||||
|
||||
context = deparse_context_for(get_rel_name(entry->relid), entry->relid);
|
||||
|
||||
for (keyno=0; keyno<entry->nkeycolumns; keyno++)
|
||||
for (keyno = 0; keyno < entry->nkeycolumns; keyno++)
|
||||
{
|
||||
Oid indcoll;
|
||||
Oid keycoltype;
|
||||
|
|
@ -1551,10 +1558,10 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
int32 keycoltypmod;
|
||||
#if PG_VERSION_NUM >= 110000
|
||||
appendStringInfo(&buf, "%s", get_attname(entry->relid,
|
||||
entry->indexkeys[keyno], false));
|
||||
entry->indexkeys[keyno], false));
|
||||
#else
|
||||
appendStringInfo(&buf, "%s", get_attname(entry->relid,
|
||||
entry->indexkeys[keyno]));
|
||||
entry->indexkeys[keyno]));
|
||||
#endif
|
||||
|
||||
get_atttypetypmodcoll(entry->relid, entry->indexkeys[keyno],
|
||||
|
|
@ -1576,7 +1583,7 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
|
||||
/* Need parens if it's not a bare function call */
|
||||
if (indexkey && IsA(indexkey, FuncExpr) &&
|
||||
((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
|
||||
((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
|
||||
appendStringInfoString(&buf, str);
|
||||
else
|
||||
appendStringInfo(&buf, "(%s)", str);
|
||||
|
|
@ -1623,13 +1630,13 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
if (entry->ncolumns > entry->nkeycolumns)
|
||||
{
|
||||
appendStringInfo(&buf, " INCLUDE (");
|
||||
for (keyno=entry->nkeycolumns; keyno<entry->ncolumns; keyno++)
|
||||
for (keyno = entry->nkeycolumns; keyno < entry->ncolumns; keyno++)
|
||||
{
|
||||
if (keyno != entry->nkeycolumns)
|
||||
appendStringInfo(&buf, ", ");
|
||||
|
||||
appendStringInfo(&buf, "%s", get_attname(entry->relid,
|
||||
entry->indexkeys[keyno], false));
|
||||
entry->indexkeys[keyno], false));
|
||||
}
|
||||
appendStringInfo(&buf, ")");
|
||||
}
|
||||
|
|
@ -1641,7 +1648,7 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
|
||||
foreach(lc, entry->options)
|
||||
{
|
||||
DefElem *elem = (DefElem *) lfirst(lc);
|
||||
DefElem *elem = (DefElem *) lfirst(lc);
|
||||
|
||||
appendStringInfo(&buf, "%s = ", elem->defname);
|
||||
|
||||
|
|
@ -1652,8 +1659,8 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
else if (strcmp(elem->defname, "length") == 0)
|
||||
appendStringInfo(&buf, "%d", (int32) intVal(elem->arg));
|
||||
else
|
||||
elog(WARNING," hypopg: option %s unhandled, please report the bug",
|
||||
elem->defname);
|
||||
elog(WARNING, " hypopg: option %s unhandled, please report the bug",
|
||||
elem->defname);
|
||||
}
|
||||
appendStringInfo(&buf, ")");
|
||||
}
|
||||
|
|
@ -1661,7 +1668,7 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
if (entry->indpred)
|
||||
{
|
||||
appendStringInfo(&buf, " WHERE %s", deparse_expression((Node *)
|
||||
make_ands_explicit(entry->indpred), context, false, false));
|
||||
make_ands_explicit(entry->indpred), context, false, false));
|
||||
}
|
||||
|
||||
PG_RETURN_TEXT_P(cstring_to_text(buf.data));
|
||||
|
|
@ -1797,7 +1804,7 @@ hypo_estimate_index(hypoIndex *entry, RelOptInfo *rel, PlannerInfo *root)
|
|||
entry->relid, InvalidOid);
|
||||
|
||||
elog(DEBUG1, "hypopg: selectivity for index \"%s\": %lf",
|
||||
entry->indexname, selectivity);
|
||||
entry->indexname, selectivity);
|
||||
|
||||
entry->tuples = selectivity * rel->tuples;
|
||||
}
|
||||
|
|
@ -1843,7 +1850,7 @@ hypo_estimate_index(hypoIndex *entry, RelOptInfo *rel, PlannerInfo *root)
|
|||
|
||||
usable_page_size = BLCKSZ - SizeOfPageHeaderData - sizeof(BTPageOpaqueData);
|
||||
bloat_factor = (200.0
|
||||
- (fillfactor == 0 ? BTREE_DEFAULT_FILLFACTOR : fillfactor)
|
||||
- (fillfactor == 0 ? BTREE_DEFAULT_FILLFACTOR : fillfactor)
|
||||
+ additional_bloat) / 100;
|
||||
|
||||
entry->pages = (BlockNumber) (entry->tuples * line_size * bloat_factor / usable_page_size);
|
||||
|
|
@ -1875,8 +1882,8 @@ hypo_estimate_index(hypoIndex *entry, RelOptInfo *rel, PlannerInfo *root)
|
|||
* BRIN access method does not bloat, don't add any additional.
|
||||
*/
|
||||
|
||||
entry->pages = 1 /* root page */
|
||||
+ (ranges / REVMAP_PAGE_MAXITEMS) + 1; /* revmap */
|
||||
entry->pages = 1 /* root page */
|
||||
+ (ranges / REVMAP_PAGE_MAXITEMS) + 1; /* revmap */
|
||||
|
||||
/* get the operator class name */
|
||||
ht_opc = SearchSysCache1(CLAOID,
|
||||
|
|
@ -1927,9 +1934,9 @@ hypo_estimate_index(hypoIndex *entry, RelOptInfo *rel, PlannerInfo *root)
|
|||
line_size = BLOOMTUPLEHDRSZ +
|
||||
sizeof_SignType * bloomLength;
|
||||
|
||||
entry->pages = 1; /* meta page */
|
||||
entry->pages = 1; /* meta page */
|
||||
entry->pages += (BlockNumber) ceil(
|
||||
((double) entry->tuples * line_size) / usable_page_size);
|
||||
((double) entry->tuples * line_size) / usable_page_size);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
|
@ -1950,8 +1957,9 @@ hypo_estimate_index(hypoIndex *entry, RelOptInfo *rel, PlannerInfo *root)
|
|||
static int
|
||||
hypo_estimate_index_colsize(hypoIndex *entry, int col)
|
||||
{
|
||||
int i, pos;
|
||||
Node *expr;
|
||||
int i,
|
||||
pos;
|
||||
Node *expr;
|
||||
|
||||
/* If simple attribute, return avg width */
|
||||
if (entry->indexkeys[col] != 0)
|
||||
|
|
@ -1960,7 +1968,7 @@ hypo_estimate_index_colsize(hypoIndex *entry, int col)
|
|||
/* It's an expression */
|
||||
pos = 0;
|
||||
|
||||
for (i=0; i<col; i++)
|
||||
for (i = 0; i < col; i++)
|
||||
{
|
||||
/* get the position in the expression list */
|
||||
if (entry->indexkeys[i] == 0)
|
||||
|
|
@ -1969,41 +1977,41 @@ hypo_estimate_index_colsize(hypoIndex *entry, int col)
|
|||
|
||||
expr = (Node *) list_nth(entry->indexprs, pos);
|
||||
|
||||
if (IsA(expr, Var) && ((Var *) expr)->varattno != InvalidAttrNumber)
|
||||
if (IsA(expr, Var) &&((Var *) expr)->varattno != InvalidAttrNumber)
|
||||
return get_attavgwidth(entry->relid, ((Var *) expr)->varattno);
|
||||
|
||||
if (IsA(expr, FuncExpr))
|
||||
{
|
||||
FuncExpr *funcexpr = (FuncExpr *) expr;
|
||||
FuncExpr *funcexpr = (FuncExpr *) expr;
|
||||
|
||||
switch (funcexpr->funcid)
|
||||
{
|
||||
case 2311:
|
||||
/* md5 */
|
||||
return 32;
|
||||
break;
|
||||
break;
|
||||
case 870:
|
||||
case 871:
|
||||
{
|
||||
/* lower and upper, detect if simple attr */
|
||||
Var *var;
|
||||
|
||||
if (IsA(linitial(funcexpr->args), Var))
|
||||
{
|
||||
var = (Var *) linitial(funcexpr->args);
|
||||
/* lower and upper, detect if simple attr */
|
||||
Var *var;
|
||||
|
||||
if (var->varattno > 0)
|
||||
return get_attavgwidth(entry->relid, var->varattno);
|
||||
if (IsA(linitial(funcexpr->args), Var))
|
||||
{
|
||||
var = (Var *) linitial(funcexpr->args);
|
||||
|
||||
if (var->varattno > 0)
|
||||
return get_attavgwidth(entry->relid, var->varattno);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* default fallback estimate will be used */
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 50; /* default fallback estimate */
|
||||
return 50; /* default fallback estimate */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
772
hypopg_table.c
772
hypopg_table.c
File diff suppressed because it is too large
Load diff
|
|
@ -20,12 +20,13 @@
|
|||
#include "include/hypopg_import.h"
|
||||
|
||||
extern bool isExplain;
|
||||
|
||||
/* GUC for enabling / disabling hypopg during EXPLAIN */
|
||||
extern bool hypo_is_enabled;
|
||||
extern MemoryContext HypoMemoryContext;
|
||||
|
||||
Oid hypo_getNewOid(Oid relid);
|
||||
void hypo_process_inval(void);
|
||||
void hypo_clear_inval(void);
|
||||
Oid hypo_getNewOid(Oid relid);
|
||||
void hypo_process_inval(void);
|
||||
void hypo_clear_inval(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,30 +23,30 @@
|
|||
|
||||
typedef struct hypoStatsKey
|
||||
{
|
||||
Oid relid;
|
||||
AttrNumber attnum;
|
||||
Oid relid;
|
||||
AttrNumber attnum;
|
||||
} hypoStatsKey;
|
||||
|
||||
typedef struct hypoStatsEntry
|
||||
{
|
||||
hypoStatsKey key;
|
||||
HeapTuple statsTuple;
|
||||
HeapTuple statsTuple;
|
||||
} hypoStatsEntry;
|
||||
|
||||
/*--- Variables exported ---*/
|
||||
|
||||
/* Hash table storing the partition-level statistics */
|
||||
extern HTAB *hypoStatsHash;
|
||||
#endif /* PG_VERSION_NUM >= 100000 */
|
||||
#endif /* PG_VERSION_NUM >= 100000 */
|
||||
|
||||
Selectivity hypo_clauselist_selectivity(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *clauses, Oid table_relid, Oid parent_oid);
|
||||
List *clauses, Oid table_relid, Oid parent_oid);
|
||||
|
||||
/*--- Functions --- */
|
||||
PGDLLEXPORT Datum hypopg_analyze(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_statistic(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_analyze(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_statistic(PG_FUNCTION_ARGS);
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
PGDLLEXPORT void hypo_stat_remove(Oid tableid);
|
||||
#endif
|
||||
|
||||
#endif /* _HYPOPG_ANALYZE_H_ */
|
||||
#endif /* _HYPOPG_ANALYZE_H_ */
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@
|
|||
#include "tcop/utility.h"
|
||||
|
||||
#define HYPO_INDEX_NB_COLS 12 /* # of column hypopg() returns */
|
||||
#define HYPO_INDEX_CREATE_COLS 2 /* # of column hypopg_create_index() returns */
|
||||
#define HYPO_INDEX_CREATE_COLS 2 /* # of column hypopg_create_index()
|
||||
* returns */
|
||||
|
||||
#if PG_VERSION_NUM >= 90600
|
||||
/* hardcode some bloom values, bloom.h is not exported */
|
||||
|
|
@ -95,8 +96,8 @@ typedef struct hypoIndex
|
|||
#if PG_VERSION_NUM >= 110000
|
||||
bool amcanparallel; /* does AM support parallel scan? */
|
||||
#endif
|
||||
bool amcanunique; /* does AM support UNIQUE indexes? */
|
||||
bool amcanmulticol; /* does AM support multi-column indexes? */
|
||||
bool amcanunique; /* does AM support UNIQUE indexes? */
|
||||
bool amcanmulticol; /* does AM support multi-column indexes? */
|
||||
|
||||
/* store some informations usually saved in catalogs */
|
||||
List *options; /* WITH clause options: a list of DefElem */
|
||||
|
|
@ -105,18 +106,18 @@ typedef struct hypoIndex
|
|||
} hypoIndex;
|
||||
|
||||
/* List of hypothetic indexes for current backend */
|
||||
extern List *hypoIndexes;
|
||||
extern List *hypoIndexes;
|
||||
|
||||
/*--- Functions --- */
|
||||
|
||||
void hypo_index_reset(void);
|
||||
void hypo_index_reset(void);
|
||||
|
||||
PGDLLEXPORT Datum hypopg(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_create_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_drop_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_relation_size(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_get_indexdef(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_reset_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_create_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_drop_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_relation_size(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_get_indexdef(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_reset_index(PG_FUNCTION_ARGS);
|
||||
|
||||
extern explain_get_index_name_hook_type prev_explain_get_index_name_hook;
|
||||
const char *hypo_explain_get_index_name_hook(Oid indexId);
|
||||
|
|
|
|||
|
|
@ -47,54 +47,55 @@ typedef struct hypoTable
|
|||
{
|
||||
Oid oid; /* hypothetical table unique identifier */
|
||||
Oid parentid; /* In case of partition, it's direct parent,
|
||||
otherwise InvalidOid */
|
||||
* otherwise InvalidOid */
|
||||
Oid rootid; /* In case of partition, its root parentid,
|
||||
otherwise its own oid */
|
||||
char tablename[NAMEDATALEN]; /* hypothetical partition name, or
|
||||
original table name for root parititon */
|
||||
* otherwise its own oid */
|
||||
char tablename[NAMEDATALEN]; /* hypothetical partition name, or
|
||||
* original table name for root
|
||||
* parititon */
|
||||
Oid namespace; /* Oid of the hypothetical table's schema */
|
||||
bool set_tuples; /* tuples are already set or not */
|
||||
int tuples; /* number of tuples of this table */
|
||||
int tuples; /* number of tuples of this table */
|
||||
List *children; /* unsorted OIDs of children, if any */
|
||||
PartitionBoundSpec *boundspec; /* Needed to generate the PartitionDesc and
|
||||
PartitionBoundInfo */
|
||||
PartitionKey partkey; /* Needed to generate the partition key
|
||||
expressions and deparsing */
|
||||
Oid *partopclass; /* oid of partkey's element opclass, needed for
|
||||
deparsing the key */
|
||||
PartitionBoundSpec *boundspec; /* Needed to generate the PartitionDesc
|
||||
* and PartitionBoundInfo */
|
||||
PartitionKey partkey; /* Needed to generate the partition key
|
||||
* expressions and deparsing */
|
||||
Oid *partopclass; /* oid of partkey's element opclass, needed
|
||||
* for deparsing the key */
|
||||
bool valid;
|
||||
} hypoTable;
|
||||
|
||||
/* List of hypothetic partitions for current backend */
|
||||
extern HTAB *hypoTables;
|
||||
extern HTAB *hypoTables;
|
||||
#else
|
||||
#define HYPO_PARTITION_NOT_SUPPORTED() elog(ERROR, "hypopg: Hypothetical partitioning requires PostgreSQl 10 or above"); PG_RETURN_VOID();
|
||||
#endif
|
||||
|
||||
/*--- Functions --- */
|
||||
|
||||
void hypo_table_reset(void);
|
||||
void hypo_table_reset(void);
|
||||
|
||||
PGDLLEXPORT Datum hypopg_table(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_add_partition(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_drop_table(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_partition_table(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_reset_table(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_table(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_add_partition(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_drop_table(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_partition_table(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_reset_table(PG_FUNCTION_ARGS);
|
||||
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
hypoTable *hypo_find_table(Oid tableid, bool missing_ok);
|
||||
hypoTable *hypo_find_table(Oid tableid, bool missing_ok);
|
||||
List *hypo_get_partition_constraints(PlannerInfo *root, RelOptInfo *rel,
|
||||
hypoTable *parent, bool force_generation);
|
||||
List *hypo_get_partition_quals_inh(hypoTable *part, hypoTable *parent);
|
||||
hypoTable *hypo_table_name_get_entry(const char *name);
|
||||
bool hypo_table_oid_is_hypothetical(Oid relid);
|
||||
bool hypo_table_remove(Oid tableid, hypoTable *parent, bool deep);
|
||||
hypoTable *parent, bool force_generation);
|
||||
List *hypo_get_partition_quals_inh(hypoTable *part, hypoTable *parent);
|
||||
hypoTable *hypo_table_name_get_entry(const char *name);
|
||||
bool hypo_table_oid_is_hypothetical(Oid relid);
|
||||
bool hypo_table_remove(Oid tableid, hypoTable *parent, bool deep);
|
||||
void hypo_injectHypotheticalPartitioning(PlannerInfo *root,
|
||||
Oid relationObjectId,
|
||||
RelOptInfo *rel);
|
||||
Oid relationObjectId,
|
||||
RelOptInfo *rel);
|
||||
#if PG_VERSION_NUM < 110000
|
||||
void hypo_markDummyIfExcluded(PlannerInfo *root, RelOptInfo *rel,
|
||||
Index rti, RangeTblEntry *rte);
|
||||
Index rti, RangeTblEntry *rte);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
753
typedefs.list
753
typedefs.list
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue