]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/varchar.c
Fix encoding issue when lc_monetary or lc_numeric are different encoding
[postgresql] / src / backend / utils / adt / varchar.c
1 /*-------------------------------------------------------------------------
2  *
3  * varchar.c
4  *        Functions for the built-in types char(n) and varchar(n).
5  *
6  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.133 2010/01/02 16:57:55 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17
18 #include "access/hash.h"
19 #include "access/tuptoaster.h"
20 #include "libpq/pqformat.h"
21 #include "utils/array.h"
22 #include "utils/builtins.h"
23 #include "mb/pg_wchar.h"
24
25
26 /* common code for bpchartypmodin and varchartypmodin */
27 static int32
28 anychar_typmodin(ArrayType *ta, const char *typename)
29 {
30         int32           typmod;
31         int32      *tl;
32         int                     n;
33
34         tl = ArrayGetIntegerTypmods(ta, &n);
35
36         /*
37          * we're not too tense about good error message here because grammar
38          * shouldn't allow wrong number of modifiers for CHAR
39          */
40         if (n != 1)
41                 ereport(ERROR,
42                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
43                                  errmsg("invalid type modifier")));
44
45         if (*tl < 1)
46                 ereport(ERROR,
47                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
48                                  errmsg("length for type %s must be at least 1", typename)));
49         if (*tl > MaxAttrSize)
50                 ereport(ERROR,
51                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
52                                  errmsg("length for type %s cannot exceed %d",
53                                                 typename, MaxAttrSize)));
54
55         /*
56          * For largely historical reasons, the typmod is VARHDRSZ plus the number
57          * of characters; there is enough client-side code that knows about that
58          * that we'd better not change it.
59          */
60         typmod = VARHDRSZ + *tl;
61
62         return typmod;
63 }
64
65 /* common code for bpchartypmodout and varchartypmodout */
66 static char *
67 anychar_typmodout(int32 typmod)
68 {
69         char       *res = (char *) palloc(64);
70
71         if (typmod > VARHDRSZ)
72                 snprintf(res, 64, "(%d)", (int) (typmod - VARHDRSZ));
73         else
74                 *res = '\0';
75
76         return res;
77 }
78
79
80 /*
81  * CHAR() and VARCHAR() types are part of the SQL standard. CHAR()
82  * is for blank-padded string whose length is specified in CREATE TABLE.
83  * VARCHAR is for storing string whose length is at most the length specified
84  * at CREATE TABLE time.
85  *
86  * It's hard to implement these types because we cannot figure out
87  * the length of the type from the type itself. I changed (hopefully all) the
88  * fmgr calls that invoke input functions of a data type to supply the
89  * length also. (eg. in INSERTs, we have the tupleDescriptor which contains
90  * the length of the attributes and hence the exact length of the char() or
91  * varchar(). We pass this to bpcharin() or varcharin().) In the case where
92  * we cannot determine the length, we pass in -1 instead and the input
93  * converter does not enforce any length check.
94  *
95  * We actually implement this as a varlena so that we don't have to pass in
96  * the length for the comparison functions. (The difference between these
97  * types and "text" is that we truncate and possibly blank-pad the string
98  * at insertion time.)
99  *
100  *                                                                                                                        - ay 6/95
101  */
102
103
104 /*****************************************************************************
105  *       bpchar - char()                                                                                                                 *
106  *****************************************************************************/
107
108 /*
109  * bpchar_input -- common guts of bpcharin and bpcharrecv
110  *
111  * s is the input text of length len (may not be null-terminated)
112  * atttypmod is the typmod value to apply
113  *
114  * Note that atttypmod is measured in characters, which
115  * is not necessarily the same as the number of bytes.
116  *
117  * If the input string is too long, raise an error, unless the extra
118  * characters are spaces, in which case they're truncated.  (per SQL)
119  */
120 static BpChar *
121 bpchar_input(const char *s, size_t len, int32 atttypmod)
122 {
123         BpChar     *result;
124         char       *r;
125         size_t          maxlen;
126
127         /* If typmod is -1 (or invalid), use the actual string length */
128         if (atttypmod < (int32) VARHDRSZ)
129                 maxlen = len;
130         else
131         {
132                 size_t          charlen;        /* number of CHARACTERS in the input */
133
134                 maxlen = atttypmod - VARHDRSZ;
135                 charlen = pg_mbstrlen_with_len(s, len);
136                 if (charlen > maxlen)
137                 {
138                         /* Verify that extra characters are spaces, and clip them off */
139                         size_t          mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
140                         size_t          j;
141
142                         /*
143                          * at this point, len is the actual BYTE length of the input
144                          * string, maxlen is the max number of CHARACTERS allowed for this
145                          * bpchar type, mbmaxlen is the length in BYTES of those chars.
146                          */
147                         for (j = mbmaxlen; j < len; j++)
148                         {
149                                 if (s[j] != ' ')
150                                         ereport(ERROR,
151                                                         (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
152                                                          errmsg("value too long for type character(%d)",
153                                                                         (int) maxlen)));
154                         }
155
156                         /*
157                          * Now we set maxlen to the necessary byte length, not the number
158                          * of CHARACTERS!
159                          */
160                         maxlen = len = mbmaxlen;
161                 }
162                 else
163                 {
164                         /*
165                          * Now we set maxlen to the necessary byte length, not the number
166                          * of CHARACTERS!
167                          */
168                         maxlen = len + (maxlen - charlen);
169                 }
170         }
171
172         result = (BpChar *) palloc(maxlen + VARHDRSZ);
173         SET_VARSIZE(result, maxlen + VARHDRSZ);
174         r = VARDATA(result);
175         memcpy(r, s, len);
176
177         /* blank pad the string if necessary */
178         if (maxlen > len)
179                 memset(r + len, ' ', maxlen - len);
180
181         return result;
182 }
183
184 /*
185  * Convert a C string to CHARACTER internal representation.  atttypmod
186  * is the declared length of the type plus VARHDRSZ.
187  */
188 Datum
189 bpcharin(PG_FUNCTION_ARGS)
190 {
191         char       *s = PG_GETARG_CSTRING(0);
192
193 #ifdef NOT_USED
194         Oid                     typelem = PG_GETARG_OID(1);
195 #endif
196         int32           atttypmod = PG_GETARG_INT32(2);
197         BpChar     *result;
198
199         result = bpchar_input(s, strlen(s), atttypmod);
200         PG_RETURN_BPCHAR_P(result);
201 }
202
203
204 /*
205  * Convert a CHARACTER value to a C string.
206  *
207  * Uses the text conversion functions, which is only appropriate if BpChar
208  * and text are equivalent types.
209  */
210 Datum
211 bpcharout(PG_FUNCTION_ARGS)
212 {
213         Datum           txt = PG_GETARG_DATUM(0);
214
215         PG_RETURN_CSTRING(TextDatumGetCString(txt));
216 }
217
218 /*
219  *              bpcharrecv                      - converts external binary format to bpchar
220  */
221 Datum
222 bpcharrecv(PG_FUNCTION_ARGS)
223 {
224         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
225
226 #ifdef NOT_USED
227         Oid                     typelem = PG_GETARG_OID(1);
228 #endif
229         int32           atttypmod = PG_GETARG_INT32(2);
230         BpChar     *result;
231         char       *str;
232         int                     nbytes;
233
234         str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
235         result = bpchar_input(str, nbytes, atttypmod);
236         pfree(str);
237         PG_RETURN_BPCHAR_P(result);
238 }
239
240 /*
241  *              bpcharsend                      - converts bpchar to binary format
242  */
243 Datum
244 bpcharsend(PG_FUNCTION_ARGS)
245 {
246         /* Exactly the same as textsend, so share code */
247         return textsend(fcinfo);
248 }
249
250
251 /*
252  * Converts a CHARACTER type to the specified size.
253  *
254  * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
255  * isExplicit is true if this is for an explicit cast to char(N).
256  *
257  * Truncation rules: for an explicit cast, silently truncate to the given
258  * length; for an implicit cast, raise error unless extra characters are
259  * all spaces.  (This is sort-of per SQL: the spec would actually have us
260  * raise a "completion condition" for the explicit cast case, but Postgres
261  * hasn't got such a concept.)
262  */
263 Datum
264 bpchar(PG_FUNCTION_ARGS)
265 {
266         BpChar     *source = PG_GETARG_BPCHAR_PP(0);
267         int32           maxlen = PG_GETARG_INT32(1);
268         bool            isExplicit = PG_GETARG_BOOL(2);
269         BpChar     *result;
270         int32           len;
271         char       *r;
272         char       *s;
273         int                     i;
274         int                     charlen;                /* number of characters in the input string +
275                                                                  * VARHDRSZ */
276
277         /* No work if typmod is invalid */
278         if (maxlen < (int32) VARHDRSZ)
279                 PG_RETURN_BPCHAR_P(source);
280
281         maxlen -= VARHDRSZ;
282
283         len = VARSIZE_ANY_EXHDR(source);
284         s = VARDATA_ANY(source);
285
286         charlen = pg_mbstrlen_with_len(s, len);
287
288         /* No work if supplied data matches typmod already */
289         if (charlen == maxlen)
290                 PG_RETURN_BPCHAR_P(source);
291
292         if (charlen > maxlen)
293         {
294                 /* Verify that extra characters are spaces, and clip them off */
295                 size_t          maxmblen;
296
297                 maxmblen = pg_mbcharcliplen(s, len, maxlen);
298
299                 if (!isExplicit)
300                 {
301                         for (i = maxmblen; i < len; i++)
302                                 if (s[i] != ' ')
303                                         ereport(ERROR,
304                                                         (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
305                                                          errmsg("value too long for type character(%d)",
306                                                                         maxlen)));
307                 }
308
309                 len = maxmblen;
310
311                 /*
312                  * At this point, maxlen is the necessary byte length, not the number
313                  * of CHARACTERS!
314                  */
315                 maxlen = len;
316         }
317         else
318         {
319                 /*
320                  * At this point, maxlen is the necessary byte length, not the number
321                  * of CHARACTERS!
322                  */
323                 maxlen = len + (maxlen - charlen);
324         }
325
326         Assert(maxlen >= len);
327
328         result = palloc(maxlen + VARHDRSZ);
329         SET_VARSIZE(result, maxlen + VARHDRSZ);
330         r = VARDATA(result);
331
332         memcpy(r, s, len);
333
334         /* blank pad the string if necessary */
335         if (maxlen > len)
336                 memset(r + len, ' ', maxlen - len);
337
338         PG_RETURN_BPCHAR_P(result);
339 }
340
341
342 /* char_bpchar()
343  * Convert char to bpchar(1).
344  */
345 Datum
346 char_bpchar(PG_FUNCTION_ARGS)
347 {
348         char            c = PG_GETARG_CHAR(0);
349         BpChar     *result;
350
351         result = (BpChar *) palloc(VARHDRSZ + 1);
352
353         SET_VARSIZE(result, VARHDRSZ + 1);
354         *(VARDATA(result)) = c;
355
356         PG_RETURN_BPCHAR_P(result);
357 }
358
359
360 /* bpchar_name()
361  * Converts a bpchar() type to a NameData type.
362  */
363 Datum
364 bpchar_name(PG_FUNCTION_ARGS)
365 {
366         BpChar     *s = PG_GETARG_BPCHAR_PP(0);
367         char       *s_data;
368         Name            result;
369         int                     len;
370
371         len = VARSIZE_ANY_EXHDR(s);
372         s_data = VARDATA_ANY(s);
373
374         /* Truncate to max length for a Name */
375         if (len >= NAMEDATALEN)
376                 len = NAMEDATALEN - 1;
377
378         /* Remove trailing blanks */
379         while (len > 0)
380         {
381                 if (s_data[len - 1] != ' ')
382                         break;
383                 len--;
384         }
385
386         result = (NameData *) palloc(NAMEDATALEN);
387         memcpy(NameStr(*result), s_data, len);
388
389         /* Now null pad to full length... */
390         while (len < NAMEDATALEN)
391         {
392                 *(NameStr(*result) + len) = '\0';
393                 len++;
394         }
395
396         PG_RETURN_NAME(result);
397 }
398
399 /* name_bpchar()
400  * Converts a NameData type to a bpchar type.
401  *
402  * Uses the text conversion functions, which is only appropriate if BpChar
403  * and text are equivalent types.
404  */
405 Datum
406 name_bpchar(PG_FUNCTION_ARGS)
407 {
408         Name            s = PG_GETARG_NAME(0);
409         BpChar     *result;
410
411         result = (BpChar *) cstring_to_text(NameStr(*s));
412         PG_RETURN_BPCHAR_P(result);
413 }
414
415 Datum
416 bpchartypmodin(PG_FUNCTION_ARGS)
417 {
418         ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
419
420         PG_RETURN_INT32(anychar_typmodin(ta, "char"));
421 }
422
423 Datum
424 bpchartypmodout(PG_FUNCTION_ARGS)
425 {
426         int32           typmod = PG_GETARG_INT32(0);
427
428         PG_RETURN_CSTRING(anychar_typmodout(typmod));
429 }
430
431
432 /*****************************************************************************
433  *       varchar - varchar(n)
434  *
435  * Note: varchar piggybacks on type text for most operations, and so has no
436  * C-coded functions except for I/O and typmod checking.
437  *****************************************************************************/
438
439 /*
440  * varchar_input -- common guts of varcharin and varcharrecv
441  *
442  * s is the input text of length len (may not be null-terminated)
443  * atttypmod is the typmod value to apply
444  *
445  * Note that atttypmod is measured in characters, which
446  * is not necessarily the same as the number of bytes.
447  *
448  * If the input string is too long, raise an error, unless the extra
449  * characters are spaces, in which case they're truncated.  (per SQL)
450  *
451  * Uses the C string to text conversion function, which is only appropriate
452  * if VarChar and text are equivalent types.
453  */
454 static VarChar *
455 varchar_input(const char *s, size_t len, int32 atttypmod)
456 {
457         VarChar    *result;
458         size_t          maxlen;
459
460         maxlen = atttypmod - VARHDRSZ;
461
462         if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
463         {
464                 /* Verify that extra characters are spaces, and clip them off */
465                 size_t          mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
466                 size_t          j;
467
468                 for (j = mbmaxlen; j < len; j++)
469                 {
470                         if (s[j] != ' ')
471                                 ereport(ERROR,
472                                                 (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
473                                           errmsg("value too long for type character varying(%d)",
474                                                          (int) maxlen)));
475                 }
476
477                 len = mbmaxlen;
478         }
479
480         result = (VarChar *) cstring_to_text_with_len(s, len);
481         return result;
482 }
483
484 /*
485  * Convert a C string to VARCHAR internal representation.  atttypmod
486  * is the declared length of the type plus VARHDRSZ.
487  */
488 Datum
489 varcharin(PG_FUNCTION_ARGS)
490 {
491         char       *s = PG_GETARG_CSTRING(0);
492
493 #ifdef NOT_USED
494         Oid                     typelem = PG_GETARG_OID(1);
495 #endif
496         int32           atttypmod = PG_GETARG_INT32(2);
497         VarChar    *result;
498
499         result = varchar_input(s, strlen(s), atttypmod);
500         PG_RETURN_VARCHAR_P(result);
501 }
502
503
504 /*
505  * Convert a VARCHAR value to a C string.
506  *
507  * Uses the text to C string conversion function, which is only appropriate
508  * if VarChar and text are equivalent types.
509  */
510 Datum
511 varcharout(PG_FUNCTION_ARGS)
512 {
513         Datum           txt = PG_GETARG_DATUM(0);
514
515         PG_RETURN_CSTRING(TextDatumGetCString(txt));
516 }
517
518 /*
519  *              varcharrecv                     - converts external binary format to varchar
520  */
521 Datum
522 varcharrecv(PG_FUNCTION_ARGS)
523 {
524         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
525
526 #ifdef NOT_USED
527         Oid                     typelem = PG_GETARG_OID(1);
528 #endif
529         int32           atttypmod = PG_GETARG_INT32(2);
530         VarChar    *result;
531         char       *str;
532         int                     nbytes;
533
534         str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
535         result = varchar_input(str, nbytes, atttypmod);
536         pfree(str);
537         PG_RETURN_VARCHAR_P(result);
538 }
539
540 /*
541  *              varcharsend                     - converts varchar to binary format
542  */
543 Datum
544 varcharsend(PG_FUNCTION_ARGS)
545 {
546         /* Exactly the same as textsend, so share code */
547         return textsend(fcinfo);
548 }
549
550
551 /*
552  * Converts a VARCHAR type to the specified size.
553  *
554  * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
555  * isExplicit is true if this is for an explicit cast to varchar(N).
556  *
557  * Truncation rules: for an explicit cast, silently truncate to the given
558  * length; for an implicit cast, raise error unless extra characters are
559  * all spaces.  (This is sort-of per SQL: the spec would actually have us
560  * raise a "completion condition" for the explicit cast case, but Postgres
561  * hasn't got such a concept.)
562  */
563 Datum
564 varchar(PG_FUNCTION_ARGS)
565 {
566         VarChar    *source = PG_GETARG_VARCHAR_PP(0);
567         int32           typmod = PG_GETARG_INT32(1);
568         bool            isExplicit = PG_GETARG_BOOL(2);
569         int32           len,
570                                 maxlen;
571         size_t          maxmblen;
572         int                     i;
573         char       *s_data;
574
575         len = VARSIZE_ANY_EXHDR(source);
576         s_data = VARDATA_ANY(source);
577         maxlen = typmod - VARHDRSZ;
578
579         /* No work if typmod is invalid or supplied data fits it already */
580         if (maxlen < 0 || len <= maxlen)
581                 PG_RETURN_VARCHAR_P(source);
582
583         /* only reach here if string is too long... */
584
585         /* truncate multibyte string preserving multibyte boundary */
586         maxmblen = pg_mbcharcliplen(s_data, len, maxlen);
587
588         if (!isExplicit)
589         {
590                 for (i = maxmblen; i < len; i++)
591                         if (s_data[i] != ' ')
592                                 ereport(ERROR,
593                                                 (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
594                                           errmsg("value too long for type character varying(%d)",
595                                                          maxlen)));
596         }
597
598         PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text_with_len(s_data,
599                                                                                                                          maxmblen));
600 }
601
602 Datum
603 varchartypmodin(PG_FUNCTION_ARGS)
604 {
605         ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
606
607         PG_RETURN_INT32(anychar_typmodin(ta, "varchar"));
608 }
609
610 Datum
611 varchartypmodout(PG_FUNCTION_ARGS)
612 {
613         int32           typmod = PG_GETARG_INT32(0);
614
615         PG_RETURN_CSTRING(anychar_typmodout(typmod));
616 }
617
618
619 /*****************************************************************************
620  * Exported functions
621  *****************************************************************************/
622
623 /* "True" length (not counting trailing blanks) of a BpChar */
624 static int
625 bcTruelen(BpChar *arg)
626 {
627         char       *s = VARDATA_ANY(arg);
628         int                     i;
629         int                     len;
630
631         len = VARSIZE_ANY_EXHDR(arg);
632         for (i = len - 1; i >= 0; i--)
633         {
634                 if (s[i] != ' ')
635                         break;
636         }
637         return i + 1;
638 }
639
640 Datum
641 bpcharlen(PG_FUNCTION_ARGS)
642 {
643         BpChar     *arg = PG_GETARG_BPCHAR_PP(0);
644         int                     len;
645
646         /* get number of bytes, ignoring trailing spaces */
647         len = bcTruelen(arg);
648
649         /* in multibyte encoding, convert to number of characters */
650         if (pg_database_encoding_max_length() != 1)
651                 len = pg_mbstrlen_with_len(VARDATA_ANY(arg), len);
652
653         PG_RETURN_INT32(len);
654 }
655
656 Datum
657 bpcharoctetlen(PG_FUNCTION_ARGS)
658 {
659         Datum           arg = PG_GETARG_DATUM(0);
660
661         /* We need not detoast the input at all */
662         PG_RETURN_INT32(toast_raw_datum_size(arg) - VARHDRSZ);
663 }
664
665
666 /*****************************************************************************
667  *      Comparison Functions used for bpchar
668  *
669  * Note: btree indexes need these routines not to leak memory; therefore,
670  * be careful to free working copies of toasted datums.  Most places don't
671  * need to be so careful.
672  *****************************************************************************/
673
674 Datum
675 bpchareq(PG_FUNCTION_ARGS)
676 {
677         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
678         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
679         int                     len1,
680                                 len2;
681         bool            result;
682
683         len1 = bcTruelen(arg1);
684         len2 = bcTruelen(arg2);
685
686         /*
687          * Since we only care about equality or not-equality, we can avoid all the
688          * expense of strcoll() here, and just do bitwise comparison.
689          */
690         if (len1 != len2)
691                 result = false;
692         else
693                 result = (strncmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) == 0);
694
695         PG_FREE_IF_COPY(arg1, 0);
696         PG_FREE_IF_COPY(arg2, 1);
697
698         PG_RETURN_BOOL(result);
699 }
700
701 Datum
702 bpcharne(PG_FUNCTION_ARGS)
703 {
704         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
705         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
706         int                     len1,
707                                 len2;
708         bool            result;
709
710         len1 = bcTruelen(arg1);
711         len2 = bcTruelen(arg2);
712
713         /*
714          * Since we only care about equality or not-equality, we can avoid all the
715          * expense of strcoll() here, and just do bitwise comparison.
716          */
717         if (len1 != len2)
718                 result = true;
719         else
720                 result = (strncmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) != 0);
721
722         PG_FREE_IF_COPY(arg1, 0);
723         PG_FREE_IF_COPY(arg2, 1);
724
725         PG_RETURN_BOOL(result);
726 }
727
728 Datum
729 bpcharlt(PG_FUNCTION_ARGS)
730 {
731         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
732         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
733         int                     len1,
734                                 len2;
735         int                     cmp;
736
737         len1 = bcTruelen(arg1);
738         len2 = bcTruelen(arg2);
739
740         cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
741
742         PG_FREE_IF_COPY(arg1, 0);
743         PG_FREE_IF_COPY(arg2, 1);
744
745         PG_RETURN_BOOL(cmp < 0);
746 }
747
748 Datum
749 bpcharle(PG_FUNCTION_ARGS)
750 {
751         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
752         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
753         int                     len1,
754                                 len2;
755         int                     cmp;
756
757         len1 = bcTruelen(arg1);
758         len2 = bcTruelen(arg2);
759
760         cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
761
762         PG_FREE_IF_COPY(arg1, 0);
763         PG_FREE_IF_COPY(arg2, 1);
764
765         PG_RETURN_BOOL(cmp <= 0);
766 }
767
768 Datum
769 bpchargt(PG_FUNCTION_ARGS)
770 {
771         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
772         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
773         int                     len1,
774                                 len2;
775         int                     cmp;
776
777         len1 = bcTruelen(arg1);
778         len2 = bcTruelen(arg2);
779
780         cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
781
782         PG_FREE_IF_COPY(arg1, 0);
783         PG_FREE_IF_COPY(arg2, 1);
784
785         PG_RETURN_BOOL(cmp > 0);
786 }
787
788 Datum
789 bpcharge(PG_FUNCTION_ARGS)
790 {
791         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
792         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
793         int                     len1,
794                                 len2;
795         int                     cmp;
796
797         len1 = bcTruelen(arg1);
798         len2 = bcTruelen(arg2);
799
800         cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
801
802         PG_FREE_IF_COPY(arg1, 0);
803         PG_FREE_IF_COPY(arg2, 1);
804
805         PG_RETURN_BOOL(cmp >= 0);
806 }
807
808 Datum
809 bpcharcmp(PG_FUNCTION_ARGS)
810 {
811         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
812         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
813         int                     len1,
814                                 len2;
815         int                     cmp;
816
817         len1 = bcTruelen(arg1);
818         len2 = bcTruelen(arg2);
819
820         cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
821
822         PG_FREE_IF_COPY(arg1, 0);
823         PG_FREE_IF_COPY(arg2, 1);
824
825         PG_RETURN_INT32(cmp);
826 }
827
828 Datum
829 bpchar_larger(PG_FUNCTION_ARGS)
830 {
831         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
832         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
833         int                     len1,
834                                 len2;
835         int                     cmp;
836
837         len1 = bcTruelen(arg1);
838         len2 = bcTruelen(arg2);
839
840         cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
841
842         PG_RETURN_BPCHAR_P((cmp >= 0) ? arg1 : arg2);
843 }
844
845 Datum
846 bpchar_smaller(PG_FUNCTION_ARGS)
847 {
848         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
849         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
850         int                     len1,
851                                 len2;
852         int                     cmp;
853
854         len1 = bcTruelen(arg1);
855         len2 = bcTruelen(arg2);
856
857         cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
858
859         PG_RETURN_BPCHAR_P((cmp <= 0) ? arg1 : arg2);
860 }
861
862
863 /*
864  * bpchar needs a specialized hash function because we want to ignore
865  * trailing blanks in comparisons.
866  *
867  * Note: currently there is no need for locale-specific behavior here,
868  * but if we ever change the semantics of bpchar comparison to trust
869  * strcoll() completely, we'd need to do something different in non-C locales.
870  */
871 Datum
872 hashbpchar(PG_FUNCTION_ARGS)
873 {
874         BpChar     *key = PG_GETARG_BPCHAR_PP(0);
875         char       *keydata;
876         int                     keylen;
877         Datum           result;
878
879         keydata = VARDATA_ANY(key);
880         keylen = bcTruelen(key);
881
882         result = hash_any((unsigned char *) keydata, keylen);
883
884         /* Avoid leaking memory for toasted inputs */
885         PG_FREE_IF_COPY(key, 0);
886
887         return result;
888 }
889
890
891 /*
892  * The following operators support character-by-character comparison
893  * of bpchar datums, to allow building indexes suitable for LIKE clauses.
894  * Note that the regular bpchareq/bpcharne comparison operators are assumed
895  * to be compatible with these!
896  */
897
898 static int
899 internal_bpchar_pattern_compare(BpChar *arg1, BpChar *arg2)
900 {
901         int                     result;
902         int                     len1,
903                                 len2;
904
905         len1 = bcTruelen(arg1);
906         len2 = bcTruelen(arg2);
907
908         result = strncmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
909         if (result != 0)
910                 return result;
911         else if (len1 < len2)
912                 return -1;
913         else if (len1 > len2)
914                 return 1;
915         else
916                 return 0;
917 }
918
919
920 Datum
921 bpchar_pattern_lt(PG_FUNCTION_ARGS)
922 {
923         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
924         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
925         int                     result;
926
927         result = internal_bpchar_pattern_compare(arg1, arg2);
928
929         PG_FREE_IF_COPY(arg1, 0);
930         PG_FREE_IF_COPY(arg2, 1);
931
932         PG_RETURN_BOOL(result < 0);
933 }
934
935
936 Datum
937 bpchar_pattern_le(PG_FUNCTION_ARGS)
938 {
939         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
940         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
941         int                     result;
942
943         result = internal_bpchar_pattern_compare(arg1, arg2);
944
945         PG_FREE_IF_COPY(arg1, 0);
946         PG_FREE_IF_COPY(arg2, 1);
947
948         PG_RETURN_BOOL(result <= 0);
949 }
950
951
952 Datum
953 bpchar_pattern_ge(PG_FUNCTION_ARGS)
954 {
955         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
956         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
957         int                     result;
958
959         result = internal_bpchar_pattern_compare(arg1, arg2);
960
961         PG_FREE_IF_COPY(arg1, 0);
962         PG_FREE_IF_COPY(arg2, 1);
963
964         PG_RETURN_BOOL(result >= 0);
965 }
966
967
968 Datum
969 bpchar_pattern_gt(PG_FUNCTION_ARGS)
970 {
971         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
972         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
973         int                     result;
974
975         result = internal_bpchar_pattern_compare(arg1, arg2);
976
977         PG_FREE_IF_COPY(arg1, 0);
978         PG_FREE_IF_COPY(arg2, 1);
979
980         PG_RETURN_BOOL(result > 0);
981 }
982
983
984 Datum
985 btbpchar_pattern_cmp(PG_FUNCTION_ARGS)
986 {
987         BpChar     *arg1 = PG_GETARG_BPCHAR_PP(0);
988         BpChar     *arg2 = PG_GETARG_BPCHAR_PP(1);
989         int                     result;
990
991         result = internal_bpchar_pattern_compare(arg1, arg2);
992
993         PG_FREE_IF_COPY(arg1, 0);
994         PG_FREE_IF_COPY(arg2, 1);
995
996         PG_RETURN_INT32(result);
997 }