Re: BUG #8198: ROW() literals not supported in an IN clause
| От | Amit Kapila |
|---|---|
| Тема | Re: BUG #8198: ROW() literals not supported in an IN clause |
| Дата | |
| Msg-id | 000301ce610f$2ee8de60$8cba9b20$@kapila@huawei.com обсуждение исходный текст |
| Ответ на | BUG #8198: ROW() literals not supported in an IN clause (divided.mind@gmail.com) |
| Список | pgsql-bugs |
On Saturday, June 01, 2013 9:37 PM=20
=20
> 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.
>=20
> To wit:
> divide=3D# create type the_row as (mfg text, id text);
> CREATE TYPE
> divide=3D# create table the_table (widget the_row);
>=20
>=20
> CREATE TABLE
>=20
>=20
> divide=3D# insert into the_table values(row('foo', 'bar')::the_row);
>=20
>=20
> INSERT 0 1
>=20
>=20
> divide=3D# insert into the_table values('(bar,baz)'::the_row);
>=20
>=20
> INSERT 0 1
> divide=3D# select * from the_table;
> widget
> -----------
> (foo,bar)
> (bar,baz)
> (2 rows)
>=20
> divide=3D# select * from the_table where widget in
> ('(foo,bar)'::the_row);
> widget
> -----------
> (foo,bar)
> (1 row)
>=20
> divide=3D# 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 ('=3D') operator works fine.
select * from the_table where widget =3D (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() =20
else if (lexpr && IsA(lexpr, RowExpr) &&=20
rexpr && IsA(rexpr, RowExpr))=20
{=20
....
result =3D make_row_comparison_op(pstate,=20
=
a->name,=20
=
((RowExpr *) lexpr)->args,=20
=
((RowExpr *) rexpr)->args,=20
=
a->location);=20
}=20
else=20
{=20
....
result =3D (Node *) make_op(pstate,=20
=
a->name,=20
lexpr, =
rexpr, =
=
a->location);=20
}
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)=20
{=20
if (!IsA(lexpr, RowExpr) ||=20
!IsA(rexpr, RowExpr))=20
ereport(ERROR,=20
=
(errcode(ERRCODE_SYNTAX_ERROR),=20
errmsg("arguments of row IN must all =
be row expressions"),=20
=
parser_errposition(pstate, a->location)));=20
cmp =3D make_row_comparison_op(pstate,=20
=
a->name,=20
(List *) =
copyObject(((RowExpr *) lexpr)->args),=20
=
((RowExpr *) rexpr)->args,=20
=
a->location);=20
}=20
else=20
cmp =3D (Node *) make_op(pstate,=20
=
a->name,=20
=
copyObject(lexpr),=20
=
rexpr,=20
=
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.
В списке pgsql-bugs по дате отправления: