Files
openGauss-server/src/include/parser/parse_hint.h
2021-09-23 15:19:37 +08:00

313 lines
10 KiB
C

/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ---------------------------------------------------------------------------------------
*
* parse_hint.h
* Table parse hint header file, include struct member declaration.
*
*
* IDENTIFICATION
* src/include/parser/parse_hint.h
*
* ---------------------------------------------------------------------------------------
*/
#ifndef PARSE_HINT_h
#define PARSE_HINT_h
#include "optimizer/streamplan.h"
#include "parser/parse_node.h"
#include "tcop/dest.h"
#include "utils/guc.h"
/* hint keywords */
#define HINT_NESTLOOP "NestLoop"
#define HINT_MERGEJOIN "MergeJoin"
#define HINT_HASHJOIN "HashJoin"
#define HINT_NO "No"
#define HINT_LEADING "Leading"
#define HINT_ROWS "Rows"
#define HINT_BROADCAST "Broadcast"
#define HINT_REDISTRIBUTE "Redistribute"
#define HINT_BLOCKNAME "BlockName"
#define HINT_TABLESCAN "TableScan"
#define HINT_INDEXSCAN "IndexScan"
#define HINT_INDEXONLYSCAN "IndexOnlyScan"
#define HINT_SKEW "Skew"
#define HINT_MULTI_NODE "MultiNode"
#define HINT_NULL "Null"
#define HINT_TRUE "True"
#define HINT_FALSE "False"
#define HINT_PRED_PUSH "Predpush"
#define HINT_REWRITE "Rewrite_rule"
#define HINT_GATHER "Gather"
#define HINT_NO_EXPAND "No_expand"
#define HINT_SET "Set"
#define HINT_CPLAN "Use_cplan"
#define HINT_GPLAN "Use_gplan"
#define HINT_NO_GPC "No_gpc"
#define BLOCK_COMMENT_START "/*"
#define BLOCK_COMMENT_END "*/"
#define HINT_COMMENT_KEYWORD "+"
#define HINT_START BLOCK_COMMENT_START HINT_COMMENT_KEYWORD
#define HINT_END BLOCK_COMMENT_END
typedef struct pull_hint_warning_context {
List* warning;
} pull_qual_vars_context;
#define append_warning_to_list(root, hint, format, ...) \
do { \
StringInfoData buf; \
char* hint_string = descHint(hint); \
initStringInfo(&buf); \
appendStringInfo(&buf, format, ##__VA_ARGS__); \
root->glob->hint_warning = lappend(root->glob->hint_warning, makeString(buf.data)); \
pfree(hint_string); \
} while (0)
extern THR_LOCAL List* hint_list;
extern THR_LOCAL List* hint_warning;
/* hint keyword of enum type. DO NOT change the order! */
typedef enum HintKeyword {
HINT_KEYWORD_NESTLOOP = 0,
HINT_KEYWORD_MERGEJOIN,
HINT_KEYWORD_HASHJOIN,
HINT_KEYWORD_LEADING,
HINT_KEYWORD_ROWS,
HINT_KEYWORD_BROADCAST,
HINT_KEYWORD_REDISTRIBUTE,
HINT_KEYWORD_BLOCKNAME,
HINT_KEYWORD_TABLESCAN,
HINT_KEYWORD_INDEXSCAN,
HINT_KEYWORD_INDEXONLYSCAN,
HINT_KEYWORD_SKEW,
HINT_KEYWORD_PREDPUSH,
HINT_KEYWORD_REWRITE,
HINT_KEYWORD_GATHER,
HINT_KEYWORD_NO_EXPAND,
HINT_KEYWORD_SET,
HINT_KEYWORD_CPLAN,
HINT_KEYWORD_GPLAN,
HINT_KEYWORD_NO_GPC,
} HintKeyword;
/* hint status */
typedef enum HintStatus {
HINT_STATE_NOTUSED = 0, /* specified relation not used in query */
HINT_STATE_USED, /* hint is used */
HINT_STATE_DUPLICATION, /* specified hint duplication */
HINT_STATE_ERROR /* hint contains error */
} HintStatus;
/* gather source */
typedef enum GatherSource {
HINT_GATHER_GUC = 0, /* exist as guc */
HINT_GATHER_REL, /* Gather baserel */
HINT_GATHER_JOIN, /* Gather joinrel */
HINT_GATHER_ALL, /* Gather baserel and joinrel, and find the best */
HINT_GATHER_UNKNOWN /* unknown, should report error */
} GatherSource;
/* common data for all hints. */
struct Hint {
NodeTag type; /* Hint type */
List* relnames; /* relation name list */
HintKeyword hint_keyword; /* Hint Keyword */
HintStatus state; /* hint used state */
};
typedef struct LeadingHint {
Hint base; /* Base hint */
bool join_order_hint; /* If join order is hinted */
} LeadingHint;
/* join method hints */
typedef struct JoinMethodHint {
Hint base; /* Base hint */
bool negative; /* Positive or negative? */
Relids joinrelids; /* Join relids */
Relids inner_joinrelids; /* Inner relids */
} JoinMethodHint;
/* rows hints kind */
typedef enum RowsValueType {
RVT_ABSOLUTE, /* Rows(... #1000) absolute rows */
RVT_ADD, /* Rows(... +1000) add rows */
RVT_SUB, /* Rows(... -1000) subtract rows */
RVT_MULTI /* Rows(... *1.2) multiply rows */
} RowsValueType;
/* rows hint */
typedef struct RowsHint {
Hint base; /* base hint */
Relids joinrelids; /* Join relids */
char* rows_str; /* Row string */
RowsValueType value_type; /* hints kind */
double rows; /* Rows */
} RowsHint;
typedef struct StreamHint {
Hint base; /* base hint */
bool negative; /* Positive or negative? */
Relids joinrelids; /* Join relids */
StreamType stream_type; /* Stream type, redistribute or broadcast */
} StreamHint;
typedef struct BlockNameHint {
Hint base; /* base hint */
/* Block name will be stored in base.relname. */
} BlockNameHint;
/* scan method hints */
typedef struct ScanMethodHint {
Hint base;
bool negative;
Relids relid;
List* indexlist;
} ScanMethodHint;
/* skew hints */
typedef struct SkewHint {
Hint base; /* base hint */
Relids relid; /* skew relation relids */
List* column_list; /* skew column list */
List* value_list; /* skew value list */
} SkewHint;
/* multinode hints */
typedef struct MultiNodeHint {
Hint base; /* base hint */
bool multi_node_hint;
} MultiNodeHint;
/* relation information from RangeTblEntry and pg_class */
typedef struct SkewRelInfo {
NodeTag type;
char* relation_name; /* relation name */
Oid relation_oid; /* relation`s oid */
RangeTblEntry* rte; /* relation`s rte */
RangeTblEntry* parent_rte; /* if relation comes from subquery, then it`s subquery`s rte */
} SkewRelInfo;
/* column information from PG_ATTRIBUTE or targetEntry */
typedef struct SkewColumnInfo {
NodeTag type;
Oid relation_Oid; /* table`s oid */
char* column_name; /* column`s name */
AttrNumber attnum; /* column's location in relation */
Oid column_typid; /* column`s type oid */
Expr* expr; /* expr that column comes from */
} SkewColumnInfo;
/* make skew value to Const */
typedef struct SkewValueInfo {
NodeTag type;
bool support_redis; /* column type whether support redistribution, if not the const_value will be null */
Const* const_value; /* skew value */
} SkewValueInfo;
/* SkewHint structure after transform */
typedef struct SkewHintTransf {
NodeTag type;
SkewHint* before; /* skew hint struct before transform */
List* rel_info_list; /* relation info list after transform */
List* column_info_list; /* column info list after transform */
List* value_info_list; /* value info list after transform */
} SkewHintTransf;
/* prompts which predicates can be pushdown */
typedef struct PredpushHint {
Hint base; /* base hint */
bool negative;
char *dest_name;
int dest_id;
Relids candidates; /* which one will be push down */
} PredpushHint;
/* Enable/disable rewrites with hint */
typedef struct RewriteHint {
Hint base; /* base hint */
List* param_names; /* rewrite parameters */
unsigned int param_bits;
} RewriteHint;
/* Enable/disable CN gather with hint */
typedef struct GatherHint {
Hint base; /* base hint */
GatherSource source; /* rewrite parameters */
} GatherHint;
/* Enforce custom/generic plan with hint */
typedef struct NoExpandHint {
Hint base; /* base hint */
} NoExpandHint;
/* Hint session level optimizer guc parameter */
typedef struct SetHint {
Hint base; /* base hint */
char* name;
char* value;
} SetHint;
typedef struct PlanCacheHint {
Hint base; /* base hint */
bool chooseCustomPlan;
} PlanCacheHint;
/* Avoid saving global plan with hint */
typedef struct NoGPCHint {
Hint base; /* base hint */
} NoGPCHint;
typedef struct hintKeyword {
const char* name;
int value;
} hintKeyword;
extern HintState* HintStateCreate();
extern HintState* create_hintstate(const char* hints);
extern List* find_specific_join_hint(
HintState* hstate, Relids joinrelids, Relids innerrelids, HintKeyword keyWord, bool leading = true);
extern List* find_specific_scan_hint(HintState* hstate, Relids relids, HintKeyword keyWord);
extern ScanMethodHint* find_scan_hint(HintState* hstate, Relids relid, HintKeyword keyWord);
extern char* descHint(Hint* hint);
extern void hintDelete(Hint* hint);
extern void desc_hint_in_state(PlannerInfo* root, HintState* hstate);
extern void transform_hints(PlannerInfo* root, Query* parse, HintState* hstate);
extern void check_scan_hint_validity(PlannerInfo* root);
extern void adjust_scanhint_relid(HintState* hstate, Index oldIdx, Index newIdx);
extern bool pull_hint_warning_walker(Node* node, pull_qual_vars_context* context);
extern List* retrieve_query_hint_warning(Node* parse);
extern void output_utility_hint_warning(Node* query, int lev);
extern void output_hint_warning(List* warning, int lev);
extern void HintStateDelete(HintState* hintState);
extern bool permit_predpush(PlannerInfo *root);
extern bool permit_from_rewrite_hint(PlannerInfo *root, unsigned int params);
extern Relids predpush_candidates_same_level(PlannerInfo *root);
extern bool permit_gather(PlannerInfo *root, GatherSource src = HINT_GATHER_GUC);
extern GatherSource get_gather_hint_source(PlannerInfo *root);
extern bool check_set_hint_in_white_list(const char* name);
extern bool has_no_expand_hint(Query* subquery);
extern bool has_no_gpc_hint(HintState* hintState);
#define skip_space(str) \
while (isspace(*str)) \
str++;
#endif