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