PostgreSQL Source Code: src/backend/utils/adt/jsonfuncs.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17#include <limits.h>
18
33#include "utils/fmgroids.h"
42
43
44#define JB_PATH_CREATE 0x0001
45#define JB_PATH_DELETE 0x0002
46#define JB_PATH_REPLACE 0x0004
47#define JB_PATH_INSERT_BEFORE 0x0008
48#define JB_PATH_INSERT_AFTER 0x0010
49#define JB_PATH_CREATE_OR_INSERT \
50 (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
51#define JB_PATH_FILL_GAPS 0x0020
52#define JB_PATH_CONSISTENT_POSITION 0x0040
53
54
56{
63
64
66{
69
70 void *action_state;
72
74
75
77{
81
82 void *action_state;
84
85
87{
94 char **path_names;
98
100
101
103{
107
108
110{
120
121
123{
134
135
137{
145
146
148{
153
154
156{
160
161
164
165
167{
172
173
175{
176
177
178
179
182
185
186 void *domain_info;
188
189
191{
195 void *domain_info;
197
198
200{
207
208
209
210
212{
217
218 union
219 {
224
225};
226
227
229{
234};
235
236
238{
243
244
246{
257
258
260{
271
272
274{
277 const char *element_start;
279
282
283
285{
291
292
294{
296 union
297 {
298 struct
299 {
304
308
310{
312 union
313 {
318
319
320#define JsValueIsNull(jsv) \
321 ((jsv)->is_json ? \
322 (!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
323 (!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
324
325#define JsValueIsString(jsv) \
326 ((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
327 : ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
328
329#define JsObjectIsEmpty(jso) \
330 ((jso)->is_json \
331 ? hash_get_num_entries((jso)->val.json_hash) == 0 \
332 : ((jso)->val.jsonb_cont == NULL || \
333 JsonContainerSize((jso)->val.jsonb_cont) == 0))
334
335#define JsObjectFree(jso) \
336 do { \
337 if ((jso)->is_json) \
338 hash_destroy((jso)->val.json_hash); \
339 } while (0)
340
342
343
347
348
358
359
361static text *get_worker(text *json, char **tpath, int *ipath, int npath,
362 bool normalize_results);
365
366
370
371
374 bool as_text);
375
376
381
382
384 bool as_text);
386 bool as_text);
387
388
393
394
396 Node *escontext);
397
398
404
405
410
411
419
420
428
429
431 bool is_json, bool have_record_arg);
433 bool is_json, bool have_record_arg,
434 Node *escontext);
435
436
450 Node *escontext);
452 bool *isnull, Node *escontext, bool omit_quotes);
457 JsValue *jsv, bool *isnull, Node *escontext,
458 bool omit_scalar_quotes);
464 int ndim);
471 bool *isnull,
472 Node *escontext);
475 Node *escontext, bool omit_quotes);
476
477
481 const bool *path_nulls, int path_len,
483 int op_type);
485 const bool *path_nulls, int path_len, JsonbInState *st,
486 int level,
489 const bool *path_nulls, int path_len, JsonbInState *st,
490 int level,
492
493
496
497
505
506
507
508
509
510
511
512
513
514
515
516
517
518bool
520 Node *escontext)
521{
523
526 {
528 return false;
529 }
530 return true;
531}
532
533
534
535
536
537
538
541{
542
543
544
545
547
552 need_escapes);
553}
554
555
556
557
558
559
560
561
562
563
564
565
566
569{
572
574 {
577 bool skipNested = false;
581
584 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
585 errmsg("cannot call %s on a scalar",
586 "jsonb_object_keys")));
589 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
590 errmsg("cannot call %s on an array",
591 "jsonb_object_keys")));
592
595
597
599 state->result_count = 0;
600 state->sent_count = 0;
602
604
606 {
607 skipNested = true;
608
610 {
611 char *cstr;
612
613 cstr = palloc(v.val.string.len + 1 * sizeof(char));
614 memcpy(cstr, v.val.string.val, v.val.string.len);
615 cstr[v.val.string.len] = '\0';
616 state->result[state->result_count++] = cstr;
617 }
618 }
619
622 }
623
626
628 {
629 char *nxt = state->result[state->sent_count++];
630
632 }
633
635}
636
637
638
639
640void
642 Node *escontext)
643{
648 (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
649 errmsg("unsupported Unicode escape sequence"),
653 {
654
656 elog(ERROR, "JSON semantic action function did not provide error information");
657 }
658 else
660 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
661 errmsg("invalid input syntax for type %s", "json"),
664}
665
666
667
668
669
670
671
672
673
674
675
676static int
678{
679 const char *context_start;
680 const char *context_end;
681 const char *line_start;
682 char *ctxt;
683 int ctxtlen;
684 const char *prefix;
685 const char *suffix;
686
687
689 context_start = line_start;
691 Assert(context_end >= context_start);
692
693
694 while (context_end - context_start >= 50)
695 {
696
698 context_start += pg_mblen(context_start);
699 else
700 context_start++;
701 }
702
703
704
705
706
707
708 if (context_start - line_start <= 3)
709 context_start = line_start;
710
711
712 ctxtlen = context_end - context_start;
713 ctxt = palloc(ctxtlen + 1);
714 memcpy(ctxt, context_start, ctxtlen);
715 ctxt[ctxtlen] = '\0';
716
717
718
719
720
721 prefix = (context_start > line_start) ? "..." : "";
724 *context_end != '\n' && *context_end != '\r') ? "..." : "";
725
726 return errcontext("JSON data, line %d: %s%s%s",
728}
729
730
733{
736
738 {
743
746
749
751 state->result_size = 256;
752 state->result_count = 0;
753 state->sent_count = 0;
755
760
761
763
764
767
770 }
771
774
776 {
777 char *nxt = state->result[state->sent_count++];
778
780 }
781
783}
784
787{
789
790
793
794
796 {
798 _state->result = (char **)
800 }
801
802
804
806}
807
810{
812
813
816 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
817 errmsg("cannot call %s on an array",
818 "json_object_keys")));
819
821}
822
825{
827
828
831 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
832 errmsg("cannot call %s on a scalar",
833 "json_object_keys")));
834
836}
837
838
839
840
841
842
843
844
847{
851 text *result;
852
853 result = get_worker(json, &fnamestr, NULL, 1, false);
854
855 if (result != NULL)
857 else
859}
860
863{
868
871
875 &vbuf);
876
877 if (v != NULL)
879
881}
882
885{
889 text *result;
890
891 result = get_worker(json, &fnamestr, NULL, 1, true);
892
893 if (result != NULL)
895 else
897}
898
901{
906
909
913 &vbuf);
914
917
919}
920
923{
926 text *result;
927
929
930 if (result != NULL)
932 else
934}
935
938{
942
945
946
948 {
950
953 else
955 }
956
958 if (v != NULL)
960
962}
963
966{
969 text *result;
970
972
973 if (result != NULL)
975 else
977}
978
981{
985
988
989
991 {
993
996 else
998 }
999
1001
1004
1006}
1007
1010{
1012}
1013
1016{
1018}
1019
1020
1021
1022
1025{
1028 text *result;
1029 Datum *pathtext;
1030 bool *pathnulls;
1031 int npath;
1032 char **tpath;
1033 int *ipath;
1034 int i;
1035
1036
1037
1038
1039
1040
1041
1042
1045
1047
1050
1051 for (i = 0; i < npath; i++)
1052 {
1055
1056
1057
1058
1059
1060
1061 if (*tpath[i] != '\0')
1062 {
1063 int ind;
1064 char *endptr;
1065
1066 errno = 0;
1068 if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
1069 ipath[i] = INT_MIN;
1070 else
1072 }
1073 else
1074 ipath[i] = INT_MIN;
1075 }
1076
1077 result = get_worker(json, tpath, ipath, npath, as_text);
1078
1079 if (result != NULL)
1081 else
1083}
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102static text *
1104 char **tpath,
1105 int *ipath,
1106 int npath,
1107 bool normalize_results)
1108{
1111
1113
1115
1116
1117 state->normalize_results = normalize_results;
1118 state->npath = npath;
1119 state->path_names = tpath;
1120 state->path_indexes = ipath;
1123
1124 if (npath > 0)
1125 state->pathok[0] = true;
1126
1128
1129
1130
1131
1132
1134 if (npath == 0)
1135 {
1140 }
1141 if (tpath != NULL)
1142 {
1145 }
1146 if (ipath != NULL)
1147 {
1151 }
1152
1155
1156 return state->tresult;
1157}
1158
1161{
1164
1165 if (lex_level == 0 && _state->npath == 0)
1166 {
1167
1168
1169
1170
1171
1173 }
1174
1176}
1177
1180{
1183
1184 if (lex_level == 0 && _state->npath == 0)
1185 {
1186
1189
1191 }
1192
1194}
1195
1198{
1200 bool get_next = false;
1202
1203 if (lex_level <= _state->npath &&
1204 _state->pathok[lex_level - 1] &&
1206 _state->path_names[lex_level - 1] != NULL &&
1207 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1208 {
1209 if (lex_level < _state->npath)
1210 {
1211
1212 _state->pathok[lex_level] = true;
1213 }
1214 else
1215 {
1216
1217 get_next = true;
1218 }
1219 }
1220
1221 if (get_next)
1222 {
1223
1226
1229 {
1230
1232 }
1233 else
1234 {
1235
1237 }
1238 }
1239
1241}
1242
1245{
1247 bool get_last = false;
1249
1250
1251 if (lex_level <= _state->npath &&
1252 _state->pathok[lex_level - 1] &&
1254 _state->path_names[lex_level - 1] != NULL &&
1255 strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1256 {
1257 if (lex_level < _state->npath)
1258 {
1259
1260 _state->pathok[lex_level] = false;
1261 }
1262 else
1263 {
1264
1265 get_last = true;
1266 }
1267 }
1268
1269
1270 if (get_last && _state->result_start != NULL)
1271 {
1272
1273
1274
1275
1276
1279 else
1280 {
1283
1285 }
1286
1287
1289 }
1290
1292}
1293
1296{
1299
1300 if (lex_level < _state->npath)
1301 {
1302
1304
1305
1308 {
1309
1311 int nelements;
1312
1316
1317 if (-_state->path_indexes[lex_level] <= nelements)
1318 _state->path_indexes[lex_level] += nelements;
1319 }
1320 }
1321 else if (lex_level == 0 && _state->npath == 0)
1322 {
1323
1324
1325
1326
1327
1329 }
1330
1332}
1333
1336{
1339
1340 if (lex_level == 0 && _state->npath == 0)
1341 {
1342
1345
1347 }
1348
1350}
1351
1354{
1356 bool get_next = false;
1358
1359
1360 if (lex_level <= _state->npath)
1362
1363 if (lex_level <= _state->npath &&
1364 _state->pathok[lex_level - 1] &&
1367 {
1368 if (lex_level < _state->npath)
1369 {
1370
1371 _state->pathok[lex_level] = true;
1372 }
1373 else
1374 {
1375
1376 get_next = true;
1377 }
1378 }
1379
1380
1381 if (get_next)
1382 {
1385
1388 {
1390 }
1391 else
1392 {
1394 }
1395 }
1396
1398}
1399
1402{
1404 bool get_last = false;
1406
1407
1408 if (lex_level <= _state->npath &&
1409 _state->pathok[lex_level - 1] &&
1412 {
1413 if (lex_level < _state->npath)
1414 {
1415
1416 _state->pathok[lex_level] = false;
1417 }
1418 else
1419 {
1420
1421 get_last = true;
1422 }
1423 }
1424
1425
1426 if (get_last && _state->result_start != NULL)
1427 {
1430 else
1431 {
1434
1436 }
1437
1439 }
1440
1442}
1443
1446{
1449
1450
1451 if (lex_level == 0 && _state->npath == 0)
1452 {
1454 {
1455
1457 }
1459 {
1461 }
1462 else
1463 {
1464
1465
1466
1467
1468
1471
1473 }
1474 }
1475
1477 {
1478
1480
1482 }
1483
1485}
1486
1489{
1491}
1492
1495{
1497}
1498
1501{
1504 Datum *pathtext;
1505 bool *pathnulls;
1506 bool isnull;
1507 int npath;
1509
1510
1511
1512
1513
1514
1515
1516
1519
1521
1523
1524 if (isnull)
1526 else
1528}
1529
1532{
1535 int i;
1536 bool have_object = false,
1537 have_array = false;
1538
1539 *isnull = false;
1540
1541
1543 have_object = true;
1545 have_array = true;
1546 else
1547 {
1549
1550 if (npath <= 0)
1552 }
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562 if (npath <= 0 && jbvp == NULL)
1563 {
1564 if (as_text)
1565 {
1567 container,
1569 }
1570 else
1571 {
1572
1574 }
1575 }
1576
1577 for (i = 0; i < npath; i++)
1578 {
1579 if (have_object)
1580 {
1582
1586 NULL);
1587 }
1588 else if (have_array)
1589 {
1590 int lindex;
1593 char *endptr;
1594
1595 errno = 0;
1596 lindex = strtoint(indextext, &endptr, 10);
1597 if (endptr == indextext || *endptr != '\0' || errno != 0)
1598 {
1599 *isnull = true;
1601 }
1602
1603 if (lindex >= 0)
1604 {
1606 }
1607 else
1608 {
1609
1611
1612
1614 elog(ERROR, "not a jsonb array");
1615
1617
1618 if (lindex == INT_MIN || -lindex > nelements)
1619 {
1620 *isnull = true;
1622 }
1623 else
1624 index = nelements + lindex;
1625 }
1626
1628 }
1629 else
1630 {
1631
1632 *isnull = true;
1634 }
1635
1636 if (jbvp == NULL)
1637 {
1638 *isnull = true;
1640 }
1641 else if (i == npath - 1)
1642 break;
1643
1645 {
1646 container = jbvp->val.binary.data;
1650 }
1651 else
1652 {
1654 have_object = false;
1655 have_array = false;
1656 }
1657 }
1658
1659 if (as_text)
1660 {
1662 {
1663 *isnull = true;
1665 }
1666
1668 }
1669 else
1670 {
1672
1673
1675 }
1676}
1677
1681{
1684 bool *path_nulls = palloc0_array(bool, path_len);
1685
1688
1690
1694
1695 pfree(path_nulls);
1696
1698}
1699
1700static void
1702{
1704
1706
1707 while (num-- > 0)
1709}
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719static void
1722{
1723
1724
1725
1726
1727
1728
1731
1732
1733
1734
1735
1736
1737 for (int i = level + 1; i < path_len; i++)
1738 {
1739 char *c,
1740 *badp;
1741 int lindex;
1742
1743 if (path_nulls[i])
1744 break;
1745
1746
1747
1748
1749
1751 errno = 0;
1752 lindex = strtoint(c, &badp, 10);
1753 if (badp == c || *badp != '\0' || errno != 0)
1754 {
1755
1757 newkey.val.string.val = c;
1758 newkey.val.string.len = strlen(c);
1759
1762
1764 }
1765 else
1766 {
1767
1769
1771
1773 }
1774 }
1775
1776
1777 if (tpath[(path_len - level) - 1] == jbvArray)
1779 else
1781
1782
1783
1784
1785
1786 for (int i = path_len - 1; i > level; i--)
1787 {
1788 if (path_nulls[i])
1789 break;
1790
1793 else
1795 }
1796}
1797
1798
1799
1800
1801static text *
1803{
1804 switch (v->type)
1805 {
1807 return NULL;
1808
1810 return v->val.boolean ?
1813
1816 v->val.string.len);
1817
1819 {
1821
1824
1826 }
1827
1829 {
1831
1834 v->val.binary.len);
1835
1837 }
1838
1839 default:
1840 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1841 return NULL;
1842 }
1843}
1844
1845
1846
1847
1850{
1855
1858
1859#if 0
1860 state->count = 0;
1861#endif
1862
1868
1870
1872}
1873
1876{
1878
1881 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1882 errmsg("cannot get array length of a scalar")));
1885 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1886 errmsg("cannot get array length of a non-array")));
1887
1889}
1890
1891
1892
1893
1894
1895
1898{
1900
1901
1904 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1905 errmsg("cannot get array length of a non-array")));
1906
1908}
1909
1912{
1914
1915
1918 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1919 errmsg("cannot get array length of a scalar")));
1920
1922}
1923
1926{
1928
1929
1931 _state->count++;
1932
1934}
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1948{
1950}
1951
1954{
1956}
1957
1960{
1962}
1963
1966{
1968}
1969
1972{
1976 tmp_cxt;
1977 bool skipNested = false;
1981
1984 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1985 errmsg("cannot call %s on a non-object",
1987
1990
1992 "jsonb_each temporary cxt",
1994
1996
1998 {
1999 skipNested = true;
2000
2002 {
2005 bool nulls[2] = {false, false};
2006
2007
2009
2011
2012
2013
2014
2015
2018
2020
2021 if (as_text)
2022 {
2024 {
2025
2026 nulls[1] = true;
2028 }
2029 else
2031 }
2032 else
2033 {
2034
2036
2038 }
2039
2041
2042
2045 }
2046 }
2047
2049
2051}
2052
2053
2056{
2062
2065
2067
2071
2077
2078 state->normalize_results = as_text;
2079 state->next_scalar = false;
2082 "json_each temporary cxt",
2084
2086
2089
2091}
2092
2093
2096{
2098
2099
2101 {
2102
2103
2104
2105
2106
2109 else
2111 }
2112
2114}
2115
2118{
2121 int len;
2125 bool nulls[2] = {false, false};
2126
2127
2130
2131
2133
2135
2137 {
2138 nulls[1] = true;
2140 }
2142 {
2145 }
2146 else
2147 {
2151 }
2152
2154
2156
2157
2160
2162}
2163
2166{
2168
2169
2172 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2173 errmsg("cannot deconstruct an array as an object")));
2174
2176}
2177
2180{
2182
2183
2186 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2187 errmsg("cannot deconstruct a scalar")));
2188
2189
2192
2194}
2195
2196
2197
2198
2199
2200
2201
2202
2203
2206{
2208}
2209
2212{
2214}
2215
2218 bool as_text)
2219{
2223 tmp_cxt;
2224 bool skipNested = false;
2228
2231 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2232 errmsg("cannot extract elements from a scalar")));
2235 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2236 errmsg("cannot extract elements from an object")));
2237
2239
2241
2243 "jsonb_array_elements temporary cxt",
2245
2247
2249 {
2250 skipNested = true;
2251
2253 {
2255 bool nulls[1] = {false};
2256
2257
2259
2260 if (as_text)
2261 {
2263 {
2264
2265 nulls[0] = true;
2267 }
2268 else
2270 }
2271 else
2272 {
2273
2275
2277 }
2278
2280
2281
2284 }
2285 }
2286
2288
2290}
2291
2294{
2295 return elements_worker(fcinfo, "json_array_elements", false);
2296}
2297
2300{
2301 return elements_worker(fcinfo, "json_array_elements_text", true);
2302}
2303
2306{
2312
2313
2315
2318
2323
2329
2331 state->normalize_results = as_text;
2332 state->next_scalar = false;
2333 state->lex = &lex;
2335 "json_array_elements temporary cxt",
2337
2339
2342
2344}
2345
2348{
2350
2351
2353 {
2354
2355
2356
2357
2358
2361 else
2363 }
2364
2366}
2367
2370{
2373 int len;
2377 bool nulls[1] = {false};
2378
2379
2382
2383
2385
2387 {
2388 nulls[0] = true;
2390 }
2392 {
2395 }
2396 else
2397 {
2401 }
2402
2404
2406
2407
2410
2412}
2413
2416{
2418
2419
2422 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2423 errmsg("cannot call %s on a non-array",
2425
2427}
2428
2431{
2433
2434
2437 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2438 errmsg("cannot call %s on a scalar",
2440
2441
2444
2446}
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2462{
2464 false, true, NULL);
2465}
2466
2467
2468
2469
2470
2471
2472
2475{
2477
2479 false, true, (Node *) &escontext);
2480
2482}
2483
2486{
2488 false, false, NULL);
2489}
2490
2493{
2495 true, true, NULL);
2496}
2497
2500{
2502 true, false, NULL);
2503}
2504
2505
2506static void
2508{
2509 if (ndim <= 0)
2510 {
2513 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2514 errmsg("expected JSON array"),
2515 errhint("See the value of key \"%s\".", ctx->colname)));
2516 else
2518 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2519 errmsg("expected JSON array")));
2520 return;
2521 }
2522 else
2523 {
2525 int i;
2526
2528
2529 Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2530
2531 for (i = 0; i < ndim; i++)
2533
2536 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2537 errmsg("expected JSON array"),
2538 errhint("See the array element %s of key \"%s\".",
2540 else
2542 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2543 errmsg("expected JSON array"),
2544 errhint("See the array element %s.",
2545 indices.data)));
2546 return;
2547 }
2548}
2549
2550
2551
2552
2553
2554
2555
2556static bool
2558{
2559 int i;
2560
2562
2563 if (ndims <= 0)
2564 {
2566
2568 return false;
2569 }
2570
2571 ctx->ndims = ndims;
2574
2575 for (i = 0; i < ndims; i++)
2577
2578 return true;
2579}
2580
2581
2582
2583
2584
2585
2586static bool
2588{
2589 int dim = ctx->sizes[ndim];
2590
2591 if (ctx->dims[ndim] == -1)
2592 ctx->dims[ndim] = dim;
2593 else if (ctx->dims[ndim] != dim)
2595 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2596 errmsg("malformed JSON array"),
2597 errdetail("Multidimensional arrays must have "
2598 "sub-arrays with matching dimensions.")));
2599
2600
2601 ctx->sizes[ndim] = 0;
2602
2603
2604 if (ndim > 0)
2605 ctx->sizes[ndim - 1]++;
2606
2607 return true;
2608}
2609
2610
2611
2612
2613
2614static bool
2616{
2618 bool element_isnull;
2619
2620
2625 jsv, &element_isnull, ctx->escontext,
2626 false);
2627
2629 return false;
2630
2633
2635 ctx->sizes[ndim - 1]++;
2636
2637 return true;
2638}
2639
2640
2643{
2645 int ndim = state->lex->lex_level;
2646
2647 if (state->ctx->ndims <= 0)
2648 {
2651 }
2652 else if (ndim < state->ctx->ndims)
2653 {
2655
2658 }
2659
2661}
2662
2663
2666{
2669 int ndim = state->lex->lex_level;
2670
2671 if (ctx->ndims <= 0)
2672 {
2675 }
2676
2677 if (ndim < ctx->ndims)
2678 {
2679
2682 }
2683
2685}
2686
2687
2690{
2692 int ndim = state->lex->lex_level;
2693
2694 if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2695 {
2696
2697 state->element_start = state->lex->token_start;
2698 state->element_type = state->lex->token_type;
2699 state->element_scalar = NULL;
2700 }
2701
2703}
2704
2705
2708{
2711 int ndim = state->lex->lex_level;
2712
2714
2715 if (ndim == ctx->ndims)
2716 {
2718
2721
2722 if (isnull)
2723 {
2727 }
2728 else if (state->element_scalar)
2729 {
2732 }
2733 else
2734 {
2737 state->element_start) * sizeof(char);
2738 }
2739
2740
2743 }
2744
2746}
2747
2748
2751{
2754 int ndim = state->lex->lex_level;
2755
2756 if (ctx->ndims <= 0)
2757 {
2760 }
2761 else if (ndim < ctx->ndims)
2762 {
2764
2767 }
2768
2769 if (ndim == ctx->ndims)
2770 {
2771
2773
2774 Assert(state->element_type == tokentype);
2775 }
2776
2778}
2779
2780
2781
2782
2783
2784
2785static bool
2787{
2790
2793 state.ctx = ctx;
2794
2795 memset(&sem, 0, sizeof(sem));
2802
2804 {
2805
2807 }
2808
2810
2812}
2813
2814
2815
2816
2817
2818
2819
2820
2821static bool
2823 JsonbValue *jbv,
2824 int ndim)
2825{
2831
2833
2834
2837 {
2839
2841 return false;
2842 }
2843
2845
2848
2850
2851
2852
2853
2854
2855
2856 if (ctx->ndims <= 0 &&
2861 {
2863 return false;
2864 }
2865
2868
2869
2871 {
2872
2873
2874
2875
2876 if (ctx->ndims > 0 && ndim >= ctx->ndims)
2877 {
2879 return false;
2880 }
2881 else
2882 {
2883
2885 return false;
2886
2887
2889
2891 return false;
2892 }
2893
2895 }
2896
2898
2899
2902
2903 return true;
2904}
2905
2906
2907
2908
2909
2910
2913 const char *colname,
2916 bool *isnull,
2917 Node *escontext)
2918{
2921 int *lbs;
2922 int i;
2923
2924 ctx.aio = aio;
2925 ctx.mcxt = mcxt;
2929 ctx.ndims = 0;
2930 ctx.dims = NULL;
2931 ctx.sizes = NULL;
2933
2935 {
2936
2940 {
2941 *isnull = true;
2942 return (Datum) 0;
2943 }
2944 }
2945 else
2946 {
2947
2949 {
2950 *isnull = true;
2951 return (Datum) 0;
2952 }
2954 }
2955
2957
2959
2960 for (i = 0; i < ctx.ndims; i++)
2961 lbs[i] = 1;
2962
2964 ctx.acxt, true);
2965
2969
2970 *isnull = false;
2971 return result;
2972}
2973
2974
2975
2976
2977
2978static bool
2980{
2982
2984 {
2985
2991 "populate_composite",
2992 escontext);
2994 }
2995 else
2996 {
2998
3001 {
3003 }
3004 else
3005 {
3006 bool is_scalar;
3007
3012 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3013 is_scalar
3014 ? errmsg("cannot call %s on a scalar",
3015 "populate_composite")
3016 : errmsg("cannot call %s on an array",
3017 "populate_composite")));
3018 }
3019 }
3020
3022}
3023
3024
3025static void
3027{
3031 {
3035
3038
3039
3043
3045 }
3046}
3047
3048
3049
3050
3051
3052
3053
3056 Oid typid,
3057 const char *colname,
3061 bool *isnull,
3062 Node *escontext)
3063{
3065
3066
3068
3069 if (*isnull)
3070 result = (Datum) 0;
3071 else
3072 {
3075
3076
3078 {
3079 *isnull = true;
3080 return (Datum) 0;
3081 }
3082
3083
3085 defaultval, mcxt, &jso, escontext);
3086
3088 {
3089 *isnull = true;
3090 return (Datum) 0;
3091 }
3093
3095 }
3096
3097
3098
3099
3100
3101
3102 if (typid != io->base_typid && typid != RECORDOID)
3103 {
3105 escontext))
3106 {
3107 *isnull = true;
3108 return (Datum) 0;
3109 }
3110 }
3111
3112 return result;
3113}
3114
3115
3116
3117
3118
3119
3120
3123 bool *isnull, Node *escontext, bool omit_quotes)
3124{
3126 char *str = NULL;
3127 const char *json = NULL;
3128
3130 {
3132
3135
3136
3137 if ((typid == JSONOID || typid == JSONBOID) &&
3139 {
3141
3143 if (len >= 0)
3145 else
3148 }
3149 else if (len >= 0)
3150 {
3151
3155 }
3156 else
3157 {
3158
3160 }
3161 }
3162 else
3163 {
3165
3168 else if (typid == JSONBOID)
3169 {
3171
3173 }
3174
3175 else if (typid == JSONOID && jbv->type != jbvBinary)
3176 {
3177
3178
3179
3180
3182
3184 }
3185 else if (jbv->type == jbvString)
3188 str = pstrdup(jbv->val.boolean ? "true" : "false");
3194 jbv->val.binary.len);
3195 else
3196 elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
3197 }
3198
3200 escontext, &res))
3201 {
3202 res = (Datum) 0;
3203 *isnull = true;
3204 }
3205
3206
3207 if (str != json)
3209
3210 return res;
3211}
3212
3215 Oid typid,
3216 const char *colname,
3219 bool *isnull,
3220 Node *escontext,
3221 bool omit_quotes)
3222{
3224
3225 if (*isnull)
3226 res = (Datum) 0;
3227 else
3228 {
3232 jsv, isnull, escontext, omit_quotes);
3234 }
3235
3237 escontext))
3238 {
3239 *isnull = true;
3240 return (Datum) 0;
3241 }
3242
3243 return res;
3244}
3245
3246
3247static void
3249 Oid typid,
3252 bool need_scalar)
3253{
3256
3257 column->typid = typid;
3258 column->typmod = typmod;
3259
3262 elog(ERROR, "cache lookup failed for type %u", typid);
3263
3265
3266 if (type->typtype == TYPTYPE_DOMAIN)
3267 {
3268
3269
3270
3271
3272 Oid base_typid;
3273 int32 base_typmod = typmod;
3274
3276 if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
3277 {
3278
3285 }
3286 else
3287 {
3288
3295 }
3296 }
3297 else if (type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
3298 {
3305 }
3306 else if (IsTrueArrayType(type))
3307 {
3312
3314 }
3315 else
3316 {
3318 need_scalar = true;
3319 }
3320
3321
3322 if (need_scalar)
3323 {
3324 Oid typioproc;
3325
3328 }
3329
3331}
3332
3333
3334
3335
3336
3337
3338
3339
3340
3345 bool *isnull, bool omit_quotes,
3346 Node *escontext)
3347{
3350
3351 jsv.is_json = json_type == JSONOID;
3352
3353 if (*isnull)
3354 {
3357 else
3359 }
3361 {
3363
3367
3368 }
3369 else
3370 {
3372
3374
3375 if (omit_quotes)
3376 {
3378
3379
3381 jbv.val.string.len = strlen(str);
3382 jbv.val.string.val = str;
3383 }
3384 else
3385 {
3386
3388 jbv.val.binary.data = &jsonb->root;
3390 }
3391 }
3392
3393 if (*cache == NULL)
3395
3398 escontext, omit_quotes);
3399}
3400
3401
3404 Oid typid,
3406 const char *colname,
3408 Datum defaultval,
3410 bool *isnull,
3411 Node *escontext,
3412 bool omit_scalar_quotes)
3413{
3415
3417
3418
3419
3420
3421
3422 if (col->typid != typid || col->typmod != typmod)
3424
3426
3427 typcat = col->typcat;
3428
3429
3435
3436
3437 if (*isnull &&
3440 return (Datum) 0;
3441
3442 switch (typcat)
3443 {
3446 isnull, escontext, omit_scalar_quotes);
3447
3450 isnull, escontext);
3451
3455 colname, mcxt,
3458 : NULL,
3459 jsv, isnull,
3460 escontext);
3461
3464 jsv, isnull, escontext, omit_scalar_quotes);
3465
3466 default:
3467 elog(ERROR, "unrecognized type category '%c'", typcat);
3468 return (Datum) 0;
3469 }
3470}
3471
3474{
3479
3481 data->record_typmod = 0;
3482 data->ncolumns = ncolumns;
3484
3485 return data;
3486}
3487
3488static bool
3490{
3492
3494 {
3497
3500 hashentry->val;
3502
3503 return hashentry != NULL;
3504 }
3505 else
3506 {
3509 NULL);
3510
3511 return jsv->val.jsonb != NULL;
3512 }
3513}
3514
3515
3522 Node *escontext)
3523{
3526 bool *nulls;
3528 int ncolumns = tupdesc->natts;
3529 int i;
3530
3531
3532
3533
3534
3535
3537 return defaultval;
3538
3539
3540 if (record == NULL ||
3541 record->ncolumns != ncolumns)
3543
3544
3547 {
3552 record->ncolumns = ncolumns;
3553 }
3554
3556 nulls = (bool *) palloc(ncolumns * sizeof(bool));
3557
3558 if (defaultval)
3559 {
3561
3562
3566 tuple.t_data = defaultval;
3567
3568
3570 }
3571 else
3572 {
3573 for (i = 0; i < ncolumns; ++i)
3574 {
3576 nulls[i] = true;
3577 }
3578 }
3579
3580 for (i = 0; i < ncolumns; ++i)
3581 {
3583 char *colname = NameStr(att->attname);
3585 bool found;
3586
3587
3588 if (att->attisdropped)
3589 {
3590 nulls[i] = true;
3591 continue;
3592 }
3593
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604 if (defaultval && !found)
3605 continue;
3606
3608 att->atttypid,
3609 att->atttypmod,
3610 colname,
3611 mcxt,
3613 &field,
3614 &nulls[i],
3615 escontext,
3616 false);
3617 }
3618
3620
3623
3625}
3626
3627
3628
3629
3630
3631
3632static void
3636{
3644 (errcode(ERRCODE_DATATYPE_MISMATCH),
3645
3646 errmsg("first argument of %s must be a row type",
3648}
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658static void
3662{
3665
3668 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3669
3670 errmsg("could not determine row type for result of %s",
3672 errhint("Provide a non-null record argument, "
3673 "or call the function in the FROM clause "
3674 "using a column definition list.")));
3675
3678
3679
3682
3683
3689}
3690
3691
3692
3693
3694
3697 bool is_json, bool have_record_arg,
3698 Node *escontext)
3699{
3700 int json_arg_num = have_record_arg ? 1 : 0;
3704 bool isnull;
3708
3709
3710
3711
3712
3713
3714 if (!cache)
3715 {
3718 cache->fn_mcxt = fnmcxt;
3719
3720 if (have_record_arg)
3722 else
3724 }
3725
3726
3727 if (!have_record_arg)
3728 rec = NULL;
3730 {
3732
3733
3734
3735
3736
3737 if (cache->argtype == RECORDOID)
3738 {
3741 }
3742 }
3743 else
3744 {
3745 rec = NULL;
3746
3747
3748
3749
3750
3751 if (cache->argtype == RECORDOID)
3752 {
3754
3756 }
3757 }
3758
3759
3761 {
3762 if (rec)
3764 else
3766 }
3767
3769
3770 if (is_json)
3771 {
3773
3777
3778 }
3779 else
3780 {
3782
3784
3785
3787 jbv.val.binary.data = &jb->root;
3789 }
3790
3791 isnull = false;
3793 NULL, fnmcxt, rec, &jsv, &isnull,
3794 escontext);
3796
3798}
3799
3800
3801
3802
3803
3804
3805
3806
3807static HTAB *
3809 Node *escontext)
3810{
3815
3819 tab = hash_create("json object hashtable",
3820 100,
3823
3826
3828 state->hash = tab;
3831
3837
3839 {
3841 tab = NULL;
3842 }
3843
3845
3846 return tab;
3847}
3848
3851{
3853
3856
3857
3859
3862 {
3863
3865 }
3866 else
3867 {
3868
3870 }
3871
3873}
3874
3877{
3880 bool found;
3881
3882
3883
3884
3887
3888
3889
3890
3891
3892
3893
3894
3897
3899
3900
3901
3902
3903
3904
3907
3909 {
3911 char *val = palloc((len + 1) * sizeof(char));
3912
3916 }
3917 else
3918 {
3919
3921 }
3922
3924}
3925
3928{
3930
3933 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3935
3937}
3938
3941{
3943
3946 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3948
3950 {
3952
3954 }
3955
3957}
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3972{
3974 false, true);
3975}
3976
3979{
3981 false, false);
3982}
3983
3986{
3988 true, true);
3989}
3990
3993{
3995 true, false);
3996}
3997
3998static void
4000{
4004
4005
4007
4008
4013 obj,
4014 NULL);
4015
4016
4022 NULL);
4023
4024
4028 tuple.t_data = tuphead;
4029
4031}
4032
4033
4034
4035
4036
4039 bool is_json, bool have_record_arg)
4040{
4041 int json_arg_num = have_record_arg ? 1 : 0;
4047
4049
4052 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4053 errmsg("set-valued function called in context that cannot accept a set")));
4054
4057 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4058 errmsg("materialize mode required, but it is not allowed in this context")));
4059
4061
4062
4063
4064
4065
4066
4067 if (!cache)
4068 {
4072
4073 if (have_record_arg)
4075 else
4077 }
4078
4079
4080 if (!have_record_arg)
4081 rec = NULL;
4083 {
4085
4086
4087
4088
4089
4090 if (cache->argtype == RECORDOID)
4091 {
4094 }
4095 }
4096 else
4097 {
4098 rec = NULL;
4099
4100
4101
4102
4103
4104 if (cache->argtype == RECORDOID)
4105 {
4107
4109 }
4110 }
4111
4112
4115
4116
4117
4118
4119
4121
4123
4124
4130
4132 state->cache = cache;
4133 state->rec = rec;
4134
4135 if (is_json)
4136 {
4140
4142
4144
4153
4154 state->lex = &lex;
4155
4157
4159 state->lex = NULL;
4160 }
4161 else
4162 {
4166 bool skipNested = false;
4168
4171 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4172 errmsg("cannot call %s on a non-array",
4174
4176
4178 {
4179 skipNested = true;
4180
4182 {
4184
4188 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4189 errmsg("argument of %s must be an array of objects",
4191
4194
4196 }
4197 }
4198 }
4199
4200
4201
4202
4203
4204
4207
4209}
4210
4213{
4217
4218
4219 if (lex_level == 0)
4221 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4222 errmsg("cannot call %s on an object",
4224
4225
4226 if (lex_level > 1)
4228
4229
4234 100,
4237
4239}
4240
4243{
4246
4247
4250
4253
4254
4256
4257
4260
4262}
4263
4266{
4268
4272 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4273 errmsg("argument of %s must be an array of objects",
4275
4277}
4278
4281{
4282
4284}
4285
4288{
4290
4293 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4294 errmsg("cannot call %s on a scalar",
4296
4299
4301}
4302
4305{
4307
4310
4312
4315 {
4317 }
4318 else
4319 {
4321 }
4322
4324}
4325
4328{
4331 bool found;
4332
4333
4334
4335
4338
4339
4340
4341
4342
4343
4344
4345
4348
4350
4351
4352
4353
4354
4355
4358
4360 {
4362 char *val = palloc((len + 1) * sizeof(char));
4363
4367 }
4368 else
4369 {
4370
4372 }
4373
4375}
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4388{
4390
4392
4394}
4395
4398{
4400
4402
4404}
4405
4408{
4410
4412
4414}
4415
4418{
4420
4422
4424}
4425
4428{
4430
4431 if (isnull)
4432 {
4433
4434
4435
4436
4437
4440 }
4441
4444
4445
4446
4447
4448
4450
4452
4454}
4455
4458{
4460
4461
4463 {
4466 }
4467
4468
4471 {
4473 }
4474
4476}
4477
4480{
4482
4484 {
4488 }
4489
4492 else
4494
4496}
4497
4498
4499
4500
4503{
4510
4514
4516 state->strval = &strbuf;
4517 state->skip_next_null = false;
4518 state->strip_in_arrays = strip_in_arrays;
4519
4528
4530
4532 state->strval->len));
4533}
4534
4535
4536
4537
4540{
4542 bool strip_in_arrays = false;
4546 k;
4548 bool last_was_key = false;
4549
4552
4555
4557
4559 {
4561
4563 {
4564
4565 k = v;
4566 last_was_key = true;
4567 continue;
4568 }
4569
4570 if (last_was_key)
4571 {
4572
4573 last_was_key = false;
4574
4575
4577 continue;
4578
4579
4581 }
4582
4583
4584 if (strip_in_arrays)
4586 continue;
4587
4590 else
4592 }
4593
4595}
4596
4597
4598
4599
4600
4601
4604{
4607
4610
4612}
4613
4614
4615
4616
4617
4618
4621{
4626 *it2;
4627
4628
4629
4630
4631
4632
4633
4635 {
4640 }
4641
4644
4646
4648}
4649
4650
4651
4652
4653
4654
4655
4656
4659{
4667 bool skipNested = false;
4669
4672 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4673 errmsg("cannot delete from scalar")));
4674
4677
4679
4681 {
4682 skipNested = true;
4683
4686 memcmp(keyptr, v.val.string.val, keylen) == 0))
4687 {
4688
4691
4692 continue;
4693 }
4694
4696 }
4697
4699}
4700
4701
4702
4703
4704
4705
4706
4709{
4712 Datum *keys_elems;
4713 bool *keys_nulls;
4714 int keys_len;
4718 bool skipNested = false;
4720
4723 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4724 errmsg("wrong number of array subscripts")));
4725
4728 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4729 errmsg("cannot delete from scalar")));
4730
4733
4735
4736 if (keys_len == 0)
4738
4740
4742 {
4743 skipNested = true;
4744
4746 {
4747 int i;
4748 bool found = false;
4749
4750 for (i = 0; i < keys_len; i++)
4751 {
4752 char *keyptr;
4753 int keylen;
4754
4755 if (keys_nulls[i])
4756 continue;
4757
4758
4761 if (keylen == v.val.string.len &&
4762 memcmp(keyptr, v.val.string.val, keylen) == 0)
4763 {
4764 found = true;
4765 break;
4766 }
4767 }
4768 if (found)
4769 {
4770
4773
4774 continue;
4775 }
4776 }
4777
4779 }
4780
4782}
4783
4784
4785
4786
4787
4788
4789
4790
4793{
4799 n;
4802
4805 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4806 errmsg("cannot delete from scalar")));
4807
4810 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4811 errmsg("cannot delete from object using integer index")));
4812
4815
4817
4820 n = v.val.array.nElems;
4821
4822 if (idx < 0)
4823 {
4825 idx = n;
4826 else
4828 }
4829
4830 if (idx >= n)
4832
4834
4836 {
4838 {
4840 continue;
4841 }
4842
4844 }
4845
4847}
4848
4849
4850
4851
4854{
4860 Datum *path_elems;
4861 bool *path_nulls;
4862 int path_len;
4865
4867
4870 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4871 errmsg("wrong number of array subscripts")));
4872
4875 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4876 errmsg("cannot set path in scalar")));
4877
4880
4882
4883 if (path_len == 0)
4885
4887
4888 setPath(&it, path_elems, path_nulls, path_len, &st,
4890
4892}
4893
4894
4895
4896
4897
4900{
4901
4902
4903
4904
4905 text *handle_null;
4906 char *handle_val;
4907
4910
4911
4914 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4915 errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4916
4917
4920
4923
4924 if (strcmp(handle_val, "raise_exception") == 0)
4925 {
4927 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4928 errmsg("JSON value must not be null"),
4929 errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4930 errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4931 return (Datum) 0;
4932 }
4933 else if (strcmp(handle_val, "use_json_null") == 0)
4934 {
4936
4938
4939 fcinfo->args[2].value = newval;
4940 fcinfo->args[2].isnull = false;
4942 }
4943 else if (strcmp(handle_val, "delete_key") == 0)
4944 {
4946 }
4947 else if (strcmp(handle_val, "return_target") == 0)
4948 {
4950
4952 }
4953 else
4954 {
4956 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4957 errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4958 return (Datum) 0;
4959 }
4960}
4961
4962
4963
4964
4967{
4970 Datum *path_elems;
4971 bool *path_nulls;
4972 int path_len;
4975
4978 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4979 errmsg("wrong number of array subscripts")));
4980
4983 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4984 errmsg("cannot delete path in scalar")));
4985
4988
4990
4991 if (path_len == 0)
4993
4995
4996 setPath(&it, path_elems, path_nulls, path_len, &st,
4998
5000}
5001
5002
5003
5004
5007{
5013 Datum *path_elems;
5014 bool *path_nulls;
5015 int path_len;
5018
5020
5023 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5024 errmsg("wrong number of array subscripts")));
5025
5028 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5029 errmsg("cannot set path in scalar")));
5030
5032
5033 if (path_len == 0)
5035
5037
5038 setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
5040
5042}
5043
5044
5045
5046
5047
5048
5049
5050
5051static void
5054{
5056 v2;
5058 r2,
5059 rk1,
5060 rk2;
5061
5064
5065
5066
5067
5068
5070 {
5071
5072
5073
5074
5075
5076
5080
5081
5082
5083
5084
5085
5088 }
5090 {
5091
5092
5093
5095
5097 {
5100 }
5101
5103 {
5106 }
5107
5109 }
5111 {
5112
5113
5114
5116
5118
5122
5125 }
5126 else
5127 {
5128
5129
5130
5133
5135
5138
5142
5144 }
5145}
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176static void
5178 const bool *path_nulls, int path_len,
5180{
5183
5185
5186 if (path_nulls[level])
5188 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5189 errmsg("path element at position %d is null",
5190 level + 1)));
5191
5193
5194 switch (r)
5195 {
5197
5198
5199
5200
5201
5202
5203
5205 v.val.array.rawScalar)
5207 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5208 errmsg("cannot replace existing key"),
5209 errdetail("The path assumes key is a composite object, "
5210 "but it is a scalar value.")));
5211
5213 setPathArray(it, path_elems, path_nulls, path_len, st, level,
5214 newval, v.val.array.nElems, op_type);
5218 break;
5221 setPathObject(it, path_elems, path_nulls, path_len, st, level,
5222 newval, v.val.object.nPairs, op_type);
5226 break;
5229
5230
5231
5232
5233
5234
5235
5238 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5239 errmsg("cannot replace existing key"),
5240 errdetail("The path assumes key is a composite object, "
5241 "but it is a scalar value.")));
5242
5244 break;
5245 default:
5246 elog(ERROR, "unrecognized iterator result: %d", (int) r);
5247 break;
5248 }
5249}
5250
5251
5252
5253
5254static void
5258{
5259 text *pathelem = NULL;
5260 int i;
5262 v;
5263 bool done = false;
5264
5265 if (level >= path_len || path_nulls[level])
5266 done = true;
5267 else
5268 {
5269
5271 }
5272
5273
5275 (level == path_len - 1))
5276 {
5278
5282
5285 }
5286
5287 for (i = 0; i < npairs; i++)
5288 {
5290
5292
5293 if (!done &&
5296 k.val.string.len) == 0)
5297 {
5298 done = true;
5299
5300 if (level == path_len - 1)
5301 {
5302
5303
5304
5305
5308 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5309 errmsg("cannot replace existing key"),
5310 errhint("Try using the function jsonb_set "
5311 "to replace key value.")));
5312
5315 {
5318 }
5319 }
5320 else
5321 {
5323 setPath(it, path_elems, path_nulls, path_len,
5324 st, level + 1, newval, op_type);
5325 }
5326 }
5327 else
5328 {
5330 level == path_len - 1 && i == npairs - 1)
5331 {
5333
5337
5340 }
5341
5346 {
5347 int walking_level = 1;
5348
5349 while (walking_level != 0)
5350 {
5352
5354 ++walking_level;
5356 --walking_level;
5357
5359 }
5360 }
5361 }
5362 }
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374 if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5375 {
5377
5381
5383 push_path(st, level, path_elems, path_nulls, path_len, newval);
5384
5385
5386 }
5387}
5388
5389
5390
5391
5392static void
5396{
5398 int idx,
5399 i;
5400 bool done = false;
5401
5402
5403 if (level < path_len && !path_nulls[level])
5404 {
5406 char *badp;
5407
5408 errno = 0;
5410 if (badp == c || *badp != '\0' || errno != 0)
5412 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5413 errmsg("path element at position %d is not an integer: \"%s\"",
5414 level + 1, c)));
5415 }
5416 else
5417 idx = nelems;
5418
5419 if (idx < 0)
5420 {
5422 {
5423
5424
5425
5426
5429 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5430 errmsg("path element at position %d is out of range: %d",
5431 level + 1, idx)));
5432 else
5434 }
5435 else
5437 }
5438
5439
5440
5441
5442
5444 {
5445 if (idx > 0 && idx > nelems)
5446 idx = nelems;
5447 }
5448
5449
5450
5451
5452
5453
5454 if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5456 {
5458
5461
5463
5464 done = true;
5465 }
5466
5467
5468 for (i = 0; i < nelems; i++)
5469 {
5471
5472 if (i == idx && level < path_len)
5473 {
5474 done = true;
5475
5476 if (level == path_len - 1)
5477 {
5479
5482
5483
5484
5485
5486
5487
5490
5493 }
5494 else
5495 setPath(it, path_elems, path_nulls, path_len,
5496 st, level + 1, newval, op_type);
5497 }
5498 else
5499 {
5501
5503
5505 {
5506 int walking_level = 1;
5507
5508 while (walking_level != 0)
5509 {
5511
5513 ++walking_level;
5515 --walking_level;
5516
5518 }
5519 }
5520 }
5521 }
5522
5524 {
5525
5526
5527
5528
5531
5533 done = true;
5534 }
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546 if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5547 {
5548 if (idx > 0)
5550
5551 push_path(st, level, path_elems, path_nulls, path_len, newval);
5552
5553
5554 }
5555}
5556
5557
5558
5559
5560
5561
5564{
5569
5571
5573
5574
5575
5576
5577
5578
5581 errmsg("wrong flag type, only arrays and scalars are allowed")));
5582
5584 {
5587 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5588 errmsg("flag array element is not a string"),
5589 errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5590
5591 if (v.val.string.len == 3 &&
5594 else if (v.val.string.len == 3 &&
5597 else if (v.val.string.len == 6 &&
5600 else if (v.val.string.len == 7 &&
5603 else if (v.val.string.len == 7 &&
5606 else
5608 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5609 errmsg("wrong flag in flag array: \"%s\"",
5611 errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5612 }
5613
5614
5616 elog(ERROR, "unexpected end of flag array");
5617
5618
5621 elog(ERROR, "unexpected end of flag array");
5622
5623 return flags;
5624}
5625
5626
5627
5628
5629
5630void
5633{
5637
5639
5640
5641
5642
5643
5645 {
5647 {
5650
5651 continue;
5652 }
5654 {
5655
5656 continue;
5657 }
5658
5659
5660 switch (v.type)
5661 {
5665 break;
5668 {
5669 char *val;
5670
5673
5676 }
5677 break;
5680 {
5681 if (v.val.boolean)
5683 else
5685 }
5686 break;
5687 default:
5688
5689 break;
5690 }
5691 }
5692}
5693
5694
5695
5696
5697
5698void
5701{
5705
5708 state->action_state = action_state;
5709 state->flags = flags;
5710
5714
5717}
5718
5719
5720
5721
5722
5725{
5727
5728 switch (tokentype)
5729 {
5733 break;
5737 break;
5742 break;
5743 default:
5744
5745 break;
5746 }
5747
5749}
5750
5753{
5755
5757 {
5759
5761 }
5762
5764}
5765
5766
5767
5768
5769
5770
5771
5775{
5781 bool is_scalar = false;
5782
5785
5787 {
5789 {
5790 out = transform_action(action_state, v.val.string.val, v.val.string.len);
5791
5796 }
5797 else
5798 {
5802 }
5803 }
5804
5806 st.result->val.array.rawScalar = is_scalar;
5807
5809}
5810
5811
5812
5813
5814
5815
5816
5817
5821{
5826
5828
5830 state->strval = &strbuf;
5831 state->action = transform_action;
5832 state->action_state = action_state;
5833
5842
5845
5847}
5848
5849
5850
5851
5852
5853
5856{
5858
5860
5862}
5863
5866{
5868
5870
5872}
5873
5876{
5878
5880
5882}
5883
5886{
5888
5890
5892}
5893
5896{
5898
5901
5902
5903
5904
5905
5908
5910}
5911
5914{
5916
5919
5921}
5922
5925{
5927
5929 {
5931
5933 }
5934 else
5936
5938}
5939
5942{
5945
5947
5948
5950
5953
5954 if (throw_error)
5956
5958}
5959
5960
5961
5962
5963
5964
5965
5966
5967void
5970{
5971 bool typisvarlena;
5972
5973
5975
5977
5978 switch (typoid)
5979 {
5980 case BOOLOID:
5981 *outfuncoid = F_BOOLOUT;
5983 break;
5984
5985 case INT2OID:
5986 case INT4OID:
5987 case INT8OID:
5988 case FLOAT4OID:
5989 case FLOAT8OID:
5990 case NUMERICOID:
5993 break;
5994
5995 case DATEOID:
5996 *outfuncoid = F_DATE_OUT;
5998 break;
5999
6000 case TIMESTAMPOID:
6001 *outfuncoid = F_TIMESTAMP_OUT;
6003 break;
6004
6005 case TIMESTAMPTZOID:
6006 *outfuncoid = F_TIMESTAMPTZ_OUT;
6008 break;
6009
6010 case JSONOID:
6013 break;
6014
6015 case JSONBOID:
6018 break;
6019
6020 default:
6021
6023 || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
6024 {
6025 *outfuncoid = F_ARRAY_OUT;
6027 }
6028 else if (type_is_rowtype(typoid))
6029 {
6030 *outfuncoid = F_RECORD_OUT;
6032 }
6033 else
6034 {
6035
6036
6037
6038
6039
6042 {
6043 Oid castfunc;
6045
6048 &castfunc);
6050 {
6051 *outfuncoid = castfunc;
6053 }
6054 else
6055 {
6056
6058 }
6059 }
6060 else
6061 {
6062
6064 }
6065 }
6066 break;
6067 }
6068}
Datum idx(PG_FUNCTION_ARGS)
#define PG_GETARG_ARRAYTYPE_P(n)
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
bool array_contains_nulls(const ArrayType *array)
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Datum numeric_out(PG_FUNCTION_ARGS)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define TextDatumGetCString(d)
#define unconstify(underlying_type, expr)
#define IS_HIGHBIT_SET(ch)
#define FLEXIBLE_ARRAY_MEMBER
#define MemSet(start, val, len)
#define OidIsValid(objectId)
bool domain_check_safe(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt, Node *escontext)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
void hash_destroy(HTAB *hashp)
int errdetail_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereturn(context, dummy_value,...)
#define errsave(context,...)
#define ereport(elevel,...)
Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
@ SFRM_Materialize_Random
#define palloc_object(type)
#define palloc_array(type, count)
#define palloc0_array(type, count)
#define palloc0_object(type)
struct varlena * pg_detoast_datum_packed(struct varlena *datum)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
#define PG_GETARG_TEXT_PP(n)
#define DatumGetHeapTupleHeader(X)
#define DatumGetTextPP(X)
#define DirectFunctionCall1(func, arg1)
#define PG_GETARG_HEAPTUPLEHEADER(n)
#define PG_RETURN_TEXT_P(x)
#define PG_RETURN_INT32(x)
#define PG_GETARG_INT32(n)
#define PG_GETARG_BOOL(n)
#define PG_RETURN_DATUM(x)
#define PG_RETURN_POINTER(x)
#define PG_GETARG_TEXT_P(n)
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
#define SRF_RETURN_DONE(_funcctx)
#define MAT_SRF_USE_EXPECTED_DESC
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
#define HeapTupleIsValid(tuple)
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static void * GETSTRUCT(const HeapTupleData *tuple)
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
static uint32 pg_abs_s32(int32 a)
if(TABLE==NULL||TABLE_index==NULL)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
void escape_json_text(StringInfo buf, const text *txt)
void escape_json_with_len(StringInfo buf, const char *str, int len)
void escape_json(StringInfo buf, const char *str)
JsonParseErrorType pg_parse_json(JsonLexContext *lex, const JsonSemAction *sem)
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
JsonParseErrorType json_lex(JsonLexContext *lex)
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
JsonParseErrorType json_count_array_elements(JsonLexContext *lex, int *elements)
void freeJsonLexContext(JsonLexContext *lex)
@ JSON_UNICODE_CODE_POINT_ZERO
@ JSON_UNICODE_UNTRANSLATABLE
@ JSON_UNICODE_HIGH_ESCAPE
@ JSON_TOKEN_OBJECT_START
char * JsonbUnquote(Jsonb *jb)
Datum jsonb_in(PG_FUNCTION_ARGS)
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
#define JsonContainerIsScalar(jc)
#define JsonContainerIsArray(jc)
#define JsonContainerSize(jc)
#define JB_ROOT_IS_OBJECT(jbp_)
static Datum JsonbPGetDatum(const Jsonb *p)
#define IsAJsonbScalar(jsonbval)
#define PG_RETURN_JSONB_P(x)
#define JB_ROOT_IS_ARRAY(jbp_)
#define PG_GETARG_JSONB_P(x)
#define JsonContainerIsObject(jc)
static Jsonb * DatumGetJsonbP(Datum d)
#define JB_ROOT_IS_SCALAR(jbp_)
#define JB_ROOT_COUNT(jbp_)
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Datum jsonb_populate_recordset(PG_FUNCTION_ARGS)
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
static JsonParseErrorType get_array_element_end(void *state, bool isnull)
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
static JsonParseErrorType hash_array_start(void *state)
Datum jsonb_object_keys(PG_FUNCTION_ARGS)
static JsonParseErrorType populate_recordset_array_start(void *state)
static JsonParseErrorType transform_string_values_array_start(void *state)
static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull)
static JsonParseErrorType elements_object_start(void *state)
static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull)
Datum jsonb_array_elements(PG_FUNCTION_ARGS)
static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull)
struct PopulateArrayContext PopulateArrayContext
static void IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbInState *state)
Datum json_each_text(PG_FUNCTION_ARGS)
static void push_path(JsonbInState *st, int level, const Datum *path_elems, const bool *path_nulls, int path_len, JsonbValue *newval)
Datum json_populate_recordset(PG_FUNCTION_ARGS)
static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
text * transform_json_string_values(text *json, void *action_state, JsonTransformStringValuesAction transform_action)
Datum jsonb_delete(PG_FUNCTION_ARGS)
struct TransformJsonStringValuesState TransformJsonStringValuesState
Datum json_populate_type(Datum json_val, Oid json_type, Oid typid, int32 typmod, void **cache, MemoryContext mcxt, bool *isnull, bool omit_quotes, Node *escontext)
Datum jsonb_delete_array(PG_FUNCTION_ARGS)
Datum jsonb_pretty(PG_FUNCTION_ARGS)
static void setPathArray(JsonbIterator **it, const Datum *path_elems, const bool *path_nulls, int path_len, JsonbInState *st, int level, JsonbValue *newval, uint32 nelems, int op_type)
struct DomainIOData DomainIOData
static JsonParseErrorType transform_string_values_array_end(void *state)
static JsonParseErrorType populate_recordset_object_start(void *state)
static RecordIOData * allocate_record_info(MemoryContext mcxt, int ncolumns)
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
static text * JsonbValueAsText(JsonbValue *v)
Datum jsonb_insert(PG_FUNCTION_ARGS)
static JsonParseErrorType get_object_start(void *state)
static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull)
static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull)
static JsonParseErrorType populate_array_object_start(void *_state)
#define JsObjectIsEmpty(jso)
static void get_record_type_from_argument(FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
Datum json_array_element(PG_FUNCTION_ARGS)
Datum jsonb_delete_idx(PG_FUNCTION_ARGS)
static JsonParseErrorType sn_object_end(void *state)
#define JB_PATH_CREATE_OR_INSERT
Datum jsonb_populate_record_valid(PG_FUNCTION_ARGS)
Datum json_array_elements_text(PG_FUNCTION_ARGS)
struct EachState EachState
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype)
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg, Node *escontext)
static HTAB * get_json_object_as_hash(const char *json, int len, const char *funcname, Node *escontext)
static bool populate_array_json(PopulateArrayContext *ctx, const char *json, int len)
struct StripnullState StripnullState
struct IterateJsonStringValuesState IterateJsonStringValuesState
#define JsValueIsString(jsv)
static JsonParseErrorType populate_recordset_object_end(void *state)
static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull, Node *escontext, bool omit_scalar_quotes)
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
struct CompositeIOData CompositeIOData
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull)
Datum jsonb_object_field_text(PG_FUNCTION_ARGS)
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
static JsonParseErrorType get_array_start(void *state)
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype)
static int report_json_context(JsonLexContext *lex)
Datum json_strip_nulls(PG_FUNCTION_ARGS)
struct JsonHashEntry JsonHashEntry
Datum json_array_elements(PG_FUNCTION_ARGS)
Datum jsonb_concat(PG_FUNCTION_ARGS)
struct ArrayIOData ArrayIOData
static JsonParseErrorType okeys_array_start(void *state)
Datum json_object_field_text(PG_FUNCTION_ARGS)
uint32 parse_jsonb_index_flags(Jsonb *jb)
Datum jsonb_extract_path_text(PG_FUNCTION_ARGS)
Datum json_each(PG_FUNCTION_ARGS)
static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype)
Datum jsonb_set_element(Jsonb *jb, const Datum *path, int path_len, JsonbValue *newval)
static JsonParseErrorType sn_object_start(void *state)
static JsonParseErrorType sn_array_start(void *state)
static bool populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
static JsonParseErrorType sn_array_end(void *state)
static void setPathObject(JsonbIterator **it, const Datum *path_elems, const bool *path_nulls, int path_len, JsonbInState *st, int level, JsonbValue *newval, uint32 npairs, int op_type)
Datum json_to_recordset(PG_FUNCTION_ARGS)
static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype)
#define JB_PATH_CONSISTENT_POSITION
static bool populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
JsonTokenType json_get_first_token(text *json, bool throw_error)
Datum jsonb_set(PG_FUNCTION_ARGS)
#define JsValueIsNull(jsv)
static void update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
struct ColumnIOData ColumnIOData
void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
static JsonParseErrorType populate_array_element_end(void *_state, bool isnull)
Datum jsonb_set_lax(PG_FUNCTION_ARGS)
static JsonParseErrorType elements_array_element_end(void *state, bool isnull)
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull)
Datum jsonb_each_text(PG_FUNCTION_ARGS)
static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype)
struct ScalarIOData ScalarIOData
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull)
Datum jsonb_strip_nulls(PG_FUNCTION_ARGS)
struct OkeysState OkeysState
struct PopulateArrayState PopulateArrayState
struct PopulateRecordCache PopulateRecordCache
Datum jsonb_extract_path(PG_FUNCTION_ARGS)
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
static Datum populate_array(ArrayIOData *aio, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext)
static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull)
Datum jsonb_get_element(Jsonb *jb, const Datum *path, int npath, bool *isnull, bool as_text)
Datum json_array_length(PG_FUNCTION_ARGS)
struct JHashState JHashState
void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
struct ElementsState ElementsState
Datum jsonb_array_length(PG_FUNCTION_ARGS)
Datum jsonb_object_field(PG_FUNCTION_ARGS)
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
void iterate_json_values(text *json, uint32 flags, void *action_state, JsonIterateStringValuesAction action)
Datum jsonb_populate_record(PG_FUNCTION_ARGS)
Datum json_extract_path(PG_FUNCTION_ARGS)
static void push_null_elements(JsonbInState *ps, int num)
Datum json_extract_path_text(PG_FUNCTION_ARGS)
static JsonParseErrorType elements_array_element_start(void *state, bool isnull)
static void get_record_type_from_query(FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
Datum json_populate_record(PG_FUNCTION_ARGS)
static JsonParseErrorType populate_recordset_array_element_start(void *state, bool isnull)
#define JB_PATH_FILL_GAPS
Jsonb * transform_jsonb_string_values(Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
static JsonParseErrorType transform_string_values_object_end(void *state)
static bool JsValueToJsObject(JsValue *jsv, JsObject *jso, Node *escontext)
Datum json_object_field(PG_FUNCTION_ARGS)
static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype)
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
static JsonParseErrorType get_object_end(void *state)
static Datum populate_composite(CompositeIOData *io, Oid typid, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv, bool *isnull, Node *escontext)
Datum jsonb_to_record(PG_FUNCTION_ARGS)
Datum jsonb_array_element(PG_FUNCTION_ARGS)
Datum json_object_keys(PG_FUNCTION_ARGS)
struct AlenState AlenState
#define JB_PATH_INSERT_BEFORE
static JsonParseErrorType populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull)
bool pg_parse_json_or_errsave(JsonLexContext *lex, const JsonSemAction *sem, Node *escontext)
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj, Node *escontext)
static void setPath(JsonbIterator **it, const Datum *path_elems, const bool *path_nulls, int path_len, JsonbInState *st, int level, JsonbValue *newval, int op_type)
static JsonParseErrorType alen_object_start(void *state)
static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
static bool populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
static JsonParseErrorType populate_array_element_start(void *_state, bool isnull)
static JsonParseErrorType populate_array_array_end(void *_state)
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
static JsonParseErrorType get_array_end(void *state)
Datum jsonb_to_recordset(PG_FUNCTION_ARGS)
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
#define JB_PATH_INSERT_AFTER
Datum jsonb_each(PG_FUNCTION_ARGS)
static JsonParseErrorType get_array_element_start(void *state, bool isnull)
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull)
static void populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
#define JsObjectFree(jso)
struct PopulateRecordsetState PopulateRecordsetState
static JsonParseErrorType transform_string_values_object_start(void *state)
static JsonParseErrorType transform_string_values_array_element_start(void *state, bool isnull)
static JsonParseErrorType alen_array_element_start(void *state, bool isnull)
static Datum populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
static bool populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
Datum jsonb_array_element_text(PG_FUNCTION_ARGS)
@ TYPECAT_COMPOSITE_DOMAIN
Datum json_to_record(PG_FUNCTION_ARGS)
static JsonParseErrorType each_array_start(void *state)
Datum json_array_element_text(PG_FUNCTION_ARGS)
static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Datum jsonb_array_elements_text(PG_FUNCTION_ARGS)
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
#define pg_parse_json_or_ereport(lex, sem)
text *(* JsonTransformStringValuesAction)(void *state, char *elem_value, int elem_len)
void(* JsonIterateStringValuesAction)(void *state, char *elem_value, int elem_len)
Oid get_element_type(Oid typid)
bool type_is_rowtype(Oid typid)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
char get_typtype(Oid typid)
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Oid getBaseType(Oid typid)
int GetDatabaseEncoding(void)
int pg_mblen(const char *mbstr)
void * MemoryContextAlloc(MemoryContext context, Size size)
void MemoryContextReset(MemoryContext context)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
MemoryContext CurrentMemoryContext
char * pnstrdup(const char *in, Size len)
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define SOFT_ERROR_OCCURRED(escontext)
#define IsA(nodeptr, _type_)
static Datum NumericGetDatum(Numeric X)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
FormData_pg_attribute * Form_pg_attribute
static char buf[DEFAULT_XLOG_SEG_SIZE]
FormData_pg_type * Form_pg_type
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
static Datum PointerGetDatum(const void *X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Pointer DatumGetPointer(Datum X)
static Datum CStringGetDatum(const char *X)
static chr element(struct vars *v, const chr *startp, const chr *endp)
void check_stack_depth(void)
int strtoint(const char *restrict str, char **restrict endptr, int base)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoString(StringInfo str, const char *s)
void initStringInfo(StringInfo str)
#define appendStringInfoCharMacro(str, ch)
ColumnIOData * element_info
CompositeIOData composite
union ColumnIOData::@26 io
const char * result_start
Tuplestorestate * tuple_store
Tuplestorestate * tuple_store
const char * function_name
const char * result_start
MemoryContext ecxt_per_query_memory
MemoryContext multi_call_memory_ctx
const char * result_start
JsonIterateStringValuesAction action
const char * save_json_start
const char * function_name
JsonTokenType saved_token_type
JsonbContainer * jsonb_cont
struct JsValue::@27::@28 json
const char * prev_token_terminator
const char * token_terminator
json_struct_action array_end
json_struct_action object_start
json_ofield_action object_field_start
json_aelem_action array_element_start
json_scalar_action scalar
json_aelem_action array_element_end
json_struct_action array_start
json_struct_action object_end
json_ofield_action object_field_end
JsonTokenType element_type
PopulateArrayContext * ctx
const char * element_start
const char * save_json_start
const char * function_name
Tuplestorestate * tuple_store
PopulateRecordCache * cache
JsonTokenType saved_token_type
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
SetFunctionReturnMode returnMode
Tuplestorestate * setResult
JsonTransformStringValuesAction action
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define FirstNormalObjectId
void FreeTupleDesc(TupleDesc tupdesc)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
#define ReleaseTupleDesc(tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
static Size VARSIZE_ANY_EXHDR(const void *PTR)
static Size VARSIZE(const void *PTR)
static char * VARDATA_ANY(const void *PTR)
text * cstring_to_text_with_len(const char *s, int len)
text * cstring_to_text(const char *s)
char * text_to_cstring(const text *t)