(5 rows)
LOAD 'pg_hint_plan';
+SET pg_hint_plan.debug_print TO on;
+SET client_min_messages TO LOG;
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
QUERY PLAN
--------------------------------------
SET pg_hint_plan.enable TO on;
/*+Set(enable_indexscan off)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+Set(enable_indexscan off)
+
QUERY PLAN
------------------------------
Hash Join
/*+ Set(enable_indexscan off) Set(enable_hashjoin off) */
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+Set(enable_indexscan off)
+Set(enable_hashjoin off)
+
QUERY PLAN
-------------------------------
Merge Join
/*+ Set ( enable_indexscan off ) */
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+Set(enable_indexscan off)
+
QUERY PLAN
------------------------------
Hash Join
)
*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+Set(enable_indexscan off)
+
QUERY PLAN
------------------------------
Hash Join
Set(enable_seqscan off)
*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+Set(enable_indexscan off)
+Set(enable_nestloop off)
+Set(enable_mergejoin off)
+Set(enable_seqscan off)
+
QUERY PLAN
--------------------------------------------
Hash Join
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
INFO: invalid value for parameter "work_mem": "1M"
HINT: Valid units for this parameter are "kB", "MB", and "GB".
+LOG: pg_hint_plan:
+used hint:
+Set(work_mem 1M)
+
QUERY PLAN
--------------------------------------
Merge Join
/*+Set(work_mem "1MB")*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+Set(work_mem 1MB)
+
QUERY PLAN
--------------------------------------
Merge Join
/*+SeqScan(t1)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+SeqScan(t1)
+
QUERY PLAN
------------------------------
Hash Join
/*+SeqScan(t1)IndexScan(t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+SeqScan(t1)
+IndexScan(t2)
+
QUERY PLAN
--------------------------------------------
Hash Join
/*+BitmapScan(t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+BitmapScan(t2)
+
QUERY PLAN
--------------------------------------
Nested Loop
/*+BitmapScan(t2)NoSeqScan(t1)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+NoSeqScan(t1)
+BitmapScan(t2)
+
QUERY PLAN
--------------------------------------
Nested Loop
/*+NoIndexScan(t1)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+NoIndexScan(t1)
+
QUERY PLAN
------------------------------
Hash Join
/*+NoBitmapScan(t1)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t4 WHERE t1.val < 10;
+LOG: pg_hint_plan:
+used hint:
+NoBitmapScan(t1)
+
QUERY PLAN
----------------------------
Nested Loop
/*+TidScan(t4)*/
EXPLAIN (COSTS false) SELECT * FROM t3, t4 WHERE t3.id = t4.id AND t4.ctid = '(1,1)';
+LOG: pg_hint_plan:
+used hint:
+TidScan(t4)
+
QUERY PLAN
-----------------------------------------------
Merge Join
/*+NoTidScan(t1)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id AND t1.ctid = '(1,1)';
+LOG: pg_hint_plan:
+used hint:
+NoTidScan(t1)
+
QUERY PLAN
---------------------------------------
Nested Loop
/*+HashJoin(t1 t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+HashJoin(t1 t2)
+
QUERY PLAN
------------------------------
Hash Join
/*+NestLoop(t1 t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+NestLoop(t1 t2)
+
QUERY PLAN
--------------------------------------
Nested Loop
/*+NoMergeJoin(t1 t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+NoMergeJoin(t1 t2)
+
QUERY PLAN
------------------------------
Hash Join
/*+MergeJoin(t1 t3)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t3 WHERE t1.val = t3.val;
+LOG: pg_hint_plan:
+used hint:
+MergeJoin(t1 t3)
+
QUERY PLAN
-------------------------------------
Merge Join
/*+NestLoop(t1 t3)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t3 WHERE t1.val = t3.val;
+LOG: pg_hint_plan:
+used hint:
+NestLoop(t1 t3)
+
QUERY PLAN
-------------------------------------
Nested Loop
/*+NoHashJoin(t1 t3)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t3 WHERE t1.val = t3.val;
+LOG: pg_hint_plan:
+used hint:
+NoHashJoin(t1 t3)
+
QUERY PLAN
-------------------------------------
Nested Loop
/*+MergeJoin(t4 t1 t2 t3)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+MergeJoin(t1 t2 t3 t4)
+
QUERY PLAN
--------------------------------------------------
Merge Join
/*+HashJoin(t3 t4 t1 t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+HashJoin(t1 t2 t3 t4)
+
QUERY PLAN
--------------------------------------------------------
Hash Join
/*+NestLoop(t2 t3 t4 t1) IndexScan(t3)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+IndexScan(t3)
+NestLoop(t1 t2 t3 t4)
+
QUERY PLAN
--------------------------------------------------
Nested Loop
/*+NoNestLoop(t4 t1 t3 t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+NoNestLoop(t1 t2 t3 t4)
+
QUERY PLAN
--------------------------------------------------
Merge Join
/*+Leading(t3 t4)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+Leading(t3 t4)
+
QUERY PLAN
--------------------------------------------------
Nested Loop
/*+Leading(t3 t4 t1)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+Leading(t3 t4 t1)
+
QUERY PLAN
--------------------------------------------------
Nested Loop
/*+Leading(t3 t4 t1 t2)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+Leading(t3 t4 t1 t2)
+
QUERY PLAN
--------------------------------------------------
Nested Loop
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
INFO: hint syntax error at or near "Leading(t3 t4 t1 t2 t1)"
DETAIL: In Leading hint, specified relation name 4 or less.
+LOG: pg_hint_plan:
+used hint:
+Leading(t3 t4 t1 t2 t1)
+
QUERY PLAN
--------------------------------------------------
Nested Loop
/*+Leading(t3 t4 t4)*/
EXPLAIN (COSTS false) SELECT * FROM t1, t2, t3, t4 WHERE t1.id = t2.id AND t1.id = t3.id AND t1.id = t4.id;
+LOG: pg_hint_plan:
+used hint:
+Leading(t3 t4 t4)
+
QUERY PLAN
--------------------------------------------------
Nested Loop
EXPLAIN (COSTS false) SELECT * FROM t1, (VALUES(1,1),(2,2),(3,3)) AS t2(id,val) WHERE t1.id = t2.id;
INFO: hint syntax error at or near "HashJoin(t1 t2)"
DETAIL: Relation "t2" does not exist.
+LOG: pg_hint_plan:
+used hint:
+HashJoin(t1 t2)
+
QUERY PLAN
-----------------------------------------------
Nested Loop
/*+HashJoin(t1 *VALUES*)*/
EXPLAIN (COSTS false) SELECT * FROM t1, (VALUES(1,1),(2,2),(3,3)) AS t2(id,val) WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+HashJoin(*VALUES* t1)
+
QUERY PLAN
-------------------------------------------
Hash Join
/*+HashJoin(t1 *VALUES*) IndexScan(t1) IndexScan(*VALUES*)*/
EXPLAIN (COSTS false) SELECT * FROM t1, (VALUES(1,1),(2,2),(3,3)) AS t2(id,val) WHERE t1.id = t2.id;
+LOG: pg_hint_plan:
+used hint:
+IndexScan(*VALUES*)
+IndexScan(t1)
+HashJoin(*VALUES* t1)
+
QUERY PLAN
-------------------------------------------
Hash Join
{
HINT_STATE_NOTUSED = 0, /* specified relation not used in query */
HINT_STATE_DUPLICATION, /* specified hint duplication */
- HINT_STATE_USED, /* hint is used */
+ HINT_STATE_USED, /* hint is used */
/* execute error (parse error does not include it) */
HINT_STATE_ERROR
} HintStatus;
{
const char *hint_str; /* must not do pfree */
const char *keyword; /* must not do pfree */
- bool used;
+ HintStatus state;
HintDeleteFunction delete_func;
HintParseFunction parser_func;
};
hint = palloc(sizeof(ScanMethodHint));
hint->base.hint_str = hint_str;
hint->base.keyword = keyword;
- hint->base.used = false;
+ hint->base.state = HINT_STATE_NOTUSED;
hint->base.delete_func = (HintDeleteFunction) ScanMethodHintDelete;
hint->base.parser_func = (HintParseFunction) ScanMethodHintParse;
hint->relname = NULL;
hint = palloc(sizeof(JoinMethodHint));
hint->base.hint_str = hint_str;
hint->base.keyword = keyword;
- hint->base.used = false;
+ hint->base.state = HINT_STATE_NOTUSED;
hint->base.delete_func = (HintDeleteFunction) JoinMethodHintDelete;
hint->base.parser_func = (HintParseFunction) JoinMethodHintParse;
hint->nrels = 0;
hint = palloc(sizeof(LeadingHint));
hint->base.hint_str = hint_str;
hint->base.keyword = keyword;
- hint->base.used = false;
+ hint->base.state = HINT_STATE_NOTUSED;
hint->base.delete_func = (HintDeleteFunction)LeadingHintDelete;
hint->base.parser_func = (HintParseFunction) LeadingHintParse;
hint->relations = NIL;
hint = palloc(sizeof(SetHint));
hint->base.hint_str = hint_str;
hint->base.keyword = keyword;
- hint->base.used = false;
+ hint->base.state = HINT_STATE_NOTUSED;
hint->base.delete_func = (HintDeleteFunction) SetHintDelete;
hint->base.parser_func = (HintParseFunction) SetHintParse;
hint->name = NULL;
}
static bool
-PlanHintIsempty(PlanHint *hint)
+PlanHintIsEmpty(PlanHint *hint)
{
if (hint->nscan_hints == 0 &&
hint->njoin_hints == 0 &&
if (!hint)
{
- elog(LOG, "no hint");
+ elog(LOG, "pg_hint_plan:\nno hint");
return;
}
initStringInfo(&buf);
- appendStringInfo(&buf, "/*\n");
+ appendStringInfo(&buf, "pg_hint_plan:\nused hint:\n");
for (i = 0; i < hint->nscan_hints; i++)
{
ScanMethodHint *h = hint->scan_hints[i];
ListCell *n;
- switch(h->enforce_mask)
- {
- case(ENABLE_SEQSCAN):
- appendStringInfo(&buf, "%s(", HINT_SEQSCAN);
- break;
- case(ENABLE_INDEXSCAN):
- appendStringInfo(&buf, "%s(", HINT_INDEXSCAN);
- break;
- case(ENABLE_BITMAPSCAN):
- appendStringInfo(&buf, "%s(", HINT_BITMAPSCAN);
- break;
- case(ENABLE_TIDSCAN):
- appendStringInfo(&buf, "%s(", HINT_TIDSCAN);
- break;
- case(ENABLE_INDEXSCAN | ENABLE_BITMAPSCAN | ENABLE_TIDSCAN):
- appendStringInfo(&buf, "%s(", HINT_NOSEQSCAN);
- break;
- case(ENABLE_SEQSCAN | ENABLE_BITMAPSCAN | ENABLE_TIDSCAN):
- appendStringInfo(&buf, "%s(", HINT_NOINDEXSCAN);
- break;
- case(ENABLE_SEQSCAN | ENABLE_INDEXSCAN | ENABLE_TIDSCAN):
- appendStringInfo(&buf, "%s(", HINT_NOBITMAPSCAN);
- break;
- case(ENABLE_SEQSCAN | ENABLE_INDEXSCAN | ENABLE_BITMAPSCAN):
- appendStringInfo(&buf, "%s(", HINT_NOTIDSCAN);
- break;
- default:
- appendStringInfoString(&buf, "\?\?\?(");
- break;
- }
- appendStringInfo(&buf, "%s", h->relname);
+
+ appendStringInfo(&buf, "%s(%s", h->base.keyword, h->relname);
foreach(n, h->indexnames)
appendStringInfo(&buf, " %s", (char *) lfirst(n));
appendStringInfoString(&buf, ")\n");
{
JoinMethodHint *h = hint->join_hints[i];
int i;
- switch(h->enforce_mask)
- {
- case(ENABLE_NESTLOOP):
- appendStringInfo(&buf, "%s(", HINT_NESTLOOP);
- break;
- case(ENABLE_MERGEJOIN):
- appendStringInfo(&buf, "%s(", HINT_MERGEJOIN);
- break;
- case(ENABLE_HASHJOIN):
- appendStringInfo(&buf, "%s(", HINT_HASHJOIN);
- break;
- case(ENABLE_ALL_JOIN ^ ENABLE_NESTLOOP):
- appendStringInfo(&buf, "%s(", HINT_NONESTLOOP);
- break;
- case(ENABLE_ALL_JOIN ^ ENABLE_MERGEJOIN):
- appendStringInfo(&buf, "%s(", HINT_NOMERGEJOIN);
- break;
- case(ENABLE_ALL_JOIN ^ ENABLE_HASHJOIN):
- appendStringInfo(&buf, "%s(", HINT_NOHASHJOIN);
- break;
- case(ENABLE_ALL_JOIN):
- continue;
- default:
- appendStringInfoString(&buf, "\?\?\?(");
- break;
- }
- appendStringInfo(&buf, "%s", h->relnames[0]);
+
+ if (h->enforce_mask == ENABLE_ALL_JOIN)
+ continue;
+
+ appendStringInfo(&buf, "%s(%s", h->base.keyword, h->relnames[0]);
for (i = 1; i < h->nrels; i++)
appendStringInfo(&buf, " %s", h->relnames[i]);
appendStringInfoString(&buf, ")\n");
if (!is_first)
appendStringInfoString(&buf, ")\n");
- appendStringInfoString(&buf, "*/");
-
elog(LOG, "%s", buf.data);
pfree(buf.data);
{
const JoinMethodHint *hinta = *((const JoinMethodHint **) a);
const JoinMethodHint *hintb = *((const JoinMethodHint **) b);
+ int i;
- if (hinta->nrels == hintb->nrels)
- {
- int i;
- for (i = 0; i < hinta->nrels; i++)
- {
- int result;
- if ((result = RelnameCmp(&hinta->relnames[i], &hintb->relnames[i])) != 0)
- return result;
- }
+ if (hinta->nrels != hintb->nrels)
+ return hinta->nrels - hintb->nrels;
- /* ヒント句で指定した順を返す */
- if (order)
- return hinta->base.hint_str - hintb->base.hint_str;
- else
- return 0;
+ for (i = 0; i < hinta->nrels; i++)
+ {
+ int result;
+ if ((result = RelnameCmp(&hinta->relnames[i], &hintb->relnames[i])) != 0)
+ return result;
}
- return hinta->nrels - hintb->nrels;
+ /* ヒント句で指定した順を返す */
+ if (order)
+ return hinta->base.hint_str - hintb->base.hint_str;
+ else
+ return 0;
}
static int
return save_nestlevel;
}
-#define SET_CONFIG_OPTION(name, enforce_mask, type_bits) \
+#define SET_CONFIG_OPTION(name, type_bits) \
set_config_option((name), \
- ((enforce_mask) & (type_bits)) ? "true" : "false", \
+ (enforce_mask & (type_bits)) ? "true" : "false", \
context, PGC_S_SESSION, GUC_ACTION_SAVE, true, ERROR)
static void
set_join_config_options(unsigned char enforce_mask, GucContext context)
{
- SET_CONFIG_OPTION("enable_nestloop", enforce_mask, ENABLE_NESTLOOP);
- SET_CONFIG_OPTION("enable_mergejoin", enforce_mask, ENABLE_MERGEJOIN);
- SET_CONFIG_OPTION("enable_hashjoin", enforce_mask, ENABLE_HASHJOIN);
+ SET_CONFIG_OPTION("enable_nestloop", ENABLE_NESTLOOP);
+ SET_CONFIG_OPTION("enable_mergejoin", ENABLE_MERGEJOIN);
+ SET_CONFIG_OPTION("enable_hashjoin", ENABLE_HASHJOIN);
}
static void
set_scan_config_options(unsigned char enforce_mask, GucContext context)
{
- SET_CONFIG_OPTION("enable_seqscan", enforce_mask, ENABLE_SEQSCAN);
- SET_CONFIG_OPTION("enable_indexscan", enforce_mask, ENABLE_INDEXSCAN);
- SET_CONFIG_OPTION("enable_bitmapscan", enforce_mask, ENABLE_BITMAPSCAN);
- SET_CONFIG_OPTION("enable_tidscan", enforce_mask, ENABLE_TIDSCAN);
+ SET_CONFIG_OPTION("enable_seqscan", ENABLE_SEQSCAN);
+ SET_CONFIG_OPTION("enable_indexscan", ENABLE_INDEXSCAN);
+ SET_CONFIG_OPTION("enable_bitmapscan", ENABLE_BITMAPSCAN);
+ SET_CONFIG_OPTION("enable_tidscan", ENABLE_TIDSCAN);
#if PG_VERSION_NUM >= 90200
- SET_CONFIG_OPTION("enable_indexonlyscan", enforce_mask, ENABLE_INDEXSCAN);
+ SET_CONFIG_OPTION("enable_indexonlyscan", ENABLE_INDEXSCAN);
#endif
}
*/
if (!pg_hint_plan_enable ||
(global = parse_head_comment(parse)) == NULL ||
- PlanHintIsempty(global))
+ PlanHintIsEmpty(global))
{
PlanHintDelete(global);
global = NULL;