Alvar Freude wrote:
-- Joe Conway <[EMAIL PROTECTED]> wrote:
Please try the attached patch and let me know how it works for you. It is
against cvs HEAD, but should apply OK to 7.4.
so, I checked it with my database.
It looks good, all checks I made are OK.
The attached fixes the bytea-like bug found by Alvar -- as well as some
others I found while working on it. I would like to apply this evening
so that it can be in the 7.4.1 release. Any objections?
Thanks,
Joe
Index: src/backend/utils/adt/selfuncs.c
===
RCS file: /opt/src/cvs/pgsql-server/src/backend/utils/adt/selfuncs.c,v
retrieving revision 1.149
diff -c -r1.149 selfuncs.c
*** src/backend/utils/adt/selfuncs.c29 Nov 2003 19:51:59 - 1.149
--- src/backend/utils/adt/selfuncs.c5 Dec 2003 19:42:39 -
***
*** 184,189
--- 184,190
static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
static Datum string_to_datum(const char *str, Oid datatype);
static Const *string_to_const(const char *str, Oid datatype);
+ static Const *string_to_bytea_const(const char *str, size_t str_len);
/*
***
*** 3135,3154
}
else
{
! patt = DatumGetCString(DirectFunctionCall1(byteaout,
patt_const->constvalue));
! pattlen = toast_raw_datum_size(patt_const->constvalue) - VARHDRSZ;
}
match = palloc(pattlen + 1);
match_pos = 0;
-
for (pos = 0; pos < pattlen; pos++)
{
/* % and _ are wildcard characters in LIKE */
if (patt[pos] == '%' ||
patt[pos] == '_')
break;
! /* Backslash quotes the next character */
if (patt[pos] == '\\')
{
pos++;
--- 3136,3166
}
else
{
! bytea *bstr = DatumGetByteaP(patt_const->constvalue);
!
! pattlen = VARSIZE(bstr) - VARHDRSZ;
! if (pattlen > 0)
! {
! patt = (char *) palloc(pattlen);
! memcpy(patt, VARDATA(bstr), pattlen);
! }
! else
! patt = NULL;
!
! if ((Pointer) bstr != DatumGetPointer(patt_const->constvalue))
! pfree(bstr);
}
match = palloc(pattlen + 1);
match_pos = 0;
for (pos = 0; pos < pattlen; pos++)
{
/* % and _ are wildcard characters in LIKE */
if (patt[pos] == '%' ||
patt[pos] == '_')
break;
!
! /* Backslash escapes the next character */
if (patt[pos] == '\\')
{
pos++;
***
*** 3174,3183
match[match_pos] = '\0';
rest = &patt[pos];
! *prefix_const = string_to_const(match, typeid);
! *rest_const = string_to_const(rest, typeid);
! pfree(patt);
pfree(match);
/* in LIKE, an empty pattern is an exact match! */
--- 3186,3204
match[match_pos] = '\0';
rest = &patt[pos];
! if (typeid != BYTEAOID)
! {
! *prefix_const = string_to_const(match, typeid);
! *rest_const = string_to_const(rest, typeid);
! }
! else
! {
! *prefix_const = string_to_bytea_const(match, match_pos);
! *rest_const = string_to_bytea_const(rest, pattlen - match_pos);
! }
! if (patt != NULL)
! pfree(patt);
pfree(match);
/* in LIKE, an empty pattern is an exact match! */
***
*** 3500,3508
}
else
{
! patt = DatumGetCString(DirectFunctionCall1(byteaout,
patt_const->constvalue));
! pattlen = toast_raw_datum_size(patt_const->constvalue) - VARHDRSZ;
}
/* Skip any leading %; it's already factored into initial sel */
start = (*patt == '%') ? 1 : 0;
--- 3521,3542
}
else
{
! bytea *bstr = DatumGetByteaP(patt_const->constvalue);
!
! pattlen = VARSIZE(bstr) - VARHDRSZ;
! if (pattlen > 0)
! {
! patt = (char *) palloc(pattlen);
! memcpy(patt, VARDATA(bstr), pattlen);
! }
! else
! patt = NULL;
!
! if ((Pointer) bstr != DatumGetPointer(patt_const->constvalue))
! pfree(bstr);
}
+ /* patt should never be NULL in practice */
+ Assert(patt != NULL);
/* Skip any leading %; it's already factored into initial sel */
start = (*patt == '%') ? 1 : 0;
***
*** 3693,3700
/*
* Try to generate a string greater than the give