Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 53e7c13

Browse files
committed
Repair indexed bytea like operations, and related selectivity
functionality. Per bug report by Alvar Freude: http://archives.postgresql.org/pgsql-bugs/2003-12/msg00022.php
1 parent 7bb11a9 commit 53e7c13

File tree

1 file changed

+87
-24
lines changed

1 file changed

+87
-24
lines changed

src/backend/utils/adt/selfuncs.c

+87-24
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.149 2003/11/29 19:51:59 pgsql Exp $
18+
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.150 2003/12/07 04:14:10 joe Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -184,6 +184,7 @@ static Selectivity prefix_selectivity(Query *root, Var *var,
184184
static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
185185
static Datum string_to_datum(const char *str, Oid datatype);
186186
static Const *string_to_const(const char *str, Oid datatype);
187+
static Const *string_to_bytea_const(const char *str, size_t str_len);
187188

188189

189190
/*
@@ -3135,20 +3136,31 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive,
31353136
}
31363137
else
31373138
{
3138-
patt = DatumGetCString(DirectFunctionCall1(byteaout, patt_const->constvalue));
3139-
pattlen = toast_raw_datum_size(patt_const->constvalue) - VARHDRSZ;
3139+
bytea *bstr = DatumGetByteaP(patt_const->constvalue);
3140+
3141+
pattlen = VARSIZE(bstr) - VARHDRSZ;
3142+
if (pattlen > 0)
3143+
{
3144+
patt = (char *) palloc(pattlen);
3145+
memcpy(patt, VARDATA(bstr), pattlen);
3146+
}
3147+
else
3148+
patt = NULL;
3149+
3150+
if ((Pointer) bstr != DatumGetPointer(patt_const->constvalue))
3151+
pfree(bstr);
31403152
}
31413153

31423154
match = palloc(pattlen + 1);
31433155
match_pos = 0;
3144-
31453156
for (pos = 0; pos < pattlen; pos++)
31463157
{
31473158
/* % and _ are wildcard characters in LIKE */
31483159
if (patt[pos] == '%' ||
31493160
patt[pos] == '_')
31503161
break;
3151-
/* Backslash quotes the next character */
3162+
3163+
/* Backslash escapes the next character */
31523164
if (patt[pos] == '\\')
31533165
{
31543166
pos++;
@@ -3174,10 +3186,19 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive,
31743186
match[match_pos] = '\0';
31753187
rest = &patt[pos];
31763188

3177-
*prefix_const = string_to_const(match, typeid);
3178-
*rest_const = string_to_const(rest, typeid);
3189+
if (typeid != BYTEAOID)
3190+
{
3191+
*prefix_const = string_to_const(match, typeid);
3192+
*rest_const = string_to_const(rest, typeid);
3193+
}
3194+
else
3195+
{
3196+
*prefix_const = string_to_bytea_const(match, match_pos);
3197+
*rest_const = string_to_bytea_const(rest, pattlen - pos);
3198+
}
31793199

3180-
pfree(patt);
3200+
if (patt != NULL)
3201+
pfree(patt);
31813202
pfree(match);
31823203

31833204
/* in LIKE, an empty pattern is an exact match! */
@@ -3500,9 +3521,22 @@ like_selectivity(Const *patt_const, bool case_insensitive)
35003521
}
35013522
else
35023523
{
3503-
patt = DatumGetCString(DirectFunctionCall1(byteaout, patt_const->constvalue));
3504-
pattlen = toast_raw_datum_size(patt_const->constvalue) - VARHDRSZ;
3524+
bytea *bstr = DatumGetByteaP(patt_const->constvalue);
3525+
3526+
pattlen = VARSIZE(bstr) - VARHDRSZ;
3527+
if (pattlen > 0)
3528+
{
3529+
patt = (char *) palloc(pattlen);
3530+
memcpy(patt, VARDATA(bstr), pattlen);
3531+
}
3532+
else
3533+
patt = NULL;
3534+
3535+
if ((Pointer) bstr != DatumGetPointer(patt_const->constvalue))
3536+
pfree(bstr);
35053537
}
3538+
/* patt should never be NULL in practice */
3539+
Assert(patt != NULL);
35063540

35073541
/* Skip any leading %; it's already factored into initial sel */
35083542
start = (*patt == '%') ? 1 : 0;
@@ -3693,8 +3727,8 @@ pattern_selectivity(Const *patt, Pattern_Type ptype)
36933727

36943728
/*
36953729
* Try to generate a string greater than the given string or any
3696-
* string it is a prefix of. If successful, return a palloc'd string;
3697-
* else return NULL.
3730+
* string it is a prefix of. If successful, return a palloc'd string
3731+
* in the form of a Const pointer; else return NULL.
36983732
*
36993733
* The key requirement here is that given a prefix string, say "foo",
37003734
* we must be able to generate another string "fop" that is greater
@@ -3712,27 +3746,38 @@ Const *
37123746
make_greater_string(const Const *str_const)
37133747
{
37143748
Oid datatype = str_const->consttype;
3715-
char *str;
37163749
char *workstr;
37173750
int len;
37183751

37193752
/* Get the string and a modifiable copy */
37203753
if (datatype == NAMEOID)
37213754
{
3722-
str = DatumGetCString(DirectFunctionCall1(nameout, str_const->constvalue));
3723-
len = strlen(str);
3755+
workstr = DatumGetCString(DirectFunctionCall1(nameout,
3756+
str_const->constvalue));
3757+
len = strlen(workstr);
37243758
}
37253759
else if (datatype == BYTEAOID)
37263760
{
3727-
str = DatumGetCString(DirectFunctionCall1(byteaout, str_const->constvalue));
3728-
len = toast_raw_datum_size(str_const->constvalue) - VARHDRSZ;
3761+
bytea *bstr = DatumGetByteaP(str_const->constvalue);
3762+
3763+
len = VARSIZE(bstr) - VARHDRSZ;
3764+
if (len > 0)
3765+
{
3766+
workstr = (char *) palloc(len);
3767+
memcpy(workstr, VARDATA(bstr), len);
3768+
}
3769+
else
3770+
workstr = NULL;
3771+
3772+
if ((Pointer) bstr != DatumGetPointer(str_const->constvalue))
3773+
pfree(bstr);
37293774
}
37303775
else
37313776
{
3732-
str = DatumGetCString(DirectFunctionCall1(textout, str_const->constvalue));
3733-
len = strlen(str);
3777+
workstr = DatumGetCString(DirectFunctionCall1(textout,
3778+
str_const->constvalue));
3779+
len = strlen(workstr);
37343780
}
3735-
workstr = pstrdup(str);
37363781

37373782
while (len > 0)
37383783
{
@@ -3747,9 +3792,11 @@ make_greater_string(const Const *str_const)
37473792
Const *workstr_const;
37483793

37493794
(*lastchar)++;
3750-
workstr_const = string_to_const(workstr, datatype);
3795+
if (datatype != BYTEAOID)
3796+
workstr_const = string_to_const(workstr, datatype);
3797+
else
3798+
workstr_const = string_to_bytea_const(workstr, len);
37513799

3752-
pfree(str);
37533800
pfree(workstr);
37543801
return workstr_const;
37553802
}
@@ -3771,8 +3818,8 @@ make_greater_string(const Const *str_const)
37713818
}
37723819

37733820
/* Failed... */
3774-
pfree(str);
3775-
pfree(workstr);
3821+
if (workstr != NULL)
3822+
pfree(workstr);
37763823

37773824
return (Const *) NULL;
37783825
}
@@ -3811,6 +3858,22 @@ string_to_const(const char *str, Oid datatype)
38113858
conval, false, false);
38123859
}
38133860

3861+
/*
3862+
* Generate a Const node of bytea type from a binary C string and a length.
3863+
*/
3864+
static Const *
3865+
string_to_bytea_const(const char *str, size_t str_len)
3866+
{
3867+
bytea *bstr = palloc(VARHDRSZ + str_len);
3868+
Datum conval;
3869+
3870+
memcpy(VARDATA(bstr), str, str_len);
3871+
VARATT_SIZEP(bstr) = VARHDRSZ + str_len;
3872+
conval = PointerGetDatum(bstr);
3873+
3874+
return makeConst(BYTEAOID, -1, conval, false, false);
3875+
}
3876+
38143877
/*-------------------------------------------------------------------------
38153878
*
38163879
* Index cost estimation functions

0 commit comments

Comments
 (0)