• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: Commit

firtst release


Commit MetaInfo

Revisionffc2832f84f93e922bca81329f8d733bf63c6e36 (tree)
Time2020-02-17 15:00:43
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:
@@ -8765,6 +8810,37 @@ error hint:
87658810 -- Explain result includes "Planning time" if COSTS is enabled, but
87668811 -- this test needs it enabled for get rows count. So do tests via psql
87678812 -- and grep -v the mutable line.
8813+-- Parse error check
8814+/*+ Rows() */ 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+
8829+/*+ Rows(x) */ SELECT 1;
8830+INFO: pg_hint_plan: hint syntax error at or near " "
8831+DETAIL: Rows hint needs at least one relation followed by one correction term.
8832+LOG: pg_hint_plan:
8833+used hint:
8834+not used hint:
8835+duplication hint:
8836+error hint:
8837+Rows()
8838+
8839+ ?column?
8840+----------
8841+ 1
8842+(1 row)
8843+
87688844 -- value types
87698845 \o results/pg_hint_plan.tmpout
87708846 EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id);
--- a/pg_hint_plan.c
+++ b/pg_hint_plan.c
@@ -1185,7 +1185,8 @@ RowsHintDesc(RowsHint *hint, StringInfo buf, bool nolf)
11851185 quote_value(buf, hint->relnames[i]);
11861186 }
11871187 }
1188- appendStringInfo(buf, " %s", hint->rows_str);
1188+ if (hint->rows_str != NULL)
1189+ appendStringInfo(buf, " %s", hint->rows_str);
11891190 appendStringInfoString(buf, ")");
11901191 if (!nolf)
11911192 appendStringInfoChar(buf, '\n');
@@ -2374,6 +2375,8 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse,
23742375 List *name_list = NIL;
23752376 char *rows_str;
23762377 char *end_ptr;
2378+ ListCell *l;
2379+ int i = 0;
23772380
23782381 if ((str = parse_parentheses(str, &name_list, hint_keyword)) == NULL)
23792382 return NULL;
@@ -2381,23 +2384,28 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse,
23812384 /* Last element must be rows specification */
23822385 hint->nrels = list_length(name_list) - 1;
23832386
2384- if (hint->nrels > 0)
2387+ if (hint->nrels < 1)
23852388 {
2386- ListCell *l;
2387- int i = 0;
2389+ hint_ereport(str,
2390+ ("%s hint needs at least one relation followed by one correction term.",
2391+ hint->base.keyword));
2392+ hint->base.state = HINT_STATE_ERROR;
23882393
2389- /*
2390- * Transform relation names from list to array to sort them with qsort
2391- * after.
2392- */
2393- hint->relnames = palloc(sizeof(char *) * hint->nrels);
2394- foreach (l, name_list)
2395- {
2396- if (hint->nrels <= i)
2397- break;
2398- hint->relnames[i] = lfirst(l);
2399- i++;
2400- }
2394+ return str;
2395+ }
2396+
2397+
2398+ /*
2399+ * Transform relation names from list to array to sort them with qsort
2400+ * after.
2401+ */
2402+ hint->relnames = palloc(sizeof(char *) * hint->nrels);
2403+ foreach (l, name_list)
2404+ {
2405+ if (hint->nrels <= i)
2406+ break;
2407+ hint->relnames[i] = lfirst(l);
2408+ i++;
24012409 }
24022410
24032411 /* 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)*/
@@ -1049,6 +1052,10 @@ SELECT val::int FROM p2 WHERE id < 1000;
10491052 -- this test needs it enabled for get rows count. So do tests via psql
10501053 -- and grep -v the mutable line.
10511054
1055+-- Parse error check
1056+/*+ Rows() */ SELECT 1;
1057+/*+ Rows(x) */ SELECT 1;
1058+
10521059 -- value types
10531060 \o results/pg_hint_plan.tmpout
10541061 EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id);
Show on old repository browser