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("Expected an object key."));
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 errsave(parse->escontext,
128 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
129 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
130 errdetail("Unexpected parse state: %d", (int) parse->state));
131 break;
132 }
133
135}
136
137/*
138 * Invoked at the end of an object.
139 *
140 * Handle the end of an MVDependency object's JSON representation.
141 */
144{
146
147 MVDependency *dep;
148
149 int natts = 0;
150
151 if (parse->state != DEPS_EXPECT_KEY)
152 {
153 errsave(parse->escontext,
154 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
155 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
156 errdetail("Unexpected parse state: %d", (int) parse->state));
158 }
159
160 if (!parse->found_attributes)
161 {
162 errsave(parse->escontext,
163 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
164 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
165 errdetail("Item must contain \"%s\" key",
168 }
169
170 if (!parse->found_dependency)
171 {
172 errsave(parse->escontext,
173 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
174 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
175 errdetail("Item must contain \"%s\" key.",
178 }
179
180 if (!parse->found_degree)
181 {
182 errsave(parse->escontext,
183 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
184 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
185 errdetail("Item must contain \"%s\" key.",
188 }
189
190 /*
191 * We need at least one attribute number in a dependencies item, anything
192 * less is malformed.
193 */
194 natts = list_length(parse->attnum_list);
195 if ((natts < 1) || (natts > (STATS_MAX_DIMENSIONS - 1)))
196 {
197 errsave(parse->escontext,
198 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
199 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
200 errdetail("The \"%s\" key must contain an array of at least %d and no more than %d elements.",
204 }
205
206 /*
207 * Allocate enough space for the dependency, the attribute numbers in the
208 * list and the final attribute number for the dependency.
209 */
210 dep = palloc0(offsetof(MVDependency, attributes) + ((natts + 1) * sizeof(AttrNumber)));
211 dep->nattributes = natts + 1;
212
213 dep->attributes[natts] = parse->dependency;
214 dep->degree = parse->degree;
215
216 /*
217 * Assign attribute numbers to the attributes array, comparing each one
218 * against the dependency attribute to ensure that there there are no
219 * matches.
220 */
221 for (int i = 0; i < natts; i++)
222 {
223 dep->attributes[i] = (AttrNumber) list_nth_int(parse->attnum_list, i);
224 if (dep->attributes[i] == parse->dependency)
225 {
226 errsave(parse->escontext,
227 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
228 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
229 errdetail("Item \"%s\" value %d found in the \"%s\" list.",
233 }
234 }
235
236 parse->dependency_list = lappend(parse->dependency_list, (void *) dep);
237
238 /*
239 * Reset dependency item state variables to look for the next
240 * MVDependency.
241 */
242 list_free(parse->attnum_list);
243 parse->attnum_list = NIL;
244 parse->dependency = 0;
245 parse->degree = 0.0;
246 parse->found_attributes = false;
247 parse->found_dependency = false;
248 parse->found_degree = false;
249 parse->state = DEPS_EXPECT_ITEM;
250
251 return JSON_SUCCESS;
252}
253
254/*
255 * Invoked at the start of an array.
256 *
257 * Dependency input format does not have arrays, so any array elements
258 * encountered are an error.
259 */
262{
264
265 switch (parse->state)
266 {
268 parse->state = DEPS_EXPECT_ATTNUM;
269 break;
271 parse->state = DEPS_EXPECT_ITEM;
272 break;
273 default:
274 errsave(parse->escontext,
275 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
276 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
277 errdetail("Array found in unexpected place."));
279 }
280
281 return JSON_SUCCESS;
282}
283
284/*
285 * Invoked at the end of an array.
286 *
287 * Either the end of an attribute number list or the whole object.
288 */
291{
293
294 switch (parse->state)
295 {
297 if (list_length(parse->attnum_list) > 0)
298 {
299 parse->state = DEPS_EXPECT_KEY;
300 return JSON_SUCCESS;
301 }
302
303 errsave(parse->escontext,
304 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
305 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
306 errdetail("The \"%s\" key must be an non-empty array.",
308 break;
309
310 case DEPS_EXPECT_ITEM:
311 if (list_length(parse->dependency_list) > 0)
312 {
313 parse->state = DEPS_PARSE_COMPLETE;
314 return JSON_SUCCESS;
315 }
316
317 errsave(parse->escontext,
318 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
319 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
320 errdetail("Item array cannot be empty."));
321 break;
322
323 default:
324
325 /*
326 * This can only happen if a case was missed in
327 * dependencies_array_start().
328 */
329 errsave(parse->escontext,
330 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
331 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
332 errdetail("Array found in unexpected place."));
333 break;
334 }
336}
337
338/*
339 * Invoked at the start of a key/value field.
340 *
341 * The valid keys for the MVDependency object are:
342 * - attributes
343 * - dependency
344 * - degree
345 */
347dependencies_object_field_start(void *state, char *fname, bool isnull)
348{
350
351 if (strcmp(fname, PG_DEPENDENCIES_KEY_ATTRIBUTES) == 0)
352 {
353 if (parse->found_attributes)
354 {
355 errsave(parse->escontext,
356 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
357 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
358 errdetail("Multiple \"%s\" keys are not allowed.",
361 }
362
363 parse->found_attributes = true;
365 return JSON_SUCCESS;
366 }
367
368 if (strcmp(fname, PG_DEPENDENCIES_KEY_DEPENDENCY) == 0)
369 {
370 if (parse->found_dependency)
371 {
372 errsave(parse->escontext,
373 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
374 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
375 errdetail("Multiple \"%s\" keys are not allowed.",
378 }
379
380 parse->found_dependency = true;
382 return JSON_SUCCESS;
383 }
384
385 if (strcmp(fname, PG_DEPENDENCIES_KEY_DEGREE) == 0)
386 {
387 if (parse->found_degree)
388 {
389 errsave(parse->escontext,
390 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
391 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
392 errdetail("Multiple \"%s\" keys are not allowed.",
395 }
396
397 parse->found_degree = true;
398 parse->state = DEPS_EXPECT_DEGREE;
399 return JSON_SUCCESS;
400 }
401
402 errsave(parse->escontext,
403 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
404 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
405 errdetail("Only allowed keys are \"%s\", \"%s\" and \"%s\".",
410}
411
412/*
413 * Invoked at the start of an array element.
414 *
415 * pg_dependencies input format does not have arrays, so any array elements
416 * encountered are an error.
417 */
420{
422
423 switch (parse->state)
424 {
426 if (!isnull)
427 return JSON_SUCCESS;
428
429 errsave(parse->escontext,
430 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
431 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
432 errdetail("Attribute number array cannot be null."));
433 break;
434
435 case DEPS_EXPECT_ITEM:
436 if (!isnull)
437 return JSON_SUCCESS;
438
439 errsave(parse->escontext,
440 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
441 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
442 errdetail("Item list elements cannot be null."));
443 break;
444
445 default:
446 errsave(parse->escontext,
447 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
448 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
449 errdetail("Unexpected array element."));
450 break;
451 }
452
454}
455
456/*
457 * Test for valid subsequent attribute number.
458 *
459 * If the previous value is positive, then current value must either be
460 * greater than the previous value, or negative.
461 *
462 * If the previous value is negative, then the value must be less than
463 * the previous value.
464 *
465 * Duplicate values are not allowed; that is already covered by the rules
466 * described above.
467 */
468static bool
470{
471 Assert(prev != 0);
472
473 if (prev > 0)
474 return ((cur > prev) || (cur < 0));
475
476 return (cur < prev);
477}
478
479/*
480 * Handle scalar events from the dependencies input parser.
481 *
482 * There is only one case where we will encounter a scalar, and that is the
483 * dependency degree for the previous object key.
484 */
487{
490 ErrorSaveContext escontext = {T_ErrorSaveContext};
491
492 switch (parse->state)
493 {
495 attnum = pg_strtoint16_safe(token, (Node *) &escontext);
496
497 if (escontext.error_occurred)
498 {
499 errsave(parse->escontext,
500 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
501 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
502 errdetail("Invalid \"%s\" value.", PG_DEPENDENCIES_KEY_ATTRIBUTES));
504 }
505
506 /*
507 * An attribute number cannot be zero or a negative number beyond
508 * the number of the possible expressions.
509 */
510 if (attnum == 0 || attnum < (0 - STATS_MAX_DIMENSIONS))
511 {
512 errsave(parse->escontext,
513 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
514 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
515 errdetail("Invalid \"%s\" element: %d.",
518 }
519
520 if (parse->attnum_list != NIL)
521 {
522 const AttrNumber prev = llast_int(parse->attnum_list);
523
525 {
526 errsave(parse->escontext,
527 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
528 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
529 errdetail("Invalid \"%s\" element: %d cannot follow %d.",
532 }
533 }
534
535 parse->attnum_list = lappend_int(parse->attnum_list, (int) attnum);
536 return JSON_SUCCESS;
537
539 parse->dependency = (AttrNumber)
540 pg_strtoint16_safe(token, (Node *) &escontext);
541
542 if (escontext.error_occurred)
543 {
544 errsave(parse->escontext,
545 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
546 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
547 errdetail("Invalid \"%s\" value.", PG_DEPENDENCIES_KEY_DEPENDENCY));
549 }
550
551 /*
552 * The dependency attribute number cannot be zero or a negative
553 * number beyond the number of the possible expressions.
554 */
555 if (parse->dependency == 0 || parse->dependency < (0 - STATS_MAX_DIMENSIONS))
556 {
557 errsave(parse->escontext,
558 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
559 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
560 errdetail("Invalid \"%s\" value: %d.",
563 }
564
565 parse->state = DEPS_EXPECT_KEY;
566 return JSON_SUCCESS;
567
569 parse->degree = float8in_internal(token, NULL, "double",
570 token, (Node *) &escontext);
571
572 if (escontext.error_occurred)
573 {
574 errsave(parse->escontext,
575 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
576 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
577 errdetail("Invalid \"%s\" value.", PG_DEPENDENCIES_KEY_DEGREE));
579 }
580
581 parse->state = DEPS_EXPECT_KEY;
582 return JSON_SUCCESS;
583
584 default:
585 errsave(parse->escontext,
586 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
587 errmsg("malformed pg_dependencies: \"%s\"", parse->str),
588 errdetail("Unexpected scalar."));
589 break;
590 }
591
593}
594
595/*
596 * Compare the attribute arrays of two MVDependency values,
597 * looking for duplicated sets.
598 */
599static bool
601{
602 int i;
603
604 if (a->nattributes != b->nattributes)
605 return false;
606
607 for (i = 0; i < a->nattributes; i++)
608 {
609 if (a->attributes[i] != b->attributes[i])
610 return false;
611 }
612
613 return true;
614}
615
616/*
617 * Generate a string representing an array of attribute numbers.
618 * Internally, the dependency attribute is the last element, so we
619 * leave that off.
620 *
621 * Freeing the allocated string is the responsibility of the caller.
622 */
623static char *
625{
627
629
630 appendStringInfo(&str, "%d", item->attributes[0]);
631
632 for (int i = 1; i < item->nattributes - 1; i++)
633 appendStringInfo(&str, ", %d", item->attributes[i]);
634
635 return str.data;
636}
637
638/*
639 * Return the dependency, which is the last attribute element.
640 */
641static AttrNumber
643{
644 return item->attributes[item->nattributes - 1];
645}
646
647/*
648 * Attempt to build and serialize the MVDependencies object.
649 *
650 * This can only be executed after the completion of the JSON parsing.
651 *
652 * In the event of an error, set the error context and return NULL.
653 */
654static bytea *
656{
657 int ndeps = list_length(parse->dependency_list);
658
659 MVDependencies *mvdeps;
660 bytea *bytes;
661
662 switch (parse->state)
663 {
665
666 /*
667 * Parse ended in the expected place. We should have a list of
668 * items, but if we do not there is an issue with one of the
669 * earlier parse steps.
670 */
671 if (ndeps == 0)
672 elog(ERROR,
673 "pg_dependencies parsing claims success with an empty item list.");
674 break;
675
677 /* blank */
678 errsave(parse->escontext,
679 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
680 errmsg("malformed pg_dependencies: \"%s\"", str),
681 errdetail("Value cannot be empty."));
682 return NULL;
683
684 default:
685 /* Unexpected end-state. */
686 errsave(parse->escontext,
687 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
688 errmsg("malformed pg_dependencies: \"%s\"", str),
689 errdetail("Unexpected end state %d.", parse->state));
690 return NULL;
691 }
692
693 mvdeps = palloc0(offsetof(MVDependencies, deps)
694 + (ndeps * sizeof(MVDependency *)));
695 mvdeps->magic = STATS_DEPS_MAGIC;
696 mvdeps->type = STATS_DEPS_TYPE_BASIC;
697 mvdeps->ndeps = ndeps;
698
699 for (int i = 0; i < ndeps; i++)
700 {
701 /*
702 * Use the MVDependency objects in the dependency_list.
703 *
704 * Because we free the dependency_list after parsing is done, we
705 * cannot free it here.
706 */
707 mvdeps->deps[i] = list_nth(parse->dependency_list, i);
708
709 /*
710 * Ensure that this item does not duplicate the attributes of any
711 * pre-existing item.
712 */
713 for (int j = 0; j < i; j++)
714 {
715 if (dep_attributes_eq(mvdeps->deps[i], mvdeps->deps[j]))
716 {
717 MVDependency *dep = mvdeps->deps[i];
718 char *attnum_list = dep_attnum_list(dep);
719 AttrNumber attnum_dep = dep_attnum_dependency(dep);
720
721 errsave(parse->escontext,
722 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
723 errmsg("malformed pg_dependencies: \"%s\"", str),
724 errdetail("Duplicate \"%s\" array: [%s] with \"%s\": %d.",
726 PG_DEPENDENCIES_KEY_DEPENDENCY, attnum_dep));
727 pfree(mvdeps);
728 return NULL;
729 }
730 }
731 }
732
733 bytes = statext_dependencies_serialize(mvdeps);
734
735 /*
736 * No need to free the individual MVDependency objects, because they are
737 * still in the dependency_list, and will be freed with that.
738 */
739 pfree(mvdeps);
740
741 return bytes;
742}
743
744
745/*
746 * pg_dependencies_in - input routine for type pg_dependencies.
747 *
748 * This format is valid JSON, with the expected format:
749 * [{"attributes": [1,2], "dependency": -1, "degree": 1.0000},
750 * {"attributes": [1,-1], "dependency": 2, "degree": 0.0000},
751 * {"attributes": [2,-1], "dependency": 1, "degree": 1.0000}]
752 *
753 */
754Datum
756{
757 char *str = PG_GETARG_CSTRING(0);
758 bytea *bytes = NULL;
759
760 DependenciesParseState parse_state;
761 JsonParseErrorType result;
762 JsonLexContext *lex;
763 JsonSemAction sem_action;
764
765 /* initialize the semantic state */
766 parse_state.str = str;
767 parse_state.state = DEPS_EXPECT_START;
768 parse_state.dependency_list = NIL;
769 parse_state.attnum_list = NIL;
770 parse_state.dependency = 0;
771 parse_state.degree = 0.0;
772 parse_state.found_attributes = false;
773 parse_state.found_dependency = false;
774 parse_state.found_degree = false;
775 parse_state.escontext = fcinfo->context;
776
777 /* set callbacks */
778 sem_action.semstate = (void *) &parse_state;
784 sem_action.array_element_end = NULL;
786 sem_action.object_field_end = NULL;
787 sem_action.scalar = dependencies_scalar;
788
789 lex = makeJsonLexContextCstringLen(NULL, str, strlen(str), PG_UTF8, true);
790
791 result = pg_parse_json(lex, &sem_action);
793
794 if (result == JSON_SUCCESS)
795 bytes = build_mvdependencies(&parse_state, str);
796
797 list_free_deep(parse_state.dependency_list);
798 list_free(parse_state.attnum_list);
799
800 if (bytes)
801 PG_RETURN_BYTEA_P(bytes);
802
803 /*
804 * If escontext already set, just use that. Anything else is a generic
805 * JSON parse error.
806 */
807 if (!SOFT_ERROR_OCCURRED(parse_state.escontext))
808 errsave(parse_state.escontext,
809 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
810 errmsg("malformed pg_dependencies: \"%s\"", str),
811 errdetail("Must be valid JSON."));
812
814}
815
816
817/*
818 * pg_dependencies_out - output routine for type pg_dependencies.
819 */
820Datum
822{
826
829
830 for (int i = 0; i < dependencies->ndeps; i++)
831 {
832 MVDependency *dependency = dependencies->deps[i];
833
834 if (i > 0)
836
837 if (dependency->nattributes <= 1)
838 elog(ERROR, "invalid zero-length nattributes array in MVDependencies");
839
841 dependency->attributes[0]);
842
843 for (int j = 1; j < dependency->nattributes - 1; j++)
844 appendStringInfo(&str, ", %d", dependency->attributes[j]);
845
847 "\"" PG_DEPENDENCIES_KEY_DEGREE "\": %f}",
848 dependency->attributes[dependency->nattributes - 1],
849 dependency->degree);
850 }
851
853
855}
856
857/*
858 * pg_dependencies_recv - binary input routine for type pg_dependencies.
859 */
860Datum
862{
864 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
865 errmsg("cannot accept a value of type %s", "pg_dependencies")));
866
867 PG_RETURN_VOID(); /* keep compiler quiet */
868}
869
870/*
871 * pg_dependencies_send - binary output routine for type pg_dependencies.
872 *
873 * Functional dependencies are serialized in a bytea value (although the type
874 * is named differently), so let's just send that.
875 */
876Datum
878{
879 return byteasend(fcinfo);
880}
int16 AttrNumber
Definition: attnum.h:21
Datum byteasend(PG_FUNCTION_ARGS)
Definition: bytea.c:363
MVDependencies * statext_dependencies_deserialize(bytea *data)
Definition: dependencies.c:493
bytea * statext_dependencies_serialize(MVDependencies *dependencies)
Definition: dependencies.c:438
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:695