15
15
*
16
16
*
17
17
* 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 $
19
19
*
20
20
*-------------------------------------------------------------------------
21
21
*/
@@ -184,6 +184,7 @@ static Selectivity prefix_selectivity(Query *root, Var *var,
184
184
static Selectivity pattern_selectivity (Const * patt , Pattern_Type ptype );
185
185
static Datum string_to_datum (const char * str , Oid datatype );
186
186
static Const * string_to_const (const char * str , Oid datatype );
187
+ static Const * string_to_bytea_const (const char * str , size_t str_len );
187
188
188
189
189
190
/*
@@ -3135,20 +3136,31 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive,
3135
3136
}
3136
3137
else
3137
3138
{
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 );
3140
3152
}
3141
3153
3142
3154
match = palloc (pattlen + 1 );
3143
3155
match_pos = 0 ;
3144
-
3145
3156
for (pos = 0 ; pos < pattlen ; pos ++ )
3146
3157
{
3147
3158
/* % and _ are wildcard characters in LIKE */
3148
3159
if (patt [pos ] == '%' ||
3149
3160
patt [pos ] == '_' )
3150
3161
break ;
3151
- /* Backslash quotes the next character */
3162
+
3163
+ /* Backslash escapes the next character */
3152
3164
if (patt [pos ] == '\\' )
3153
3165
{
3154
3166
pos ++ ;
@@ -3174,10 +3186,19 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive,
3174
3186
match [match_pos ] = '\0' ;
3175
3187
rest = & patt [pos ];
3176
3188
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
+ }
3179
3199
3180
- pfree (patt );
3200
+ if (patt != NULL )
3201
+ pfree (patt );
3181
3202
pfree (match );
3182
3203
3183
3204
/* in LIKE, an empty pattern is an exact match! */
@@ -3500,9 +3521,22 @@ like_selectivity(Const *patt_const, bool case_insensitive)
3500
3521
}
3501
3522
else
3502
3523
{
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 );
3505
3537
}
3538
+ /* patt should never be NULL in practice */
3539
+ Assert (patt != NULL );
3506
3540
3507
3541
/* Skip any leading %; it's already factored into initial sel */
3508
3542
start = (* patt == '%' ) ? 1 : 0 ;
@@ -3693,8 +3727,8 @@ pattern_selectivity(Const *patt, Pattern_Type ptype)
3693
3727
3694
3728
/*
3695
3729
* 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.
3698
3732
*
3699
3733
* The key requirement here is that given a prefix string, say "foo",
3700
3734
* we must be able to generate another string "fop" that is greater
@@ -3712,27 +3746,38 @@ Const *
3712
3746
make_greater_string (const Const * str_const )
3713
3747
{
3714
3748
Oid datatype = str_const -> consttype ;
3715
- char * str ;
3716
3749
char * workstr ;
3717
3750
int len ;
3718
3751
3719
3752
/* Get the string and a modifiable copy */
3720
3753
if (datatype == NAMEOID )
3721
3754
{
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 );
3724
3758
}
3725
3759
else if (datatype == BYTEAOID )
3726
3760
{
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 );
3729
3774
}
3730
3775
else
3731
3776
{
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 );
3734
3780
}
3735
- workstr = pstrdup (str );
3736
3781
3737
3782
while (len > 0 )
3738
3783
{
@@ -3747,9 +3792,11 @@ make_greater_string(const Const *str_const)
3747
3792
Const * workstr_const ;
3748
3793
3749
3794
(* 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 );
3751
3799
3752
- pfree (str );
3753
3800
pfree (workstr );
3754
3801
return workstr_const ;
3755
3802
}
@@ -3771,8 +3818,8 @@ make_greater_string(const Const *str_const)
3771
3818
}
3772
3819
3773
3820
/* Failed... */
3774
- pfree ( str );
3775
- pfree (workstr );
3821
+ if ( workstr != NULL )
3822
+ pfree (workstr );
3776
3823
3777
3824
return (Const * ) NULL ;
3778
3825
}
@@ -3811,6 +3858,22 @@ string_to_const(const char *str, Oid datatype)
3811
3858
conval , false, false);
3812
3859
}
3813
3860
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
+
3814
3877
/*-------------------------------------------------------------------------
3815
3878
*
3816
3879
* Index cost estimation functions
0 commit comments