~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/varchar.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * varchar.c
 
4
 *        Functions for the built-in types char(n) and varchar(n).
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, 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.108 2004-12-31 22:01:22 pgsql Exp $
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#include "postgres.h"
 
16
 
 
17
#include "access/hash.h"
 
18
#include "catalog/pg_type.h"
 
19
#include "miscadmin.h"
 
20
#include "utils/array.h"
 
21
#include "utils/builtins.h"
 
22
#include "utils/fmgroids.h"
 
23
 
 
24
#include "mb/pg_wchar.h"
 
25
 
 
26
 
 
27
/*
 
28
 * CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
 
29
 * is for blank-padded string whose length is specified in CREATE TABLE.
 
30
 * VARCHAR is for storing string whose length is at most the length specified
 
31
 * at CREATE TABLE time.
 
32
 *
 
33
 * It's hard to implement these types because we cannot figure out
 
34
 * the length of the type from the type itself. I changed (hopefully all) the
 
35
 * fmgr calls that invoke input functions of a data type to supply the
 
36
 * length also. (eg. in INSERTs, we have the tupleDescriptor which contains
 
37
 * the length of the attributes and hence the exact length of the char() or
 
38
 * varchar(). We pass this to bpcharin() or varcharin().) In the case where
 
39
 * we cannot determine the length, we pass in -1 instead and the input string
 
40
 * must be null-terminated.
 
41
 *
 
42
 * We actually implement this as a varlena so that we don't have to pass in
 
43
 * the length for the comparison functions. (The difference between these
 
44
 * types and "text" is that we truncate and possibly blank-pad the string
 
45
 * at insertion time.)
 
46
 *
 
47
 *                                                                                                                        - ay 6/95
 
48
 */
 
49
 
 
50
 
 
51
/*****************************************************************************
 
52
 *       bpchar - char()                                                                                                                 *
 
53
 *****************************************************************************/
 
54
 
 
55
/*
 
56
 * Convert a C string to CHARACTER internal representation.  atttypmod
 
57
 * is the declared length of the type plus VARHDRSZ.
 
58
 *
 
59
 * If the C string is too long, raise an error, unless the extra
 
60
 * characters are spaces, in which case they're truncated.  (per SQL)
 
61
 */
 
62
Datum
 
63
bpcharin(PG_FUNCTION_ARGS)
 
64
{
 
65
        char       *s = PG_GETARG_CSTRING(0);
 
66
 
 
67
#ifdef NOT_USED
 
68
        Oid                     typelem = PG_GETARG_OID(1);
 
69
#endif
 
70
        int32           atttypmod = PG_GETARG_INT32(2);
 
71
        BpChar     *result;
 
72
        char       *r;
 
73
        size_t          len,
 
74
                                maxlen;
 
75
        int                     i;
 
76
        int                     charlen;                /* number of charcters in the input string */
 
77
 
 
78
        /* verify encoding */
 
79
        len = strlen(s);
 
80
        pg_verifymbstr(s, len, false);
 
81
 
 
82
        charlen = pg_mbstrlen(s);
 
83
 
 
84
        /* If typmod is -1 (or invalid), use the actual string length */
 
85
        if (atttypmod < (int32) VARHDRSZ)
 
86
                maxlen = charlen;
 
87
        else
 
88
                maxlen = atttypmod - VARHDRSZ;
 
89
 
 
90
        if (charlen > maxlen)
 
91
        {
 
92
                /* Verify that extra characters are spaces, and clip them off */
 
93
                size_t          mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
 
94
 
 
95
                /*
 
96
                 * at this point, len is the actual BYTE length of the input
 
97
                 * string, maxlen is the max number of CHARACTERS allowed for this
 
98
                 * bpchar type.
 
99
                 */
 
100
                if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
 
101
                        len = mbmaxlen;
 
102
                else
 
103
                        ereport(ERROR,
 
104
                                        (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 
105
                                         errmsg("value too long for type character(%d)",
 
106
                                                        (int) maxlen)));
 
107
 
 
108
                /*
 
109
                 * XXX: at this point, maxlen is the necessary byte length, not
 
110
                 * the number of CHARACTERS!
 
111
                 */
 
112
                maxlen = len;
 
113
        }
 
114
        else
 
115
        {
 
116
                /*
 
117
                 * XXX: at this point, maxlen is the necessary byte length, not
 
118
                 * the number of CHARACTERS!
 
119
                 */
 
120
                maxlen = len + (maxlen - charlen);
 
121
        }
 
122
 
 
123
        result = palloc(maxlen + VARHDRSZ);
 
124
        VARATT_SIZEP(result) = maxlen + VARHDRSZ;
 
125
        r = VARDATA(result);
 
126
        for (i = 0; i < len; i++)
 
127
                *r++ = *s++;
 
128
 
 
129
        /* blank pad the string if necessary */
 
130
        for (; i < maxlen; i++)
 
131
                *r++ = ' ';
 
132
 
 
133
        PG_RETURN_BPCHAR_P(result);
 
134
}
 
135
 
 
136
 
 
137
/*
 
138
 * Convert a CHARACTER value to a C string.
 
139
 */
 
140
Datum
 
141
bpcharout(PG_FUNCTION_ARGS)
 
142
{
 
143
        BpChar     *s = PG_GETARG_BPCHAR_P(0);
 
144
        char       *result;
 
145
        int                     len;
 
146
 
 
147
        /* copy and add null term */
 
148
        len = VARSIZE(s) - VARHDRSZ;
 
149
        result = (char *) palloc(len + 1);
 
150
        memcpy(result, VARDATA(s), len);
 
151
        result[len] = '\0';
 
152
 
 
153
        PG_RETURN_CSTRING(result);
 
154
}
 
155
 
 
156
/*
 
157
 *              bpcharrecv                      - converts external binary format to bpchar
 
158
 */
 
159
Datum
 
160
bpcharrecv(PG_FUNCTION_ARGS)
 
161
{
 
162
        /* Exactly the same as textrecv, so share code */
 
163
        return textrecv(fcinfo);
 
164
}
 
165
 
 
166
/*
 
167
 *              bpcharsend                      - converts bpchar to binary format
 
168
 */
 
169
Datum
 
170
bpcharsend(PG_FUNCTION_ARGS)
 
171
{
 
172
        /* Exactly the same as textsend, so share code */
 
173
        return textsend(fcinfo);
 
174
}
 
175
 
 
176
 
 
177
/*
 
178
 * Converts a CHARACTER type to the specified size.
 
179
 *
 
180
 * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
 
181
 * isExplicit is true if this is for an explicit cast to char(N).
 
182
 *
 
183
 * Truncation rules: for an explicit cast, silently truncate to the given
 
184
 * length; for an implicit cast, raise error unless extra characters are
 
185
 * all spaces.  (This is sort-of per SQL: the spec would actually have us
 
186
 * raise a "completion condition" for the explicit cast case, but Postgres
 
187
 * hasn't got such a concept.)
 
188
 */
 
189
Datum
 
190
bpchar(PG_FUNCTION_ARGS)
 
191
{
 
192
        BpChar     *source = PG_GETARG_BPCHAR_P(0);
 
193
        int32           maxlen = PG_GETARG_INT32(1);
 
194
        bool            isExplicit = PG_GETARG_BOOL(2);
 
195
        BpChar     *result;
 
196
        int32           len;
 
197
        char       *r;
 
198
        char       *s;
 
199
        int                     i;
 
200
        int                     charlen;                /* number of charcters in the input string
 
201
                                                                 * + VARHDRSZ */
 
202
 
 
203
        len = VARSIZE(source);
 
204
 
 
205
        charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ;
 
206
 
 
207
        /* No work if typmod is invalid or supplied data matches it already */
 
208
        if (maxlen < (int32) VARHDRSZ || charlen == maxlen)
 
209
                PG_RETURN_BPCHAR_P(source);
 
210
 
 
211
        if (charlen > maxlen)
 
212
        {
 
213
                /* Verify that extra characters are spaces, and clip them off */
 
214
                size_t          maxmblen;
 
215
 
 
216
                maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
 
217
                                                                        maxlen - VARHDRSZ) + VARHDRSZ;
 
218
 
 
219
                if (!isExplicit)
 
220
                {
 
221
                        for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
 
222
                                if (*(VARDATA(source) + i) != ' ')
 
223
                                        ereport(ERROR,
 
224
                                                  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 
225
                                                   errmsg("value too long for type character(%d)",
 
226
                                                                  maxlen - VARHDRSZ)));
 
227
                }
 
228
 
 
229
                len = maxmblen;
 
230
 
 
231
                /*
 
232
                 * XXX: at this point, maxlen is the necessary byte
 
233
                 * length+VARHDRSZ, not the number of CHARACTERS!
 
234
                 */
 
235
                maxlen = len;
 
236
        }
 
237
        else
 
238
        {
 
239
                /*
 
240
                 * XXX: at this point, maxlen is the necessary byte
 
241
                 * length+VARHDRSZ, not the number of CHARACTERS!
 
242
                 */
 
243
                maxlen = len + (maxlen - charlen);
 
244
        }
 
245
 
 
246
        s = VARDATA(source);
 
247
 
 
248
        result = palloc(maxlen);
 
249
        VARATT_SIZEP(result) = maxlen;
 
250
        r = VARDATA(result);
 
251
 
 
252
        for (i = 0; i < len - VARHDRSZ; i++)
 
253
                *r++ = *s++;
 
254
 
 
255
        /* blank pad the string if necessary */
 
256
        for (; i < maxlen - VARHDRSZ; i++)
 
257
                *r++ = ' ';
 
258
 
 
259
        PG_RETURN_BPCHAR_P(result);
 
260
}
 
261
 
 
262
 
 
263
/* char_bpchar()
 
264
 * Convert char to bpchar(1).
 
265
 */
 
266
Datum
 
267
char_bpchar(PG_FUNCTION_ARGS)
 
268
{
 
269
        char            c = PG_GETARG_CHAR(0);
 
270
        BpChar     *result;
 
271
 
 
272
        result = (BpChar *) palloc(VARHDRSZ + 1);
 
273
 
 
274
        VARATT_SIZEP(result) = VARHDRSZ + 1;
 
275
        *(VARDATA(result)) = c;
 
276
 
 
277
        PG_RETURN_BPCHAR_P(result);
 
278
}
 
279
 
 
280
 
 
281
/* bpchar_name()
 
282
 * Converts a bpchar() type to a NameData type.
 
283
 */
 
284
Datum
 
285
bpchar_name(PG_FUNCTION_ARGS)
 
286
{
 
287
        BpChar     *s = PG_GETARG_BPCHAR_P(0);
 
288
        Name            result;
 
289
        int                     len;
 
290
 
 
291
        len = VARSIZE(s) - VARHDRSZ;
 
292
 
 
293
        /* Truncate to max length for a Name */
 
294
        if (len >= NAMEDATALEN)
 
295
                len = NAMEDATALEN - 1;
 
296
 
 
297
        /* Remove trailing blanks */
 
298
        while (len > 0)
 
299
        {
 
300
                if (*(VARDATA(s) + len - 1) != ' ')
 
301
                        break;
 
302
                len--;
 
303
        }
 
304
 
 
305
        result = (NameData *) palloc(NAMEDATALEN);
 
306
        memcpy(NameStr(*result), VARDATA(s), len);
 
307
 
 
308
        /* Now null pad to full length... */
 
309
        while (len < NAMEDATALEN)
 
310
        {
 
311
                *(NameStr(*result) + len) = '\0';
 
312
                len++;
 
313
        }
 
314
 
 
315
        PG_RETURN_NAME(result);
 
316
}
 
317
 
 
318
/* name_bpchar()
 
319
 * Converts a NameData type to a bpchar type.
 
320
 */
 
321
Datum
 
322
name_bpchar(PG_FUNCTION_ARGS)
 
323
{
 
324
        Name            s = PG_GETARG_NAME(0);
 
325
        BpChar     *result;
 
326
        int                     len;
 
327
 
 
328
        len = strlen(NameStr(*s));
 
329
        result = (BpChar *) palloc(VARHDRSZ + len);
 
330
        memcpy(VARDATA(result), NameStr(*s), len);
 
331
        VARATT_SIZEP(result) = len + VARHDRSZ;
 
332
 
 
333
        PG_RETURN_BPCHAR_P(result);
 
334
}
 
335
 
 
336
 
 
337
/*****************************************************************************
 
338
 *       varchar - varchar(n)
 
339
 *
 
340
 * Note: varchar piggybacks on type text for most operations, and so has no
 
341
 * C-coded functions except for I/O and typmod checking.
 
342
 *****************************************************************************/
 
343
 
 
344
/*
 
345
 * Convert a C string to VARCHAR internal representation.  atttypmod
 
346
 * is the declared length of the type plus VARHDRSZ.
 
347
 *
 
348
 * Note that atttypmod is regarded as the number of characters, which
 
349
 * is not necessarily the same as the number of bytes.
 
350
 *
 
351
 * If the C string is too long, raise an error, unless the extra characters
 
352
 * are spaces, in which case they're truncated.  (per SQL)
 
353
 */
 
354
Datum
 
355
varcharin(PG_FUNCTION_ARGS)
 
356
{
 
357
        char       *s = PG_GETARG_CSTRING(0);
 
358
 
 
359
#ifdef NOT_USED
 
360
        Oid                     typelem = PG_GETARG_OID(1);
 
361
#endif
 
362
        int32           atttypmod = PG_GETARG_INT32(2);
 
363
        VarChar    *result;
 
364
        size_t          len,
 
365
                                maxlen;
 
366
 
 
367
        /* verify encoding */
 
368
        len = strlen(s);
 
369
        pg_verifymbstr(s, len, false);
 
370
 
 
371
        maxlen = atttypmod - VARHDRSZ;
 
372
 
 
373
        if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
 
374
        {
 
375
                /* Verify that extra characters are spaces, and clip them off */
 
376
                size_t          mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
 
377
 
 
378
                if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
 
379
                        len = mbmaxlen;
 
380
                else
 
381
                        ereport(ERROR,
 
382
                                        (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 
383
                                  errmsg("value too long for type character varying(%d)",
 
384
                                                 (int) maxlen)));
 
385
        }
 
386
 
 
387
        result = palloc(len + VARHDRSZ);
 
388
        VARATT_SIZEP(result) = len + VARHDRSZ;
 
389
        memcpy(VARDATA(result), s, len);
 
390
 
 
391
        PG_RETURN_VARCHAR_P(result);
 
392
}
 
393
 
 
394
 
 
395
/*
 
396
 * Convert a VARCHAR value to a C string.
 
397
 */
 
398
Datum
 
399
varcharout(PG_FUNCTION_ARGS)
 
400
{
 
401
        VarChar    *s = PG_GETARG_VARCHAR_P(0);
 
402
        char       *result;
 
403
        int32           len;
 
404
 
 
405
        /* copy and add null term */
 
406
        len = VARSIZE(s) - VARHDRSZ;
 
407
        result = palloc(len + 1);
 
408
        memcpy(result, VARDATA(s), len);
 
409
        result[len] = '\0';
 
410
 
 
411
        PG_RETURN_CSTRING(result);
 
412
}
 
413
 
 
414
/*
 
415
 *              varcharrecv                     - converts external binary format to varchar
 
416
 */
 
417
Datum
 
418
varcharrecv(PG_FUNCTION_ARGS)
 
419
{
 
420
        /* Exactly the same as textrecv, so share code */
 
421
        return textrecv(fcinfo);
 
422
}
 
423
 
 
424
/*
 
425
 *              varcharsend                     - converts varchar to binary format
 
426
 */
 
427
Datum
 
428
varcharsend(PG_FUNCTION_ARGS)
 
429
{
 
430
        /* Exactly the same as textsend, so share code */
 
431
        return textsend(fcinfo);
 
432
}
 
433
 
 
434
 
 
435
/*
 
436
 * Converts a VARCHAR type to the specified size.
 
437
 *
 
438
 * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
 
439
 * isExplicit is true if this is for an explicit cast to varchar(N).
 
440
 *
 
441
 * Truncation rules: for an explicit cast, silently truncate to the given
 
442
 * length; for an implicit cast, raise error unless extra characters are
 
443
 * all spaces.  (This is sort-of per SQL: the spec would actually have us
 
444
 * raise a "completion condition" for the explicit cast case, but Postgres
 
445
 * hasn't got such a concept.)
 
446
 */
 
447
Datum
 
448
varchar(PG_FUNCTION_ARGS)
 
449
{
 
450
        VarChar    *source = PG_GETARG_VARCHAR_P(0);
 
451
        int32           maxlen = PG_GETARG_INT32(1);
 
452
        bool            isExplicit = PG_GETARG_BOOL(2);
 
453
        VarChar    *result;
 
454
        int32           len;
 
455
        size_t          maxmblen;
 
456
        int                     i;
 
457
 
 
458
        len = VARSIZE(source);
 
459
        /* No work if typmod is invalid or supplied data fits it already */
 
460
        if (maxlen < (int32) VARHDRSZ || len <= maxlen)
 
461
                PG_RETURN_VARCHAR_P(source);
 
462
 
 
463
        /* only reach here if string is too long... */
 
464
 
 
465
        /* truncate multibyte string preserving multibyte boundary */
 
466
        maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
 
467
                                                                maxlen - VARHDRSZ);
 
468
 
 
469
        if (!isExplicit)
 
470
        {
 
471
                for (i = maxmblen; i < len - VARHDRSZ; i++)
 
472
                        if (*(VARDATA(source) + i) != ' ')
 
473
                                ereport(ERROR,
 
474
                                                (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 
475
                                  errmsg("value too long for type character varying(%d)",
 
476
                                                 maxlen - VARHDRSZ)));
 
477
        }
 
478
 
 
479
        len = maxmblen + VARHDRSZ;
 
480
        result = palloc(len);
 
481
        VARATT_SIZEP(result) = len;
 
482
        memcpy(VARDATA(result), VARDATA(source), len - VARHDRSZ);
 
483
 
 
484
        PG_RETURN_VARCHAR_P(result);
 
485
}
 
486
 
 
487
 
 
488
/*****************************************************************************
 
489
 * Exported functions
 
490
 *****************************************************************************/
 
491
 
 
492
/* "True" length (not counting trailing blanks) of a BpChar */
 
493
static int
 
494
bcTruelen(BpChar *arg)
 
495
{
 
496
        char       *s = VARDATA(arg);
 
497
        int                     i;
 
498
        int                     len;
 
499
 
 
500
        len = VARSIZE(arg) - VARHDRSZ;
 
501
        for (i = len - 1; i >= 0; i--)
 
502
        {
 
503
                if (s[i] != ' ')
 
504
                        break;
 
505
        }
 
506
        return i + 1;
 
507
}
 
508
 
 
509
Datum
 
510
bpcharlen(PG_FUNCTION_ARGS)
 
511
{
 
512
        BpChar     *arg = PG_GETARG_BPCHAR_P(0);
 
513
        int                     len;
 
514
 
 
515
        /* get number of bytes, ignoring trailing spaces */
 
516
        len = bcTruelen(arg);
 
517
 
 
518
        /* in multibyte encoding, convert to number of characters */
 
519
        if (pg_database_encoding_max_length() != 1)
 
520
                len = pg_mbstrlen_with_len(VARDATA(arg), len);
 
521
 
 
522
        PG_RETURN_INT32(len);
 
523
}
 
524
 
 
525
Datum
 
526
bpcharoctetlen(PG_FUNCTION_ARGS)
 
527
{
 
528
        BpChar     *arg = PG_GETARG_BPCHAR_P(0);
 
529
 
 
530
        PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);
 
531
}
 
532
 
 
533
 
 
534
/*****************************************************************************
 
535
 *      Comparison Functions used for bpchar
 
536
 *
 
537
 * Note: btree indexes need these routines not to leak memory; therefore,
 
538
 * be careful to free working copies of toasted datums.  Most places don't
 
539
 * need to be so careful.
 
540
 *****************************************************************************/
 
541
 
 
542
Datum
 
543
bpchareq(PG_FUNCTION_ARGS)
 
544
{
 
545
        BpChar     *arg1 = PG_GETARG_BPCHAR_P(0);
 
546
        BpChar     *arg2 = PG_GETARG_BPCHAR_P(1);
 
547
        int                     len1,
 
548
                                len2;
 
549
        bool            result;
 
550
 
 
551
        len1 = bcTruelen(arg1);
 
552
        len2 = bcTruelen(arg2);
 
553
 
 
554
        /* fast path for different-length inputs */
 
555
        if (len1 != len2)
 
556
                result = false;
 
557
        else
 
558
                result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) == 0);
 
559
 
 
560
        PG_FREE_IF_COPY(arg1, 0);
 
561
        PG_FREE_IF_COPY(arg2, 1);
 
562
 
 
563
        PG_RETURN_BOOL(result);
 
564
}
 
565
 
 
566
Datum
 
567
bpcharne(PG_FUNCTION_ARGS)
 
568
{
 
569
        BpChar     *arg1 = PG_GETARG_BPCHAR_P(0);
 
570
        BpChar     *arg2 = PG_GETARG_BPCHAR_P(1);
 
571
        int                     len1,
 
572
                                len2;
 
573
        bool            result;
 
574
 
 
575
        len1 = bcTruelen(arg1);
 
576
        len2 = bcTruelen(arg2);
 
577
 
 
578
        /* fast path for different-length inputs */
 
579
        if (len1 != len2)
 
580
                result = true;
 
581
        else
 
582
                result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) != 0);
 
583
 
 
584
        PG_FREE_IF_COPY(arg1, 0);
 
585
        PG_FREE_IF_COPY(arg2, 1);
 
586
 
 
587
        PG_RETURN_BOOL(result);
 
588
}
 
589
 
 
590
Datum
 
591
bpcharlt(PG_FUNCTION_ARGS)
 
592
{
 
593
        BpChar     *arg1 = PG_GETARG_BPCHAR_P(0);
 
594
        BpChar     *arg2 = PG_GETARG_BPCHAR_P(1);
 
595
        int                     len1,
 
596
                                len2;
 
597
        int                     cmp;
 
598
 
 
599
        len1 = bcTruelen(arg1);
 
600
        len2 = bcTruelen(arg2);
 
601
 
 
602
        cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
 
603
 
 
604
        PG_FREE_IF_COPY(arg1, 0);
 
605
        PG_FREE_IF_COPY(arg2, 1);
 
606
 
 
607
        PG_RETURN_BOOL(cmp < 0);
 
608
}
 
609
 
 
610
Datum
 
611
bpcharle(PG_FUNCTION_ARGS)
 
612
{
 
613
        BpChar     *arg1 = PG_GETARG_BPCHAR_P(0);
 
614
        BpChar     *arg2 = PG_GETARG_BPCHAR_P(1);
 
615
        int                     len1,
 
616
                                len2;
 
617
        int                     cmp;
 
618
 
 
619
        len1 = bcTruelen(arg1);
 
620
        len2 = bcTruelen(arg2);
 
621
 
 
622
        cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
 
623
 
 
624
        PG_FREE_IF_COPY(arg1, 0);
 
625
        PG_FREE_IF_COPY(arg2, 1);
 
626
 
 
627
        PG_RETURN_BOOL(cmp <= 0);
 
628
}
 
629
 
 
630
Datum
 
631
bpchargt(PG_FUNCTION_ARGS)
 
632
{
 
633
        BpChar     *arg1 = PG_GETARG_BPCHAR_P(0);
 
634
        BpChar     *arg2 = PG_GETARG_BPCHAR_P(1);
 
635
        int                     len1,
 
636
                                len2;
 
637
        int                     cmp;
 
638
 
 
639
        len1 = bcTruelen(arg1);
 
640
        len2 = bcTruelen(arg2);
 
641
 
 
642
        cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
 
643
 
 
644
        PG_FREE_IF_COPY(arg1, 0);
 
645
        PG_FREE_IF_COPY(arg2, 1);
 
646
 
 
647
        PG_RETURN_BOOL(cmp > 0);
 
648
}
 
649
 
 
650
Datum
 
651
bpcharge(PG_FUNCTION_ARGS)
 
652
{
 
653
        BpChar     *arg1 = PG_GETARG_BPCHAR_P(0);
 
654
        BpChar     *arg2 = PG_GETARG_BPCHAR_P(1);
 
655
        int                     len1,
 
656
                                len2;
 
657
        int                     cmp;
 
658
 
 
659
        len1 = bcTruelen(arg1);
 
660
        len2 = bcTruelen(arg2);
 
661
 
 
662
        cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
 
663
 
 
664
        PG_FREE_IF_COPY(arg1, 0);
 
665
        PG_FREE_IF_COPY(arg2, 1);
 
666
 
 
667
        PG_RETURN_BOOL(cmp >= 0);
 
668
}
 
669
 
 
670
Datum
 
671
bpcharcmp(PG_FUNCTION_ARGS)
 
672
{
 
673
        BpChar     *arg1 = PG_GETARG_BPCHAR_P(0);
 
674
        BpChar     *arg2 = PG_GETARG_BPCHAR_P(1);
 
675
        int                     len1,
 
676
                                len2;
 
677
        int                     cmp;
 
678
 
 
679
        len1 = bcTruelen(arg1);
 
680
        len2 = bcTruelen(arg2);
 
681
 
 
682
        cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
 
683
 
 
684
        PG_FREE_IF_COPY(arg1, 0);
 
685
        PG_FREE_IF_COPY(arg2, 1);
 
686
 
 
687
        PG_RETURN_INT32(cmp);
 
688
}
 
689
 
 
690
 
 
691
/*
 
692
 * bpchar needs a specialized hash function because we want to ignore
 
693
 * trailing blanks in comparisons.
 
694
 *
 
695
 * XXX is there any need for locale-specific behavior here?
 
696
 */
 
697
Datum
 
698
hashbpchar(PG_FUNCTION_ARGS)
 
699
{
 
700
        BpChar     *key = PG_GETARG_BPCHAR_P(0);
 
701
        char       *keydata;
 
702
        int                     keylen;
 
703
        Datum           result;
 
704
 
 
705
        keydata = VARDATA(key);
 
706
        keylen = bcTruelen(key);
 
707
 
 
708
        result = hash_any((unsigned char *) keydata, keylen);
 
709
 
 
710
        /* Avoid leaking memory for toasted inputs */
 
711
        PG_FREE_IF_COPY(key, 0);
 
712
 
 
713
        return result;
 
714
}