Обсуждение: textlike under the LIKE operator for char(n)

Поиск
Список
Период
Сортировка

textlike under the LIKE operator for char(n)

От
Kohei KaiGai
Дата:
Hi,

I found a mysterious behavior when we use LIKE operator on char(n) data type.


postgres=# select 'abcd'::char(20) LIKE 'ab%cd';?column?
----------f
(1 row)

postgres=# select 'abcd'::char(4) LIKE 'ab%cd';?column?
----------t
(1 row)

LIKE operator (that is eventually processed by textlike) considers the
padding space of char(n) data type as a part of string.

On the other hands, equal operator ignores the padding space when it
compares two strings.

postgres=# select 'abcd'::char(20) = 'abcd';?column?
----------t
(1 row)

postgres=# select 'abcd'::char(4) = 'abcd';?column?
----------t
(1 row)

The LIKE operator on char(n) data type is implemented by textlike().

at pg_proc.h:
DATA(insert OID = 1631 (  bpcharlike       PGNSP PGUID 12 1 0 0 0 f f
f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_
textlike _null_ _null_ _null_ ));

It calls GenericMatchText() with length of the target string,
calculated by VARSIZE_ANY_EXHDR, however, it includes the padding
space.
It seems to me bcTruelen() gives the correct length for char(n) data
types, instead of this macro.

Is this behavior as expected? or, bug?

Thanks,
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>



Re: textlike under the LIKE operator for char(n)

От
Kevin Grittner
Дата:
<div dir="ltr">On Fri, May 6, 2016 at 8:58 AM, Kohei KaiGai <<a
href="mailto:kaigai@kaigai.gr.jp">kaigai@kaigai.gr.jp</a>>wrote:<br /><br />> postgres=# select 'abcd'::char(20)
LIKE'ab%cd';<br />>  ?column?<br />> ----------<br />>  f<br />> (1 row)<br />><br />> postgres=#
select'abcd'::char(4) LIKE 'ab%cd';<br />>  ?column?<br />> ----------<br />>  t<br />> (1 row)<br
/>><br/>> LIKE operator (that is eventually processed by textlike) considers the<br />> padding space of
char(n)data type as a part of string.<br /><br />The SQL standard generally requires this for CHAR(n) columns.<br /><br
/>>On the other hands, equal operator ignores the padding space when it<br />> compares two strings.<br />><br
/>>postgres=# select 'abcd'::char(20) = 'abcd';<br />>  ?column?<br />> ----------<br />>  t<br />> (1
row)<br/>><br />> postgres=# select 'abcd'::char(4) = 'abcd';<br />>  ?column?<br />> ----------<br />> 
t<br/>> (1 row)<br /><br />The SQL standard specifically requires this exception to the<br />general rule.<br /><br
/>>Is this behavior as expected? or, bug?<br /><br />This has been discussed on community lists multiple times in
the<br/>past; you might want to search the archives.  I'm not inclined to<br />dig through the standard for details on
thispoint again right now,<br />but in general the behaviors we provide for CHAR(n) are mandated by<br />standard.  It
wouldnot entirely shock me if there are some corner<br />cases where different behavior could be allowed or even
more<br/>correct, but my recollection is that what you have shown is all<br />required to work that way.<br /><br
/>Generally,I recommend avoiding CHAR(n) columns like the plague.<br /><br />--<br />Kevin Grittner<br />EDB: <a
href="http://www.enterprisedb.com">http://www.enterprisedb.com</a><br/>The Enterprise PostgreSQL Company<br /></div> 

Re: textlike under the LIKE operator for char(n)

От
Kohei KaiGai
Дата:
2016-05-06 23:17 GMT+09:00 Kevin Grittner <kgrittn@gmail.com>:
> On Fri, May 6, 2016 at 8:58 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>
>> postgres=# select 'abcd'::char(20) LIKE 'ab%cd';
>>  ?column?
>> ----------
>>  f
>> (1 row)
>>
>> postgres=# select 'abcd'::char(4) LIKE 'ab%cd';
>>  ?column?
>> ----------
>>  t
>> (1 row)
>>
>> LIKE operator (that is eventually processed by textlike) considers the
>> padding space of char(n) data type as a part of string.
>
> The SQL standard generally requires this for CHAR(n) columns.
>
>> On the other hands, equal operator ignores the padding space when it
>> compares two strings.
>>
>> postgres=# select 'abcd'::char(20) = 'abcd';
>>  ?column?
>> ----------
>>  t
>> (1 row)
>>
>> postgres=# select 'abcd'::char(4) = 'abcd';
>>  ?column?
>> ----------
>>  t
>> (1 row)
>
> The SQL standard specifically requires this exception to the
> general rule.
>
>> Is this behavior as expected? or, bug?
>
> This has been discussed on community lists multiple times in the
> past; you might want to search the archives.  I'm not inclined to
> dig through the standard for details on this point again right now,
> but in general the behaviors we provide for CHAR(n) are mandated by
> standard.  It would not entirely shock me if there are some corner
> cases where different behavior could be allowed or even more
> correct, but my recollection is that what you have shown is all
> required to work that way.
>
Thanks, I couldn't find out the reason of the behavior shortly.
Requirement by SQL standard is a clear guidance even if it looks
a bit mysterious.

> Generally, I recommend avoiding CHAR(n) columns like the plague.
>
Yep, I agree. I found this matter when I port LIKE operator on GPU,
not a time when some real-life query tried to use char(n).

Best regards,
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>