Re: BUG #5478: ILIKE operator returns wrong result - Mailing list pgsql-bugs
| From | Bruce Momjian |
|---|---|
| Subject | Re: BUG #5478: ILIKE operator returns wrong result |
| Date | |
| Msg-id | 201005281538.o4SFcTW16083@momjian.us Whole thread Raw |
| In response to | Re: BUG #5478: ILIKE operator returns wrong result (Tom Lane <tgl@sss.pgh.pa.us>) |
| Responses |
Re: BUG #5478: ILIKE operator returns wrong result
|
| List | pgsql-bugs |
Tom Lane wrote:
> Bruce Momjian <bruce@momjian.us> writes:
> > Tom Lane wrote:
> >> I have a feeling that this represents still another bug in the
> >> special-case path for % followed by _ (cf bug #4821). If so,
> >> maybe we ought to just toss out that optimization?
>
> > Yea, looks like it is this code in like_match.c:
>
> No, actually it's the bit right after that:
>
> /* Look for a place that matches the rest of the pattern */
> while (tlen > 0)
> {
> int matched = MatchText(t, tlen, p, plen);
>
> if (matched != LIKE_FALSE)
> return matched; /* TRUE or ABORT */
>
> NextChar(t, tlen);
> }
>
> If tlen == 0 when we reach this loop, we'll fall through and fail.
> But that is wrong since we need to consider the possibility that
> the remaining pattern can match a zero-length substring. So the
> loop needs to be changed to attempt a recursive MatchText for
> tlen equal to zero as well as greater than zero.
I took a different approach. I think the problem is that we check for
end of pattern without consuming '%' patterns. I copied that consume
loop from code above that where we also test for end of pattern.
With the attached patch (which includes a regression test addition), it
works fine:
test=> select 'ba' like '%__%';
?column?
----------
t
(1 row)
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
Index: src/backend/utils/adt/like_match.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/like_match.c,v
retrieving revision 1.27
diff -c -c -r1.27 like_match.c
*** src/backend/utils/adt/like_match.c 2 Jan 2010 16:57:54 -0000 1.27
--- src/backend/utils/adt/like_match.c 28 May 2010 15:36:09 -0000
***************
*** 139,144 ****
--- 139,146 ----
* n _'s matches any string of at least n characters, and we
* have now found there are at least n characters.
*/
+ while (plen > 0 && *p == '%')
+ NextByte(p, plen);
if (plen <= 0)
return LIKE_TRUE;
Index: src/test/regress/expected/strings.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/strings.out,v
retrieving revision 1.40
diff -c -c -r1.40 strings.out
*** src/test/regress/expected/strings.out 25 Jan 2010 20:55:32 -0000 1.40
--- src/test/regress/expected/strings.out 28 May 2010 15:36:12 -0000
***************
*** 943,948 ****
--- 943,954 ----
t
(1 row)
+ SELECT 'jack' LIKE '%____%' AS "true";
+ true
+ ------
+ t
+ (1 row)
+
--
-- test ILIKE (case-insensitive LIKE)
-- Be sure to form every test as an ILIKE/NOT ILIKE pair.
Index: src/test/regress/sql/strings.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/strings.sql,v
retrieving revision 1.28
diff -c -c -r1.28 strings.sql
*** src/test/regress/sql/strings.sql 25 Jan 2010 20:55:32 -0000 1.28
--- src/test/regress/sql/strings.sql 28 May 2010 15:36:12 -0000
***************
*** 282,287 ****
--- 282,288 ----
SELECT 'be_r' LIKE '__e__r' ESCAPE '_' AS "false";
SELECT 'be_r' NOT LIKE '__e__r' ESCAPE '_' AS "true";
+ SELECT 'jack' LIKE '%____%' AS "true";
--
-- test ILIKE (case-insensitive LIKE)
***************
*** 310,316 ****
SELECT 'foo' LIKE '__%' as t, 'foo' LIKE '___%' as t, 'foo' LIKE '____%' as f;
SELECT 'foo' LIKE '%__' as t, 'foo' LIKE '%___' as t, 'foo' LIKE '%____' as f;
-
--
-- test implicit type conversion
--
--- 311,316 ----
pgsql-bugs by date: