firtst release
リビジョン | 4bd82297178b63b72cf5d6451983362ef7d398b7 (tree) |
---|---|
日時 | 2020-02-17 14:59:15 |
作者 | 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.
@@ -276,6 +276,21 @@ Set(work_mem TO 1MB) | ||
276 | 276 | -> Index Scan using t2_pkey on t2 |
277 | 277 | (4 rows) |
278 | 278 | |
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 | + | |
279 | 294 | /*+SeqScan(t1 t2)*/ |
280 | 295 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
281 | 296 | INFO: pg_hint_plan: hint syntax error at or near "" |
@@ -445,6 +460,36 @@ error hint: | ||
445 | 460 | Index Cond: (id = t1.id) |
446 | 461 | (5 rows) |
447 | 462 | |
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 | + | |
448 | 493 | /*+HashJoin(t1 t2)*/ |
449 | 494 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
450 | 495 | LOG: pg_hint_plan: |
@@ -8750,6 +8795,37 @@ error hint: | ||
8750 | 8795 | -- Explain result includes "Planning time" if COSTS is enabled, but |
8751 | 8796 | -- this test needs it enabled for get rows count. So do tests via psql |
8752 | 8797 | -- 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 | + | |
8753 | 8829 | -- value types |
8754 | 8830 | \o results/pg_hint_plan.tmpout |
8755 | 8831 | EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id); |
@@ -1176,7 +1176,8 @@ RowsHintDesc(RowsHint *hint, StringInfo buf, bool nolf) | ||
1176 | 1176 | quote_value(buf, hint->relnames[i]); |
1177 | 1177 | } |
1178 | 1178 | } |
1179 | - appendStringInfo(buf, " %s", hint->rows_str); | |
1179 | + if (hint->rows_str != NULL) | |
1180 | + appendStringInfo(buf, " %s", hint->rows_str); | |
1180 | 1181 | appendStringInfoString(buf, ")"); |
1181 | 1182 | if (!nolf) |
1182 | 1183 | appendStringInfoChar(buf, '\n'); |
@@ -2375,6 +2376,8 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse, | ||
2375 | 2376 | List *name_list = NIL; |
2376 | 2377 | char *rows_str; |
2377 | 2378 | char *end_ptr; |
2379 | + ListCell *l; | |
2380 | + int i = 0; | |
2378 | 2381 | |
2379 | 2382 | if ((str = parse_parentheses(str, &name_list, hint_keyword)) == NULL) |
2380 | 2383 | return NULL; |
@@ -2382,23 +2385,28 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse, | ||
2382 | 2385 | /* Last element must be rows specification */ |
2383 | 2386 | hint->nrels = list_length(name_list) - 1; |
2384 | 2387 | |
2385 | - if (hint->nrels > 0) | |
2388 | + if (hint->nrels < 1) | |
2386 | 2389 | { |
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; | |
2389 | 2394 | |
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++; | |
2402 | 2410 | } |
2403 | 2411 | |
2404 | 2412 | /* Retieve rows estimation */ |
@@ -52,6 +52,7 @@ EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; | ||
52 | 52 | /*+Set(work_mem TO "1MB")*/ |
53 | 53 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
54 | 54 | |
55 | +/*+SeqScan() */ SELECT 1; | |
55 | 56 | /*+SeqScan(t1 t2)*/ |
56 | 57 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
57 | 58 | /*+SeqScan(t1)*/ |
@@ -72,6 +73,8 @@ EXPLAIN (COSTS false) SELECT * FROM t3, t4 WHERE t3.id = t4.id AND t4.ctid = '(1 | ||
72 | 73 | /*+NoTidScan(t1)*/ |
73 | 74 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id AND t1.ctid = '(1,1)'; |
74 | 75 | |
76 | +/*+ NestLoop() */ SELECT 1; | |
77 | +/*+ NestLoop(x) */ SELECT 1; | |
75 | 78 | /*+HashJoin(t1 t2)*/ |
76 | 79 | EXPLAIN (COSTS false) SELECT * FROM t1, t2 WHERE t1.id = t2.id; |
77 | 80 | /*+NestLoop(t1 t2)*/ |
@@ -1045,6 +1048,10 @@ SELECT val::int FROM p2 WHERE id < 1000; | ||
1045 | 1048 | -- this test needs it enabled for get rows count. So do tests via psql |
1046 | 1049 | -- and grep -v the mutable line. |
1047 | 1050 | |
1051 | +-- Parse error check | |
1052 | +/*+ Rows() */ SELECT 1; | |
1053 | +/*+ Rows(x) */ SELECT 1; | |
1054 | + | |
1048 | 1055 | -- value types |
1049 | 1056 | \o results/pg_hint_plan.tmpout |
1050 | 1057 | EXPLAIN SELECT * FROM t1 JOIN t2 ON (t1.id = t2.id); |