firtst release
リビジョン | 52d9acd38b91e8fe6b1b76bde5f1d591780fe279 (tree) |
---|---|
日時 | 2020-02-17 14:55:03 |
作者 | Kyotaro Horiguchi <horikyota.ntt@gmai...> |
コミッター | Kyotaro Horiguchi |
Fix Rows hint parsing
This is a long standing bug that Rows hint with no parameter causees a
crash. Fixed the Rows hint parser.
@@ -275,6 +275,21 @@ Set(work_mem TO 1MB) | ||
275 | 275 | -> Index Scan using t2_pkey on t2 |
276 | 276 | (4 rows) |
277 | 277 | |
278 | +/*+SeqScan() */ SELECT 1; | |
279 | +INFO: pg_hint_plan: hint syntax error at or near " " | |
280 | +DETAIL: SeqScan hint requires a relation. | |
281 | +LOG: pg_hint_plan: | |
282 | +used hint: | |
283 | +not used hint: | |
284 | +duplication hint: | |
285 | +error hint: | |
286 | +SeqScan() | |
287 | + | |
288 | + ?column? | |
289 | +---------- | |
290 | + 1 | |
291 | +(1 row) | |
292 | + | |
278 | 293 | /*+SeqScan(t1 t2)*/ |
279 | 294 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
280 | 295 | INFO: pg_hint_plan: hint syntax error at or near "" |
@@ -444,6 +459,36 @@ error hint: | ||
444 | 459 | Index Cond: (id = t1.id) |
445 | 460 | (5 rows) |
446 | 461 | |
462 | +/*+ NestLoop() */ SELECT 1; | |
463 | +INFO: pg_hint_plan: hint syntax error at or near " " | |
464 | +DETAIL: NestLoop hint requires at least two relations. | |
465 | +LOG: pg_hint_plan: | |
466 | +used hint: | |
467 | +not used hint: | |
468 | +duplication hint: | |
469 | +error hint: | |
470 | +NestLoop() | |
471 | + | |
472 | + ?column? | |
473 | +---------- | |
474 | + 1 | |
475 | +(1 row) | |
476 | + | |
477 | +/*+ NestLoop(x) */ SELECT 1; | |
478 | +INFO: pg_hint_plan: hint syntax error at or near " " | |
479 | +DETAIL: NestLoop hint requires at least two relations. | |
480 | +LOG: pg_hint_plan: | |
481 | +used hint: | |
482 | +not used hint: | |
483 | +duplication hint: | |
484 | +error hint: | |
485 | +NestLoop(x) | |
486 | + | |
487 | + ?column? | |
488 | +---------- | |
489 | + 1 | |
490 | +(1 row) | |
491 | + | |
447 | 492 | /*+HashJoin(t1 t2)*/ |
448 | 493 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
449 | 494 | LOG: pg_hint_plan: |
@@ -8751,6 +8796,37 @@ error hint: | ||
8751 | 8796 | -- Explain result includes "Planning time" if COSTS is enabled, but |
8752 | 8797 | -- this test needs it enabled for get rows count. So do tests via psql |
8753 | 8798 | -- and grep -v the mutable line. |
8799 | +-- Parse error check | |
8800 | +/*+ Rows() */ SELECT 1; | |
8801 | +INFO: pg_hint_plan: hint syntax error at or near " " | |
8802 | +DETAIL: Rows hint needs at least one relation followed by one correction term. | |
8803 | +LOG: pg_hint_plan: | |
8804 | +used hint: | |
8805 | +not used hint: | |
8806 | +duplication hint: | |
8807 | +error hint: | |
8808 | +Rows() | |
8809 | + | |
8810 | + ?column? | |
8811 | +---------- | |
8812 | + 1 | |
8813 | +(1 row) | |
8814 | + | |
8815 | +/*+ Rows(x) */ SELECT 1; | |
8816 | +INFO: pg_hint_plan: hint syntax error at or near " " | |
8817 | +DETAIL: Rows hint needs at least one relation followed by one correction term. | |
8818 | +LOG: pg_hint_plan: | |
8819 | +used hint: | |
8820 | +not used hint: | |
8821 | +duplication hint: | |
8822 | +error hint: | |
8823 | +Rows() | |
8824 | + | |
8825 | + ?column? | |
8826 | +---------- | |
8827 | + 1 | |
8828 | +(1 row) | |
8829 | + | |
8754 | 8830 | -- value types |
8755 | 8831 | \o results/pg_hint_plan.tmpout |
8756 | 8832 | EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id); |
@@ -1067,7 +1067,8 @@ RowsHintDesc(RowsHint *hint, StringInfo buf, bool nolf) | ||
1067 | 1067 | quote_value(buf, hint->relnames[i]); |
1068 | 1068 | } |
1069 | 1069 | } |
1070 | - appendStringInfo(buf, " %s", hint->rows_str); | |
1070 | + if (hint->rows_str != NULL) | |
1071 | + appendStringInfo(buf, " %s", hint->rows_str); | |
1071 | 1072 | appendStringInfoString(buf, ")"); |
1072 | 1073 | if (!nolf) |
1073 | 1074 | appendStringInfoChar(buf, '\n'); |
@@ -2241,6 +2242,8 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse, | ||
2241 | 2242 | List *name_list = NIL; |
2242 | 2243 | char *rows_str; |
2243 | 2244 | char *end_ptr; |
2245 | + ListCell *l; | |
2246 | + int i = 0; | |
2244 | 2247 | |
2245 | 2248 | if ((str = parse_parentheses(str, &name_list, hint_keyword)) == NULL) |
2246 | 2249 | return NULL; |
@@ -2248,23 +2251,28 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse, | ||
2248 | 2251 | /* Last element must be rows specification */ |
2249 | 2252 | hint->nrels = list_length(name_list) - 1; |
2250 | 2253 | |
2251 | - if (hint->nrels > 0) | |
2254 | + if (hint->nrels < 1) | |
2252 | 2255 | { |
2253 | - ListCell *l; | |
2254 | - int i = 0; | |
2256 | + hint_ereport(str, | |
2257 | + ("%s hint needs at least one relation followed by one correction term.", | |
2258 | + hint->base.keyword)); | |
2259 | + hint->base.state = HINT_STATE_ERROR; | |
2255 | 2260 | |
2256 | - /* | |
2257 | - * Transform relation names from list to array to sort them with qsort | |
2258 | - * after. | |
2259 | - */ | |
2260 | - hint->relnames = palloc(sizeof(char *) * hint->nrels); | |
2261 | - foreach (l, name_list) | |
2262 | - { | |
2263 | - if (hint->nrels <= i) | |
2264 | - break; | |
2265 | - hint->relnames[i] = lfirst(l); | |
2266 | - i++; | |
2267 | - } | |
2261 | + return str; | |
2262 | + } | |
2263 | + | |
2264 | + | |
2265 | + /* | |
2266 | + * Transform relation names from list to array to sort them with qsort | |
2267 | + * after. | |
2268 | + */ | |
2269 | + hint->relnames = palloc(sizeof(char *) * hint->nrels); | |
2270 | + foreach (l, name_list) | |
2271 | + { | |
2272 | + if (hint->nrels <= i) | |
2273 | + break; | |
2274 | + hint->relnames[i] = lfirst(l); | |
2275 | + i++; | |
2268 | 2276 | } |
2269 | 2277 | |
2270 | 2278 | /* Retieve rows estimation */ |
@@ -51,6 +51,7 @@ EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; | ||
51 | 51 | /*+Set(work_mem TO "1MB")*/ |
52 | 52 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
53 | 53 | |
54 | +/*+SeqScan() */ SELECT 1; | |
54 | 55 | /*+SeqScan(t1 t2)*/ |
55 | 56 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
56 | 57 | /*+SeqScan(t1)*/ |
@@ -71,6 +72,8 @@ EXPLAIN (COSTS false) SELECT * FROM t3, t4 WHERE t3.id = t4.id AND t4.ctid = '(1 | ||
71 | 72 | /*+NoTidScan(t1)*/ |
72 | 73 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id AND t1.ctid = '(1,1)'; |
73 | 74 | |
75 | +/*+ NestLoop() */ SELECT 1; | |
76 | +/*+ NestLoop(x) */ SELECT 1; | |
74 | 77 | /*+HashJoin(t1 t2)*/ |
75 | 78 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
76 | 79 | /*+NestLoop(t1 t2)*/ |
@@ -1044,6 +1047,10 @@ SELECT val::int FROM p2 WHERE id < 1000; | ||
1044 | 1047 | -- this test needs it enabled for get rows count. So do tests via psql |
1045 | 1048 | -- and grep -v the mutable line. |
1046 | 1049 | |
1050 | +-- Parse error check | |
1051 | +/*+ Rows() */ SELECT 1; | |
1052 | +/*+ Rows(x) */ SELECT 1; | |
1053 | + | |
1047 | 1054 | -- value types |
1048 | 1055 | \o results/pg_hint_plan.tmpout |
1049 | 1056 | EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id); |