• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: Commit

firtst release


Commit MetaInfo

Revision4bd82297178b63b72cf5d6451983362ef7d398b7 (tree)
Time2020-02-17 14:59:15
AuthorKyotaro Horiguchi <horikyota.ntt@gmai...>
CommiterKyotaro Horiguchi

Log Message

Fix Rows hint parsing

This is a long standing bug that Rows hint with no parameter causees a
crash. Fixed the Rows hint parser.

Change Summary

Incremental Difference

--- a/expected/pg_hint_plan.out
+++ b/expected/pg_hint_plan.out
@@ -276,6 +276,21 @@ Set(work_mem TO 1MB)
276276 -> Index Scan using t2_pkey on t2
277277 (4 rows)
278278
279+/*+SeqScan() */ SELECT 1;
280+INFO: pg_hint_plan: hint syntax error at or near " "
281+DETAIL: SeqScan hint requires a relation.
282+LOG: pg_hint_plan:
283+used hint:
284+not used hint:
285+duplication hint:
286+error hint:
287+SeqScan()
288+
289+ ?column?
290+----------
291+ 1
292+(1 row)
293+
279294 /*+SeqScan(t1 t2)*/
280295 EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
281296 INFO: pg_hint_plan: hint syntax error at or near ""
@@ -445,6 +460,36 @@ error hint:
445460 Index Cond: (id = t1.id)
446461 (5 rows)
447462
463+/*+ NestLoop() */ SELECT 1;
464+INFO: pg_hint_plan: hint syntax error at or near " "
465+DETAIL: NestLoop hint requires at least two relations.
466+LOG: pg_hint_plan:
467+used hint:
468+not used hint:
469+duplication hint:
470+error hint:
471+NestLoop()
472+
473+ ?column?
474+----------
475+ 1
476+(1 row)
477+
478+/*+ NestLoop(x) */ SELECT 1;
479+INFO: pg_hint_plan: hint syntax error at or near " "
480+DETAIL: NestLoop hint requires at least two relations.
481+LOG: pg_hint_plan:
482+used hint:
483+not used hint:
484+duplication hint:
485+error hint:
486+NestLoop(x)
487+
488+ ?column?
489+----------
490+ 1
491+(1 row)
492+
448493 /*+HashJoin(t1 t2)*/
449494 EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
450495 LOG: pg_hint_plan:
@@ -8750,6 +8795,37 @@ error hint:
87508795 -- Explain result includes "Planning time" if COSTS is enabled, but
87518796 -- this test needs it enabled for get rows count. So do tests via psql
87528797 -- and grep -v the mutable line.
8798+-- Parse error check
8799+/*+ Rows() */ SELECT 1;
8800+INFO: pg_hint_plan: hint syntax error at or near " "
8801+DETAIL: Rows hint needs at least one relation followed by one correction term.
8802+LOG: pg_hint_plan:
8803+used hint:
8804+not used hint:
8805+duplication hint:
8806+error hint:
8807+Rows()
8808+
8809+ ?column?
8810+----------
8811+ 1
8812+(1 row)
8813+
8814+/*+ Rows(x) */ SELECT 1;
8815+INFO: pg_hint_plan: hint syntax error at or near " "
8816+DETAIL: Rows hint needs at least one relation followed by one correction term.
8817+LOG: pg_hint_plan:
8818+used hint:
8819+not used hint:
8820+duplication hint:
8821+error hint:
8822+Rows()
8823+
8824+ ?column?
8825+----------
8826+ 1
8827+(1 row)
8828+
87538829 -- value types
87548830 \o results/pg_hint_plan.tmpout
87558831 EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id);
--- a/pg_hint_plan.c
+++ b/pg_hint_plan.c
@@ -1176,7 +1176,8 @@ RowsHintDesc(RowsHint *hint, StringInfo buf, bool nolf)
11761176 quote_value(buf, hint->relnames[i]);
11771177 }
11781178 }
1179- appendStringInfo(buf, " %s", hint->rows_str);
1179+ if (hint->rows_str != NULL)
1180+ appendStringInfo(buf, " %s", hint->rows_str);
11801181 appendStringInfoString(buf, ")");
11811182 if (!nolf)
11821183 appendStringInfoChar(buf, '\n');
@@ -2375,6 +2376,8 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse,
23752376 List *name_list = NIL;
23762377 char *rows_str;
23772378 char *end_ptr;
2379+ ListCell *l;
2380+ int i = 0;
23782381
23792382 if ((str = parse_parentheses(str, &name_list, hint_keyword)) == NULL)
23802383 return NULL;
@@ -2382,23 +2385,28 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse,
23822385 /* Last element must be rows specification */
23832386 hint->nrels = list_length(name_list) - 1;
23842387
2385- if (hint->nrels > 0)
2388+ if (hint->nrels < 1)
23862389 {
2387- ListCell *l;
2388- int i = 0;
2390+ hint_ereport(str,
2391+ ("%s hint needs at least one relation followed by one correction term.",
2392+ hint->base.keyword));
2393+ hint->base.state = HINT_STATE_ERROR;
23892394
2390- /*
2391- * Transform relation names from list to array to sort them with qsort
2392- * after.
2393- */
2394- hint->relnames = palloc(sizeof(char *) * hint->nrels);
2395- foreach (l, name_list)
2396- {
2397- if (hint->nrels <= i)
2398- break;
2399- hint->relnames[i] = lfirst(l);
2400- i++;
2401- }
2395+ return str;
2396+ }
2397+
2398+
2399+ /*
2400+ * Transform relation names from list to array to sort them with qsort
2401+ * after.
2402+ */
2403+ hint->relnames = palloc(sizeof(char *) * hint->nrels);
2404+ foreach (l, name_list)
2405+ {
2406+ if (hint->nrels <= i)
2407+ break;
2408+ hint->relnames[i] = lfirst(l);
2409+ i++;
24022410 }
24032411
24042412 /* Retieve rows estimation */
--- a/sql/pg_hint_plan.sql
+++ b/sql/pg_hint_plan.sql
@@ -52,6 +52,7 @@ EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
5252 /*+Set(work_mem TO "1MB")*/
5353 EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
5454
55+/*+SeqScan() */ SELECT 1;
5556 /*+SeqScan(t1 t2)*/
5657 EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
5758 /*+SeqScan(t1)*/
@@ -72,6 +73,8 @@ EXPLAIN (COSTS false) SELECT * FROM t3, t4 WHERE t3.id = t4.id AND t4.ctid = '(1
7273 /*+NoTidScan(t1)*/
7374 EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id AND t1.ctid = '(1,1)';
7475
76+/*+ NestLoop() */ SELECT 1;
77+/*+ NestLoop(x) */ SELECT 1;
7578 /*+HashJoin(t1 t2)*/
7679 EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id;
7780 /*+NestLoop(t1 t2)*/
@@ -1045,6 +1048,10 @@ SELECT val::int FROM p2 WHERE id < 1000;
10451048 -- this test needs it enabled for get rows count. So do tests via psql
10461049 -- and grep -v the mutable line.
10471050
1051+-- Parse error check
1052+/*+ Rows() */ SELECT 1;
1053+/*+ Rows(x) */ SELECT 1;
1054+
10481055 -- value types
10491056 \o results/pg_hint_plan.tmpout
10501057 EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id);
Show on old repository browser