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("A key was expected."));
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 elog(ERROR,
115 "object start of \"%s\" found in unexpected parse state: %d.",
116 "pg_ndistinct", (int) parse->state);
117 break;
118 }
119
121}
122
123/*
124 * Invoked at the end of an object.
125 *
126 * Check to ensure that it was a complete MVNDistinctItem
127 */
130{
132
133 int natts = 0;
134
135 MVNDistinctItem *item;
136
137 if (parse->state != NDIST_EXPECT_KEY)
138 elog(ERROR,
139 "object end of \"%s\" found in unexpected parse state: %d.",
140 "pg_ndistinct", (int) parse->state);
141
142 if (!parse->found_attributes)
143 {
144 errsave(parse->escontext,
145 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
146 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
147 errdetail("Item must contain \"%s\" key.",
150 }
151
152 if (!parse->found_ndistinct)
153 {
154 errsave(parse->escontext,
155 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
156 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
157 errdetail("Item must contain \"%s\" key.",
160 }
161
162 /*
163 * We need at least two attribute numbers for a ndistinct item, anything
164 * less is malformed.
165 */
166 natts = list_length(parse->attnum_list);
167 if ((natts < 2) || (natts > STATS_MAX_DIMENSIONS))
168 {
169 errsave(parse->escontext,
170 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
171 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
172 errdetail("The \"%s\" key must contain an array of at least %d and no more than %d attributes.",
175 }
176
177 /* Create the MVNDistinctItem */
179 item->nattributes = natts;
180 item->attributes = palloc0(natts * sizeof(AttrNumber));
181 item->ndistinct = (double) parse->ndistinct;
182
183 for (int i = 0; i < natts; i++)
184 item->attributes[i] = (AttrNumber) list_nth_int(parse->attnum_list, i);
185
186 parse->distinct_items = lappend(parse->distinct_items, (void *) item);
187
188 /* reset item state vars */
189 list_free(parse->attnum_list);
190 parse->attnum_list = NIL;
191 parse->ndistinct = 0;
192 parse->found_attributes = false;
193 parse->found_ndistinct = false;
194
195 /* Now we are looking for the next MVNDistinctItem */
196 parse->state = NDIST_EXPECT_ITEM;
197 return JSON_SUCCESS;
198}
199
200
201/*
202 * Invoked at the start of an array.
203 *
204 * ndistinct input format has two types of arrays, the outer MVNDistinctItem
205 * array and the attribute number array within each MVNDistinctItem.
206 */
209{
211
212 switch (parse->state)
213 {
215 parse->state = NDIST_EXPECT_ATTNUM;
216 break;
217
219 parse->state = NDIST_EXPECT_ITEM;
220 break;
221
222 default:
223 errsave(parse->escontext,
224 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
225 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
226 errdetail("Array has been found at an unexpected location."));
228 }
229
230 return JSON_SUCCESS;
231}
232
233
234/*
235 * Invoked at the end of an array.
236 *
237 * Arrays can never be empty.
238 */
241{
243
244 switch (parse->state)
245 {
247 if (list_length(parse->attnum_list) > 0)
248 {
249 /*
250 * The attribute number list is complete, look for more
251 * MVNDistinctItem keys.
252 */
253 parse->state = NDIST_EXPECT_KEY;
254 return JSON_SUCCESS;
255 }
256
257 errsave(parse->escontext,
258 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
259 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
260 errdetail("The \"%s\" key must be a non-empty array.",
262 break;
263
265 if (list_length(parse->distinct_items) > 0)
266 {
267 /* Item list is complete, we are done. */
269 return JSON_SUCCESS;
270 }
271
272 errsave(parse->escontext,
273 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
274 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
275 errdetail("Item array cannot be empty."));
276 break;
277
278 default:
279
280 /*
281 * This can only happen if a case was missed in
282 * ndistinct_array_start().
283 */
284 elog(ERROR,
285 "array end of \"%s\" found in unexpected parse state: %d.",
286 "pg_ndistinct", (int) parse->state);
287 break;
288 }
289
291}
292
293/*
294 * Invoked at the start of a key/value field.
295 *
296 * The valid keys for the MVNDistinctItem object are:
297 * - attributes
298 * - ndistinct
299 */
301ndistinct_object_field_start(void *state, char *fname, bool isnull)
302{
304
305 if (strcmp(fname, PG_NDISTINCT_KEY_ATTRIBUTES) == 0)
306 {
307 if (parse->found_attributes)
308 {
309 errsave(parse->escontext,
310 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
311 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
312 errdetail("Multiple \"%s\" keys are not allowed.",
315 }
316 parse->found_attributes = true;
318 return JSON_SUCCESS;
319 }
320
321 if (strcmp(fname, PG_NDISTINCT_KEY_NDISTINCT) == 0)
322 {
323 if (parse->found_ndistinct)
324 {
325 errsave(parse->escontext,
326 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
327 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
328 errdetail("Multiple \"%s\" keys are not allowed.",
331 }
332 parse->found_ndistinct = true;
334 return JSON_SUCCESS;
335 }
336
337 errsave(parse->escontext,
338 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
339 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
340 errdetail("Only allowed keys are \"%s\" and \"%s\".",
344}
345
346/*
347 * Invoked at the start of an array element.
348 *
349 * The overall structure of the datatype is an array, but there are also
350 * arrays as the value of every attributes key.
351 */
354{
356
357 switch (parse->state)
358 {
360 if (!isnull)
361 return JSON_SUCCESS;
362
363 errsave(parse->escontext,
364 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
365 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
366 errdetail("Attribute number array cannot be null."));
367 break;
368
370 if (!isnull)
371 return JSON_SUCCESS;
372
373 errsave(parse->escontext,
374 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
375 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
376 errdetail("Item list elements cannot be null."));
377
378 break;
379
380 default:
381 elog(ERROR,
382 "array element start of \"%s\" found in unexpected parse state: %d.",
383 "pg_ndistinct", (int) parse->state);
384 break;
385 }
386
388}
389
390/*
391 * Test for valid subsequent attribute number.
392 *
393 * If the previous value is positive, then current value must either be
394 * greater than the previous value, or negative.
395 *
396 * If the previous value is negative, then the value must be less than
397 * the previous value.
398 *
399 * Duplicate values are obviously not allowed, but that is already covered
400 * by the rules listed above.
401 */
402static bool
404{
405 Assert(prev != 0);
406
407 if (prev > 0)
408 return ((cur > prev) || (cur < 0));
409
410 return (cur < prev);
411}
412
413/*
414 * Handle scalar events from the ndistinct input parser.
415 *
416 * Override integer parse error messages and replace them with errors
417 * specific to the context.
418 */
421{
424 ErrorSaveContext escontext = {T_ErrorSaveContext};
425
426 switch (parse->state)
427 {
429 attnum = pg_strtoint16_safe(token, (Node *) &escontext);
430
431 if (escontext.error_occurred)
432 {
433 errsave(parse->escontext,
434 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
435 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
436 errdetail("Key \"%s\" has an incorrect value.", PG_NDISTINCT_KEY_ATTRIBUTES));
438 }
439
440 /*
441 * The attribute number cannot be zero a negative number beyond
442 * the number of the possible expressions.
443 */
444 if (attnum == 0 || attnum < (0 - STATS_MAX_DIMENSIONS))
445 {
446 errsave(parse->escontext,
447 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
448 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
449 errdetail("Invalid \"%s\" element has been found: %d.",
452 }
453
454 if (list_length(parse->attnum_list) > 0)
455 {
456 const AttrNumber prev = llast_int(parse->attnum_list);
457
459 {
460 errsave(parse->escontext,
461 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
462 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
463 errdetail("Invalid \"%s\" element has been found: %d cannot follow %d.",
466 }
467 }
468
469 parse->attnum_list = lappend_int(parse->attnum_list, (int) attnum);
470 return JSON_SUCCESS;
471
473
474 /*
475 * While the structure dictates that ndistinct is a double
476 * precision floating point, it has always been an integer in the
477 * output generated. Therefore, we parse it as an integer here.
478 */
479 parse->ndistinct = pg_strtoint32_safe(token, (Node *) &escontext);
480
481 if (!escontext.error_occurred)
482 {
483 parse->state = NDIST_EXPECT_KEY;
484 return JSON_SUCCESS;
485 }
486
487 errsave(parse->escontext,
488 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
489 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
490 errdetail("Key \"%s\" has an incorrect value.",
492 break;
493
494 default:
495 errsave(parse->escontext,
496 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
497 errmsg("malformed pg_ndistinct: \"%s\"", parse->str),
498 errdetail("Unexpected scalar has been found."));
499 break;
500 }
501
503}
504
505/*
506 * Compare the attribute arrays of two MVNDistinctItem values,
507 * looking for duplicate sets. Return true if a duplicate set is found.
508 *
509 * The arrays are required to be in canonical order (all positive numbers
510 * in ascending order first, followed by all negative numbers in descending
511 * order) so it's safe to compare the attrnums in order, stopping at the
512 * first difference.
513 */
514static bool
516{
517 if (a->nattributes != b->nattributes)
518 return false;
519
520 for (int i = 0; i < a->nattributes; i++)
521 {
522 if (a->attributes[i] != b->attributes[i])
523 return false;
524 }
525
526 return true;
527}
528
529/*
530 * Ensure that an attribute number appears as one of the attribute numbers
531 * in a MVNDistinctItem.
532 */
533static bool
535{
536 for (int i = 0; i < item->nattributes; i++)
537 {
538 if (attnum == item->attributes[i])
539 return true;
540 }
541 return false;
542}
543
544/*
545 * Ensure that the attributes in MVNDistinctItem A are a subset of the
546 * reference MVNDistinctItem B.
547 */
548static bool
550 const MVNDistinctItem *refitem)
551{
552 for (int i = 0; i < item->nattributes; i++)
553 {
554 if (!item_has_attnum(refitem, item->attributes[i]))
555 return false;
556 }
557 return true;
558}
559
560/*
561 * Generate a string representing an array of attribute numbers.
562 *
563 * Freeing the allocated string is the responsibility of the caller.
564 */
565static char *
567{
569
571
572 appendStringInfo(&str, "%d", item->attributes[0]);
573
574 for (int i = 1; i < item->nattributes; i++)
575 appendStringInfo(&str, ", %d", item->attributes[i]);
576
577 return str.data;
578}
579
580/*
581 * Attempt to build and serialize the MVNDistinct object.
582 *
583 * This can only be executed after the completion of the JSON parsing.
584 *
585 * In the event of an error, set the error context and return NULL.
586 */
587static bytea *
589{
590 MVNDistinct *ndistinct;
591 int nitems = list_length(parse->distinct_items);
592 bytea *bytes;
593 int item_most_attrs = 0;
594 int item_most_attrs_idx = 0;
595
596 switch (parse->state)
597 {
599
600 /*
601 * Parsing has ended correctly and we should have a list of items.
602 * If we don't, something has been done wrong in one of the
603 * earlier parsing steps.
604 */
605 if (nitems == 0)
606 elog(ERROR,
607 "cannot have empty item list after parsing success.");
608 break;
609
611 /* blank */
612 errsave(parse->escontext,
613 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
614 errmsg("malformed pg_ndistinct: \"%s\"", str),
615 errdetail("Value cannot be empty."));
616 return NULL;
617
618 default:
619 /* Unexpected end-state. */
620 errsave(parse->escontext,
621 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
622 errmsg("malformed pg_ndistinct: \"%s\"", str),
623 errdetail("Unexpected end state has been found: %d.", parse->state));
624 return NULL;
625 }
626
627 ndistinct = palloc(offsetof(MVNDistinct, items) +
628 nitems * sizeof(MVNDistinctItem));
629
630 ndistinct->magic = STATS_NDISTINCT_MAGIC;
631 ndistinct->type = STATS_NDISTINCT_TYPE_BASIC;
632 ndistinct->nitems = nitems;
633
634 for (int i = 0; i < nitems; i++)
635 {
636 MVNDistinctItem *item = list_nth(parse->distinct_items, i);
637
638 /*
639 * Ensure that this item does not duplicate the attributes of any
640 * pre-existing item.
641 */
642 for (int j = 0; j < i; j++)
643 {
644 if (item_attributes_eq(item, &ndistinct->items[j]))
645 {
646 char *s = item_attnum_list(item);
647
648 errsave(parse->escontext,
649 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
650 errmsg("malformed pg_ndistinct: \"%s\"", str),
651 errdetail("Duplicated \"%s\" array has been found: [%s].",
653 pfree(s);
654 return NULL;
655 }
656 }
657
658 ndistinct->items[i].ndistinct = item->ndistinct;
659 ndistinct->items[i].nattributes = item->nattributes;
660
661 /*
662 * This transfers free-ing responsibility from the distinct_items list
663 * to the ndistinct object.
664 */
665 ndistinct->items[i].attributes = item->attributes;
666
667 /*
668 * Keep track of the first longest attribute list. All other attribute
669 * lists must be a subset of this list.
670 */
671 if (item->nattributes > item_most_attrs)
672 {
673 item_most_attrs = item->nattributes;
674 item_most_attrs_idx = i;
675 }
676 }
677
678 /*
679 * Verify that all the sets of attribute numbers are a proper subset of
680 * the longest set recorded. This acts as an extra sanity check based on
681 * the input given. Note that this still needs to be cross-checked with
682 * the extended statistics objects this would be assigned to, but it
683 * provides one extra layer of protection.
684 */
685 for (int i = 0; i < nitems; i++)
686 {
687 if (i == item_most_attrs_idx)
688 continue;
689
690 if (!item_is_attnum_subset(&ndistinct->items[i],
691 &ndistinct->items[item_most_attrs_idx]))
692 {
693 const MVNDistinctItem *item = &ndistinct->items[i];
694 const MVNDistinctItem *refitem = &ndistinct->items[item_most_attrs_idx];
695 char *item_list = item_attnum_list(item);
696 char *refitem_list = item_attnum_list(refitem);
697
698 errsave(parse->escontext,
699 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
700 errmsg("malformed pg_ndistinct: \"%s\"", str),
701 errdetail("\"%s\" array [%s] must be a subset of array [%s].",
703 item_list, refitem_list));
704 pfree(item_list);
705 pfree(refitem_list);
706 return NULL;
707 }
708 }
709
710 bytes = statext_ndistinct_serialize(ndistinct);
711
712 /*
713 * Free the attribute lists, before the ndistinct itself.
714 */
715 for (int i = 0; i < nitems; i++)
716 pfree(ndistinct->items[i].attributes);
717 pfree(ndistinct);
718
719 return bytes;
720}
721
722/*
723 * pg_ndistinct_in
724 * input routine for type pg_ndistinct.
725 */
726Datum
728{
729 char *str = PG_GETARG_CSTRING(0);
730 NDistinctParseState parse_state;
731 JsonParseErrorType result;
732 JsonLexContext *lex;
733 JsonSemAction sem_action;
734 bytea *bytes = NULL;
735
736 /* initialize semantic state */
737 parse_state.str = str;
738 parse_state.state = NDIST_EXPECT_START;
739 parse_state.distinct_items = NIL;
740 parse_state.escontext = fcinfo->context;
741 parse_state.found_attributes = false;
742 parse_state.found_ndistinct = false;
743 parse_state.attnum_list = NIL;
744 parse_state.ndistinct = 0;
745
746 /* set callbacks */
747 sem_action.semstate = (void *) &parse_state;
749 sem_action.object_end = ndistinct_object_end;
751 sem_action.array_end = ndistinct_array_end;
753 sem_action.object_field_end = NULL;
755 sem_action.array_element_end = NULL;
756 sem_action.scalar = ndistinct_scalar;
757
758 lex = makeJsonLexContextCstringLen(NULL, str, strlen(str),
759 PG_UTF8, true);
760 result = pg_parse_json(lex, &sem_action);
762
763 if (result == JSON_SUCCESS)
764 bytes = build_mvndistinct(&parse_state, str);
765
766 list_free(parse_state.attnum_list);
767 list_free_deep(parse_state.distinct_items);
768
769 if (bytes)
770 PG_RETURN_BYTEA_P(bytes);
771
772 /*
773 * If escontext already set, just use that. Anything else is a generic
774 * JSON parse error.
775 */
776 if (!SOFT_ERROR_OCCURRED(parse_state.escontext))
777 errsave(parse_state.escontext,
778 errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
779 errmsg("malformed pg_ndistinct: \"%s\"", str),
780 errdetail("Input data must be valid JSON."));
781
783}
784
785/*
786 * pg_ndistinct_out
787 * output routine for type pg_ndistinct
788 *
789 * Produces a human-readable representation of the value.
790 */
791Datum
793{
796 int i;
798
801
802 for (i = 0; i < ndist->nitems; i++)
803 {
804 MVNDistinctItem item = ndist->items[i];
805
806 if (i > 0)
808
809 if (item.nattributes <= 0)
810 elog(ERROR, "invalid zero-length attribute array in MVNDistinct");
811
813 item.attributes[0]);
814
815 for (int j = 1; j < item.nattributes; j++)
816 appendStringInfo(&str, ", %d", item.attributes[j]);
817
819 (int) item.ndistinct);
820 }
821
823
825}
826
827/*
828 * pg_ndistinct_recv
829 * binary input routine for type pg_ndistinct
830 */
831Datum
833{
835 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
836 errmsg("cannot accept a value of type %s", "pg_ndistinct")));
837
838 PG_RETURN_VOID(); /* keep compiler quiet */
839}
840
841/*
842 * pg_ndistinct_send
843 * binary output routine for type pg_ndistinct
844 *
845 * n-distinct is serialized into a bytea value, so let's send that.
846 */
847Datum
849{
850 return byteasend(fcinfo);
851}
int16 AttrNumber
Definition: attnum.h:21
Datum byteasend(PG_FUNCTION_ARGS)
Definition: bytea.c:377
int32_t int32
Definition: c.h:548
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 palloc_object(type)
Definition: fe_memutils.h:74
#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:1616
void * palloc0(Size size)
Definition: mcxt.c:1417
void * palloc(Size size)
Definition: mcxt.c:1387
#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:792
static char * item_attnum_list(const MVNDistinctItem *item)
Definition: pg_ndistinct.c:566
static JsonParseErrorType ndistinct_array_element_start(void *state, bool isnull)
Definition: pg_ndistinct.c:353
static JsonParseErrorType ndistinct_array_end(void *state)
Definition: pg_ndistinct.c:240
static JsonParseErrorType ndistinct_object_start(void *state)
Definition: pg_ndistinct.c:60
Datum pg_ndistinct_in(PG_FUNCTION_ARGS)
Definition: pg_ndistinct.c:727
static JsonParseErrorType ndistinct_array_start(void *state)
Definition: pg_ndistinct.c:208
Datum pg_ndistinct_recv(PG_FUNCTION_ARGS)
Definition: pg_ndistinct.c:832
static JsonParseErrorType ndistinct_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: pg_ndistinct.c:420
static bytea * build_mvndistinct(NDistinctParseState *parse, char *str)
Definition: pg_ndistinct.c:588
static JsonParseErrorType ndistinct_object_end(void *state)
Definition: pg_ndistinct.c:129
static bool item_attributes_eq(const MVNDistinctItem *a, const MVNDistinctItem *b)
Definition: pg_ndistinct.c:515
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:301
Datum pg_ndistinct_send(PG_FUNCTION_ARGS)
Definition: pg_ndistinct.c:848
static bool item_has_attnum(const MVNDistinctItem *item, AttrNumber attnum)
Definition: pg_ndistinct.c:534
static bool item_is_attnum_subset(const MVNDistinctItem *item, const MVNDistinctItem *refitem)
Definition: pg_ndistinct.c:549
static bool valid_subsequent_attnum(AttrNumber prev, AttrNumber cur)
Definition: pg_ndistinct.c:403
@ 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:706
static ItemArray items
Definition: test_tidstore.c:48