LCOV - differential code coverage report
Current view: top level - contrib/hstore - hstore_io.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: 85.0 % 680 578 16 28 56 2 36 283 35 224 60 313 4 13
Current Date: 2023-04-08 17:13:01 Functions: 90.2 % 41 37 4 33 4 4 37
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 65.2 % 46 30 16 30
Legend: Lines: hit not hit (180,240] days: 100.0 % 2 2 2
(240..) days: 86.4 % 632 546 28 56 2 36 283 3 224 58 288
Function coverage date bins:
(60,120] days: 100.0 % 4 4 4
(240..) days: 42.3 % 78 33 4 33 4 37

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * contrib/hstore/hstore_io.c
                                  3                 :  */
                                  4                 : #include "postgres.h"
                                  5                 : 
                                  6                 : #include <ctype.h>
                                  7                 : 
                                  8                 : #include "access/htup_details.h"
                                  9                 : #include "catalog/pg_type.h"
                                 10                 : #include "common/jsonapi.h"
                                 11                 : #include "funcapi.h"
                                 12                 : #include "hstore.h"
                                 13                 : #include "lib/stringinfo.h"
                                 14                 : #include "libpq/pqformat.h"
                                 15                 : #include "nodes/miscnodes.h"
                                 16                 : #include "utils/builtins.h"
                                 17                 : #include "utils/json.h"
                                 18                 : #include "utils/jsonb.h"
                                 19                 : #include "utils/lsyscache.h"
                                 20                 : #include "utils/memutils.h"
                                 21                 : #include "utils/typcache.h"
                                 22                 : 
 6060 teodor                     23 GIC          17 : PG_MODULE_MAGIC;
 6060 teodor                     24 ECB             : 
                                 25                 : /* old names for C functions */
 4790 bruce                      26 UIC           0 : HSTORE_POLLUTE(hstore_from_text, tconvert);
 4939 tgl                        27 EUB             : 
                                 28                 : 
                                 29                 : typedef struct
                                 30                 : {
                                 31                 :     char       *begin;
                                 32                 :     char       *ptr;
                                 33                 :     char       *cur;
                                 34                 :     char       *word;
                                 35                 :     int         wordlen;
                                 36                 :     Node       *escontext;
                                 37                 : 
                                 38                 :     Pairs      *pairs;
                                 39                 :     int         pcur;
                                 40                 :     int         plen;
                                 41                 : } HSParser;
                                 42                 : 
                                 43                 : static bool hstoreCheckKeyLength(size_t len, HSParser *state);
                                 44                 : static bool hstoreCheckValLength(size_t len, HSParser *state);
                                 45                 : 
                                 46                 : 
                                 47                 : #define RESIZEPRSBUF \
                                 48                 : do { \
                                 49                 :         if ( state->cur - state->word + 1 >= state->wordlen ) \
                                 50                 :         { \
                                 51                 :                 int32 clen = state->cur - state->word; \
                                 52                 :                 state->wordlen *= 2; \
                                 53                 :                 state->word = (char*)repalloc( (void*)state->word, state->wordlen ); \
                                 54                 :                 state->cur = state->word + clen; \
                                 55                 :         } \
                                 56                 : } while (0)
                                 57                 : 
                                 58                 : #define PRSSYNTAXERROR return prssyntaxerror(state)
                                 59                 : 
                                 60                 : static bool
  103 tgl                        61 GNC           4 : prssyntaxerror(HSParser *state)
                                 62                 : {
                                 63               4 :     errsave(state->escontext,
                                 64                 :             (errcode(ERRCODE_SYNTAX_ERROR),
                                 65                 :              errmsg("syntax error in hstore, near \"%.*s\" at position %d",
                                 66                 :                     pg_mblen(state->ptr), state->ptr,
                                 67                 :                     (int) (state->ptr - state->begin))));
                                 68                 :     /* In soft error situation, return false as convenience for caller */
                                 69               3 :     return false;
                                 70                 : }
                                 71                 : 
                                 72                 : #define PRSEOF return prseof(state)
                                 73                 : 
                                 74                 : static bool
                                 75               1 : prseof(HSParser *state)
                                 76                 : {
                                 77               1 :     errsave(state->escontext,
                                 78                 :             (errcode(ERRCODE_SYNTAX_ERROR),
                                 79                 :              errmsg("syntax error in hstore: unexpected end of string")));
                                 80                 :     /* In soft error situation, return false as convenience for caller */
  103 tgl                        81 UNC           0 :     return false;
                                 82                 : }
                                 83                 : 
                                 84                 : 
                                 85                 : #define GV_WAITVAL 0
                                 86                 : #define GV_INVAL 1
                                 87                 : #define GV_INESCVAL 2
                                 88                 : #define GV_WAITESCIN 3
                                 89                 : #define GV_WAITESCESCIN 4
                                 90                 : 
                                 91                 : static bool
 5050 bruce                      92 GIC       10816 : get_val(HSParser *state, bool ignoreeq, bool *escaped)
 6031 bruce                      93 ECB             : {
 6031 bruce                      94 GIC       10816 :     int         st = GV_WAITVAL;
 6031 bruce                      95 ECB             : 
 6031 bruce                      96 GIC       10816 :     state->wordlen = 32;
                                 97           10816 :     state->cur = state->word = palloc(state->wordlen);
                                 98           10816 :     *escaped = false;
                                 99                 : 
                                100                 :     while (1)
 6031 bruce                     101 ECB             :     {
 6031 bruce                     102 GIC       52034 :         if (st == GV_WAITVAL)
                                103                 :         {
                                104           15079 :             if (*(state->ptr) == '"')
                                105                 :             {
                                106              89 :                 *escaped = true;
 6060 teodor                    107 CBC          89 :                 st = GV_INESCVAL;
                                108                 :             }
 6031 bruce                     109           14990 :             else if (*(state->ptr) == '\0')
                                110                 :             {
 6060 teodor                    111 GIC         146 :                 return false;
                                112                 :             }
 6031 bruce                     113 GBC       14844 :             else if (*(state->ptr) == '=' && !ignoreeq)
                                114                 :             {
  103 tgl                       115 GNC           2 :                 PRSSYNTAXERROR;
                                116                 :             }
 6031 bruce                     117 GIC       14842 :             else if (*(state->ptr) == '\\')
                                118                 :             {
 6060 teodor                    119               2 :                 st = GV_WAITESCIN;
                                120                 :             }
 6031 bruce                     121           14840 :             else if (!isspace((unsigned char) *(state->ptr)))
 6031 bruce                     122 ECB             :             {
 6060 teodor                    123 GIC       10577 :                 *(state->cur) = *(state->ptr);
 6060 teodor                    124 CBC       10577 :                 state->cur++;
 6060 teodor                    125 GIC       10577 :                 st = GV_INVAL;
 6060 teodor                    126 ECB             :             }
 6031 bruce                     127                 :         }
 6031 bruce                     128 CBC       36955 :         else if (st == GV_INVAL)
                                129                 :         {
 6031 bruce                     130 GIC       36554 :             if (*(state->ptr) == '\\')
                                131                 :             {
 6060 teodor                    132 CBC           1 :                 st = GV_WAITESCIN;
                                133                 :             }
 6031 bruce                     134           36553 :             else if (*(state->ptr) == '=' && !ignoreeq)
                                135                 :             {
 6060 teodor                    136            5261 :                 state->ptr--;
                                137            5261 :                 return true;
                                138                 :             }
 6031 bruce                     139           31292 :             else if (*(state->ptr) == ',' && ignoreeq)
                                140                 :             {
 6060 teodor                    141            4131 :                 state->ptr--;
 6060 teodor                    142 GIC        4131 :                 return true;
 6031 bruce                     143 ECB             :             }
 6031 bruce                     144 GIC       27161 :             else if (isspace((unsigned char) *(state->ptr)))
 6031 bruce                     145 ECB             :             {
 6060 teodor                    146 GIC          90 :                 return true;
 6031 bruce                     147 ECB             :             }
 6031 bruce                     148 GIC       27071 :             else if (*(state->ptr) == '\0')
 6031 bruce                     149 ECB             :             {
 6060 teodor                    150 GIC        1097 :                 state->ptr--;
 6060 teodor                    151 CBC        1097 :                 return true;
                                152                 :             }
 6031 bruce                     153 ECB             :             else
                                154                 :             {
 6060 teodor                    155 CBC       25974 :                 RESIZEPRSBUF;
 6060 teodor                    156 GIC       25974 :                 *(state->cur) = *(state->ptr);
                                157           25974 :                 state->cur++;
 6060 teodor                    158 ECB             :             }
                                159                 :         }
 6031 bruce                     160 CBC         401 :         else if (st == GV_INESCVAL)
                                161                 :         {
                                162             397 :             if (*(state->ptr) == '\\')
                                163                 :             {
 6060 teodor                    164               1 :                 st = GV_WAITESCESCIN;
                                165                 :             }
 6031 bruce                     166             396 :             else if (*(state->ptr) == '"')
 6031 bruce                     167 ECB             :             {
 6060 teodor                    168 GIC          88 :                 return true;
 6031 bruce                     169 ECB             :             }
 6031 bruce                     170 GIC         308 :             else if (*(state->ptr) == '\0')
 6031 bruce                     171 ECB             :             {
  103 tgl                       172 GNC           1 :                 PRSEOF;
                                173                 :             }
 6031 bruce                     174 ECB             :             else
                                175                 :             {
 6060 teodor                    176 CBC         307 :                 RESIZEPRSBUF;
 6060 teodor                    177 GIC         307 :                 *(state->cur) = *(state->ptr);
 6060 teodor                    178 CBC         307 :                 state->cur++;
                                179                 :             }
 6031 bruce                     180 ECB             :         }
 6031 bruce                     181 CBC           4 :         else if (st == GV_WAITESCIN)
                                182                 :         {
 6031 bruce                     183 GIC           3 :             if (*(state->ptr) == '\0')
  103 tgl                       184 UNC           0 :                 PRSEOF;
 6060 teodor                    185 CBC           3 :             RESIZEPRSBUF;
                                186               3 :             *(state->cur) = *(state->ptr);
                                187               3 :             state->cur++;
 6031 bruce                     188 GIC           3 :             st = GV_INVAL;
                                189                 :         }
 6031 bruce                     190 CBC           1 :         else if (st == GV_WAITESCESCIN)
                                191                 :         {
                                192               1 :             if (*(state->ptr) == '\0')
  103 tgl                       193 UNC           0 :                 PRSEOF;
 6060 teodor                    194 CBC           1 :             RESIZEPRSBUF;
 6060 teodor                    195 GIC           1 :             *(state->cur) = *(state->ptr);
 6060 teodor                    196 CBC           1 :             state->cur++;
 6060 teodor                    197 GIC           1 :             st = GV_INESCVAL;
 6031 bruce                     198 ECB             :         }
                                199                 :         else
  103 tgl                       200 UNC           0 :             elog(ERROR, "unrecognized get_val state: %d", st);
                                201                 : 
 6060 teodor                    202 CBC       41218 :         state->ptr++;
                                203                 :     }
                                204                 : }
                                205                 : 
 6060 teodor                    206 ECB             : #define WKEY    0
                                207                 : #define WVAL    1
 6031 bruce                     208                 : #define WEQ 2
                                209                 : #define WGT 3
                                210                 : #define WDEL    4
 6060 teodor                    211                 : 
                                212                 : 
                                213                 : static bool
 5050 bruce                     214 GBC        1281 : parse_hstore(HSParser *state)
 6031 bruce                     215 ECB             : {
 6031 bruce                     216 CBC        1281 :     int         st = WKEY;
                                217            1281 :     bool        escaped = false;
 6031 bruce                     218 ECB             : 
 6031 bruce                     219 GIC        1281 :     state->plen = 16;
 6031 bruce                     220 CBC        1281 :     state->pairs = (Pairs *) palloc(sizeof(Pairs) * state->plen);
 6031 bruce                     221 GIC        1281 :     state->pcur = 0;
 6060 teodor                    222 CBC        1281 :     state->ptr = state->begin;
 6031 bruce                     223 GBC        1281 :     state->word = NULL;
 6060 teodor                    224 ECB             : 
 6031 bruce                     225                 :     while (1)
                                226                 :     {
 6031 bruce                     227 CBC       26833 :         if (st == WKEY)
                                228                 :         {
 6031 bruce                     229 GIC        5483 :             if (!get_val(state, false, &escaped))
                                230                 :             {
  103 tgl                       231 GNC         147 :                 if (SOFT_ERROR_OCCURRED(state->escontext))
                                232               1 :                     return false;
                                233             146 :                 return true;    /* EOF, all okay */
                                234                 :             }
 6031 bruce                     235 GIC        5335 :             if (state->pcur >= state->plen)
 6031 bruce                     236 ECB             :             {
 6060 teodor                    237 UIC           0 :                 state->plen *= 2;
 6031 bruce                     238               0 :                 state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
                                239                 :             }
  103 tgl                       240 GNC        5335 :             if (!hstoreCheckKeyLength(state->cur - state->word, state))
  103 tgl                       241 UNC           0 :                 return false;
 6031 bruce                     242 GIC        5335 :             state->pairs[state->pcur].key = state->word;
  103 tgl                       243 GNC        5335 :             state->pairs[state->pcur].keylen = state->cur - state->word;
 6031 bruce                     244 GIC        5335 :             state->pairs[state->pcur].val = NULL;
                                245            5335 :             state->word = NULL;
 6060 teodor                    246            5335 :             st = WEQ;
                                247                 :         }
 6031 bruce                     248           21350 :         else if (st == WEQ)
                                249                 :         {
 6031 bruce                     250 CBC        5346 :             if (*(state->ptr) == '=')
                                251                 :             {
 6060 teodor                    252            5335 :                 st = WGT;
 6060 teodor                    253 ECB             :             }
 6031 bruce                     254 GIC          11 :             else if (*(state->ptr) == '\0')
 6031 bruce                     255 ECB             :             {
  103 tgl                       256 UNC           0 :                 PRSEOF;
 6031 bruce                     257 ECB             :             }
 6031 bruce                     258 CBC          11 :             else if (!isspace((unsigned char) *(state->ptr)))
 6031 bruce                     259 ECB             :             {
  103 tgl                       260 UNC           0 :                 PRSSYNTAXERROR;
 6031 bruce                     261 ECB             :             }
                                262                 :         }
 6031 bruce                     263 CBC       16004 :         else if (st == WGT)
                                264                 :         {
                                265            5335 :             if (*(state->ptr) == '>')
 6031 bruce                     266 ECB             :             {
 6060 teodor                    267 CBC        5333 :                 st = WVAL;
                                268                 :             }
 6031 bruce                     269               2 :             else if (*(state->ptr) == '\0')
                                270                 :             {
  103 tgl                       271 UNC           0 :                 PRSEOF;
 6031 bruce                     272 EUB             :             }
                                273                 :             else
 6031 bruce                     274 ECB             :             {
  103 tgl                       275 GNC           2 :                 PRSSYNTAXERROR;
 6031 bruce                     276 ECB             :             }
                                277                 :         }
 6031 bruce                     278 CBC       10669 :         else if (st == WVAL)
                                279                 :         {
                                280            5333 :             if (!get_val(state, true, &escaped))
                                281                 :             {
  103 tgl                       282 UNC           0 :                 if (SOFT_ERROR_OCCURRED(state->escontext))
                                283               0 :                     return false;
                                284               0 :                 PRSEOF;
                                285                 :             }
  103 tgl                       286 GNC        5332 :             if (!hstoreCheckValLength(state->cur - state->word, state))
  103 tgl                       287 UNC           0 :                 return false;
 6031 bruce                     288 CBC        5332 :             state->pairs[state->pcur].val = state->word;
  103 tgl                       289 GNC        5332 :             state->pairs[state->pcur].vallen = state->cur - state->word;
 6031 bruce                     290 CBC        5332 :             state->pairs[state->pcur].isnull = false;
 6031 bruce                     291 GIC        5332 :             state->pairs[state->pcur].needfree = true;
 6031 bruce                     292 CBC        5332 :             if (state->cur - state->word == 4 && !escaped)
                                293                 :             {
 6060 teodor                    294 GBC          73 :                 state->word[4] = '\0';
  103 tgl                       295 GNC          73 :                 if (pg_strcasecmp(state->word, "null") == 0)
 6031 bruce                     296 CBC          69 :                     state->pairs[state->pcur].isnull = true;
                                297                 :             }
 6031 bruce                     298 GBC        5332 :             state->word = NULL;
 6060 teodor                    299 GIC        5332 :             state->pcur++;
                                300            5332 :             st = WDEL;
 6031 bruce                     301 ECB             :         }
 6031 bruce                     302 GIC        5336 :         else if (st == WDEL)
 6031 bruce                     303 ECB             :         {
 6031 bruce                     304 GIC        5336 :             if (*(state->ptr) == ',')
 6031 bruce                     305 ECB             :             {
 6060 teodor                    306 GIC        4202 :                 st = WKEY;
 6031 bruce                     307 ECB             :             }
 6031 bruce                     308 GIC        1134 :             else if (*(state->ptr) == '\0')
 6031 bruce                     309 EUB             :             {
  103 tgl                       310 GNC        1130 :                 return true;
                                311                 :             }
 6031 bruce                     312 GIC           4 :             else if (!isspace((unsigned char) *(state->ptr)))
 6031 bruce                     313 ECB             :             {
  103 tgl                       314 UNC           0 :                 PRSSYNTAXERROR;
                                315                 :             }
 6031 bruce                     316 ECB             :         }
                                317                 :         else
  103 tgl                       318 UNC           0 :             elog(ERROR, "unrecognized parse_hstore state: %d", st);
 6060 teodor                    319 EUB             : 
 6060 teodor                    320 GBC       25552 :         state->ptr++;
                                321                 :     }
 6031 bruce                     322 ECB             : }
 6060 teodor                    323 EUB             : 
 4939 tgl                       324 ECB             : static int
 6031 bruce                     325 CBC       12691 : comparePairs(const void *a, const void *b)
 6031 bruce                     326 ECB             : {
 4228 peter_e                   327 CBC       12691 :     const Pairs *pa = a;
                                328           12691 :     const Pairs *pb = b;
                                329                 : 
                                330           12691 :     if (pa->keylen == pb->keylen)
 6031 bruce                     331 ECB             :     {
 4228 peter_e                   332 CBC        2531 :         int         res = memcmp(pa->key, pb->key, pa->keylen);
                                333                 : 
 6031 bruce                     334            2531 :         if (res)
 6060 teodor                    335            2531 :             return res;
 6060 teodor                    336 ECB             : 
                                337                 :         /* guarantee that needfree will be later */
 4228 peter_e                   338 LBC           0 :         if (pb->needfree == pa->needfree)
 6060 teodor                    339 UIC           0 :             return 0;
 4228 peter_e                   340 LBC           0 :         else if (pa->needfree)
 6060 teodor                    341 UIC           0 :             return 1;
 6060 teodor                    342 ECB             :         else
 6031 bruce                     343 UIC           0 :             return -1;
 6060 teodor                    344 ECB             :     }
 4228 peter_e                   345 GIC       10160 :     return (pa->keylen > pb->keylen) ? 1 : -1;
 6060 teodor                    346 ECB             : }
                                347                 : 
 4939 tgl                       348                 : /*
                                349                 :  * this code still respects pairs.needfree, even though in general
 4939 tgl                       350 EUB             :  * it should never be called in a context where anything needs freeing.
                                351                 :  * we keep it because (a) those calls are in a rare code path anyway,
                                352                 :  * and (b) who knows whether they might be needed by some caller.
                                353                 :  */
 6060 teodor                    354                 : int
 3940 peter_e                   355 GIC        4144 : hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen)
 6031 bruce                     356 ECB             : {
                                357                 :     Pairs      *ptr,
                                358                 :                *res;
                                359                 : 
 6031 bruce                     360 GIC        4144 :     *buflen = 0;
 6031 bruce                     361 CBC        4144 :     if (l < 2)
                                362                 :     {
                                363             230 :         if (l == 1)
                                364              82 :             *buflen = a->keylen + ((a->isnull) ? 0 : a->vallen);
 6060 teodor                    365 GIC         230 :         return l;
 6060 teodor                    366 ECB             :     }
                                367                 : 
   61 peter                     368 GNC        3914 :     qsort(a, l, sizeof(Pairs), comparePairs);
                                369                 : 
 1249 tmunro                    370 ECB             :     /*
                                371                 :      * We can't use qunique here because we have some clean-up code to run on
                                372                 :      * removed elements.
                                373                 :      */
 6031 bruce                     374 GBC        3914 :     ptr = a + 1;
                                375            3914 :     res = a;
                                376           11022 :     while (ptr - a < l)
 6031 bruce                     377 EUB             :     {
 4939 tgl                       378 GIC        7108 :         if (ptr->keylen == res->keylen &&
 4492 rhaas                     379 GBC        1874 :             memcmp(ptr->key, res->key, res->keylen) == 0)
                                380                 :         {
 6031 bruce                     381 LBC           0 :             if (ptr->needfree)
                                382                 :             {
 6060 teodor                    383 UIC           0 :                 pfree(ptr->key);
                                384               0 :                 pfree(ptr->val);
                                385                 :             }
                                386                 :         }
                                387                 :         else
                                388                 :         {
 6031 bruce                     389 GIC        7108 :             *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
 6060 teodor                    390            7108 :             res++;
 1961 tgl                       391 CBC        7108 :             if (res != ptr)
 1961 tgl                       392 UIC           0 :                 memcpy(res, ptr, sizeof(Pairs));
                                393                 :         }
                                394                 : 
 6060 teodor                    395 GIC        7108 :         ptr++;
 6060 teodor                    396 ECB             :     }
                                397                 : 
 6031 bruce                     398 GIC        3914 :     *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
 6060 teodor                    399 CBC        3914 :     return res + 1 - a;
 6060 teodor                    400 ECB             : }
                                401                 : 
                                402                 : size_t
 5138 tgl                       403 GIC         135 : hstoreCheckKeyLen(size_t len)
 5138 tgl                       404 ECB             : {
 5138 tgl                       405 GIC         135 :     if (len > HSTORE_MAX_KEY_LEN)
 5138 tgl                       406 UIC           0 :         ereport(ERROR,
                                407                 :                 (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
                                408                 :                  errmsg("string too long for hstore key")));
 5138 tgl                       409 GIC         135 :     return len;
 5138 tgl                       410 ECB             : }
                                411                 : 
                                412                 : static bool
  103 tgl                       413 GNC        5335 : hstoreCheckKeyLength(size_t len, HSParser *state)
                                414                 : {
                                415            5335 :     if (len > HSTORE_MAX_KEY_LEN)
  103 tgl                       416 UNC           0 :         ereturn(state->escontext, false,
                                417                 :                 (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
                                418                 :                  errmsg("string too long for hstore key")));
  103 tgl                       419 GNC        5335 :     return true;
                                420                 : }
                                421                 : 
 5138 tgl                       422 ECB             : size_t
 5138 tgl                       423 GIC          98 : hstoreCheckValLen(size_t len)
 5138 tgl                       424 ECB             : {
 5138 tgl                       425 CBC          98 :     if (len > HSTORE_MAX_VALUE_LEN)
 5138 tgl                       426 UIC           0 :         ereport(ERROR,
 5138 tgl                       427 EUB             :                 (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
                                428                 :                  errmsg("string too long for hstore value")));
 5138 tgl                       429 GBC          98 :     return len;
 5138 tgl                       430 EUB             : }
                                431                 : 
                                432                 : static bool
  103 tgl                       433 GNC        5332 : hstoreCheckValLength(size_t len, HSParser *state)
                                434                 : {
                                435            5332 :     if (len > HSTORE_MAX_VALUE_LEN)
  103 tgl                       436 UNC           0 :         ereturn(state->escontext, false,
                                437                 :                 (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
                                438                 :                  errmsg("string too long for hstore value")));
  103 tgl                       439 GNC        5332 :     return true;
                                440                 : }
                                441                 : 
                                442                 : 
                                443                 : HStore *
 3940 peter_e                   444 GIC        1352 : hstorePairs(Pairs *pairs, int32 pcount, int32 buflen)
 4939 tgl                       445 ECB             : {
 4790 bruce                     446                 :     HStore     *out;
 4939 tgl                       447                 :     HEntry     *entry;
 4939 tgl                       448 EUB             :     char       *ptr;
                                449                 :     char       *buf;
                                450                 :     int32       len;
 3940 peter_e                   451 ECB             :     int32       i;
                                452                 : 
 4939 tgl                       453 GIC        1352 :     len = CALCDATASIZE(pcount, buflen);
 4939 tgl                       454 CBC        1352 :     out = palloc(len);
                                455            1352 :     SET_VARSIZE(out, len);
 4939 tgl                       456 GIC        1352 :     HS_SETCOUNT(out, pcount);
                                457                 : 
                                458            1352 :     if (pcount == 0)
 4939 tgl                       459 CBC         151 :         return out;
                                460                 : 
                                461            1201 :     entry = ARRPTR(out);
 4939 tgl                       462 GBC        1201 :     buf = ptr = STRPTR(out);
                                463                 : 
 4939 tgl                       464 GIC        6675 :     for (i = 0; i < pcount; i++)
 4790 bruce                     465 CBC        5474 :         HS_ADDITEM(entry, buf, ptr, pairs[i]);
                                466                 : 
 4790 bruce                     467 GIC        1201 :     HS_FINALIZE(out, pcount, buf, ptr);
                                468                 : 
 4939 tgl                       469 CBC        1201 :     return out;
                                470                 : }
 4939 tgl                       471 ECB             : 
 4939 tgl                       472 EUB             : 
 6060 teodor                    473 GIC          15 : PG_FUNCTION_INFO_V1(hstore_in);
                                474                 : Datum
 6031 bruce                     475 CBC        1281 : hstore_in(PG_FUNCTION_ARGS)
                                476                 : {
  103 tgl                       477 GNC        1281 :     char       *str = PG_GETARG_CSTRING(0);
                                478            1281 :     Node       *escontext = fcinfo->context;
                                479                 :     HSParser    state;
                                480                 :     int32       buflen;
 6031 bruce                     481 ECB             :     HStore     *out;
                                482                 : 
  103 tgl                       483 GNC        1281 :     state.begin = str;
                                484            1281 :     state.escontext = escontext;
 6060 teodor                    485 EUB             : 
  103 tgl                       486 GNC        1281 :     if (!parse_hstore(&state))
                                487               3 :         PG_RETURN_NULL();
                                488                 : 
 4939 tgl                       489 CBC        1276 :     state.pcur = hstoreUniquePairs(state.pairs, state.pcur, &buflen);
                                490                 : 
 4939 tgl                       491 GIC        1276 :     out = hstorePairs(state.pairs, state.pcur, buflen);
                                492                 : 
 4939 tgl                       493 CBC        1276 :     PG_RETURN_POINTER(out);
                                494                 : }
 4939 tgl                       495 ECB             : 
 4939 tgl                       496 EUB             : 
 4939 tgl                       497 GIC           8 : PG_FUNCTION_INFO_V1(hstore_recv);
                                498                 : Datum
 4939 tgl                       499 LBC           0 : hstore_recv(PG_FUNCTION_ARGS)
                                500                 : {
                                501                 :     int32       buflen;
                                502                 :     HStore     *out;
                                503                 :     Pairs      *pairs;
 3940 peter_e                   504 ECB             :     int32       i;
                                505                 :     int32       pcount;
 4790 bruce                     506 UIC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
                                507                 : 
 4939 tgl                       508               0 :     pcount = pq_getmsgint(buf, 4);
                                509                 : 
                                510               0 :     if (pcount == 0)
                                511                 :     {
                                512               0 :         out = hstorePairs(NULL, 0, 0);
 6060 teodor                    513 LBC           0 :         PG_RETURN_POINTER(out);
 6060 teodor                    514 ECB             :     }
                                515                 : 
 3338 noah                      516 LBC           0 :     if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs))
 3338 noah                      517 UIC           0 :         ereport(ERROR,
 3338 noah                      518 ECB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 2118 tgl                       519                 :                  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
                                520                 :                         pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
 4939 tgl                       521 LBC           0 :     pairs = palloc(pcount * sizeof(Pairs));
 6060 teodor                    522 ECB             : 
 4939 tgl                       523 UIC           0 :     for (i = 0; i < pcount; ++i)
 4939 tgl                       524 ECB             :     {
 4790 bruce                     525 LBC           0 :         int         rawlen = pq_getmsgint(buf, 4);
                                526                 :         int         len;
 4939 tgl                       527 ECB             : 
 4939 tgl                       528 UIC           0 :         if (rawlen < 0)
 4939 tgl                       529 LBC           0 :             ereport(ERROR,
                                530                 :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                                531                 :                      errmsg("null value not allowed for hstore key")));
                                532                 : 
                                533               0 :         pairs[i].key = pq_getmsgtext(buf, rawlen, &len);
 4939 tgl                       534 UIC           0 :         pairs[i].keylen = hstoreCheckKeyLen(len);
 4939 tgl                       535 LBC           0 :         pairs[i].needfree = true;
                                536                 : 
                                537               0 :         rawlen = pq_getmsgint(buf, 4);
                                538               0 :         if (rawlen < 0)
                                539                 :         {
 4939 tgl                       540 UIC           0 :             pairs[i].val = NULL;
                                541               0 :             pairs[i].vallen = 0;
                                542               0 :             pairs[i].isnull = true;
 4939 tgl                       543 ECB             :         }
                                544                 :         else
                                545                 :         {
 4939 tgl                       546 LBC           0 :             pairs[i].val = pq_getmsgtext(buf, rawlen, &len);
                                547               0 :             pairs[i].vallen = hstoreCheckValLen(len);
 4939 tgl                       548 UIC           0 :             pairs[i].isnull = false;
 4939 tgl                       549 ECB             :         }
                                550                 :     }
                                551                 : 
 4939 tgl                       552 UIC           0 :     pcount = hstoreUniquePairs(pairs, pcount, &buflen);
 4939 tgl                       553 ECB             : 
 4939 tgl                       554 UIC           0 :     out = hstorePairs(pairs, pcount, buflen);
                                555                 : 
                                556               0 :     PG_RETURN_POINTER(out);
 4939 tgl                       557 ECB             : }
                                558                 : 
 4939 tgl                       559 EUB             : 
 4939 tgl                       560 GIC          15 : PG_FUNCTION_INFO_V1(hstore_from_text);
                                561                 : Datum
                                562              36 : hstore_from_text(PG_FUNCTION_ARGS)
                                563                 : {
                                564                 :     text       *key;
 4790 bruce                     565              36 :     text       *val = NULL;
 4790 bruce                     566 EUB             :     Pairs       p;
                                567                 :     HStore     *out;
 4939 tgl                       568                 : 
 4939 tgl                       569 GIC          36 :     if (PG_ARGISNULL(0))
 4939 tgl                       570 GBC           1 :         PG_RETURN_NULL();
                                571                 : 
                                572              35 :     p.needfree = false;
                                573              35 :     key = PG_GETARG_TEXT_PP(0);
 4939 tgl                       574 GIC          35 :     p.key = VARDATA_ANY(key);
                                575              35 :     p.keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key));
 4939 tgl                       576 EUB             : 
 4939 tgl                       577 GBC          35 :     if (PG_ARGISNULL(1))
                                578                 :     {
 4939 tgl                       579 GIC           8 :         p.vallen = 0;
                                580               8 :         p.isnull = true;
 4939 tgl                       581 EUB             :     }
                                582                 :     else
                                583                 :     {
 4939 tgl                       584 GIC          27 :         val = PG_GETARG_TEXT_PP(1);
 4939 tgl                       585 GBC          27 :         p.val = VARDATA_ANY(val);
 4939 tgl                       586 GIC          27 :         p.vallen = hstoreCheckValLen(VARSIZE_ANY_EXHDR(val));
                                587              27 :         p.isnull = false;
 4939 tgl                       588 EUB             :     }
                                589                 : 
 4939 tgl                       590 GIC          35 :     out = hstorePairs(&p, 1, p.keylen + p.vallen);
                                591                 : 
                                592              35 :     PG_RETURN_POINTER(out);
 4939 tgl                       593 EUB             : }
                                594                 : 
                                595                 : 
 4939 tgl                       596 GIC           8 : PG_FUNCTION_INFO_V1(hstore_from_arrays);
 4939 tgl                       597 EUB             : Datum
 4939 tgl                       598 GBC          10 : hstore_from_arrays(PG_FUNCTION_ARGS)
                                599                 : {
 3940 peter_e                   600 EUB             :     int32       buflen;
 4939 tgl                       601                 :     HStore     *out;
                                602                 :     Pairs      *pairs;
                                603                 :     Datum      *key_datums;
                                604                 :     bool       *key_nulls;
                                605                 :     int         key_count;
                                606                 :     Datum      *value_datums;
                                607                 :     bool       *value_nulls;
 4790 bruce                     608                 :     int         value_count;
                                609                 :     ArrayType  *key_array;
                                610                 :     ArrayType  *value_array;
                                611                 :     int         i;
 4939 tgl                       612                 : 
 4939 tgl                       613 GIC          10 :     if (PG_ARGISNULL(0))
 4939 tgl                       614 UBC           0 :         PG_RETURN_NULL();
                                615                 : 
 4939 tgl                       616 GBC          10 :     key_array = PG_GETARG_ARRAYTYPE_P(0);
                                617                 : 
 4939 tgl                       618 GIC          10 :     Assert(ARR_ELEMTYPE(key_array) == TEXTOID);
                                619                 : 
 4939 tgl                       620 ECB             :     /*
                                621                 :      * must check >1 rather than != 1 because empty arrays have 0 dimensions,
 4790 bruce                     622                 :      * not 1
                                623                 :      */
                                624                 : 
 4939 tgl                       625 CBC          10 :     if (ARR_NDIM(key_array) > 1)
 4939 tgl                       626 UIC           0 :         ereport(ERROR,
                                627                 :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                628                 :                  errmsg("wrong number of array subscripts")));
 4939 tgl                       629 ECB             : 
  282 peter                     630 GNC          10 :     deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
 4939 tgl                       631 ECB             : 
 3338 noah                      632                 :     /* see discussion in hstoreArrayToPairs() */
 3338 noah                      633 CBC          10 :     if (key_count > MaxAllocSize / sizeof(Pairs))
 3338 noah                      634 UIC           0 :         ereport(ERROR,
 3338 noah                      635 ECB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                636                 :                  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
 2118 tgl                       637                 :                         key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
 3338 noah                      638                 : 
                                639                 :     /* value_array might be NULL */
                                640                 : 
 4939 tgl                       641 GIC          10 :     if (PG_ARGISNULL(1))
 4939 tgl                       642 ECB             :     {
 4939 tgl                       643 CBC           2 :         value_array = NULL;
                                644               2 :         value_count = key_count;
                                645               2 :         value_datums = NULL;
 4939 tgl                       646 GIC           2 :         value_nulls = NULL;
                                647                 :     }
 4939 tgl                       648 ECB             :     else
                                649                 :     {
 4939 tgl                       650 CBC           8 :         value_array = PG_GETARG_ARRAYTYPE_P(1);
                                651                 : 
 4939 tgl                       652 GIC           8 :         Assert(ARR_ELEMTYPE(value_array) == TEXTOID);
                                653                 : 
 4939 tgl                       654 CBC           8 :         if (ARR_NDIM(value_array) > 1)
 4939 tgl                       655 UIC           0 :             ereport(ERROR,
 4939 tgl                       656 ECB             :                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                657                 :                      errmsg("wrong number of array subscripts")));
                                658                 : 
 4939 tgl                       659 GIC           8 :         if ((ARR_NDIM(key_array) > 0 || ARR_NDIM(value_array) > 0) &&
                                660               7 :             (ARR_NDIM(key_array) != ARR_NDIM(value_array) ||
                                661               5 :              ARR_DIMS(key_array)[0] != ARR_DIMS(value_array)[0] ||
                                662               5 :              ARR_LBOUND(key_array)[0] != ARR_LBOUND(value_array)[0]))
                                663               2 :             ereport(ERROR,
                                664                 :                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                665                 :                      errmsg("arrays must have same bounds")));
                                666                 : 
  282 peter                     667 GNC           6 :         deconstruct_array_builtin(value_array, TEXTOID, &value_datums, &value_nulls, &value_count);
                                668                 : 
 4939 tgl                       669 CBC           6 :         Assert(key_count == value_count);
 4939 tgl                       670 EUB             :     }
                                671                 : 
 4939 tgl                       672 CBC           8 :     pairs = palloc(key_count * sizeof(Pairs));
                                673                 : 
                                674              28 :     for (i = 0; i < key_count; ++i)
                                675                 :     {
 4939 tgl                       676 GIC          20 :         if (key_nulls[i])
 4939 tgl                       677 UIC           0 :             ereport(ERROR,
                                678                 :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                                679                 :                      errmsg("null value not allowed for hstore key")));
                                680                 : 
 4939 tgl                       681 CBC          20 :         if (!value_nulls || value_nulls[i])
 4939 tgl                       682 EUB             :         {
 2219 noah                      683 GIC           9 :             pairs[i].key = VARDATA(key_datums[i]);
 4939 tgl                       684               9 :             pairs[i].val = NULL;
 2219 noah                      685              18 :             pairs[i].keylen =
 2219 noah                      686 CBC           9 :                 hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
 4939 tgl                       687 GIC           9 :             pairs[i].vallen = 4;
                                688               9 :             pairs[i].isnull = true;
 4939 tgl                       689 CBC           9 :             pairs[i].needfree = false;
 4939 tgl                       690 EUB             :         }
                                691                 :         else
                                692                 :         {
 2219 noah                      693 GIC          11 :             pairs[i].key = VARDATA(key_datums[i]);
                                694              11 :             pairs[i].val = VARDATA(value_datums[i]);
                                695              22 :             pairs[i].keylen =
                                696              11 :                 hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
 2219 noah                      697 CBC          22 :             pairs[i].vallen =
 2219 noah                      698 GIC          11 :                 hstoreCheckValLen(VARSIZE(value_datums[i]) - VARHDRSZ);
 4939 tgl                       699 CBC          11 :             pairs[i].isnull = false;
                                700              11 :             pairs[i].needfree = false;
 4939 tgl                       701 ECB             :         }
                                702                 :     }
                                703                 : 
 4939 tgl                       704 GIC           8 :     key_count = hstoreUniquePairs(pairs, key_count, &buflen);
                                705                 : 
 4939 tgl                       706 CBC           8 :     out = hstorePairs(pairs, key_count, buflen);
                                707                 : 
                                708               8 :     PG_RETURN_POINTER(out);
                                709                 : }
 4939 tgl                       710 ECB             : 
 4939 tgl                       711 EUB             : 
 4939 tgl                       712 GIC           8 : PG_FUNCTION_INFO_V1(hstore_from_array);
                                713                 : Datum
                                714              14 : hstore_from_array(PG_FUNCTION_ARGS)
 4939 tgl                       715 ECB             : {
 4939 tgl                       716 CBC          14 :     ArrayType  *in_array = PG_GETARG_ARRAYTYPE_P(0);
 4790 bruce                     717              14 :     int         ndims = ARR_NDIM(in_array);
 4790 bruce                     718 ECB             :     int         count;
 3940 peter_e                   719                 :     int32       buflen;
                                720                 :     HStore     *out;
                                721                 :     Pairs      *pairs;
                                722                 :     Datum      *in_datums;
 4939 tgl                       723                 :     bool       *in_nulls;
                                724                 :     int         in_count;
 4790 bruce                     725                 :     int         i;
                                726                 : 
 4939 tgl                       727 GIC          14 :     Assert(ARR_ELEMTYPE(in_array) == TEXTOID);
 4939 tgl                       728 ECB             : 
 4939 tgl                       729 GIC          14 :     switch (ndims)
 4939 tgl                       730 ECB             :     {
 4939 tgl                       731 GIC           2 :         case 0:
 4939 tgl                       732 CBC           2 :             out = hstorePairs(NULL, 0, 0);
 4939 tgl                       733 GBC           2 :             PG_RETURN_POINTER(out);
                                734                 : 
 4939 tgl                       735 GIC           5 :         case 1:
                                736               5 :             if ((ARR_DIMS(in_array)[0]) % 2)
 4939 tgl                       737 CBC           2 :                 ereport(ERROR,
                                738                 :                         (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 4939 tgl                       739 ECB             :                          errmsg("array must have even number of elements")));
 4939 tgl                       740 CBC           3 :             break;
 4939 tgl                       741 ECB             : 
 4939 tgl                       742 CBC           5 :         case 2:
                                743               5 :             if ((ARR_DIMS(in_array)[1]) != 2)
                                744               2 :                 ereport(ERROR,
 4939 tgl                       745 ECB             :                         (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                746                 :                          errmsg("array must have two columns")));
 4939 tgl                       747 GIC           3 :             break;
                                748                 : 
 4939 tgl                       749 CBC           2 :         default:
                                750               2 :             ereport(ERROR,
 4939 tgl                       751 ECB             :                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                752                 :                      errmsg("wrong number of array subscripts")));
 4790 bruce                     753                 :     }
 4939 tgl                       754                 : 
  282 peter                     755 GNC           6 :     deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
                                756                 : 
 4939 tgl                       757 GIC           6 :     count = in_count / 2;
 4939 tgl                       758 ECB             : 
                                759                 :     /* see discussion in hstoreArrayToPairs() */
 3338 noah                      760 CBC           6 :     if (count > MaxAllocSize / sizeof(Pairs))
 3338 noah                      761 UIC           0 :         ereport(ERROR,
 3338 noah                      762 ECB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                763                 :                  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
                                764                 :                         count, (int) (MaxAllocSize / sizeof(Pairs)))));
                                765                 : 
 4939 tgl                       766 CBC           6 :     pairs = palloc(count * sizeof(Pairs));
                                767                 : 
                                768              24 :     for (i = 0; i < count; ++i)
                                769                 :     {
 4790 bruce                     770              18 :         if (in_nulls[i * 2])
 4939 tgl                       771 LBC           0 :             ereport(ERROR,
                                772                 :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                                773                 :                      errmsg("null value not allowed for hstore key")));
                                774                 : 
 4790 bruce                     775 GIC          18 :         if (in_nulls[i * 2 + 1])
                                776                 :         {
 2219 noah                      777 UIC           0 :             pairs[i].key = VARDATA(in_datums[i * 2]);
 4939 tgl                       778               0 :             pairs[i].val = NULL;
 2219 noah                      779               0 :             pairs[i].keylen =
                                780               0 :                 hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
 4939 tgl                       781 LBC           0 :             pairs[i].vallen = 4;
 4939 tgl                       782 UIC           0 :             pairs[i].isnull = true;
 4939 tgl                       783 LBC           0 :             pairs[i].needfree = false;
                                784                 :         }
 4939 tgl                       785 ECB             :         else
                                786                 :         {
 2219 noah                      787 CBC          18 :             pairs[i].key = VARDATA(in_datums[i * 2]);
 2219 noah                      788 GIC          18 :             pairs[i].val = VARDATA(in_datums[i * 2 + 1]);
 2219 noah                      789 CBC          36 :             pairs[i].keylen =
                                790              18 :                 hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
                                791              36 :             pairs[i].vallen =
 2219 noah                      792 GIC          18 :                 hstoreCheckValLen(VARSIZE(in_datums[i * 2 + 1]) - VARHDRSZ);
 4939 tgl                       793              18 :             pairs[i].isnull = false;
 4939 tgl                       794 CBC          18 :             pairs[i].needfree = false;
                                795                 :         }
 4939 tgl                       796 ECB             :     }
                                797                 : 
 4939 tgl                       798 CBC           6 :     count = hstoreUniquePairs(pairs, count, &buflen);
                                799                 : 
 4939 tgl                       800 GIC           6 :     out = hstorePairs(pairs, count, buflen);
 4939 tgl                       801 ECB             : 
 4939 tgl                       802 GIC           6 :     PG_RETURN_POINTER(out);
 4939 tgl                       803 ECB             : }
                                804                 : 
                                805                 : /* most of hstore_from_record is shamelessly swiped from record_out */
                                806                 : 
                                807                 : /*
                                808                 :  * structure to cache metadata needed for record I/O
                                809                 :  */
                                810                 : typedef struct ColumnIOData
                                811                 : {
                                812                 :     Oid         column_type;
                                813                 :     Oid         typiofunc;
                                814                 :     Oid         typioparam;
 4939 tgl                       815 EUB             :     FmgrInfo    proc;
                                816                 : } ColumnIOData;
                                817                 : 
                                818                 : typedef struct RecordIOData
                                819                 : {
 4939 tgl                       820 ECB             :     Oid         record_type;
                                821                 :     int32       record_typmod;
 1991                           822                 :     /* this field is used only if target type is domain over composite: */
                                823                 :     void       *domain_info;    /* opaque cache for domain checks */
 4939                           824                 :     int         ncolumns;
 2970 tgl                       825 EUB             :     ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
                                826                 : } RecordIOData;
                                827                 : 
 4939 tgl                       828 GIC           8 : PG_FUNCTION_INFO_V1(hstore_from_record);
 4939 tgl                       829 ECB             : Datum
 4939 tgl                       830 GIC           5 : hstore_from_record(PG_FUNCTION_ARGS)
 4939 tgl                       831 EUB             : {
                                832                 :     HeapTupleHeader rec;
 3940 peter_e                   833                 :     int32       buflen;
 4939 tgl                       834                 :     HStore     *out;
 4790 bruce                     835                 :     Pairs      *pairs;
 4939 tgl                       836                 :     Oid         tupType;
                                837                 :     int32       tupTypmod;
                                838                 :     TupleDesc   tupdesc;
                                839                 :     HeapTupleData tuple;
                                840                 :     RecordIOData *my_extra;
 4939 tgl                       841 ECB             :     int         ncolumns;
 4790 bruce                     842                 :     int         i,
                                843                 :                 j;
 4939 tgl                       844                 :     Datum      *values;
                                845                 :     bool       *nulls;
                                846                 : 
 4939 tgl                       847 CBC           5 :     if (PG_ARGISNULL(0))
 4939 tgl                       848 ECB             :     {
 4790 bruce                     849 GIC           2 :         Oid         argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
                                850                 : 
                                851                 :         /*
 1991 tgl                       852 ECB             :          * We have no tuple to look at, so the only source of type info is the
                                853                 :          * argtype --- which might be domain over composite, but we don't care
                                854                 :          * here, since we have no need to be concerned about domain
                                855                 :          * constraints.  The lookup_rowtype_tupdesc_domain call below will
                                856                 :          * error out if we don't have a known composite type oid here.
                                857                 :          */
 4939 tgl                       858 GIC           2 :         tupType = argtype;
                                859               2 :         tupTypmod = -1;
                                860                 : 
                                861               2 :         rec = NULL;
                                862                 :     }
                                863                 :     else
                                864                 :     {
                                865               3 :         rec = PG_GETARG_HEAPTUPLEHEADER(0);
                                866                 : 
                                867                 :         /*
                                868                 :          * Extract type info from the tuple itself -- this will work even for
                                869                 :          * anonymous record types.
                                870                 :          */
                                871               3 :         tupType = HeapTupleHeaderGetTypeId(rec);
                                872               3 :         tupTypmod = HeapTupleHeaderGetTypMod(rec);
                                873                 :     }
                                874                 : 
 1991                           875               5 :     tupdesc = lookup_rowtype_tupdesc_domain(tupType, tupTypmod, false);
 4939                           876               5 :     ncolumns = tupdesc->natts;
                                877                 : 
                                878                 :     /*
                                879                 :      * We arrange to look up the needed I/O info just once per series of
                                880                 :      * calls, assuming the record type doesn't change underneath us.
                                881                 :      */
 4939 tgl                       882 CBC           5 :     my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
 4939 tgl                       883 GIC           5 :     if (my_extra == NULL ||
 4939 tgl                       884 LBC           0 :         my_extra->ncolumns != ncolumns)
                                885                 :     {
 4939 tgl                       886 GIC          10 :         fcinfo->flinfo->fn_extra =
                                887               5 :             MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
                                888                 :                                offsetof(RecordIOData, columns) +
 2970                           889               5 :                                ncolumns * sizeof(ColumnIOData));
 4939                           890               5 :         my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
                                891               5 :         my_extra->record_type = InvalidOid;
                                892               5 :         my_extra->record_typmod = 0;
                                893                 :     }
                                894                 : 
                                895               5 :     if (my_extra->record_type != tupType ||
 4939 tgl                       896 UIC           0 :         my_extra->record_typmod != tupTypmod)
                                897                 :     {
 4939 tgl                       898 GIC         204 :         MemSet(my_extra, 0,
                                899                 :                offsetof(RecordIOData, columns) +
                                900                 :                ncolumns * sizeof(ColumnIOData));
 4939 tgl                       901 CBC           5 :         my_extra->record_type = tupType;
 4939 tgl                       902 GIC           5 :         my_extra->record_typmod = tupTypmod;
 4939 tgl                       903 CBC           5 :         my_extra->ncolumns = ncolumns;
                                904                 :     }
                                905                 : 
 2118 tgl                       906 GIC           5 :     Assert(ncolumns <= MaxTupleAttributeNumber); /* thus, no overflow */
 4939                           907               5 :     pairs = palloc(ncolumns * sizeof(Pairs));
                                908                 : 
                                909               5 :     if (rec)
                                910                 :     {
                                911                 :         /* Build a temporary HeapTuple control structure */
 4939 tgl                       912 CBC           3 :         tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
                                913               3 :         ItemPointerSetInvalid(&(tuple.t_self));
 4939 tgl                       914 GIC           3 :         tuple.t_tableOid = InvalidOid;
 4939 tgl                       915 CBC           3 :         tuple.t_data = rec;
                                916                 : 
 4939 tgl                       917 GIC           3 :         values = (Datum *) palloc(ncolumns * sizeof(Datum));
                                918               3 :         nulls = (bool *) palloc(ncolumns * sizeof(bool));
 4939 tgl                       919 ECB             : 
                                920                 :         /* Break down the tuple into fields */
 4939 tgl                       921 GIC           3 :         heap_deform_tuple(&tuple, tupdesc, values, nulls);
                                922                 :     }
                                923                 :     else
                                924                 :     {
 4939 tgl                       925 CBC           2 :         values = NULL;
                                926               2 :         nulls = NULL;
                                927                 :     }
                                928                 : 
                                929              28 :     for (i = 0, j = 0; i < ncolumns; ++i)
 4939 tgl                       930 ECB             :     {
 4939 tgl                       931 GIC          23 :         ColumnIOData *column_info = &my_extra->columns[i];
 2058 andres                    932              23 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
                                933              23 :         Oid         column_type = att->atttypid;
                                934                 :         char       *value;
                                935                 : 
 4939 tgl                       936 ECB             :         /* Ignore dropped columns in datatype */
 2058 andres                    937 CBC          23 :         if (att->attisdropped)
 4939 tgl                       938 UBC           0 :             continue;
                                939                 : 
 2058 andres                    940 CBC          23 :         pairs[j].key = NameStr(att->attname);
                                941              23 :         pairs[j].keylen = hstoreCheckKeyLen(strlen(NameStr(att->attname)));
                                942                 : 
 4939 tgl                       943              23 :         if (!nulls || nulls[i])
 4939 tgl                       944 ECB             :         {
 4939 tgl                       945 CBC           9 :             pairs[j].val = NULL;
                                946               9 :             pairs[j].vallen = 4;
 4939 tgl                       947 GIC           9 :             pairs[j].isnull = true;
                                948               9 :             pairs[j].needfree = false;
 4939 tgl                       949 CBC           9 :             ++j;
 4939 tgl                       950 GBC           9 :             continue;
                                951                 :         }
 4939 tgl                       952 ECB             : 
                                953                 :         /*
                                954                 :          * Convert the column value to text
                                955                 :          */
 4939 tgl                       956 CBC          14 :         if (column_info->column_type != column_type)
 4939 tgl                       957 ECB             :         {
                                958                 :             bool        typIsVarlena;
                                959                 : 
 4939 tgl                       960 CBC          14 :             getTypeOutputInfo(column_type,
 4939 tgl                       961 ECB             :                               &column_info->typiofunc,
                                962                 :                               &typIsVarlena);
 4939 tgl                       963 CBC          14 :             fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
 4939 tgl                       964 GIC          14 :                           fcinfo->flinfo->fn_mcxt);
                                965              14 :             column_info->column_type = column_type;
 4939 tgl                       966 ECB             :         }
                                967                 : 
 4939 tgl                       968 CBC          14 :         value = OutputFunctionCall(&column_info->proc, values[i]);
 4939 tgl                       969 ECB             : 
 4939 tgl                       970 GIC          14 :         pairs[j].val = value;
 4939 tgl                       971 CBC          14 :         pairs[j].vallen = hstoreCheckValLen(strlen(value));
                                972              14 :         pairs[j].isnull = false;
 4939 tgl                       973 GIC          14 :         pairs[j].needfree = false;
                                974              14 :         ++j;
 6060 teodor                    975 ECB             :     }
                                976                 : 
 4939 tgl                       977 GIC           5 :     ncolumns = hstoreUniquePairs(pairs, j, &buflen);
                                978                 : 
 4939 tgl                       979 CBC           5 :     out = hstorePairs(pairs, ncolumns, buflen);
 4939 tgl                       980 ECB             : 
 4939 tgl                       981 GIC           5 :     ReleaseTupleDesc(tupdesc);
                                982                 : 
 6060 teodor                    983 CBC           5 :     PG_RETURN_POINTER(out);
                                984                 : }
 6060 teodor                    985 ECB             : 
 4939 tgl                       986                 : 
 4939 tgl                       987 CBC           8 : PG_FUNCTION_INFO_V1(hstore_populate_record);
                                988                 : Datum
 4939 tgl                       989 GIC          33 : hstore_populate_record(PG_FUNCTION_ARGS)
                                990                 : {
 4790 bruce                     991 CBC          33 :     Oid         argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
 4790 bruce                     992 EUB             :     HStore     *hs;
                                993                 :     HEntry     *entries;
 4790 bruce                     994 ECB             :     char       *ptr;
 4939 tgl                       995                 :     HeapTupleHeader rec;
                                996                 :     Oid         tupType;
                                997                 :     int32       tupTypmod;
                                998                 :     TupleDesc   tupdesc;
                                999                 :     HeapTupleData tuple;
 4790 bruce                    1000                 :     HeapTuple   rettuple;
 4939 tgl                      1001                 :     RecordIOData *my_extra;
 4790 bruce                    1002                 :     int         ncolumns;
 4939 tgl                      1003                 :     int         i;
                               1004                 :     Datum      *values;
                               1005                 :     bool       *nulls;
                               1006                 : 
 4939 tgl                      1007 GIC          33 :     if (!type_is_rowtype(argtype))
 4939 tgl                      1008 UIC           0 :         ereport(ERROR,
                               1009                 :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
 4939 tgl                      1010 ECB             :                  errmsg("first argument must be a rowtype")));
                               1011                 : 
 4939 tgl                      1012 GIC          33 :     if (PG_ARGISNULL(0))
                               1013                 :     {
 4939 tgl                      1014 CBC           8 :         if (PG_ARGISNULL(1))
 4939 tgl                      1015 UIC           0 :             PG_RETURN_NULL();
                               1016                 : 
 4939 tgl                      1017 CBC           8 :         rec = NULL;
 4939 tgl                      1018 ECB             : 
                               1019                 :         /*
                               1020                 :          * We have no tuple to look at, so the only source of type info is the
                               1021                 :          * argtype.  The lookup_rowtype_tupdesc_domain call below will error
 1991                          1022                 :          * out if we don't have a known composite type oid here.
                               1023                 :          */
 4939 tgl                      1024 CBC           8 :         tupType = argtype;
                               1025               8 :         tupTypmod = -1;
 4939 tgl                      1026 ECB             :     }
                               1027                 :     else
                               1028                 :     {
 4939 tgl                      1029 GIC          25 :         rec = PG_GETARG_HEAPTUPLEHEADER(0);
                               1030                 : 
 4939 tgl                      1031 CBC          25 :         if (PG_ARGISNULL(1))
 4939 tgl                      1032 UIC           0 :             PG_RETURN_POINTER(rec);
 4939 tgl                      1033 ECB             : 
                               1034                 :         /*
 1991                          1035                 :          * Extract type info from the tuple itself -- this will work even for
                               1036                 :          * anonymous record types.
                               1037                 :          */
 4939 tgl                      1038 GIC          25 :         tupType = HeapTupleHeaderGetTypeId(rec);
                               1039              25 :         tupTypmod = HeapTupleHeaderGetTypMod(rec);
                               1040                 :     }
 4939 tgl                      1041 ECB             : 
 2029 tgl                      1042 GIC          33 :     hs = PG_GETARG_HSTORE_P(1);
 4939 tgl                      1043 CBC          33 :     entries = ARRPTR(hs);
 4939 tgl                      1044 GIC          33 :     ptr = STRPTR(hs);
 4939 tgl                      1045 ECB             : 
                               1046                 :     /*
                               1047                 :      * if the input hstore is empty, we can only skip the rest if we were
                               1048                 :      * passed in a non-null record, since otherwise there may be issues with
                               1049                 :      * domain nulls.
                               1050                 :      */
                               1051                 : 
 4939 tgl                      1052 GIC          33 :     if (HS_COUNT(hs) == 0 && rec)
                               1053               4 :         PG_RETURN_POINTER(rec);
                               1054                 : 
                               1055                 :     /*
                               1056                 :      * Lookup the input record's tupdesc.  For the moment, we don't worry
                               1057                 :      * about whether it is a domain over composite.
                               1058                 :      */
 1991                          1059              29 :     tupdesc = lookup_rowtype_tupdesc_domain(tupType, tupTypmod, false);
 4939                          1060              29 :     ncolumns = tupdesc->natts;
 4939 tgl                      1061 ECB             : 
 4939 tgl                      1062 GBC          29 :     if (rec)
                               1063                 :     {
                               1064                 :         /* Build a temporary HeapTuple control structure */
 4939 tgl                      1065 GIC          21 :         tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
 4939 tgl                      1066 CBC          21 :         ItemPointerSetInvalid(&(tuple.t_self));
 4939 tgl                      1067 GIC          21 :         tuple.t_tableOid = InvalidOid;
 4939 tgl                      1068 CBC          21 :         tuple.t_data = rec;
 4939 tgl                      1069 EUB             :     }
                               1070                 : 
 4939 tgl                      1071 ECB             :     /*
                               1072                 :      * We arrange to look up the needed I/O info just once per series of
                               1073                 :      * calls, assuming the record type doesn't change underneath us.
                               1074                 :      */
 4939 tgl                      1075 GIC          29 :     my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
                               1076              29 :     if (my_extra == NULL ||
                               1077               4 :         my_extra->ncolumns != ncolumns)
 4939 tgl                      1078 ECB             :     {
 4939 tgl                      1079 CBC          50 :         fcinfo->flinfo->fn_extra =
 4939 tgl                      1080 GIC          25 :             MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
                               1081                 :                                offsetof(RecordIOData, columns) +
 2970                          1082              25 :                                ncolumns * sizeof(ColumnIOData));
 4939 tgl                      1083 CBC          25 :         my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
 4939 tgl                      1084 GIC          25 :         my_extra->record_type = InvalidOid;
 4939 tgl                      1085 CBC          25 :         my_extra->record_typmod = 0;
 1991 tgl                      1086 GBC          25 :         my_extra->domain_info = NULL;
                               1087                 :     }
                               1088                 : 
 4939 tgl                      1089 GIC          29 :     if (my_extra->record_type != tupType ||
                               1090               4 :         my_extra->record_typmod != tupTypmod)
                               1091                 :     {
 4939 tgl                      1092 CBC        1068 :         MemSet(my_extra, 0,
 2970 tgl                      1093 ECB             :                offsetof(RecordIOData, columns) +
                               1094                 :                ncolumns * sizeof(ColumnIOData));
 4939 tgl                      1095 GIC          25 :         my_extra->record_type = tupType;
 4939 tgl                      1096 CBC          25 :         my_extra->record_typmod = tupTypmod;
                               1097              25 :         my_extra->ncolumns = ncolumns;
 4939 tgl                      1098 ECB             :     }
                               1099                 : 
 4939 tgl                      1100 GIC          29 :     values = (Datum *) palloc(ncolumns * sizeof(Datum));
                               1101              29 :     nulls = (bool *) palloc(ncolumns * sizeof(bool));
                               1102                 : 
                               1103              29 :     if (rec)
                               1104                 :     {
                               1105                 :         /* Break down the tuple into fields */
 4939 tgl                      1106 CBC          21 :         heap_deform_tuple(&tuple, tupdesc, values, nulls);
 4939 tgl                      1107 ECB             :     }
                               1108                 :     else
                               1109                 :     {
 4939 tgl                      1110 GIC          46 :         for (i = 0; i < ncolumns; ++i)
                               1111                 :         {
                               1112              38 :             values[i] = (Datum) 0;
 4939 tgl                      1113 CBC          38 :             nulls[i] = true;
 4939 tgl                      1114 ECB             :         }
                               1115                 :     }
                               1116                 : 
 4939 tgl                      1117 GIC         163 :     for (i = 0; i < ncolumns; ++i)
                               1118                 :     {
 4939 tgl                      1119 CBC         141 :         ColumnIOData *column_info = &my_extra->columns[i];
 2058 andres                   1120             141 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
                               1121             141 :         Oid         column_type = att->atttypid;
 4939 tgl                      1122 ECB             :         char       *value;
                               1123                 :         int         idx;
                               1124                 :         int         vallen;
                               1125                 : 
                               1126                 :         /* Ignore dropped columns in datatype */
 2058 andres                   1127 GIC         141 :         if (att->attisdropped)
                               1128                 :         {
 4939 tgl                      1129 LBC           0 :             nulls[i] = true;
                               1130               0 :             continue;
 4939 tgl                      1131 ECB             :         }
                               1132                 : 
 4939 tgl                      1133 CBC         141 :         idx = hstoreFindKey(hs, 0,
 2058 andres                   1134             141 :                             NameStr(att->attname),
 2058 andres                   1135 GIC         141 :                             strlen(NameStr(att->attname)));
 4790 bruce                    1136 ECB             : 
 4939 tgl                      1137                 :         /*
 4790 bruce                    1138                 :          * we can't just skip here if the key wasn't found since we might have
                               1139                 :          * a domain to deal with. If we were passed in a non-null record
                               1140                 :          * datum, we assume that the existing values are valid (if they're
                               1141                 :          * not, then it's not our fault), but if we were passed in a null,
                               1142                 :          * then every field which we don't populate needs to be run through
                               1143                 :          * the input function just in case it's a domain type.
 4939 tgl                      1144                 :          */
 4939 tgl                      1145 GIC         141 :         if (idx < 0 && rec)
 4939 tgl                      1146 CBC          79 :             continue;
                               1147                 : 
                               1148                 :         /*
 4939 tgl                      1149 ECB             :          * Prepare to convert the column value from text
                               1150                 :          */
 4939 tgl                      1151 CBC          62 :         if (column_info->column_type != column_type)
                               1152                 :         {
 4939 tgl                      1153 GIC          61 :             getTypeInputInfo(column_type,
 4939 tgl                      1154 ECB             :                              &column_info->typiofunc,
                               1155                 :                              &column_info->typioparam);
 4939 tgl                      1156 GIC          61 :             fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
 4939 tgl                      1157 CBC          61 :                           fcinfo->flinfo->fn_mcxt);
 4939 tgl                      1158 GIC          61 :             column_info->column_type = column_type;
                               1159                 :         }
 4939 tgl                      1160 ECB             : 
 2698 tgl                      1161 GIC          62 :         if (idx < 0 || HSTORE_VALISNULL(entries, idx))
                               1162                 :         {
                               1163                 :             /*
 4790 bruce                    1164 ECB             :              * need InputFunctionCall to happen even for nulls, so that domain
                               1165                 :              * checks are done
 4939 tgl                      1166                 :              */
 4939 tgl                      1167 CBC          36 :             values[i] = InputFunctionCall(&column_info->proc, NULL,
                               1168                 :                                           column_info->typioparam,
                               1169                 :                                           att->atttypmod);
 4939 tgl                      1170 GIC          29 :             nulls[i] = true;
 4939 tgl                      1171 ECB             :         }
                               1172                 :         else
                               1173                 :         {
 2698 tgl                      1174 CBC          26 :             vallen = HSTORE_VALLEN(entries, idx);
 4939                          1175              26 :             value = palloc(1 + vallen);
 2698 tgl                      1176 GIC          26 :             memcpy(value, HSTORE_VAL(entries, ptr, idx), vallen);
 4939                          1177              26 :             value[vallen] = 0;
                               1178                 : 
                               1179              26 :             values[i] = InputFunctionCall(&column_info->proc, value,
                               1180                 :                                           column_info->typioparam,
 2058 andres                   1181 ECB             :                                           att->atttypmod);
 4939 tgl                      1182 GIC          26 :             nulls[i] = false;
 4939 tgl                      1183 EUB             :         }
                               1184                 :     }
                               1185                 : 
 4939 tgl                      1186 GIC          22 :     rettuple = heap_form_tuple(tupdesc, values, nulls);
 4939 tgl                      1187 ECB             : 
 1991                          1188                 :     /*
                               1189                 :      * If the target type is domain over composite, all we know at this point
                               1190                 :      * is that we've made a valid value of the base composite type.  Must
                               1191                 :      * check domain constraints before deciding we're done.
                               1192                 :      */
 1991 tgl                      1193 GIC          22 :     if (argtype != tupdesc->tdtypeid)
 1991 tgl                      1194 UIC           0 :         domain_check(HeapTupleGetDatum(rettuple), false,
                               1195                 :                      argtype,
                               1196                 :                      &my_extra->domain_info,
                               1197               0 :                      fcinfo->flinfo->fn_mcxt);
                               1198                 : 
 4939 tgl                      1199 CBC          22 :     ReleaseTupleDesc(tupdesc);
 4939 tgl                      1200 ECB             : 
 4939 tgl                      1201 GIC          22 :     PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
                               1202                 : }
                               1203                 : 
                               1204                 : 
 6031 bruce                    1205 ECB             : static char *
 6031 bruce                    1206 GIC         487 : cpw(char *dst, char *src, int len)
 6031 bruce                    1207 ECB             : {
 6031 bruce                    1208 GIC         487 :     char       *ptr = src;
                               1209                 : 
 6031 bruce                    1210 CBC        1363 :     while (ptr - src < len)
 6031 bruce                    1211 ECB             :     {
 6031 bruce                    1212 CBC         876 :         if (*ptr == '"' || *ptr == '\\')
 6031 bruce                    1213 GIC           3 :             *dst++ = '\\';
 6060 teodor                   1214             876 :         *dst++ = *ptr++;
 6060 teodor                   1215 ECB             :     }
 6060 teodor                   1216 GIC         487 :     return dst;
                               1217                 : }
                               1218                 : 
                               1219              16 : PG_FUNCTION_INFO_V1(hstore_out);
                               1220                 : Datum
 6031 bruce                    1221 CBC         138 : hstore_out(PG_FUNCTION_ARGS)
                               1222                 : {
 2029 tgl                      1223 GIC         138 :     HStore     *in = PG_GETARG_HSTORE_P(0);
 6031 bruce                    1224 ECB             :     int         buflen,
                               1225                 :                 i;
 4790 bruce                    1226 GIC         138 :     int         count = HS_COUNT(in);
                               1227                 :     char       *out,
 6031 bruce                    1228 ECB             :                *ptr;
 6031 bruce                    1229 CBC         138 :     char       *base = STRPTR(in);
                               1230             138 :     HEntry     *entries = ARRPTR(in);
 6031 bruce                    1231 ECB             : 
 4939 tgl                      1232 GIC         138 :     if (count == 0)
 3380 peter_e                  1233 CBC          13 :         PG_RETURN_CSTRING(pstrdup(""));
                               1234                 : 
 4939 tgl                      1235 GIC         125 :     buflen = 0;
 4939 tgl                      1236 ECB             : 
                               1237                 :     /*
                               1238                 :      * this loop overestimates due to pessimistic assumptions about escaping,
                               1239                 :      * so very large hstore values can't be output. this could be fixed, but
 4790 bruce                    1240                 :      * many other data types probably have the same issue. This replaced code
                               1241                 :      * that used the original varlena size for calculations, which was wrong
                               1242                 :      * in some subtle ways.
                               1243                 :      */
                               1244                 : 
 4939 tgl                      1245 GIC         386 :     for (i = 0; i < count; i++)
                               1246                 :     {
 4939 tgl                      1247 ECB             :         /* include "" and => and comma-space */
 2698 tgl                      1248 GBC         261 :         buflen += 6 + 2 * HSTORE_KEYLEN(entries, i);
                               1249                 :         /* include "" only if nonnull */
 2698 tgl                      1250 GIC         487 :         buflen += 2 + (HSTORE_VALISNULL(entries, i)
 4939 tgl                      1251 EUB             :                        ? 2
 2698 tgl                      1252 GIC         226 :                        : 2 * HSTORE_VALLEN(entries, i));
 4939 tgl                      1253 ECB             :     }
                               1254                 : 
 6031 bruce                    1255 CBC         125 :     out = ptr = palloc(buflen);
                               1256                 : 
 4939 tgl                      1257 GIC         386 :     for (i = 0; i < count; i++)
                               1258                 :     {
 6031 bruce                    1259             261 :         *ptr++ = '"';
 2698 tgl                      1260 CBC         261 :         ptr = cpw(ptr, HSTORE_KEY(entries, base, i), HSTORE_KEYLEN(entries, i));
 6031 bruce                    1261 GIC         261 :         *ptr++ = '"';
 6031 bruce                    1262 CBC         261 :         *ptr++ = '=';
 6031 bruce                    1263 GIC         261 :         *ptr++ = '>';
 2698 tgl                      1264 CBC         261 :         if (HSTORE_VALISNULL(entries, i))
                               1265                 :         {
 6031 bruce                    1266              35 :             *ptr++ = 'N';
                               1267              35 :             *ptr++ = 'U';
                               1268              35 :             *ptr++ = 'L';
 6031 bruce                    1269 GIC          35 :             *ptr++ = 'L';
 6031 bruce                    1270 ECB             :         }
                               1271                 :         else
                               1272                 :         {
 6031 bruce                    1273 CBC         226 :             *ptr++ = '"';
 2698 tgl                      1274 GIC         226 :             ptr = cpw(ptr, HSTORE_VAL(entries, base, i), HSTORE_VALLEN(entries, i));
 6031 bruce                    1275 CBC         226 :             *ptr++ = '"';
                               1276                 :         }
 6060 teodor                   1277 ECB             : 
 4939 tgl                      1278 GIC         261 :         if (i + 1 != count)
                               1279                 :         {
 6031 bruce                    1280 CBC         136 :             *ptr++ = ',';
 6031 bruce                    1281 GIC         136 :             *ptr++ = ' ';
                               1282                 :         }
 6060 teodor                   1283 ECB             :     }
 6031 bruce                    1284 CBC         125 :     *ptr = '\0';
                               1285                 : 
 6060 teodor                   1286             125 :     PG_RETURN_CSTRING(out);
 6060 teodor                   1287 ECB             : }
                               1288                 : 
 4939 tgl                      1289                 : 
 4939 tgl                      1290 GIC           7 : PG_FUNCTION_INFO_V1(hstore_send);
                               1291                 : Datum
 4939 tgl                      1292 UIC           0 : hstore_send(PG_FUNCTION_ARGS)
                               1293                 : {
 2029                          1294               0 :     HStore     *in = PG_GETARG_HSTORE_P(0);
                               1295                 :     int         i;
 4790 bruce                    1296               0 :     int         count = HS_COUNT(in);
 4939 tgl                      1297               0 :     char       *base = STRPTR(in);
                               1298               0 :     HEntry     *entries = ARRPTR(in);
 4939 tgl                      1299 ECB             :     StringInfoData buf;
                               1300                 : 
 4939 tgl                      1301 UIC           0 :     pq_begintypsend(&buf);
 4939 tgl                      1302 ECB             : 
 2006 andres                   1303 UIC           0 :     pq_sendint32(&buf, count);
 4939 tgl                      1304 ECB             : 
 4939 tgl                      1305 UIC           0 :     for (i = 0; i < count; i++)
 4939 tgl                      1306 ECB             :     {
 2698 tgl                      1307 UIC           0 :         int32       keylen = HSTORE_KEYLEN(entries, i);
                               1308                 : 
 2006 andres                   1309 LBC           0 :         pq_sendint32(&buf, keylen);
 2698 tgl                      1310 UIC           0 :         pq_sendtext(&buf, HSTORE_KEY(entries, base, i), keylen);
 2698 tgl                      1311 LBC           0 :         if (HSTORE_VALISNULL(entries, i))
                               1312                 :         {
 2006 andres                   1313               0 :             pq_sendint32(&buf, -1);
 4939 tgl                      1314 ECB             :         }
                               1315                 :         else
                               1316                 :         {
 2698 tgl                      1317 LBC           0 :             int32       vallen = HSTORE_VALLEN(entries, i);
 4790 bruce                    1318 ECB             : 
 2006 andres                   1319 UIC           0 :             pq_sendint32(&buf, vallen);
 2698 tgl                      1320 LBC           0 :             pq_sendtext(&buf, HSTORE_VAL(entries, base, i), vallen);
 4939 tgl                      1321 ECB             :         }
                               1322                 :     }
                               1323                 : 
 4939 tgl                      1324 UIC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
                               1325                 : }
                               1326                 : 
 3682 andrew                   1327 ECB             : 
                               1328                 : /*
                               1329                 :  * hstore_to_json_loose
                               1330                 :  *
                               1331                 :  * This is a heuristic conversion to json which treats
                               1332                 :  * 't' and 'f' as booleans and strings that look like numbers as numbers,
                               1333                 :  * as long as they don't start with a leading zero followed by another digit
                               1334                 :  * (think zip codes or phone numbers starting with 0).
                               1335                 :  */
 3682 andrew                   1336 GIC           8 : PG_FUNCTION_INFO_V1(hstore_to_json_loose);
                               1337                 : Datum
 3682 andrew                   1338 CBC           3 : hstore_to_json_loose(PG_FUNCTION_ARGS)
                               1339                 : {
 2029 tgl                      1340               3 :     HStore     *in = PG_GETARG_HSTORE_P(0);
                               1341                 :     int         i;
 3682 andrew                   1342 GIC           3 :     int         count = HS_COUNT(in);
                               1343               3 :     char       *base = STRPTR(in);
 3682 andrew                   1344 CBC           3 :     HEntry     *entries = ARRPTR(in);
                               1345                 :     StringInfoData tmp,
 3682 andrew                   1346 EUB             :                 dst;
                               1347                 : 
 3682 andrew                   1348 GBC           3 :     if (count == 0)
 3260 bruce                    1349 UIC           0 :         PG_RETURN_TEXT_P(cstring_to_text_with_len("{}", 2));
 3682 andrew                   1350 EUB             : 
 3334 heikki.linnakangas       1351 GBC           3 :     initStringInfo(&tmp);
                               1352               3 :     initStringInfo(&dst);
                               1353                 : 
 3334 heikki.linnakangas       1354 GIC           3 :     appendStringInfoChar(&dst, '{');
 3682 andrew                   1355 EUB             : 
 3682 andrew                   1356 GIC          25 :     for (i = 0; i < count; i++)
 3682 andrew                   1357 EUB             :     {
 3334 heikki.linnakangas       1358 GIC          22 :         resetStringInfo(&tmp);
 2698 tgl                      1359 GBC          22 :         appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
 2698 tgl                      1360 GIC          22 :                                HSTORE_KEYLEN(entries, i));
 3334 heikki.linnakangas       1361 GBC          22 :         escape_json(&dst, tmp.data);
 3334 heikki.linnakangas       1362 GIC          22 :         appendStringInfoString(&dst, ": ");
 2698 tgl                      1363 GBC          22 :         if (HSTORE_VALISNULL(entries, i))
 3334 heikki.linnakangas       1364               2 :             appendStringInfoString(&dst, "null");
 3682 andrew                   1365 EUB             :         /* guess that values of 't' or 'f' are booleans */
 2698 tgl                      1366 GIC          20 :         else if (HSTORE_VALLEN(entries, i) == 1 &&
 2698 tgl                      1367 GBC           6 :                  *(HSTORE_VAL(entries, base, i)) == 't')
 3334 heikki.linnakangas       1368 GIC           2 :             appendStringInfoString(&dst, "true");
 2698 tgl                      1369              18 :         else if (HSTORE_VALLEN(entries, i) == 1 &&
                               1370               4 :                  *(HSTORE_VAL(entries, base, i)) == 'f')
 3334 heikki.linnakangas       1371 GBC           1 :             appendStringInfoString(&dst, "false");
                               1372                 :         else
 3682 andrew                   1373 EUB             :         {
 3334 heikki.linnakangas       1374 GBC          17 :             resetStringInfo(&tmp);
 2698 tgl                      1375 GIC          17 :             appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
                               1376              17 :                                    HSTORE_VALLEN(entries, i));
 3051 andrew                   1377              17 :             if (IsValidJsonNumber(tmp.data, tmp.len))
 3334 heikki.linnakangas       1378 GBC          12 :                 appendBinaryStringInfo(&dst, tmp.data, tmp.len);
                               1379                 :             else
 3334 heikki.linnakangas       1380 GIC           5 :                 escape_json(&dst, tmp.data);
                               1381                 :         }
                               1382                 : 
 3682 andrew                   1383              22 :         if (i + 1 != count)
 3334 heikki.linnakangas       1384              19 :             appendStringInfoString(&dst, ", ");
                               1385                 :     }
                               1386               3 :     appendStringInfoChar(&dst, '}');
                               1387                 : 
  215 drowley                  1388 GNC           3 :     PG_RETURN_TEXT_P(cstring_to_text_with_len(dst.data, dst.len));
                               1389                 : }
 3682 andrew                   1390 ECB             : 
 3682 andrew                   1391 GIC           8 : PG_FUNCTION_INFO_V1(hstore_to_json);
 3682 andrew                   1392 ECB             : Datum
 3682 andrew                   1393 GIC           4 : hstore_to_json(PG_FUNCTION_ARGS)
 3682 andrew                   1394 ECB             : {
 2029 tgl                      1395 GIC           4 :     HStore     *in = PG_GETARG_HSTORE_P(0);
 3334 heikki.linnakangas       1396 ECB             :     int         i;
 3682 andrew                   1397 CBC           4 :     int         count = HS_COUNT(in);
                               1398               4 :     char       *base = STRPTR(in);
 3682 andrew                   1399 GIC           4 :     HEntry     *entries = ARRPTR(in);
                               1400                 :     StringInfoData tmp,
                               1401                 :                 dst;
 3682 andrew                   1402 ECB             : 
 3682 andrew                   1403 GBC           4 :     if (count == 0)
 3260 bruce                    1404 UIC           0 :         PG_RETURN_TEXT_P(cstring_to_text_with_len("{}", 2));
 3682 andrew                   1405 ECB             : 
 3334 heikki.linnakangas       1406 CBC           4 :     initStringInfo(&tmp);
 3334 heikki.linnakangas       1407 GIC           4 :     initStringInfo(&dst);
 3682 andrew                   1408 ECB             : 
 3334 heikki.linnakangas       1409 GIC           4 :     appendStringInfoChar(&dst, '{');
 3682 andrew                   1410 ECB             : 
 3682 andrew                   1411 GIC          32 :     for (i = 0; i < count; i++)
 3682 andrew                   1412 ECB             :     {
 3334 heikki.linnakangas       1413 CBC          28 :         resetStringInfo(&tmp);
 2698 tgl                      1414              28 :         appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
                               1415              28 :                                HSTORE_KEYLEN(entries, i));
 3334 heikki.linnakangas       1416              28 :         escape_json(&dst, tmp.data);
                               1417              28 :         appendStringInfoString(&dst, ": ");
 2698 tgl                      1418              28 :         if (HSTORE_VALISNULL(entries, i))
 3334 heikki.linnakangas       1419 GIC           3 :             appendStringInfoString(&dst, "null");
 3682 andrew                   1420 ECB             :         else
                               1421                 :         {
 3334 heikki.linnakangas       1422 CBC          25 :             resetStringInfo(&tmp);
 2698 tgl                      1423              25 :             appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
                               1424              25 :                                    HSTORE_VALLEN(entries, i));
 3334 heikki.linnakangas       1425              25 :             escape_json(&dst, tmp.data);
                               1426                 :         }
                               1427                 : 
 3682 andrew                   1428              28 :         if (i + 1 != count)
 3334 heikki.linnakangas       1429              24 :             appendStringInfoString(&dst, ", ");
 3682 andrew                   1430 ECB             :     }
 3334 heikki.linnakangas       1431 CBC           4 :     appendStringInfoChar(&dst, '}');
 3682 andrew                   1432 ECB             : 
  215 drowley                  1433 GNC           4 :     PG_RETURN_TEXT_P(cstring_to_text_with_len(dst.data, dst.len));
 3682 andrew                   1434 ECB             : }
                               1435                 : 
 3304 andrew                   1436 GIC           8 : PG_FUNCTION_INFO_V1(hstore_to_jsonb);
 3304 andrew                   1437 ECB             : Datum
 3304 andrew                   1438 CBC           2 : hstore_to_jsonb(PG_FUNCTION_ARGS)
                               1439                 : {
 2029 tgl                      1440               2 :     HStore     *in = PG_GETARG_HSTORE_P(0);
                               1441                 :     int         i;
 3304 andrew                   1442               2 :     int         count = HS_COUNT(in);
 3304 andrew                   1443 GIC           2 :     char       *base = STRPTR(in);
                               1444               2 :     HEntry     *entries = ARRPTR(in);
 3304 andrew                   1445 CBC           2 :     JsonbParseState *state = NULL;
                               1446                 :     JsonbValue *res;
 3304 andrew                   1447 ECB             : 
 3008 heikki.linnakangas       1448 GIC           2 :     (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
 3304 andrew                   1449 ECB             : 
 3304 andrew                   1450 GIC          16 :     for (i = 0; i < count; i++)
 3304 andrew                   1451 ECB             :     {
 3260 bruce                    1452                 :         JsonbValue  key,
                               1453                 :                     val;
                               1454                 : 
 3304 andrew                   1455 GIC          14 :         key.type = jbvString;
 2698 tgl                      1456              14 :         key.val.string.len = HSTORE_KEYLEN(entries, i);
 2698 tgl                      1457 CBC          14 :         key.val.string.val = HSTORE_KEY(entries, base, i);
 3304 andrew                   1458 EUB             : 
 3008 heikki.linnakangas       1459 GIC          14 :         (void) pushJsonbValue(&state, WJB_KEY, &key);
 3304 andrew                   1460 ECB             : 
 2698 tgl                      1461 CBC          14 :         if (HSTORE_VALISNULL(entries, i))
                               1462                 :         {
 3304 andrew                   1463               2 :             val.type = jbvNull;
                               1464                 :         }
 3304 andrew                   1465 ECB             :         else
                               1466                 :         {
 3304 andrew                   1467 CBC          12 :             val.type = jbvString;
 2698 tgl                      1468              12 :             val.val.string.len = HSTORE_VALLEN(entries, i);
                               1469              12 :             val.val.string.val = HSTORE_VAL(entries, base, i);
 3304 andrew                   1470 ECB             :         }
 3008 heikki.linnakangas       1471 CBC          14 :         (void) pushJsonbValue(&state, WJB_VALUE, &val);
 3304 andrew                   1472 ECB             :     }
                               1473                 : 
 3304 andrew                   1474 GIC           2 :     res = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
                               1475                 : 
 3304 andrew                   1476 CBC           2 :     PG_RETURN_POINTER(JsonbValueToJsonb(res));
 3304 andrew                   1477 ECB             : }
                               1478                 : 
 3304 andrew                   1479 CBC           8 : PG_FUNCTION_INFO_V1(hstore_to_jsonb_loose);
                               1480                 : Datum
 3304 andrew                   1481 GIC           1 : hstore_to_jsonb_loose(PG_FUNCTION_ARGS)
 3304 andrew                   1482 ECB             : {
 2029 tgl                      1483 CBC           1 :     HStore     *in = PG_GETARG_HSTORE_P(0);
                               1484                 :     int         i;
 3304 andrew                   1485               1 :     int         count = HS_COUNT(in);
 3304 andrew                   1486 GIC           1 :     char       *base = STRPTR(in);
 3304 andrew                   1487 CBC           1 :     HEntry     *entries = ARRPTR(in);
 3304 andrew                   1488 GIC           1 :     JsonbParseState *state = NULL;
                               1489                 :     JsonbValue *res;
 3304 andrew                   1490 ECB             :     StringInfoData tmp;
                               1491                 : 
 3304 andrew                   1492 CBC           1 :     initStringInfo(&tmp);
                               1493                 : 
 3008 heikki.linnakangas       1494               1 :     (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
                               1495                 : 
 3304 andrew                   1496               9 :     for (i = 0; i < count; i++)
 3304 andrew                   1497 ECB             :     {
 3260 bruce                    1498                 :         JsonbValue  key,
                               1499                 :                     val;
                               1500                 : 
 3304 andrew                   1501 GIC           8 :         key.type = jbvString;
 2698 tgl                      1502 CBC           8 :         key.val.string.len = HSTORE_KEYLEN(entries, i);
 2698 tgl                      1503 GIC           8 :         key.val.string.val = HSTORE_KEY(entries, base, i);
 3304 andrew                   1504 ECB             : 
 3008 heikki.linnakangas       1505 GIC           8 :         (void) pushJsonbValue(&state, WJB_KEY, &key);
                               1506                 : 
 2698 tgl                      1507               8 :         if (HSTORE_VALISNULL(entries, i))
                               1508                 :         {
 3304 andrew                   1509 CBC           1 :             val.type = jbvNull;
 3304 andrew                   1510 ECB             :         }
                               1511                 :         /* guess that values of 't' or 'f' are booleans */
 2698 tgl                      1512 GIC           7 :         else if (HSTORE_VALLEN(entries, i) == 1 &&
 2698 tgl                      1513 CBC           2 :                  *(HSTORE_VAL(entries, base, i)) == 't')
                               1514                 :         {
 3304 andrew                   1515               1 :             val.type = jbvBool;
 3294 tgl                      1516 GIC           1 :             val.val.boolean = true;
 3304 andrew                   1517 ECB             :         }
 2698 tgl                      1518 GIC           6 :         else if (HSTORE_VALLEN(entries, i) == 1 &&
                               1519               1 :                  *(HSTORE_VAL(entries, base, i)) == 'f')
                               1520                 :         {
 3304 andrew                   1521 LBC           0 :             val.type = jbvBool;
 3294 tgl                      1522               0 :             val.val.boolean = false;
 3304 andrew                   1523 ECB             :         }
                               1524                 :         else
                               1525                 :         {
 3304 andrew                   1526 GIC           6 :             resetStringInfo(&tmp);
 2698 tgl                      1527               6 :             appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
 2698 tgl                      1528 CBC           6 :                                    HSTORE_VALLEN(entries, i));
 2622 tgl                      1529 GIC           6 :             if (IsValidJsonNumber(tmp.data, tmp.len))
 3304 andrew                   1530 ECB             :             {
                               1531                 :                 Datum       numd;
                               1532                 : 
 3304 andrew                   1533 CBC           4 :                 val.type = jbvNumeric;
 1803 tgl                      1534 GIC           4 :                 numd = DirectFunctionCall3(numeric_in,
 1803 tgl                      1535 ECB             :                                            CStringGetDatum(tmp.data),
                               1536                 :                                            ObjectIdGetDatum(InvalidOid),
                               1537                 :                                            Int32GetDatum(-1));
 1803 tgl                      1538 GIC           4 :                 val.val.numeric = DatumGetNumeric(numd);
 3304 andrew                   1539 ECB             :             }
                               1540                 :             else
                               1541                 :             {
 3304 andrew                   1542 CBC           2 :                 val.type = jbvString;
 2698 tgl                      1543 GIC           2 :                 val.val.string.len = HSTORE_VALLEN(entries, i);
                               1544               2 :                 val.val.string.val = HSTORE_VAL(entries, base, i);
                               1545                 :             }
 3304 andrew                   1546 ECB             :         }
 3008 heikki.linnakangas       1547 GIC           8 :         (void) pushJsonbValue(&state, WJB_VALUE, &val);
 3304 andrew                   1548 ECB             :     }
                               1549                 : 
 3304 andrew                   1550 CBC           1 :     res = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
                               1551                 : 
 3304 andrew                   1552 GIC           1 :     PG_RETURN_POINTER(JsonbValueToJsonb(res));
                               1553                 : }
        

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