LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - varchar.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 78.8 % 397 313 3 11 44 26 4 168 24 117 53 166 1 19
Current Date: 2023-04-08 15:15:32 Functions: 78.3 % 46 36 10 34 2 10 36
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a