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