PostgreSQL Source Code git master
pg_ndistinct.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_ndistinct.c
4 * pg_ndistinct 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_ndistinct.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/fmgrprotos.h"
26
27/* Parsing state data */
28typedef enum
29{
38
39typedef struct
40{
41 const char *str;
43
44 List *distinct_items; /* Accumulated complete MVNDistinctItems */
46
47 bool found_attributes; /* Item has "attributes" key */
48 bool found_ndistinct; /* Item has "ndistinct" key */
49 List *attnum_list; /* Accumulated attribute numbers */
52
53/*
54 * Invoked at the start of each MVNDistinctItem.
55 *
56 * The entire JSON document should be one array of MVNDistinctItem objects.
57 * If we are anywhere else in the document, it is an error.
58 */
61{
63
64 switch (parse->state)
65 {
67 /* Now we expect to see attributes/ndistinct keys */
68 parse->state = NDIST_EXPECT_KEY;
69 return JSON_SUCCESS;
70
72 /* pg_ndistinct must begin with a '[' */
73 errsave(parse->escontext,
74 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
75 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
76 errdetail("Initial element must be an array."));
77 break;
78
80 /* In an object, expecting key */
81 errsave(parse->escontext,
82 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
83 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
84 errdetail("Expected an object key."));
85 break;
86
88 /* Just followed an "attributes" key */
89 errsave(parse->escontext,
90 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
91 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
92 errdetail("Value of \"%s\" must be an array of attribute numbers.",
94 break;
95
97 /* In an attribute number list, expect only scalar integers */
98 errsave(parse->escontext,
99 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
100 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
101 errdetail("Attribute lists can only contain attribute numbers."));
102 break;
103
105 /* Just followed an "ndistinct" key */
106 errsave(parse->escontext,
107 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
108 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
109 errdetail("Value of \"%s\" must be an integer.",
111 break;
112
113 default:
114 errsave(parse->escontext,
115 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
116 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
117 errdetail("Unexpected parse state: %d", (int) parse->state));
118 break;
119 }
120
122}
123
124/*
125 * Invoked at the end of an object.
126 *
127 * Check to ensure that it was a complete MVNDistinctItem
128 */
131{
133
134 int natts = 0;
135
136 MVNDistinctItem *item;
137
138 if (parse->state != NDIST_EXPECT_KEY)
139 {
140 errsave(parse->escontext,
141 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
142 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
143 errdetail("Unexpected parse state: %d", (int) parse->state));
145 }
146
147 if (!parse->found_attributes)
148 {
149 errsave(parse->escontext,
150 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
151 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
152 errdetail("Item must contain \"%s\" key.",
155 }
156
157 if (!parse->found_ndistinct)
158 {
159 errsave(parse->escontext,
160 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
161 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
162 errdetail("Item must contain \"%s\" key.",
165 }
166
167 /*
168 * We need at least two attribute numbers for a ndistinct item, anything
169 * less is malformed.
170 */
171 natts = list_length(parse->attnum_list);
172 if ((natts < 2) || (natts > STATS_MAX_DIMENSIONS))
173 {
174 errsave(parse->escontext,
175 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
176 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
177 errdetail("The \"%s\" key must contain an array of at least %d and no more than %d attributes.",
180 }
181
182 /* Create the MVNDistinctItem */
183 item = palloc(sizeof(MVNDistinctItem));
184 item->nattributes = natts;
185 item->attributes = palloc0(natts * sizeof(AttrNumber));
186 item->ndistinct = (double) parse->ndistinct;
187
188 for (int i = 0; i < natts; i++)
189 item->attributes[i] = (AttrNumber) list_nth_int(parse->attnum_list, i);
190
191 parse->distinct_items = lappend(parse->distinct_items, (void *) item);
192
193 /* reset item state vars */
194 list_free(parse->attnum_list);
195 parse->attnum_list = NIL;
196 parse->ndistinct = 0;
197 parse->found_attributes = false;
198 parse->found_ndistinct = false;
199
200 /* Now we are looking for the next MVNDistinctItem */
201 parse->state = NDIST_EXPECT_ITEM;
202 return JSON_SUCCESS;
203}
204
205
206/*
207 * Invoked at the start of an array.
208 *
209 * ndistinct input format has two types of arrays, the outer MVNDistinctItem
210 * array and the attribute number array within each MVNDistinctItem.
211 */
214{
216
217 switch (parse->state)
218 {
220 parse->state = NDIST_EXPECT_ATTNUM;
221 break;
222
224 parse->state = NDIST_EXPECT_ITEM;
225 break;
226
227 default:
228 errsave(parse->escontext,
229 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
230 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
231 errdetail("Array found in unexpected place."));
233 }
234
235 return JSON_SUCCESS;
236}
237
238
239/*
240 * Invoked at the end of an array.
241 *
242 * Arrays can never be empty.
243 */
246{
248
249 switch (parse->state)
250 {
252 if (list_length(parse->attnum_list) > 0)
253 {
254 /*
255 * The attribute number list is complete, look for more
256 * MVNDistinctItem keys.
257 */
258 parse->state = NDIST_EXPECT_KEY;
259 return JSON_SUCCESS;
260 }
261
262 errsave(parse->escontext,
263 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
264 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
265 errdetail("The \"%s\" key must be a non-empty array.",
267 break;
268
270 if (list_length(parse->distinct_items) > 0)
271 {
272 /* Item list is complete, we are done. */
274 return JSON_SUCCESS;
275 }
276
277 errsave(parse->escontext,
278 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
279 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
280 errdetail("Item array cannot be empty."));
281 break;
282
283 default:
284
285 /*
286 * This can only happen if a case was missed in
287 * ndistinct_array_start().
288 */
289 errsave(parse->escontext,
290 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
291 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
292 errdetail("Array found in unexpected place."));
293 break;
294 }
295
297}
298
299/*
300 * Invoked at the start of a key/value field.
301 *
302 * The valid keys for the MVNDistinctItem object are:
303 * - attributes
304 * - ndistinct
305 */
307ndistinct_object_field_start(void *state, char *fname, bool isnull)
308{
310
311 if (strcmp(fname, PG_NDISTINCT_KEY_ATTRIBUTES) == 0)
312 {
313 if (parse->found_attributes)
314 {
315 errsave(parse->escontext,
316 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
317 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
318 errdetail("Multiple \"%s\" keys are not allowed.",
321 }
322 parse->found_attributes = true;
324 return JSON_SUCCESS;
325 }
326
327 if (strcmp(fname, PG_NDISTINCT_KEY_NDISTINCT) == 0)
328 {
329 if (parse->found_ndistinct)
330 {
331 errsave(parse->escontext,
332 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
333 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
334 errdetail("Multiple \"%s\" keys are not allowed.",
337 }
338 parse->found_ndistinct = true;
340 return JSON_SUCCESS;
341 }
342
343 errsave(parse->escontext,
344 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
345 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
346 errdetail("Only allowed keys are \"%s\" and \"%s\".",
350}
351
352/*
353 * Invoked at the start of an array element.
354 *
355 * The overall structure of the datatype is an array, but there are also
356 * arrays as the value of every attributes key.
357 */
360{
362
363 switch (parse->state)
364 {
366 if (!isnull)
367 return JSON_SUCCESS;
368
369 errsave(parse->escontext,
370 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
371 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
372 errdetail("Attribute number array cannot be null."));
373 break;
374
376 if (!isnull)
377 return JSON_SUCCESS;
378
379 errsave(parse->escontext,
380 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
381 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
382 errdetail("Item list elements cannot be null."));
383
384 break;
385
386 default:
387 errsave(parse->escontext,
388 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
389 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
390 errdetail("Unexpected array element."));
391 break;
392 }
393
395}
396
397/*
398 * Test for valid subsequent attribute number.
399 *
400 * If the previous value is positive, then current value must either be
401 * greater than the previous value, or negative.
402 *
403 * If the previous value is negative, then the value must be less than
404 * the previous value.
405 *
406 * Duplicate values are obviously not allowed, but that is already covered
407 * by the rules listed above.
408 */
409static bool
411{
412 Assert(prev != 0);
413
414 if (prev > 0)
415 return ((cur > prev) || (cur < 0));
416
417 return (cur < prev);
418}
419
420/*
421 * Handle scalar events from the ndistinct input parser.
422 *
423 * Override integer parse error messages and replace them with errors
424 * specific to the context.
425 */
428{
431 ErrorSaveContext escontext = {T_ErrorSaveContext};
432
433 switch (parse->state)
434 {
436 attnum = pg_strtoint16_safe(token, (Node *) &escontext);
437
438 if (SOFT_ERROR_OCCURRED(&escontext))
439 {
440 errsave(parse->escontext,
441 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
442 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
443 errdetail("Invalid \"%s\" value.", PG_NDISTINCT_KEY_ATTRIBUTES));
445 }
446
447 /*
448 * The attribute number cannot be zero a negative number beyond
449 * the number of the possible expressions.
450 */
451 if (attnum == 0 || attnum < (0 - STATS_MAX_DIMENSIONS))
452 {
453 errsave(parse->escontext,
454 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
455 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
456 errdetail("Invalid \"%s\" element: %d.",
459 }
460
461 if (list_length(parse->attnum_list) > 0)
462 {
463 const AttrNumber prev = llast_int(parse->attnum_list);
464
466 {
467 errsave(parse->escontext,
468 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
469 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
470 errdetail("Invalid \"%s\" element: %d cannot follow %d.",
473 }
474 }
475
476 parse->attnum_list = lappend_int(parse->attnum_list, (int) attnum);
477 return JSON_SUCCESS;
478
480
481 /*
482 * While the structure dictates that ndistinct is a double
483 * precision floating point, it has always been an integer in the
484 * output generated. Therefore, we parse it as an integer here.
485 */
486 parse->ndistinct = pg_strtoint32_safe(token, (Node *) &escontext);
487
488 if (!SOFT_ERROR_OCCURRED(&escontext))
489 {
490 parse->state = NDIST_EXPECT_KEY;
491 return JSON_SUCCESS;
492 }
493
494 errsave(parse->escontext,
495 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
496 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
497 errdetail("Invalid \"%s\" value.",
499 break;
500
501 default:
502 errsave(parse->escontext,
503 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
504 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
505 errdetail("Unexpected scalar."));
506 break;
507 }
508
510}
511
512/*
513 * Compare the attribute arrays of two MVNDistinctItem values,
514 * looking for duplicate sets. Return true if a duplicate set is found.
515 *
516 * The arrays are required to be in canonical order (all positive numbers
517 * in ascending order first, followed by all negative numbers in descending
518 * order) so it's safe to compare the attrnums in order, stopping at the
519 * first difference.
520 */
521static bool
523{
524 if (a->nattributes != b->nattributes)
525 return false;
526
527 for (int i = 0; i < a->nattributes; i++)
528 {
529 if (a->attributes[i] != b->attributes[i])
530 return false;
531 }
532
533 return true;
534}
535
536/*
537 * Ensure that an attribute number appears as one of the attribute numbers
538 * in a MVNDistinctItem.
539 */
540static bool
542{
543 for (int i = 0; i < item->nattributes; i++)
544 {
545 if (attnum == item->attributes[i])
546 return true;
547 }
548 return false;
549}
550
551/*
552 * Ensure that the attributes in MVNDistinctItem A are a subset of the
553 * reference MVNDistinctItem B.
554 */
555static bool
557 const MVNDistinctItem *refitem)
558{
559 for (int i = 0; i < item->nattributes; i++)
560 {
561 if (!item_has_attnum(refitem, item->attributes[i]))
562 return false;
563 }
564 return true;
565}
566
567/*
568 * Generate a string representing an array of attribute numbers.
569 *
570 * Freeing the allocated string is the responsibility of the caller.
571 */
572static char *
574{
576
578
579 appendStringInfo(&str, "%d", item->attributes[0]);
580
581 for (int i = 1; i < item->nattributes; i++)
582 appendStringInfo(&str, ", %d", item->attributes[i]);
583
584 return str.data;
585}
586
587/*
588 * Attempt to build and serialize the MVNDistinct object.
589 *
590 * This can only be executed after the completion of the JSON parsing.
591 *
592 * In the event of an error, set the error context and return NULL.
593 */
594static bytea *
596{
597 MVNDistinct *ndistinct;
598 int nitems = list_length(parse->distinct_items);
599 bytea *bytes;
600 int item_most_attrs = 0;
601 int item_most_attrs_idx = 0;
602
603 switch (parse->state)
604 {
606
607 /*
608 * Parsing has ended correctly and we should have a list of items.
609 * If we don't, something has been done wrong in one of the
610 * earlier parsing steps.
611 */
612 if (nitems == 0)
613 elog(ERROR,
614 "cannot have empty item list after parsing success.");
615 break;
616
618 /* blank */
619 errsave(parse->escontext,
620 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
621 errmsg("malformed pg_ndistinct: \"%s\"", str),
622 errdetail("Value cannot be empty."));
623 return NULL;
624
625 default:
626 /* Unexpected end-state. */
627 errsave(parse->escontext,
628 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
629 errmsg("malformed pg_ndistinct: \"%s\"", str),
630 errdetail("Unexpected end state %d.", parse->state));
631 return NULL;
632 }
633
634 ndistinct = palloc(offsetof(MVNDistinct, items) +
635 nitems * sizeof(MVNDistinctItem));
636
637 ndistinct->magic = STATS_NDISTINCT_MAGIC;
638 ndistinct->type = STATS_NDISTINCT_TYPE_BASIC;
639 ndistinct->nitems = nitems;
640
641 for (int i = 0; i < nitems; i++)
642 {
643 MVNDistinctItem *item = list_nth(parse->distinct_items, i);
644
645 /*
646 * Ensure that this item does not duplicate the attributes of any
647 * pre-existing item.
648 */
649 for (int j = 0; j < i; j++)
650 {
651 if (item_attributes_eq(item, &ndistinct->items[j]))
652 {
653 char *s = item_attnum_list(item);
654
655 errsave(parse->escontext,
656 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
657 errmsg("malformed pg_ndistinct: \"%s\"", str),
658 errdetail("Duplicated \"%s\" array found: [%s]",
660 pfree(s);
661 return NULL;
662 }
663 }
664
665 ndistinct->items[i].ndistinct = item->ndistinct;
666 ndistinct->items[i].nattributes = item->nattributes;
667
668 /*
669 * This transfers free-ing responsibility from the distinct_items list
670 * to the ndistinct object.
671 */
672 ndistinct->items[i].attributes = item->attributes;
673
674 /*
675 * Keep track of the first longest attribute list. All other attribute
676 * lists must be a subset of this list.
677 */
678 if (item->nattributes > item_most_attrs)
679 {
680 item_most_attrs = item->nattributes;
681 item_most_attrs_idx = i;
682 }
683 }
684
685 /*
686 * Verify that all the sets of attribute numbers are a proper subset of
687 * the longest set recorded. This acts as an extra sanity check based on
688 * the input given. Note that this still needs to be cross-checked with
689 * the extended statistics objects this would be assigned to, but it
690 * provides one extra layer of protection.
691 */
692 for (int i = 0; i < nitems; i++)
693 {
694 if (i == item_most_attrs_idx)
695 continue;
696
697 if (!item_is_attnum_subset(&ndistinct->items[i],
698 &ndistinct->items[item_most_attrs_idx]))
699 {
700 const MVNDistinctItem *item = &ndistinct->items[i];
701 const MVNDistinctItem *refitem = &ndistinct->items[item_most_attrs_idx];
702 char *item_list = item_attnum_list(item);
703 char *refitem_list = item_attnum_list(refitem);
704
705 errsave(parse->escontext,
706 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
707 errmsg("malformed pg_ndistinct: \"%s\"", str),
708 errdetail("\"%s\" array: [%s] must be a subset of array: [%s]",
710 item_list, refitem_list));
711 pfree(item_list);
712 pfree(refitem_list);
713 return NULL;
714 }
715 }
716
717 bytes = statext_ndistinct_serialize(ndistinct);
718
719 /*
720 * Free the attribute lists, before the ndistinct itself.
721 */
722 for (int i = 0; i < nitems; i++)
723 pfree(ndistinct->items[i].attributes);
724 pfree(ndistinct);
725
726 return bytes;
727}
728
729/*
730 * pg_ndistinct_in
731 * input routine for type pg_ndistinct.
732 */
733Datum
735{
736 char *str = PG_GETARG_CSTRING(0);
737 NDistinctParseState parse_state;
738 JsonParseErrorType result;
739 JsonLexContext *lex;
740 JsonSemAction sem_action;
741 bytea *bytes = NULL;
742
743 /* initialize semantic state */
744 parse_state.str = str;
745 parse_state.state = NDIST_EXPECT_START;
746 parse_state.distinct_items = NIL;
747 parse_state.escontext = fcinfo->context;
748 parse_state.found_attributes = false;
749 parse_state.found_ndistinct = false;
750 parse_state.attnum_list = NIL;
751 parse_state.ndistinct = 0;
752
753 /* set callbacks */
754 sem_action.semstate = (void *) &parse_state;
756 sem_action.object_end = ndistinct_object_end;
758 sem_action.array_end = ndistinct_array_end;
760 sem_action.object_field_end = NULL;
762 sem_action.array_element_end = NULL;
763 sem_action.scalar = ndistinct_scalar;
764
765 lex = makeJsonLexContextCstringLen(NULL, str, strlen(str),
766 PG_UTF8, true);
767 result = pg_parse_json(lex, &sem_action);
769
770 if (result == JSON_SUCCESS)
771 bytes = build_mvndistinct(&parse_state, str);
772
773 list_free(parse_state.attnum_list);
774 list_free_deep(parse_state.distinct_items);
775
776 if (bytes)
777 PG_RETURN_BYTEA_P(bytes);
778
779 /*
780 * If escontext already set, just use that. Anything else is a generic
781 * JSON parse error.
782 */
783 if (!SOFT_ERROR_OCCURRED(parse_state.escontext))
784 errsave(parse_state.escontext,
785 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
786 errmsg("malformed pg_ndistinct: \"%s\"", str),
787 errdetail("Must be valid JSON."));
788
790}
791
792/*
793 * pg_ndistinct_out
794 * output routine for type pg_ndistinct
795 *
796 * Produces a human-readable representation of the value.
797 */
798Datum
800{
803 int i;
805
808
809 for (i = 0; i < ndist->nitems; i++)
810 {
811 MVNDistinctItem item = ndist->items[i];
812
813 if (i > 0)
815
816 if (item.nattributes <= 0)
817 elog(ERROR, "invalid zero-length attribute array in MVNDistinct");
818
820 item.attributes[0]);
821
822 for (int j = 1; j < item.nattributes; j++)
823 appendStringInfo(&str, ", %d", item.attributes[j]);
824
826 (int) item.ndistinct);
827 }
828
830
832}
833
834/*
835 * pg_ndistinct_recv
836 * binary input routine for type pg_ndistinct
837 */
838Datum
840{
842 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
843 errmsg("cannot accept a value of type %s", "pg_ndistinct")));
844
845 PG_RETURN_VOID(); /* keep compiler quiet */
846}
847
848/*
849 * pg_ndistinct_send
850 * binary output routine for type pg_ndistinct
851 *
852 * n-distinct is serialized into a bytea value, so let's send that.
853 */
854Datum
856{
857 return byteasend(fcinfo);
858}
int16 AttrNumber
Definition: attnum.h:21
Datum byteasend(PG_FUNCTION_ARGS)
Definition: bytea.c:363
int32_t int32
Definition: c.h:537
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
#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
for(;;)
#define nitems(x)
Definition: indent.h:31
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
void * palloc(Size size)
Definition: mcxt.c:1365
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:53
MVNDistinct * statext_ndistinct_deserialize(bytea *data)
Definition: mvdistinct.c:247
bytea * statext_ndistinct_serialize(MVNDistinct *ndistinct)
Definition: mvdistinct.c:176
int32 pg_strtoint32_safe(const char *s, Node *escontext)
Definition: numutils.c:389
int16 pg_strtoint16_safe(const char *s, Node *escontext)
Definition: numutils.c:128
int16 attnum
Definition: pg_attribute.h:74
const void * data
#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
Datum pg_ndistinct_out(PG_FUNCTION_ARGS)
Definition: pg_ndistinct.c:799
static char * item_attnum_list(const MVNDistinctItem *item)
Definition: pg_ndistinct.c:573
static JsonParseErrorType ndistinct_array_element_start(void *state, bool isnull)
Definition: pg_ndistinct.c:359
static JsonParseErrorType ndistinct_array_end(void *state)
Definition: pg_ndistinct.c:245
static JsonParseErrorType ndistinct_object_start(void *state)
Definition: pg_ndistinct.c:60
Datum pg_ndistinct_in(PG_FUNCTION_ARGS)
Definition: pg_ndistinct.c:734
static JsonParseErrorType ndistinct_array_start(void *state)
Definition: pg_ndistinct.c:213
Datum pg_ndistinct_recv(PG_FUNCTION_ARGS)
Definition: pg_ndistinct.c:839
static JsonParseErrorType ndistinct_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: pg_ndistinct.c:427
static bytea * build_mvndistinct(NDistinctParseState *parse, char *str)
Definition: pg_ndistinct.c:595
static JsonParseErrorType ndistinct_object_end(void *state)
Definition: pg_ndistinct.c:130
static bool item_attributes_eq(const MVNDistinctItem *a, const MVNDistinctItem *b)
Definition: pg_ndistinct.c:522
NDistinctSemanticState
Definition: pg_ndistinct.c:29
@ NDIST_EXPECT_NDISTINCT
Definition: pg_ndistinct.c:35
@ NDIST_EXPECT_START
Definition: pg_ndistinct.c:30
@ NDIST_EXPECT_ATTNUM
Definition: pg_ndistinct.c:34
@ NDIST_EXPECT_ITEM
Definition: pg_ndistinct.c:31
@ NDIST_EXPECT_ATTNUM_LIST
Definition: pg_ndistinct.c:33
@ NDIST_EXPECT_KEY
Definition: pg_ndistinct.c:32
@ NDIST_EXPECT_COMPLETE
Definition: pg_ndistinct.c:36
static JsonParseErrorType ndistinct_object_field_start(void *state, char *fname, bool isnull)
Definition: pg_ndistinct.c:307
Datum pg_ndistinct_send(PG_FUNCTION_ARGS)
Definition: pg_ndistinct.c:855
static bool item_has_attnum(const MVNDistinctItem *item, AttrNumber attnum)
Definition: pg_ndistinct.c:541
static bool item_is_attnum_subset(const MVNDistinctItem *item, const MVNDistinctItem *refitem)
Definition: pg_ndistinct.c:556
static bool valid_subsequent_attnum(AttrNumber prev, AttrNumber cur)
Definition: pg_ndistinct.c:410
@ 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_NDISTINCT_MAGIC
Definition: statistics.h:22
#define STATS_NDISTINCT_TYPE_BASIC
Definition: statistics.h:23
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
#define PG_NDISTINCT_KEY_ATTRIBUTES
#define PG_NDISTINCT_KEY_NDISTINCT
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
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
double ndistinct
Definition: statistics.h:28
AttrNumber * attributes
Definition: statistics.h:30
uint32 nitems
Definition: statistics.h:38
uint32 type
Definition: statistics.h:37
uint32 magic
Definition: statistics.h:36
MVNDistinctItem items[FLEXIBLE_ARRAY_MEMBER]
Definition: statistics.h:39
const char * str
Definition: pg_ndistinct.c:41
NDistinctSemanticState state
Definition: pg_ndistinct.c:42
Definition: nodes.h:135
Definition: regguts.h:323
Definition: c.h:695
static ItemArray items
Definition: test_tidstore.c:48