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 по дате отправления: