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,
184184static Selectivity pattern_selectivity (Const * patt ,Pattern_Type ptype );
185185static Datum string_to_datum (const char * str ,Oid datatype );
186186static 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}
31363137else
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
31423154match = palloc (pattlen + 1 );
31433155match_pos = 0 ;
3144-
31453156for (pos = 0 ;pos < pattlen ;pos ++ )
31463157{
31473158/* % and _ are wildcard characters in LIKE */
31483159if (patt [pos ]== '%' ||
31493160patt [pos ]== '_' )
31503161break ;
3151- /* Backslash quotes the next character */
3162+
3163+ /* Backslash escapes the next character */
31523164if (patt [pos ]== '\\' )
31533165{
31543166pos ++ ;
@@ -3174,10 +3186,19 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive,
31743186match [match_pos ]= '\0' ;
31753187rest = & 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 );
31813202pfree (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}
35013522else
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 */
35083542start = (* 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 *
37123746make_greater_string (const Const * str_const )
37133747{
37143748Oid datatype = str_const -> consttype ;
3715- char * str ;
37163749char * workstr ;
37173750int len ;
37183751
37193752/* Get the string and a modifiable copy */
37203753if (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}
37253759else 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}
37303775else
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
37373782while (len > 0 )
37383783{
@@ -3747,9 +3792,11 @@ make_greater_string(const Const *str_const)
37473792Const * 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 );
37533800pfree (workstr );
37543801return 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
37773824return (Const * )NULL ;
37783825}
@@ -3811,6 +3858,22 @@ string_to_const(const char *str, Oid datatype)
38113858conval , 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