LCOV - code coverage report
Current view: top level - src/backend/utils/adt - varchar.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 76.4 % 533 407
Test Date: 2026-01-26 10:56:24 Functions: 71.7 % 46 33
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 53.3 % 214 114

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

Generated by: LCOV version 2.3.2-1