PostgreSQL Source Code git master
pg_dependencies.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_dependencies.c
4 * pg_dependencies data type support.
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * IDENTIFICATION
10 * src/backend/utils/adt/pg_dependencies.c
11 *
12 *-------------------------------------------------------------------------
13 */
14
15#include "postgres.h"
16
17#include "common/int.h"
18#include "common/jsonapi.h"
19#include "lib/stringinfo.h"
20#include "mb/pg_wchar.h"
21#include "nodes/miscnodes.h"
24#include "utils/builtins.h"
25#include "utils/float.h"
26#include "utils/fmgrprotos.h"
27
28typedef enum
29{
39
40typedef struct
41{
42 const char *str;
44
47
48 bool found_attributes; /* Item has an attributes key */
49 bool found_dependency; /* Item has an dependency key */
50 bool found_degree; /* Item has degree key */
51 List *attnum_list; /* Accumulated attribute numbers */
53 double degree;
55
56/*
57 * Invoked at the start of each MVDependency object.
58 *
59 * The entire JSON document should be one array of MVDependency objects.
60 *
61 * If we are anywhere else in the document, it's an error.
62 */
65{
67
68 switch (parse->state)
69 {
71 /* Now we expect to see attributes/dependency/degree keys */
72 parse->state = DEPS_EXPECT_KEY;
73 return JSON_SUCCESS;
74
76 /* pg_dependencies must begin with a '[' */
77 errsave(parse->escontext,
78 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
79 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
80 errdetail("Initial element must be an array."));
81 break;
82
83 case DEPS_EXPECT_KEY:
84 /* In an object, expecting key */
85 errsave(parse->escontext,
86 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
87 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
88 errdetail("A key was expected."));
89 break;
90
92 /* Just followed an "attributes": key */
93 errsave(parse->escontext,
94 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
95 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
96 errdetail("Value of \"%s\" must be an array of attribute numbers.",
98 break;
99
101 /* In an attribute number list, expect only scalar integers */
102 errsave(parse->escontext,
103 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
104 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
105 errdetail("Attribute lists can only contain attribute numbers."));
106 break;
107
109 /* Just followed a "dependency" key */
110 errsave(parse->escontext,
111 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
112 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
113 errdetail("Value of \"%s\" must be an integer.",
115 break;
116
118 /* Just followed a "degree" key */
119 errsave(parse->escontext,
120 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
121 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
122 errdetail("Value of \"%s\" must be an integer.",
124 break;
125
126 default:
127 elog(ERROR,
128 "object start of \"%s\" found in unexpected parse state: %d.",
129 "pg_dependencies", (int) parse->state);
130 break;
131 }
132
134}
135
136/*
137 * Invoked at the end of an object.
138 *
139 * Handle the end of an MVDependency object's JSON representation.
140 */
143{
145
146 MVDependency *dep;
147
148 int natts = 0;
149
150 if (parse->state != DEPS_EXPECT_KEY)
151 elog(ERROR,
152 "object end of \"%s\" found in unexpected parse state: %d.",
153 "pg_dependencies", (int) parse->state);
154
155 if (!parse->found_attributes)
156 {
157 errsave(parse->escontext,
158 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
159 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
160 errdetail("Item must contain \"%s\" key.",
163 }
164
165 if (!parse->found_dependency)
166 {
167 errsave(parse->escontext,
168 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
169 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
170 errdetail("Item must contain \"%s\" key.",
173 }
174
175 if (!parse->found_degree)
176 {
177 errsave(parse->escontext,
178 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
179 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
180 errdetail("Item must contain \"%s\" key.",
183 }
184
185 /*
186 * We need at least one attribute number in a dependencies item, anything
187 * less is malformed.
188 */
189 natts = list_length(parse->attnum_list);
190 if ((natts < 1) || (natts > (STATS_MAX_DIMENSIONS - 1)))
191 {
192 errsave(parse->escontext,
193 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
194 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
195 errdetail("The \"%s\" key must contain an array of at least %d and no more than %d elements.",
199 }
200
201 /*
202 * Allocate enough space for the dependency, the attribute numbers in the
203 * list and the final attribute number for the dependency.
204 */
205 dep = palloc0(offsetof(MVDependency, attributes) + ((natts + 1) * sizeof(AttrNumber)));
206 dep->nattributes = natts + 1;
207
208 dep->attributes[natts] = parse->dependency;
209 dep->degree = parse->degree;
210
211 /*
212 * Assign attribute numbers to the attributes array, comparing each one
213 * against the dependency attribute to ensure that there there are no
214 * matches.
215 */
216 for (int i = 0; i < natts; i++)
217 {
218 dep->attributes[i] = (AttrNumber) list_nth_int(parse->attnum_list, i);
219 if (dep->attributes[i] == parse->dependency)
220 {
221 errsave(parse->escontext,
222 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
223 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
224 errdetail("Item \"%s\" with value %d has been found in the \"%s\" list.",
228 }
229 }
230
231 parse->dependency_list = lappend(parse->dependency_list, (void *) dep);
232
233 /*
234 * Reset dependency item state variables to look for the next
235 * MVDependency.
236 */
237 list_free(parse->attnum_list);
238 parse->attnum_list = NIL;
239 parse->dependency = 0;
240 parse->degree = 0.0;
241 parse->found_attributes = false;
242 parse->found_dependency = false;
243 parse->found_degree = false;
244 parse->state = DEPS_EXPECT_ITEM;
245
246 return JSON_SUCCESS;
247}
248
249/*
250 * Invoked at the start of an array.
251 *
252 * Dependency input format does not have arrays, so any array elements
253 * encountered are an error.
254 */
257{
259
260 switch (parse->state)
261 {
263 parse->state = DEPS_EXPECT_ATTNUM;
264 break;
266 parse->state = DEPS_EXPECT_ITEM;
267 break;
268 default:
269 errsave(parse->escontext,
270 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
271 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
272 errdetail("Array has been found at an unexpected location."));
274 }
275
276 return JSON_SUCCESS;
277}
278
279/*
280 * Invoked at the end of an array.
281 *
282 * Either the end of an attribute number list or the whole object.
283 */
286{
288
289 switch (parse->state)
290 {
292 if (list_length(parse->attnum_list) > 0)
293 {
294 parse->state = DEPS_EXPECT_KEY;
295 return JSON_SUCCESS;
296 }
297
298 errsave(parse->escontext,
299 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
300 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
301 errdetail("The \"%s\" key must be an non-empty array.",
303 break;
304
305 case DEPS_EXPECT_ITEM:
306 if (list_length(parse->dependency_list) > 0)
307 {
308 parse->state = DEPS_PARSE_COMPLETE;
309 return JSON_SUCCESS;
310 }
311
312 errsave(parse->escontext,
313 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
314 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
315 errdetail("Item array cannot be empty."));
316 break;
317
318 default:
319
320 /*
321 * This can only happen if a case was missed in
322 * dependencies_array_start().
323 */
324 elog(ERROR,
325 "array end of \"%s\" found in unexpected parse state: %d.",
326 "pg_dependencies", (int) parse->state);
327 break;
328 }
330}
331
332/*
333 * Invoked at the start of a key/value field.
334 *
335 * The valid keys for the MVDependency object are:
336 * - attributes
337 * - dependency
338 * - degree
339 */
341dependencies_object_field_start(void *state, char *fname, bool isnull)
342{
344
345 if (strcmp(fname, PG_DEPENDENCIES_KEY_ATTRIBUTES) == 0)
346 {
347 if (parse->found_attributes)
348 {
349 errsave(parse->escontext,
350 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
351 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
352 errdetail("Multiple \"%s\" keys are not allowed.",
355 }
356
357 parse->found_attributes = true;
359 return JSON_SUCCESS;
360 }
361
362 if (strcmp(fname, PG_DEPENDENCIES_KEY_DEPENDENCY) == 0)
363 {
364 if (parse->found_dependency)
365 {
366 errsave(parse->escontext,
367 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
368 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
369 errdetail("Multiple \"%s\" keys are not allowed.",
372 }
373
374 parse->found_dependency = true;
376 return JSON_SUCCESS;
377 }
378
379 if (strcmp(fname, PG_DEPENDENCIES_KEY_DEGREE) == 0)
380 {
381 if (parse->found_degree)
382 {
383 errsave(parse->escontext,
384 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
385 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
386 errdetail("Multiple \"%s\" keys are not allowed.",
389 }
390
391 parse->found_degree = true;
392 parse->state = DEPS_EXPECT_DEGREE;
393 return JSON_SUCCESS;
394 }
395
396 errsave(parse->escontext,
397 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
398 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
399 errdetail("Only allowed keys are \"%s\", \"%s\" and \"%s\".",
404}
405
406/*
407 * Invoked at the start of an array element.
408 *
409 * pg_dependencies input format does not have arrays, so any array elements
410 * encountered are an error.
411 */
414{
416
417 switch (parse->state)
418 {
420 if (!isnull)
421 return JSON_SUCCESS;
422
423 errsave(parse->escontext,
424 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
425 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
426 errdetail("Attribute number array cannot be null."));
427 break;
428
429 case DEPS_EXPECT_ITEM:
430 if (!isnull)
431 return JSON_SUCCESS;
432
433 errsave(parse->escontext,
434 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
435 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
436 errdetail("Item list elements cannot be null."));
437 break;
438
439 default:
440 elog(ERROR,
441 "array element start of \"%s\" found in unexpected parse state: %d.",
442 "pg_dependencies", (int) parse->state);
443 break;
444 }
445
447}
448
449/*
450 * Test for valid subsequent attribute number.
451 *
452 * If the previous value is positive, then current value must either be
453 * greater than the previous value, or negative.
454 *
455 * If the previous value is negative, then the value must be less than
456 * the previous value.
457 *
458 * Duplicate values are not allowed; that is already covered by the rules
459 * described above.
460 */
461static bool
463{
464 Assert(prev != 0);
465
466 if (prev > 0)
467 return ((cur > prev) || (cur < 0));
468
469 return (cur < prev);
470}
471
472/*
473 * Handle scalar events from the dependencies input parser.
474 *
475 * There is only one case where we will encounter a scalar, and that is the
476 * dependency degree for the previous object key.
477 */
480{
483 ErrorSaveContext escontext = {T_ErrorSaveContext};
484
485 switch (parse->state)
486 {
488 attnum = pg_strtoint16_safe(token, (Node *) &escontext);
489
490 if (escontext.error_occurred)
491 {
492 errsave(parse->escontext,
493 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
494 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
495 errdetail("Key \"%s\" has an incorrect value.", PG_DEPENDENCIES_KEY_ATTRIBUTES));
497 }
498
499 /*
500 * An attribute number cannot be zero or a negative number beyond
501 * the number of the possible expressions.
502 */
503 if (attnum == 0 || attnum < (0 - STATS_MAX_DIMENSIONS))
504 {
505 errsave(parse->escontext,
506 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
507 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
508 errdetail("Invalid \"%s\" element has been found: %d.",
511 }
512
513 if (parse->attnum_list != NIL)
514 {
515 const AttrNumber prev = llast_int(parse->attnum_list);
516
518 {
519 errsave(parse->escontext,
520 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
521 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
522 errdetail("Invalid \"%s\" element has been found: %d cannot follow %d.",
525 }
526 }
527
528 parse->attnum_list = lappend_int(parse->attnum_list, (int) attnum);
529 return JSON_SUCCESS;
530
532 parse->dependency = (AttrNumber)
533 pg_strtoint16_safe(token, (Node *) &escontext);
534
535 if (escontext.error_occurred)
536 {
537 errsave(parse->escontext,
538 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
539 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
540 errdetail("Key \"%s\" has an incorrect value.", PG_DEPENDENCIES_KEY_DEPENDENCY));
542 }
543
544 /*
545 * The dependency attribute number cannot be zero or a negative
546 * number beyond the number of the possible expressions.
547 */
548 if (parse->dependency == 0 || parse->dependency < (0 - STATS_MAX_DIMENSIONS))
549 {
550 errsave(parse->escontext,
551 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
552 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
553 errdetail("Key \"%s\" has an incorrect value: %d.",
556 }
557
558 parse->state = DEPS_EXPECT_KEY;
559 return JSON_SUCCESS;
560
562 parse->degree = float8in_internal(token, NULL, "double",
563 token, (Node *) &escontext);
564
565 if (escontext.error_occurred)
566 {
567 errsave(parse->escontext,
568 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
569 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
570 errdetail("Key \"%s\" has an incorrect value.", PG_DEPENDENCIES_KEY_DEGREE));
572 }
573
574 parse->state = DEPS_EXPECT_KEY;
575 return JSON_SUCCESS;
576
577 default:
578 errsave(parse->escontext,
579 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
580 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
581 errdetail("Unexpected scalar has been found."));
582 break;
583 }
584
586}
587
588/*
589 * Compare the attribute arrays of two MVDependency values,
590 * looking for duplicated sets.
591 */
592static bool
594{
595 int i;
596
597 if (a->nattributes != b->nattributes)
598 return false;
599
600 for (i = 0; i < a->nattributes; i++)
601 {
602 if (a->attributes[i] != b->attributes[i])
603 return false;
604 }
605
606 return true;
607}
608
609/*
610 * Generate a string representing an array of attribute numbers.
611 * Internally, the dependency attribute is the last element, so we
612 * leave that off.
613 *
614 * Freeing the allocated string is the responsibility of the caller.
615 */
616static char *
618{
620
622
623 appendStringInfo(&str, "%d", item->attributes[0]);
624
625 for (int i = 1; i < item->nattributes - 1; i++)
626 appendStringInfo(&str, ", %d", item->attributes[i]);
627
628 return str.data;
629}
630
631/*
632 * Return the dependency, which is the last attribute element.
633 */
634static AttrNumber
636{
637 return item->attributes[item->nattributes - 1];
638}
639
640/*
641 * Attempt to build and serialize the MVDependencies object.
642 *
643 * This can only be executed after the completion of the JSON parsing.
644 *
645 * In the event of an error, set the error context and return NULL.
646 */
647static bytea *
649{
650 int ndeps = list_length(parse->dependency_list);
651
652 MVDependencies *mvdeps;
653 bytea *bytes;
654
655 switch (parse->state)
656 {
658
659 /*
660 * Parse ended in the expected place. We should have a list of
661 * items, but if we do not there is an issue with one of the
662 * earlier parse steps.
663 */
664 if (ndeps == 0)
665 elog(ERROR,
666 "pg_dependencies parsing claims success with an empty item list.");
667 break;
668
670 /* blank */
671 errsave(parse->escontext,
672 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
673 errmsg("malformed pg_dependencies: \"%s\"", str),
674 errdetail("Value cannot be empty."));
675 return NULL;
676
677 default:
678 /* Unexpected end-state. */
679 errsave(parse->escontext,
680 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
681 errmsg("malformed pg_dependencies: \"%s\"", str),
682 errdetail("Unexpected end state has been found: %d.", parse->state));
683 return NULL;
684 }
685
686 mvdeps = palloc0(offsetof(MVDependencies, deps)
687 + (ndeps * sizeof(MVDependency *)));
688 mvdeps->magic = STATS_DEPS_MAGIC;
689 mvdeps->type = STATS_DEPS_TYPE_BASIC;
690 mvdeps->ndeps = ndeps;
691
692 for (int i = 0; i < ndeps; i++)
693 {
694 /*
695 * Use the MVDependency objects in the dependency_list.
696 *
697 * Because we free the dependency_list after parsing is done, we
698 * cannot free it here.
699 */
700 mvdeps->deps[i] = list_nth(parse->dependency_list, i);
701
702 /*
703 * Ensure that this item does not duplicate the attributes of any
704 * pre-existing item.
705 */
706 for (int j = 0; j < i; j++)
707 {
708 if (dep_attributes_eq(mvdeps->deps[i], mvdeps->deps[j]))
709 {
710 MVDependency *dep = mvdeps->deps[i];
711 char *attnum_list = dep_attnum_list(dep);
712 AttrNumber attnum_dep = dep_attnum_dependency(dep);
713
714 errsave(parse->escontext,
715 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
716 errmsg("malformed pg_dependencies: \"%s\"", str),
717 errdetail("Duplicated \"%s\" array has been found: [%s] for key \"%s\" and value %d.",
719 PG_DEPENDENCIES_KEY_DEPENDENCY, attnum_dep));
720 pfree(mvdeps);
721 return NULL;
722 }
723 }
724 }
725
726 bytes = statext_dependencies_serialize(mvdeps);
727
728 /*
729 * No need to free the individual MVDependency objects, because they are
730 * still in the dependency_list, and will be freed with that.
731 */
732 pfree(mvdeps);
733
734 return bytes;
735}
736
737
738/*
739 * pg_dependencies_in - input routine for type pg_dependencies.
740 *
741 * This format is valid JSON, with the expected format:
742 * [{"attributes": [1,2], "dependency": -1, "degree": 1.0000},
743 * {"attributes": [1,-1], "dependency": 2, "degree": 0.0000},
744 * {"attributes": [2,-1], "dependency": 1, "degree": 1.0000}]
745 *
746 */
747Datum
749{
750 char *str = PG_GETARG_CSTRING(0);
751 bytea *bytes = NULL;
752
753 DependenciesParseState parse_state;
754 JsonParseErrorType result;
755 JsonLexContext *lex;
756 JsonSemAction sem_action;
757
758 /* initialize the semantic state */
759 parse_state.str = str;
760 parse_state.state = DEPS_EXPECT_START;
761 parse_state.dependency_list = NIL;
762 parse_state.attnum_list = NIL;
763 parse_state.dependency = 0;
764 parse_state.degree = 0.0;
765 parse_state.found_attributes = false;
766 parse_state.found_dependency = false;
767 parse_state.found_degree = false;
768 parse_state.escontext = fcinfo->context;
769
770 /* set callbacks */
771 sem_action.semstate = (void *) &parse_state;
777 sem_action.array_element_end = NULL;
779 sem_action.object_field_end = NULL;
780 sem_action.scalar = dependencies_scalar;
781
782 lex = makeJsonLexContextCstringLen(NULL, str, strlen(str), PG_UTF8, true);
783
784 result = pg_parse_json(lex, &sem_action);
786
787 if (result == JSON_SUCCESS)
788 bytes = build_mvdependencies(&parse_state, str);
789
790 list_free_deep(parse_state.dependency_list);
791 list_free(parse_state.attnum_list);
792
793 if (bytes)
794 PG_RETURN_BYTEA_P(bytes);
795
796 /*
797 * If escontext already set, just use that. Anything else is a generic
798 * JSON parse error.
799 */
800 if (!SOFT_ERROR_OCCURRED(parse_state.escontext))
801 errsave(parse_state.escontext,
802 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
803 errmsg("malformed pg_dependencies: \"%s\"", str),
804 errdetail("Input data must be valid JSON."));
805
807}
808
809
810/*
811 * pg_dependencies_out - output routine for type pg_dependencies.
812 */
813Datum
815{
819
822
823 for (int i = 0; i < dependencies->ndeps; i++)
824 {
825 MVDependency *dependency = dependencies->deps[i];
826
827 if (i > 0)
829
830 if (dependency->nattributes <= 1)
831 elog(ERROR, "invalid zero-length nattributes array in MVDependencies");
832
834 dependency->attributes[0]);
835
836 for (int j = 1; j < dependency->nattributes - 1; j++)
837 appendStringInfo(&str, ", %d", dependency->attributes[j]);
838
840 "\"" PG_DEPENDENCIES_KEY_DEGREE "\": %f}",
841 dependency->attributes[dependency->nattributes - 1],
842 dependency->degree);
843 }
844
846
848}
849
850/*
851 * pg_dependencies_recv - binary input routine for type pg_dependencies.
852 */
853Datum
855{
857 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
858 errmsg("cannot accept a value of type %s", "pg_dependencies")));
859
860 PG_RETURN_VOID(); /* keep compiler quiet */
861}
862
863/*
864 * pg_dependencies_send - binary output routine for type pg_dependencies.
865 *
866 * Functional dependencies are serialized in a bytea value (although the type
867 * is named differently), so let's just send that.
868 */
869Datum
871{
872 return byteasend(fcinfo);
873}
int16 AttrNumber
Definition: attnum.h:21
Datum byteasend(PG_FUNCTION_ARGS)
Definition: bytea.c:363
MVDependencies * statext_dependencies_deserialize(bytea *data)
Definition: dependencies.c:492
bytea * statext_dependencies_serialize(MVDependencies *dependencies)
Definition: dependencies.c:437
struct cursor * cur
Definition: ecpg.c:29
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define errsave(context,...)
Definition: elog.h:262
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition: float.c:395
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
Assert(PointerIsAligned(start, uint64))
const char * str
int b
Definition: isn.c:74
int a
Definition: isn.c:73
int j
Definition: isn.c:78
int i
Definition: isn.c:77
JsonParseErrorType pg_parse_json(JsonLexContext *lex, const JsonSemAction *sem)
Definition: jsonapi.c:744
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
Definition: jsonapi.c:392
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:687
JsonParseErrorType
Definition: jsonapi.h:35
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:59
@ JSON_SUCCESS
Definition: jsonapi.h:36
JsonTokenType
Definition: jsonapi.h:18
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
void list_free(List *list)
Definition: list.c:1546
void list_free_deep(List *list)
Definition: list.c:1560
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:53
int16 pg_strtoint16_safe(const char *s, Node *escontext)
Definition: numutils.c:128
int16 attnum
Definition: pg_attribute.h:74
const void * data
static JsonParseErrorType dependencies_array_end(void *state)
static JsonParseErrorType dependencies_array_start(void *state)
Datum pg_dependencies_in(PG_FUNCTION_ARGS)
static JsonParseErrorType dependencies_array_element_start(void *state, bool isnull)
DependenciesSemanticState
@ DEPS_EXPECT_START
@ DEPS_EXPECT_ATTNUM
@ DEPS_PARSE_COMPLETE
@ DEPS_EXPECT_ITEM
@ DEPS_EXPECT_DEPENDENCY
@ DEPS_EXPECT_ATTNUM_LIST
@ DEPS_EXPECT_KEY
@ DEPS_EXPECT_DEGREE
static JsonParseErrorType dependencies_object_end(void *state)
static bytea * build_mvdependencies(DependenciesParseState *parse, char *str)
static bool valid_subsequent_attnum(const AttrNumber prev, const AttrNumber cur)
static char * dep_attnum_list(const MVDependency *item)
Datum pg_dependencies_out(PG_FUNCTION_ARGS)
static AttrNumber dep_attnum_dependency(const MVDependency *item)
static JsonParseErrorType dependencies_scalar(void *state, char *token, JsonTokenType tokentype)
Datum pg_dependencies_send(PG_FUNCTION_ARGS)
static JsonParseErrorType dependencies_object_field_start(void *state, char *fname, bool isnull)
Datum pg_dependencies_recv(PG_FUNCTION_ARGS)
static bool dep_attributes_eq(const MVDependency *a, const MVDependency *b)
static JsonParseErrorType dependencies_object_start(void *state)
#define llast_int(l)
Definition: pg_list.h:199
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
static int list_nth_int(const List *list, int n)
Definition: pg_list.h:310
@ PG_UTF8
Definition: pg_wchar.h:232
uint64_t Datum
Definition: postgres.h:70
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
#define STATS_DEPS_MAGIC
Definition: statistics.h:43
#define STATS_DEPS_TYPE_BASIC
Definition: statistics.h:44
#define PG_DEPENDENCIES_KEY_ATTRIBUTES
#define PG_DEPENDENCIES_KEY_DEGREE
#define PG_DEPENDENCIES_KEY_DEPENDENCY
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
DependenciesSemanticState state
json_struct_action array_end
Definition: jsonapi.h:157
json_struct_action object_start
Definition: jsonapi.h:154
json_ofield_action object_field_start
Definition: jsonapi.h:158
json_aelem_action array_element_start
Definition: jsonapi.h:160
json_scalar_action scalar
Definition: jsonapi.h:162
void * semstate
Definition: jsonapi.h:153
json_aelem_action array_element_end
Definition: jsonapi.h:161
json_struct_action array_start
Definition: jsonapi.h:156
json_struct_action object_end
Definition: jsonapi.h:155
json_ofield_action object_field_end
Definition: jsonapi.h:159
Definition: pg_list.h:54
uint32 ndeps
Definition: statistics.h:61
uint32 magic
Definition: statistics.h:59
MVDependency * deps[FLEXIBLE_ARRAY_MEMBER]
Definition: statistics.h:62
AttrNumber nattributes
Definition: statistics.h:53
double degree
Definition: statistics.h:52
AttrNumber attributes[FLEXIBLE_ARRAY_MEMBER]
Definition: statistics.h:54
Definition: nodes.h:135
Definition: regguts.h:323
Definition: c.h:706