pgindent run and update changelog for last msvc commit.

Also update typedefs.list.
This commit is contained in:
Julien Rouhaud 2019-01-20 19:39:41 +01:00
parent 4a5dc56169
commit acd87ef01a
9 changed files with 1389 additions and 610 deletions

View file

@ -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
View file

@ -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);

View file

@ -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 */
}
/*

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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_ */

View file

@ -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);

View file

@ -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

File diff suppressed because it is too large Load diff