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 bool *path_nulls, int path_len,
483 int op_type);
486 int level,
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;
754 state->result = palloc(256 * sizeof(char *));
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
1048 tpath = palloc(npath * sizeof(char *));
1049 ipath = palloc(npath * sizeof(int));
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;
1121 state->pathok = palloc0(sizeof(bool) * npath);
1122 state->array_cur_index = palloc(sizeof(int) * npath);
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{
1685 bool *path_nulls = palloc0(path_len * sizeof(bool));
1686
1689
1691
1695
1696 pfree(path_nulls);
1697
1699}
1700
1701static void
1703{
1705
1707
1708 while (num-- > 0)
1710}
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720static void
1723{
1724
1725
1726
1727
1728
1729
1732
1733
1734
1735
1736
1737
1738 for (int i = level + 1; i < path_len; i++)
1739 {
1740 char *c,
1741 *badp;
1742 int lindex;
1743
1744 if (path_nulls[i])
1745 break;
1746
1747
1748
1749
1750
1752 errno = 0;
1753 lindex = strtoint(c, &badp, 10);
1754 if (badp == c || *badp != '\0' || errno != 0)
1755 {
1756
1758 newkey.val.string.val = c;
1759 newkey.val.string.len = strlen(c);
1760
1763
1765 }
1766 else
1767 {
1768
1770
1772
1774 }
1775 }
1776
1777
1778 if (tpath[(path_len - level) - 1] == jbvArray)
1779 {
1781 }
1782 else
1784
1785
1786
1787
1788
1789 for (int i = path_len - 1; i > level; i--)
1790 {
1791 if (path_nulls[i])
1792 break;
1793
1796 else
1798 }
1799}
1800
1801
1802
1803
1804static text *
1806{
1807 switch (v->type)
1808 {
1810 return NULL;
1811
1813 return v->val.boolean ?
1816
1819 v->val.string.len);
1820
1822 {
1824
1827
1829 }
1830
1832 {
1834
1837 v->val.binary.len);
1838
1840 }
1841
1842 default:
1843 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1844 return NULL;
1845 }
1846}
1847
1848
1849
1850
1853{
1858
1861
1862#if 0
1863 state->count = 0;
1864#endif
1865
1871
1873
1875}
1876
1879{
1881
1884 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1885 errmsg("cannot get array length of a scalar")));
1888 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1889 errmsg("cannot get array length of a non-array")));
1890
1892}
1893
1894
1895
1896
1897
1898
1901{
1903
1904
1907 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1908 errmsg("cannot get array length of a non-array")));
1909
1911}
1912
1915{
1917
1918
1921 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1922 errmsg("cannot get array length of a scalar")));
1923
1925}
1926
1929{
1931
1932
1934 _state->count++;
1935
1937}
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1951{
1953}
1954
1957{
1959}
1960
1963{
1965}
1966
1969{
1971}
1972
1975{
1979 tmp_cxt;
1980 bool skipNested = false;
1984
1987 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1988 errmsg("cannot call %s on a non-object",
1990
1993
1995 "jsonb_each temporary cxt",
1997
1999
2001 {
2002 skipNested = true;
2003
2005 {
2008 bool nulls[2] = {false, false};
2009
2010
2012
2014
2015
2016
2017
2018
2021
2023
2024 if (as_text)
2025 {
2027 {
2028
2029 nulls[1] = true;
2031 }
2032 else
2034 }
2035 else
2036 {
2037
2039
2041 }
2042
2044
2045
2048 }
2049 }
2050
2052
2054}
2055
2056
2059{
2065
2068
2070
2074
2080
2081 state->normalize_results = as_text;
2082 state->next_scalar = false;
2085 "json_each temporary cxt",
2087
2089
2092
2094}
2095
2096
2099{
2101
2102
2104 {
2105
2106
2107
2108
2109
2112 else
2114 }
2115
2117}
2118
2121{
2124 int len;
2128 bool nulls[2] = {false, false};
2129
2130
2133
2134
2136
2138
2140 {
2141 nulls[1] = true;
2143 }
2145 {
2148 }
2149 else
2150 {
2154 }
2155
2157
2159
2160
2163
2165}
2166
2169{
2171
2172
2175 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2176 errmsg("cannot deconstruct an array as an object")));
2177
2179}
2180
2183{
2185
2186
2189 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2190 errmsg("cannot deconstruct a scalar")));
2191
2192
2195
2197}
2198
2199
2200
2201
2202
2203
2204
2205
2206
2209{
2211}
2212
2215{
2217}
2218
2221 bool as_text)
2222{
2226 tmp_cxt;
2227 bool skipNested = false;
2231
2234 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2235 errmsg("cannot extract elements from a scalar")));
2238 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2239 errmsg("cannot extract elements from an object")));
2240
2242
2244
2246 "jsonb_array_elements temporary cxt",
2248
2250
2252 {
2253 skipNested = true;
2254
2256 {
2258 bool nulls[1] = {false};
2259
2260
2262
2263 if (as_text)
2264 {
2266 {
2267
2268 nulls[0] = true;
2270 }
2271 else
2273 }
2274 else
2275 {
2276
2278
2280 }
2281
2283
2284
2287 }
2288 }
2289
2291
2293}
2294
2297{
2298 return elements_worker(fcinfo, "json_array_elements", false);
2299}
2300
2303{
2304 return elements_worker(fcinfo, "json_array_elements_text", true);
2305}
2306
2309{
2315
2316
2318
2321
2326
2332
2334 state->normalize_results = as_text;
2335 state->next_scalar = false;
2336 state->lex = &lex;
2338 "json_array_elements temporary cxt",
2340
2342
2345
2347}
2348
2351{
2353
2354
2356 {
2357
2358
2359
2360
2361
2364 else
2366 }
2367
2369}
2370
2373{
2376 int len;
2380 bool nulls[1] = {false};
2381
2382
2385
2386
2388
2390 {
2391 nulls[0] = true;
2393 }
2395 {
2398 }
2399 else
2400 {
2404 }
2405
2407
2409
2410
2413
2415}
2416
2419{
2421
2422
2425 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2426 errmsg("cannot call %s on a non-array",
2428
2430}
2431
2434{
2436
2437
2440 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2441 errmsg("cannot call %s on a scalar",
2443
2444
2447
2449}
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2465{
2467 false, true, NULL);
2468}
2469
2470
2471
2472
2473
2474
2475
2478{
2480
2482 false, true, (Node *) &escontext);
2483
2485}
2486
2489{
2491 false, false, NULL);
2492}
2493
2496{
2498 true, true, NULL);
2499}
2500
2503{
2505 true, false, NULL);
2506}
2507
2508
2509static void
2511{
2512 if (ndim <= 0)
2513 {
2516 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2517 errmsg("expected JSON array"),
2518 errhint("See the value of key \"%s\".", ctx->colname)));
2519 else
2521 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2522 errmsg("expected JSON array")));
2523 return;
2524 }
2525 else
2526 {
2528 int i;
2529
2531
2532 Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2533
2534 for (i = 0; i < ndim; i++)
2536
2539 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2540 errmsg("expected JSON array"),
2541 errhint("See the array element %s of key \"%s\".",
2543 else
2545 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2546 errmsg("expected JSON array"),
2547 errhint("See the array element %s.",
2548 indices.data)));
2549 return;
2550 }
2551}
2552
2553
2554
2555
2556
2557
2558
2559static bool
2561{
2562 int i;
2563
2565
2566 if (ndims <= 0)
2567 {
2569
2571 return false;
2572 }
2573
2574 ctx->ndims = ndims;
2575 ctx->dims = palloc(sizeof(int) * ndims);
2577
2578 for (i = 0; i < ndims; i++)
2580
2581 return true;
2582}
2583
2584
2585
2586
2587
2588
2589static bool
2591{
2592 int dim = ctx->sizes[ndim];
2593
2594 if (ctx->dims[ndim] == -1)
2595 ctx->dims[ndim] = dim;
2596 else if (ctx->dims[ndim] != dim)
2598 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2599 errmsg("malformed JSON array"),
2600 errdetail("Multidimensional arrays must have "
2601 "sub-arrays with matching dimensions.")));
2602
2603
2604 ctx->sizes[ndim] = 0;
2605
2606
2607 if (ndim > 0)
2608 ctx->sizes[ndim - 1]++;
2609
2610 return true;
2611}
2612
2613
2614
2615
2616
2617static bool
2619{
2621 bool element_isnull;
2622
2623
2628 jsv, &element_isnull, ctx->escontext,
2629 false);
2630
2632 return false;
2633
2636
2638 ctx->sizes[ndim - 1]++;
2639
2640 return true;
2641}
2642
2643
2646{
2648 int ndim = state->lex->lex_level;
2649
2650 if (state->ctx->ndims <= 0)
2651 {
2654 }
2655 else if (ndim < state->ctx->ndims)
2656 {
2658
2661 }
2662
2664}
2665
2666
2669{
2672 int ndim = state->lex->lex_level;
2673
2674 if (ctx->ndims <= 0)
2675 {
2678 }
2679
2680 if (ndim < ctx->ndims)
2681 {
2682
2685 }
2686
2688}
2689
2690
2693{
2695 int ndim = state->lex->lex_level;
2696
2697 if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2698 {
2699
2700 state->element_start = state->lex->token_start;
2701 state->element_type = state->lex->token_type;
2702 state->element_scalar = NULL;
2703 }
2704
2706}
2707
2708
2711{
2714 int ndim = state->lex->lex_level;
2715
2717
2718 if (ndim == ctx->ndims)
2719 {
2721
2724
2725 if (isnull)
2726 {
2730 }
2731 else if (state->element_scalar)
2732 {
2735 }
2736 else
2737 {
2740 state->element_start) * sizeof(char);
2741 }
2742
2743
2746 }
2747
2749}
2750
2751
2754{
2757 int ndim = state->lex->lex_level;
2758
2759 if (ctx->ndims <= 0)
2760 {
2763 }
2764 else if (ndim < ctx->ndims)
2765 {
2767
2770 }
2771
2772 if (ndim == ctx->ndims)
2773 {
2774
2776
2777 Assert(state->element_type == tokentype);
2778 }
2779
2781}
2782
2783
2784
2785
2786
2787
2788static bool
2790{
2793
2796 state.ctx = ctx;
2797
2798 memset(&sem, 0, sizeof(sem));
2805
2807 {
2808
2810 }
2811
2813
2815}
2816
2817
2818
2819
2820
2821
2822
2823
2824static bool
2826 JsonbValue *jbv,
2827 int ndim)
2828{
2834
2836
2837
2840 {
2842
2844 return false;
2845 }
2846
2848
2851
2853
2854
2855
2856
2857
2858
2859 if (ctx->ndims <= 0 &&
2864 {
2866 return false;
2867 }
2868
2871
2872
2874 {
2875
2876
2877
2878
2879 if (ctx->ndims > 0 && ndim >= ctx->ndims)
2880 {
2882 return false;
2883 }
2884 else
2885 {
2886
2888 return false;
2889
2890
2892
2894 return false;
2895 }
2896
2898 }
2899
2901
2902
2905
2906 return true;
2907}
2908
2909
2910
2911
2912
2913
2916 const char *colname,
2919 bool *isnull,
2920 Node *escontext)
2921{
2924 int *lbs;
2925 int i;
2926
2927 ctx.aio = aio;
2928 ctx.mcxt = mcxt;
2932 ctx.ndims = 0;
2933 ctx.dims = NULL;
2934 ctx.sizes = NULL;
2936
2938 {
2939
2943 {
2944 *isnull = true;
2945 return (Datum) 0;
2946 }
2947 }
2948 else
2949 {
2950
2952 {
2953 *isnull = true;
2954 return (Datum) 0;
2955 }
2957 }
2958
2960
2962
2963 for (i = 0; i < ctx.ndims; i++)
2964 lbs[i] = 1;
2965
2967 ctx.acxt, true);
2968
2972
2973 *isnull = false;
2974 return result;
2975}
2976
2977
2978
2979
2980
2981static bool
2983{
2985
2987 {
2988
2994 "populate_composite",
2995 escontext);
2997 }
2998 else
2999 {
3001
3004 {
3006 }
3007 else
3008 {
3009 bool is_scalar;
3010
3015 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3016 is_scalar
3017 ? errmsg("cannot call %s on a scalar",
3018 "populate_composite")
3019 : errmsg("cannot call %s on an array",
3020 "populate_composite")));
3021 }
3022 }
3023
3025}
3026
3027
3028static void
3030{
3034 {
3038
3041
3042
3046
3048 }
3049}
3050
3051
3052
3053
3054
3055
3056
3059 Oid typid,
3060 const char *colname,
3064 bool *isnull,
3065 Node *escontext)
3066{
3068
3069
3071
3072 if (*isnull)
3073 result = (Datum) 0;
3074 else
3075 {
3078
3079
3081 {
3082 *isnull = true;
3083 return (Datum) 0;
3084 }
3085
3086
3088 defaultval, mcxt, &jso, escontext);
3089
3091 {
3092 *isnull = true;
3093 return (Datum) 0;
3094 }
3096
3098 }
3099
3100
3101
3102
3103
3104
3105 if (typid != io->base_typid && typid != RECORDOID)
3106 {
3108 escontext))
3109 {
3110 *isnull = true;
3111 return (Datum) 0;
3112 }
3113 }
3114
3115 return result;
3116}
3117
3118
3119
3120
3121
3122
3123
3126 bool *isnull, Node *escontext, bool omit_quotes)
3127{
3129 char *str = NULL;
3130 const char *json = NULL;
3131
3133 {
3135
3138
3139
3140 if ((typid == JSONOID || typid == JSONBOID) &&
3142 {
3144
3146 if (len >= 0)
3148 else
3151 }
3152 else if (len >= 0)
3153 {
3154
3158 }
3159 else
3160 {
3161
3163 }
3164 }
3165 else
3166 {
3168
3171 else if (typid == JSONBOID)
3172 {
3174
3176 }
3177
3178 else if (typid == JSONOID && jbv->type != jbvBinary)
3179 {
3180
3181
3182
3183
3185
3187 }
3188 else if (jbv->type == jbvString)
3191 str = pstrdup(jbv->val.boolean ? "true" : "false");
3197 jbv->val.binary.len);
3198 else
3199 elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
3200 }
3201
3203 escontext, &res))
3204 {
3205 res = (Datum) 0;
3206 *isnull = true;
3207 }
3208
3209
3210 if (str != json)
3212
3213 return res;
3214}
3215
3218 Oid typid,
3219 const char *colname,
3222 bool *isnull,
3223 Node *escontext,
3224 bool omit_quotes)
3225{
3227
3228 if (*isnull)
3229 res = (Datum) 0;
3230 else
3231 {
3235 jsv, isnull, escontext, omit_quotes);
3237 }
3238
3240 escontext))
3241 {
3242 *isnull = true;
3243 return (Datum) 0;
3244 }
3245
3246 return res;
3247}
3248
3249
3250static void
3252 Oid typid,
3255 bool need_scalar)
3256{
3259
3260 column->typid = typid;
3261 column->typmod = typmod;
3262
3265 elog(ERROR, "cache lookup failed for type %u", typid);
3266
3268
3269 if (type->typtype == TYPTYPE_DOMAIN)
3270 {
3271
3272
3273
3274
3275 Oid base_typid;
3276 int32 base_typmod = typmod;
3277
3279 if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
3280 {
3281
3288 }
3289 else
3290 {
3291
3298 }
3299 }
3300 else if (type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
3301 {
3308 }
3309 else if (IsTrueArrayType(type))
3310 {
3315
3317 }
3318 else
3319 {
3321 need_scalar = true;
3322 }
3323
3324
3325 if (need_scalar)
3326 {
3327 Oid typioproc;
3328
3331 }
3332
3334}
3335
3336
3337
3338
3339
3340
3341
3342
3343
3348 bool *isnull, bool omit_quotes,
3349 Node *escontext)
3350{
3353
3354 jsv.is_json = json_type == JSONOID;
3355
3356 if (*isnull)
3357 {
3360 else
3362 }
3364 {
3366
3370
3371 }
3372 else
3373 {
3375
3377
3378 if (omit_quotes)
3379 {
3381
3382
3384 jbv.val.string.len = strlen(str);
3385 jbv.val.string.val = str;
3386 }
3387 else
3388 {
3389
3391 jbv.val.binary.data = &jsonb->root;
3393 }
3394 }
3395
3396 if (*cache == NULL)
3398
3401 escontext, omit_quotes);
3402}
3403
3404
3407 Oid typid,
3409 const char *colname,
3411 Datum defaultval,
3413 bool *isnull,
3414 Node *escontext,
3415 bool omit_scalar_quotes)
3416{
3418
3420
3421
3422
3423
3424
3425 if (col->typid != typid || col->typmod != typmod)
3427
3429
3430 typcat = col->typcat;
3431
3432
3438
3439
3440 if (*isnull &&
3443 return (Datum) 0;
3444
3445 switch (typcat)
3446 {
3449 isnull, escontext, omit_scalar_quotes);
3450
3453 isnull, escontext);
3454
3458 colname, mcxt,
3461 : NULL,
3462 jsv, isnull,
3463 escontext);
3464
3467 jsv, isnull, escontext, omit_scalar_quotes);
3468
3469 default:
3470 elog(ERROR, "unrecognized type category '%c'", typcat);
3471 return (Datum) 0;
3472 }
3473}
3474
3477{
3482
3484 data->record_typmod = 0;
3485 data->ncolumns = ncolumns;
3487
3488 return data;
3489}
3490
3491static bool
3493{
3495
3497 {
3500
3503 hashentry->val;
3505
3506 return hashentry != NULL;
3507 }
3508 else
3509 {
3512 NULL);
3513
3514 return jsv->val.jsonb != NULL;
3515 }
3516}
3517
3518
3525 Node *escontext)
3526{
3529 bool *nulls;
3531 int ncolumns = tupdesc->natts;
3532 int i;
3533
3534
3535
3536
3537
3538
3540 return defaultval;
3541
3542
3543 if (record == NULL ||
3544 record->ncolumns != ncolumns)
3546
3547
3550 {
3555 record->ncolumns = ncolumns;
3556 }
3557
3559 nulls = (bool *) palloc(ncolumns * sizeof(bool));
3560
3561 if (defaultval)
3562 {
3564
3565
3569 tuple.t_data = defaultval;
3570
3571
3573 }
3574 else
3575 {
3576 for (i = 0; i < ncolumns; ++i)
3577 {
3579 nulls[i] = true;
3580 }
3581 }
3582
3583 for (i = 0; i < ncolumns; ++i)
3584 {
3586 char *colname = NameStr(att->attname);
3588 bool found;
3589
3590
3591 if (att->attisdropped)
3592 {
3593 nulls[i] = true;
3594 continue;
3595 }
3596
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607 if (defaultval && !found)
3608 continue;
3609
3611 att->atttypid,
3612 att->atttypmod,
3613 colname,
3614 mcxt,
3616 &field,
3617 &nulls[i],
3618 escontext,
3619 false);
3620 }
3621
3623
3626
3628}
3629
3630
3631
3632
3633
3634
3635static void
3639{
3647 (errcode(ERRCODE_DATATYPE_MISMATCH),
3648
3649 errmsg("first argument of %s must be a row type",
3651}
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661static void
3665{
3668
3671 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3672
3673 errmsg("could not determine row type for result of %s",
3675 errhint("Provide a non-null record argument, "
3676 "or call the function in the FROM clause "
3677 "using a column definition list.")));
3678
3681
3682
3685
3686
3692}
3693
3694
3695
3696
3697
3700 bool is_json, bool have_record_arg,
3701 Node *escontext)
3702{
3703 int json_arg_num = have_record_arg ? 1 : 0;
3707 bool isnull;
3711
3712
3713
3714
3715
3716
3717 if (!cache)
3718 {
3721 cache->fn_mcxt = fnmcxt;
3722
3723 if (have_record_arg)
3725 else
3727 }
3728
3729
3730 if (!have_record_arg)
3731 rec = NULL;
3733 {
3735
3736
3737
3738
3739
3740 if (cache->argtype == RECORDOID)
3741 {
3744 }
3745 }
3746 else
3747 {
3748 rec = NULL;
3749
3750
3751
3752
3753
3754 if (cache->argtype == RECORDOID)
3755 {
3757
3759 }
3760 }
3761
3762
3764 {
3765 if (rec)
3767 else
3769 }
3770
3772
3773 if (is_json)
3774 {
3776
3780
3781 }
3782 else
3783 {
3785
3787
3788
3790 jbv.val.binary.data = &jb->root;
3792 }
3793
3794 isnull = false;
3796 NULL, fnmcxt, rec, &jsv, &isnull,
3797 escontext);
3799
3801}
3802
3803
3804
3805
3806
3807
3808
3809
3810static HTAB *
3812 Node *escontext)
3813{
3818
3822 tab = hash_create("json object hashtable",
3823 100,
3826
3829
3831 state->hash = tab;
3834
3840
3842 {
3844 tab = NULL;
3845 }
3846
3848
3849 return tab;
3850}
3851
3854{
3856
3859
3860
3862
3865 {
3866
3868 }
3869 else
3870 {
3871
3873 }
3874
3876}
3877
3880{
3883 bool found;
3884
3885
3886
3887
3890
3891
3892
3893
3894
3895
3896
3897
3900
3902
3903
3904
3905
3906
3907
3910
3912 {
3914 char *val = palloc((len + 1) * sizeof(char));
3915
3919 }
3920 else
3921 {
3922
3924 }
3925
3927}
3928
3931{
3933
3936 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3938
3940}
3941
3944{
3946
3949 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3951
3953 {
3955
3957 }
3958
3960}
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3975{
3977 false, true);
3978}
3979
3982{
3984 false, false);
3985}
3986
3989{
3991 true, true);
3992}
3993
3996{
3998 true, false);
3999}
4000
4001static void
4003{
4007
4008
4010
4011
4016 obj,
4017 NULL);
4018
4019
4025 NULL);
4026
4027
4031 tuple.t_data = tuphead;
4032
4034}
4035
4036
4037
4038
4039
4042 bool is_json, bool have_record_arg)
4043{
4044 int json_arg_num = have_record_arg ? 1 : 0;
4050
4052
4055 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4056 errmsg("set-valued function called in context that cannot accept a set")));
4057
4060 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4061 errmsg("materialize mode required, but it is not allowed in this context")));
4062
4064
4065
4066
4067
4068
4069
4070 if (!cache)
4071 {
4075
4076 if (have_record_arg)
4078 else
4080 }
4081
4082
4083 if (!have_record_arg)
4084 rec = NULL;
4086 {
4088
4089
4090
4091
4092
4093 if (cache->argtype == RECORDOID)
4094 {
4097 }
4098 }
4099 else
4100 {
4101 rec = NULL;
4102
4103
4104
4105
4106
4107 if (cache->argtype == RECORDOID)
4108 {
4110
4112 }
4113 }
4114
4115
4118
4119
4120
4121
4122
4124
4126
4127
4133
4135 state->cache = cache;
4136 state->rec = rec;
4137
4138 if (is_json)
4139 {
4143
4145
4147
4156
4157 state->lex = &lex;
4158
4160
4162 state->lex = NULL;
4163 }
4164 else
4165 {
4169 bool skipNested = false;
4171
4174 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4175 errmsg("cannot call %s on a non-array",
4177
4179
4181 {
4182 skipNested = true;
4183
4185 {
4187
4191 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4192 errmsg("argument of %s must be an array of objects",
4194
4197
4199 }
4200 }
4201 }
4202
4203
4204
4205
4206
4207
4210
4212}
4213
4216{
4220
4221
4222 if (lex_level == 0)
4224 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4225 errmsg("cannot call %s on an object",
4227
4228
4229 if (lex_level > 1)
4231
4232
4237 100,
4240
4242}
4243
4246{
4249
4250
4253
4256
4257
4259
4260
4263
4265}
4266
4269{
4271
4275 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4276 errmsg("argument of %s must be an array of objects",
4278
4280}
4281
4284{
4285
4287}
4288
4291{
4293
4296 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4297 errmsg("cannot call %s on a scalar",
4299
4302
4304}
4305
4308{
4310
4313
4315
4318 {
4320 }
4321 else
4322 {
4324 }
4325
4327}
4328
4331{
4334 bool found;
4335
4336
4337
4338
4341
4342
4343
4344
4345
4346
4347
4348
4351
4353
4354
4355
4356
4357
4358
4361
4363 {
4365 char *val = palloc((len + 1) * sizeof(char));
4366
4370 }
4371 else
4372 {
4373
4375 }
4376
4378}
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4391{
4393
4395
4397}
4398
4401{
4403
4405
4407}
4408
4411{
4413
4415
4417}
4418
4421{
4423
4425
4427}
4428
4431{
4433
4434 if (isnull)
4435 {
4436
4437
4438
4439
4440
4443 }
4444
4447
4448
4449
4450
4451
4453
4455
4457}
4458
4461{
4463
4464
4466 {
4469 }
4470
4471
4474 {
4476 }
4477
4479}
4480
4483{
4485
4487 {
4491 }
4492
4495 else
4497
4499}
4500
4501
4502
4503
4506{
4512
4515
4518 state->skip_next_null = false;
4519 state->strip_in_arrays = strip_in_arrays;
4520
4529
4531
4533 state->strval->len));
4534}
4535
4536
4537
4538
4541{
4543 bool strip_in_arrays = false;
4548 k;
4550 bool last_was_key = false;
4551
4554
4557
4559
4561 {
4563
4565 {
4566
4567 k = v;
4568 last_was_key = true;
4569 continue;
4570 }
4571
4572 if (last_was_key)
4573 {
4574
4575 last_was_key = false;
4576
4577
4579 continue;
4580
4581
4583 }
4584
4585
4586 if (strip_in_arrays)
4588 continue;
4589
4592 else
4594 }
4595
4596 Assert(res != NULL);
4597
4599}
4600
4601
4602
4603
4604
4605
4608{
4611
4613
4615}
4616
4617
4618
4619
4620
4621
4624{
4630 *it2;
4631
4632
4633
4634
4635
4636
4637
4639 {
4644 }
4645
4648
4650
4651 Assert(res != NULL);
4652
4654}
4655
4656
4657
4658
4659
4660
4661
4662
4665{
4673 *res = NULL;
4674 bool skipNested = false;
4676
4679 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4680 errmsg("cannot delete from scalar")));
4681
4684
4686
4688 {
4689 skipNested = true;
4690
4693 memcmp(keyptr, v.val.string.val, keylen) == 0))
4694 {
4695
4698
4699 continue;
4700 }
4701
4703 }
4704
4705 Assert(res != NULL);
4706
4708}
4709
4710
4711
4712
4713
4714
4715
4718{
4721 Datum *keys_elems;
4722 bool *keys_nulls;
4723 int keys_len;
4727 *res = NULL;
4728 bool skipNested = false;
4730
4733 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4734 errmsg("wrong number of array subscripts")));
4735
4738 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4739 errmsg("cannot delete from scalar")));
4740
4743
4745
4746 if (keys_len == 0)
4748
4750
4752 {
4753 skipNested = true;
4754
4756 {
4757 int i;
4758 bool found = false;
4759
4760 for (i = 0; i < keys_len; i++)
4761 {
4762 char *keyptr;
4763 int keylen;
4764
4765 if (keys_nulls[i])
4766 continue;
4767
4768
4771 if (keylen == v.val.string.len &&
4772 memcmp(keyptr, v.val.string.val, keylen) == 0)
4773 {
4774 found = true;
4775 break;
4776 }
4777 }
4778 if (found)
4779 {
4780
4783
4784 continue;
4785 }
4786 }
4787
4789 }
4790
4791 Assert(res != NULL);
4792
4794}
4795
4796
4797
4798
4799
4800
4801
4802
4805{
4811 n;
4813 *res = NULL;
4815
4818 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4819 errmsg("cannot delete from scalar")));
4820
4823 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4824 errmsg("cannot delete from object using integer index")));
4825
4828
4830
4833 n = v.val.array.nElems;
4834
4835 if (idx < 0)
4836 {
4838 idx = n;
4839 else
4841 }
4842
4843 if (idx >= n)
4845
4847
4849 {
4851 {
4853 continue;
4854 }
4855
4857 }
4858
4859 Assert(res != NULL);
4860
4862}
4863
4864
4865
4866
4869{
4876 Datum *path_elems;
4877 bool *path_nulls;
4878 int path_len;
4881
4883
4886 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4887 errmsg("wrong number of array subscripts")));
4888
4891 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4892 errmsg("cannot set path in scalar")));
4893
4896
4898
4899 if (path_len == 0)
4901
4903
4904 res = setPath(&it, path_elems, path_nulls, path_len, &st,
4906
4907 Assert(res != NULL);
4908
4910}
4911
4912
4913
4914
4915
4918{
4919
4920
4921
4922
4923 text *handle_null;
4924 char *handle_val;
4925
4928
4929
4932 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4933 errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4934
4935
4938
4941
4942 if (strcmp(handle_val, "raise_exception") == 0)
4943 {
4945 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4946 errmsg("JSON value must not be null"),
4947 errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4948 errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4949 return (Datum) 0;
4950 }
4951 else if (strcmp(handle_val, "use_json_null") == 0)
4952 {
4954
4956
4957 fcinfo->args[2].value = newval;
4958 fcinfo->args[2].isnull = false;
4960 }
4961 else if (strcmp(handle_val, "delete_key") == 0)
4962 {
4964 }
4965 else if (strcmp(handle_val, "return_target") == 0)
4966 {
4968
4970 }
4971 else
4972 {
4974 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4975 errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4976 return (Datum) 0;
4977 }
4978}
4979
4980
4981
4982
4985{
4989 Datum *path_elems;
4990 bool *path_nulls;
4991 int path_len;
4994
4997 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4998 errmsg("wrong number of array subscripts")));
4999
5002 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5003 errmsg("cannot delete path in scalar")));
5004
5007
5009
5010 if (path_len == 0)
5012
5014
5015 res = setPath(&it, path_elems, path_nulls, path_len, &st,
5017
5018 Assert(res != NULL);
5019
5021}
5022
5023
5024
5025
5028{
5035 Datum *path_elems;
5036 bool *path_nulls;
5037 int path_len;
5040
5042
5045 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5046 errmsg("wrong number of array subscripts")));
5047
5050 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5051 errmsg("cannot set path in scalar")));
5052
5054
5055 if (path_len == 0)
5057
5059
5060 res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
5062
5063 Assert(res != NULL);
5064
5066}
5067
5068
5069
5070
5071
5072
5073
5074
5078{
5080 v2,
5081 *res = NULL;
5083 r2,
5084 rk1,
5085 rk2;
5086
5089
5090
5091
5092
5093
5095 {
5096
5097
5098
5099
5100
5101
5105
5106
5107
5108
5109
5110
5113 }
5115 {
5116
5117
5118
5120
5122 {
5125 }
5126
5128 {
5131 }
5132
5134 }
5136 {
5137
5138
5139
5141
5143
5147
5150 }
5151 else
5152 {
5153
5154
5155
5158
5160
5163
5167
5169 }
5170
5171 return res;
5172}
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5205 bool *path_nulls, int path_len,
5207{
5211
5213
5214 if (path_nulls[level])
5216 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5217 errmsg("path element at position %d is null",
5218 level + 1)));
5219
5221
5222 switch (r)
5223 {
5225
5226
5227
5228
5229
5230
5231
5233 v.val.array.rawScalar)
5235 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5236 errmsg("cannot replace existing key"),
5237 errdetail("The path assumes key is a composite object, "
5238 "but it is a scalar value.")));
5239
5241 setPathArray(it, path_elems, path_nulls, path_len, st, level,
5242 newval, v.val.array.nElems, op_type);
5246 break;
5249 setPathObject(it, path_elems, path_nulls, path_len, st, level,
5250 newval, v.val.object.nPairs, op_type);
5254 break;
5257
5258
5259
5260
5261
5262
5263
5266 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5267 errmsg("cannot replace existing key"),
5268 errdetail("The path assumes key is a composite object, "
5269 "but it is a scalar value.")));
5270
5272 break;
5273 default:
5274 elog(ERROR, "unrecognized iterator result: %d", (int) r);
5275 res = NULL;
5276 break;
5277 }
5278
5279 return res;
5280}
5281
5282
5283
5284
5285static void
5289{
5290 text *pathelem = NULL;
5291 int i;
5293 v;
5294 bool done = false;
5295
5296 if (level >= path_len || path_nulls[level])
5297 done = true;
5298 else
5299 {
5300
5302 }
5303
5304
5306 (level == path_len - 1))
5307 {
5309
5313
5316 }
5317
5318 for (i = 0; i < npairs; i++)
5319 {
5321
5323
5324 if (!done &&
5327 k.val.string.len) == 0)
5328 {
5329 done = true;
5330
5331 if (level == path_len - 1)
5332 {
5333
5334
5335
5336
5339 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5340 errmsg("cannot replace existing key"),
5341 errhint("Try using the function jsonb_set "
5342 "to replace key value.")));
5343
5346 {
5349 }
5350 }
5351 else
5352 {
5354 setPath(it, path_elems, path_nulls, path_len,
5355 st, level + 1, newval, op_type);
5356 }
5357 }
5358 else
5359 {
5361 level == path_len - 1 && i == npairs - 1)
5362 {
5364
5368
5371 }
5372
5377 {
5378 int walking_level = 1;
5379
5380 while (walking_level != 0)
5381 {
5383
5385 ++walking_level;
5387 --walking_level;
5388
5390 }
5391 }
5392 }
5393 }
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405 if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5406 {
5408
5412
5414 (void) push_path(st, level, path_elems, path_nulls,
5416
5417
5418 }
5419}
5420
5421
5422
5423
5424static void
5428{
5430 int idx,
5431 i;
5432 bool done = false;
5433
5434
5435 if (level < path_len && !path_nulls[level])
5436 {
5438 char *badp;
5439
5440 errno = 0;
5442 if (badp == c || *badp != '\0' || errno != 0)
5444 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5445 errmsg("path element at position %d is not an integer: \"%s\"",
5446 level + 1, c)));
5447 }
5448 else
5449 idx = nelems;
5450
5451 if (idx < 0)
5452 {
5454 {
5455
5456
5457
5458
5461 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5462 errmsg("path element at position %d is out of range: %d",
5463 level + 1, idx)));
5464 else
5466 }
5467 else
5469 }
5470
5471
5472
5473
5474
5476 {
5477 if (idx > 0 && idx > nelems)
5478 idx = nelems;
5479 }
5480
5481
5482
5483
5484
5485
5486 if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5488 {
5490
5493
5495
5496 done = true;
5497 }
5498
5499
5500 for (i = 0; i < nelems; i++)
5501 {
5503
5504 if (i == idx && level < path_len)
5505 {
5506 done = true;
5507
5508 if (level == path_len - 1)
5509 {
5511
5514
5515
5516
5517
5518
5519
5522
5525 }
5526 else
5527 (void) setPath(it, path_elems, path_nulls, path_len,
5528 st, level + 1, newval, op_type);
5529 }
5530 else
5531 {
5533
5535
5537 {
5538 int walking_level = 1;
5539
5540 while (walking_level != 0)
5541 {
5543
5545 ++walking_level;
5547 --walking_level;
5548
5550 }
5551 }
5552 }
5553 }
5554
5556 {
5557
5558
5559
5560
5563
5565 done = true;
5566 }
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578 if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5579 {
5580 if (idx > 0)
5582
5583 (void) push_path(st, level, path_elems, path_nulls,
5585
5586
5587 }
5588}
5589
5590
5591
5592
5593
5594
5597{
5602
5604
5606
5607
5608
5609
5610
5611
5614 errmsg("wrong flag type, only arrays and scalars are allowed")));
5615
5617 {
5620 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5621 errmsg("flag array element is not a string"),
5622 errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5623
5624 if (v.val.string.len == 3 &&
5627 else if (v.val.string.len == 3 &&
5630 else if (v.val.string.len == 6 &&
5633 else if (v.val.string.len == 7 &&
5636 else if (v.val.string.len == 7 &&
5639 else
5641 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5642 errmsg("wrong flag in flag array: \"%s\"",
5644 errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5645 }
5646
5647
5649 elog(ERROR, "unexpected end of flag array");
5650
5651
5654 elog(ERROR, "unexpected end of flag array");
5655
5656 return flags;
5657}
5658
5659
5660
5661
5662
5663void
5666{
5670
5672
5673
5674
5675
5676
5678 {
5680 {
5683
5684 continue;
5685 }
5687 {
5688
5689 continue;
5690 }
5691
5692
5693 switch (v.type)
5694 {
5698 break;
5701 {
5702 char *val;
5703
5706
5709 }
5710 break;
5713 {
5714 if (v.val.boolean)
5716 else
5718 }
5719 break;
5720 default:
5721
5722 break;
5723 }
5724 }
5725}
5726
5727
5728
5729
5730
5731void
5734{
5738
5741 state->action_state = action_state;
5742 state->flags = flags;
5743
5747
5750}
5751
5752
5753
5754
5755
5758{
5760
5761 switch (tokentype)
5762 {
5766 break;
5770 break;
5775 break;
5776 default:
5777
5778 break;
5779 }
5780
5782}
5783
5786{
5788
5790 {
5792
5794 }
5795
5797}
5798
5799
5800
5801
5802
5803
5804
5808{
5811 *res = NULL;
5815 bool is_scalar = false;
5816
5819
5821 {
5823 {
5824 out = transform_action(action_state, v.val.string.val, v.val.string.len);
5825
5830 }
5831 else
5832 {
5836 }
5837 }
5838
5840 res->val.array.rawScalar = is_scalar;
5841
5843}
5844
5845
5846
5847
5848
5849
5850
5851
5855{
5859
5862 state->action = transform_action;
5863 state->action_state = action_state;
5864
5873
5876
5878}
5879
5880
5881
5882
5883
5884
5887{
5889
5891
5893}
5894
5897{
5899
5901
5903}
5904
5907{
5909
5911
5913}
5914
5917{
5919
5921
5923}
5924
5927{
5929
5932
5933
5934
5935
5936
5939
5941}
5942
5945{
5947
5950
5952}
5953
5956{
5958
5960 {
5962
5964 }
5965 else
5967
5969}
5970
5973{
5976
5978
5979
5981
5984
5985 if (throw_error)
5987
5989}
5990
5991
5992
5993
5994
5995
5996
5997
5998void
6001{
6002 bool typisvarlena;
6003
6004
6006
6008
6009 switch (typoid)
6010 {
6011 case BOOLOID:
6012 *outfuncoid = F_BOOLOUT;
6014 break;
6015
6016 case INT2OID:
6017 case INT4OID:
6018 case INT8OID:
6019 case FLOAT4OID:
6020 case FLOAT8OID:
6021 case NUMERICOID:
6024 break;
6025
6026 case DATEOID:
6027 *outfuncoid = F_DATE_OUT;
6029 break;
6030
6031 case TIMESTAMPOID:
6032 *outfuncoid = F_TIMESTAMP_OUT;
6034 break;
6035
6036 case TIMESTAMPTZOID:
6037 *outfuncoid = F_TIMESTAMPTZ_OUT;
6039 break;
6040
6041 case JSONOID:
6044 break;
6045
6046 case JSONBOID:
6049 break;
6050
6051 default:
6052
6054 || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
6055 {
6056 *outfuncoid = F_ARRAY_OUT;
6058 }
6059 else if (type_is_rowtype(typoid))
6060 {
6061 *outfuncoid = F_RECORD_OUT;
6063 }
6064 else
6065 {
6066
6067
6068
6069
6070
6073 {
6074 Oid castfunc;
6076
6079 &castfunc);
6081 {
6082 *outfuncoid = castfunc;
6084 }
6085 else
6086 {
6087
6089 }
6090 }
6091 else
6092 {
6093
6095 }
6096 }
6097 break;
6098 }
6099}
Datum idx(PG_FUNCTION_ARGS)
#define PG_GETARG_ARRAYTYPE_P(n)
bool array_contains_nulls(ArrayType *array)
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
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)
void hash_destroy(HTAB *hashp)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
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
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, fmNodePtr 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_)
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
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 JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Datum json_each_text(PG_FUNCTION_ARGS)
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)
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, int op_type)
Datum jsonb_pretty(PG_FUNCTION_ARGS)
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
static void setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 nelems, int op_type)
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)
static void push_path(JsonbParseState **st, int level, Datum *path_elems, bool *path_nulls, int path_len, JsonbValue *newval)
struct JsonHashEntry JsonHashEntry
Datum jsonb_set_element(Jsonb *jb, Datum *path, int path_len, JsonbValue *newval)
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)
static JsonParseErrorType sn_object_start(void *state)
static JsonParseErrorType sn_array_start(void *state)
static bool populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
static JsonParseErrorType sn_array_end(void *state)
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)
static void push_null_elements(JsonbParseState **ps, int num)
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 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)
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 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 void setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 npairs, int op_type)
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)
void * palloc0(Size size)
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
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 *pg_restrict str, char **pg_restrict endptr, int base)
StringInfo makeStringInfo(void)
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
union ColumnIOData::@24 io
CompositeIOData composite
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::@25::@26 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)
#define VARSIZE_ANY_EXHDR(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)