|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.235 2008/10/06 17:39:26 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.236 2008/10/25 17:19:09 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
|
20 | 20 | #include "miscadmin.h"
|
21 | 21 | #include "nodes/makefuncs.h"
|
22 | 22 | #include "nodes/nodeFuncs.h"
|
| 23 | +#include "optimizer/var.h" |
23 | 24 | #include "parser/analyze.h"
|
24 | 25 | #include "parser/parse_coerce.h"
|
25 | 26 | #include "parser/parse_expr.h"
|
@@ -974,29 +975,45 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
|
974 | 975 | }
|
975 | 976 |
|
976 | 977 | /*
|
977 |
| - * If not forced by presence of RowExpr, try to resolve a common scalar |
978 |
| - * type for all the expressions, and see if it has an array type. (But if |
979 |
| - * there's only one righthand expression, we may as well just fall through |
980 |
| - * and generate a simple = comparison.) |
| 978 | + * We prefer a boolean tree to ScalarArrayOpExpr if any of these are true: |
| 979 | + * |
| 980 | + * 1. We have a RowExpr anywhere. |
| 981 | + * |
| 982 | + * 2. There's only one righthand expression --- best to just generate a |
| 983 | + * simple = comparison. |
| 984 | + * |
| 985 | + * 3. There's a reasonably small number of righthand expressions and |
| 986 | + * they contain any Vars. This is a heuristic to support cases like |
| 987 | + * WHERE '555-1212' IN (tab.home_phone, tab.work_phone), which can be |
| 988 | + * optimized into an OR of indexscans on different indexes so long as |
| 989 | + * it's left as an OR tree. (It'd be better to leave this decision |
| 990 | + * to the planner, no doubt, but the amount of code required to reformat |
| 991 | + * the expression later on seems out of proportion to the benefit.) |
981 | 992 | */
|
982 |
| - if (!haveRowExpr && list_length(rexprs) != 1) |
| 993 | + if (!(haveRowExpr || |
| 994 | + list_length(rexprs) == 1 || |
| 995 | + (list_length(rexprs) <= 32 && |
| 996 | + contain_vars_of_level((Node *) rexprs, 0)))) |
983 | 997 | {
|
984 | 998 | List *allexprs;
|
985 | 999 | Oid scalar_type;
|
986 | 1000 | Oid array_type;
|
987 | 1001 |
|
988 | 1002 | /*
|
989 |
| - * Select a common type for the array elements. Note that since the |
990 |
| - * LHS' type is first in the list, it will be preferred when there is |
991 |
| - * doubt (eg, when all the RHS items are unknown literals). |
| 1003 | + * Try to select a common type for the array elements. Note that |
| 1004 | + * since the LHS' type is first in the list, it will be preferred when |
| 1005 | + * there is doubt (eg, when all the RHS items are unknown literals). |
992 | 1006 | *
|
993 | 1007 | * Note: use list_concat here not lcons, to avoid damaging rexprs.
|
994 | 1008 | */
|
995 | 1009 | allexprs = list_concat(list_make1(lexpr), rexprs);
|
996 |
| - scalar_type = select_common_type(pstate, allexprs, "IN", NULL); |
| 1010 | + scalar_type = select_common_type(pstate, allexprs, NULL, NULL); |
997 | 1011 |
|
998 | 1012 | /* Do we have an array type to use? */
|
999 |
| - array_type = get_array_type(scalar_type); |
| 1013 | + if (OidIsValid(scalar_type)) |
| 1014 | + array_type = get_array_type(scalar_type); |
| 1015 | + else |
| 1016 | + array_type = InvalidOid; |
1000 | 1017 | if (array_type != InvalidOid)
|
1001 | 1018 | {
|
1002 | 1019 | /*
|
|
0 commit comments