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

Предыдущее
От: Naoya Anzai
Дата:
Сообщение: Memory-leak in BackgroundWriter(and Checkpointer)
Следующее
От: Stephen Frost
Дата:
Сообщение: Re: Memory-leak in BackgroundWriter(and Checkpointer)