From: | Amit Kapila <amit(dot)kapila(at)huawei(dot)com> |
---|---|
To: | <divided(dot)mind(at)gmail(dot)com>, <pgsql-bugs(at)postgresql(dot)org> |
Subject: | Re: BUG #8198: ROW() literals not supported in an IN clause |
Date: | 2013-06-04 10:35:05 |
Message-ID: | 000301ce610f$2ee8de60$8cba9b20$@kapila@huawei.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-bugs |
On Saturday, June 01, 2013 9:37 PM
> Row type literals constructed with ROW() cause an error when used in an
> IN
> clause (string literals casted appropriately are allowed). This is
> especially problematic since many client libraries use these literals
> to
> pass values of row-type arguments, hence making it impossible to use
> them in
> IN-clause queries.
>
> To wit:
> divide=# create type the_row as (mfg text, id text);
> CREATE TYPE
> divide=# create table the_table (widget the_row);
>
>
> CREATE TABLE
>
>
> divide=# insert into the_table values(row('foo', 'bar')::the_row);
>
>
> INSERT 0 1
>
>
> divide=# insert into the_table values('(bar,baz)'::the_row);
>
>
> INSERT 0 1
> divide=# select * from the_table;
> widget
> -----------
> (foo,bar)
> (bar,baz)
> (2 rows)
>
> divide=# select * from the_table where widget in
> ('(foo,bar)'::the_row);
> widget
> -----------
> (foo,bar)
> (1 row)
>
> divide=# select * from the_table where widget in
> (row('foo','bar')::the_row);
> ERROR: arguments of row IN must all be row expressions
> LINE 1: select * from the_table where widget in (row('foo','bar')::t...
The similar query for equal ('=') operator works fine.
select * from the_table where widget = (row('foo','bar')::the_row);
The reason for above is that in function transformAExprOp(..), it uses make_row_comparison_op() to operate on expressions only if both left and right are row expressions, else it will use make_op() to operate on expressions. Refer code below in function transformAExprOp()
else if (lexpr && IsA(lexpr, RowExpr) &&
rexpr && IsA(rexpr, RowExpr))
{
....
result = make_row_comparison_op(pstate,
a->name,
((RowExpr *) lexpr)->args,
((RowExpr *) rexpr)->args,
a->location);
}
else
{
....
result = (Node *) make_op(pstate,
a->name,
lexpr,
rexpr,
a->location);
}
However for IN clause, if any one expr (left or right) is RowExpr, then it will try to use make_row_comparison_op, which result in error.
Refer below code of function transformAExprIn():
if (haveRowExpr)
{
if (!IsA(lexpr, RowExpr) ||
!IsA(rexpr, RowExpr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("arguments of row IN must all be row expressions"),
parser_errposition(pstate, a->location)));
cmp = make_row_comparison_op(pstate,
a->name,
(List *) copyObject(((RowExpr *) lexpr)->args),
((RowExpr *) rexpr)->args,
a->location);
}
else
cmp = (Node *) make_op(pstate,
a->name,
copyObject(lexpr),
rexpr,
a->location);
Changing the functionality of transformAExprIn() similar to transformAExprOp() will fix this issue, but not sure if there is any other side effect of same.
With Regards,
Amit Kapila.
From | Date | Subject | |
---|---|---|---|
Next Message | Stephen Frost | 2013-06-04 12:27:36 | Re: Memory-leak in BackgroundWriter(and Checkpointer) |
Previous Message | Naoya Anzai | 2013-06-04 07:45:01 | Memory-leak in BackgroundWriter(and Checkpointer) |