PostgreSQL Source Code: src/backend/utils/adt/orderedsetaggs.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17#include <math.h>
18
27#include "utils/fmgrprotos.h"
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
50{
51
53
55
57
59
60
61
62
64
66
73
75
76
77
78
83
88
91
93{
94
96
98
100
102
105
107
108
109
110
111
114{
119 int tuplesortopt;
120
121
122
123
124
125
127 elog(ERROR, "ordered-set aggregate called in non-aggregate context");
128
129
130
131
132
134 if (qstate == NULL)
135 {
138 List *sortlist;
139 int numSortCols;
140
141
143 if (!aggref)
144 elog(ERROR, "ordered-set aggregate called in non-aggregate context");
145 if (!AGGKIND_IS_ORDERED_SET(aggref->aggkind))
146 elog(ERROR, "ordered-set aggregate support function called for non-ordered-set aggregate");
147
148
149
150
151
152
155
157 qstate->aggref = aggref;
159
160
162
163
166
167 if (use_tuples)
168 {
169 bool ishypothetical = (aggref->aggkind == AGGKIND_HYPOTHETICAL);
171 int i;
172
173 if (ishypothetical)
174 numSortCols++;
181
182 i = 0;
183 foreach(lc, sortlist)
184 {
187 aggref->args);
188
189
191
197 i++;
198 }
199
200 if (ishypothetical)
201 {
202
208 i++;
209 }
210
212
213
214
215
216
218
219
220 if (ishypothetical)
221 {
224
226 for (i = 1; i <= natts; i++)
228
231 "flag",
232 INT4OID,
233 -1,
234 0);
235
237 qstate->tupdesc = newdesc;
238 }
239
240
243 }
244 else
245 {
246
249
250 if (numSortCols != 1 || aggref->aggkind == AGGKIND_HYPOTHETICAL)
251 elog(ERROR, "ordered-set aggregate support function does not support multiple aggregated columns");
252
255
256
258
259
265
266
271 }
272
274
276 }
277
278
280
282 osastate->qstate = qstate;
283 osastate->gcontext = gcontext;
284
286
289
290
291
292
293 if (use_tuples)
301 NULL,
302 tuplesortopt);
303 else
309 NULL,
310 tuplesortopt);
311
314
315
319
321
322 return osastate;
323}
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338static void
340{
342
343
347
350}
351
352
353
354
355
356
359{
361
362
365 else
367
368
370 {
373 }
374
376}
377
378
379
380
381
384{
387 int nargs;
388 int i;
389
390
393 else
395
396
400 for (i = 0; i < nargs; i++)
401 {
404 }
405 if (osastate->qstate->aggref->aggkind == AGGKIND_HYPOTHETICAL)
406 {
407
410 i++;
411 }
414
415
418
420}
421
422
423
424
425
428{
430 double percentile;
432 bool isnull;
434
436
437
440
442
443 if (percentile < 0 || percentile > 1 || isnan(percentile))
445 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
446 errmsg("percentile value %g is not between 0 and 1",
447 percentile)));
448
449
452
454
455
458
459
461 {
464 }
465 else
467
468
469
470
471
472
473
475 Assert(rownum <= osastate->number_of_rows);
476
477 if (rownum > 1)
478 {
480 elog(ERROR, "missing row in percentile_disc");
481 }
482
484 NULL))
485 elog(ERROR, "missing row in percentile_disc");
486
487
488 if (isnull)
490 else
492}
493
494
495
496
497
498
499
501
504{
507
508 return Float8GetDatum(loval + (pct * (hival - loval)));
509}
510
513{
516 diff_result,
518
520}
521
522
523
524
527 Oid expect_type,
529{
531 double percentile;
532 int64 first_row = 0;
533 int64 second_row = 0;
536 Datum second_val;
537 double proportion;
538 bool isnull;
539
541
542
545
547
548 if (percentile < 0 || percentile > 1 || isnan(percentile))
550 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
551 errmsg("percentile value %g is not between 0 and 1",
552 percentile)));
553
554
557
559
560
563
565
566
568 {
571 }
572 else
574
575 first_row = floor(percentile * (osastate->number_of_rows - 1));
576 second_row = ceil(percentile * (osastate->number_of_rows - 1));
577
578 Assert(first_row < osastate->number_of_rows);
579
581 elog(ERROR, "missing row in percentile_cont");
582
584 &isnull, NULL))
585 elog(ERROR, "missing row in percentile_cont");
586 if (isnull)
588
589 if (first_row == second_row)
590 {
591 val = first_val;
592 }
593 else
594 {
596 &isnull, NULL))
597 elog(ERROR, "missing row in percentile_cont");
598
599 if (isnull)
601
602 proportion = (percentile * (osastate->number_of_rows - 1)) - first_row;
603 val = lerpfunc(first_val, second_val, proportion);
604 }
605
607}
608
609
610
611
614{
616}
617
618
619
620
623{
625}
626
627
628
629
630
631
632
633
635{
640};
641
642
643
644
645static int
647{
650
651 if (a->first_row != b->first_row)
652 return (a->first_row < b->first_row) ? -1 : 1;
653 if (a->second_row != b->second_row)
654 return (a->second_row < b->second_row) ? -1 : 1;
655 return 0;
656}
657
658
659
660
663 Datum *percentiles_datum,
664 bool *percentiles_null,
666 bool continuous)
667{
669 int i;
670
672
673 for (i = 0; i < num_percentiles; i++)
674 {
676
677 if (percentiles_null[i])
678 {
679
683 }
684 else
685 {
687
688 if (p < 0 || p > 1 || isnan(p))
690 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
691 errmsg("percentile value %g is not between 0 and 1",
692 p)));
693
694 if (continuous)
695 {
698 pct_info[i].proportion = (p * (rowcount - 1)) - floor(p * (rowcount - 1));
699 }
700 else
701 {
702
703
704
705
706
707
708 int64 row = (int64) ceil(p * rowcount);
709
710 row = Max(1, row);
714 }
715 }
716 }
717
718
719
720
721
723
725}
726
727
728
729
732{
735 Datum *percentiles_datum;
736 bool *percentiles_null;
737 int num_percentiles;
739 Datum *result_datum;
740 bool *result_isnull;
741 int64 rownum = 0;
743 bool isnull = true;
744 int i;
745
747
748
751
753
754
757
758
762
764 &percentiles_datum,
765 &percentiles_null,
766 &num_percentiles);
767
768 if (num_percentiles == 0)
770
772 percentiles_datum,
773 percentiles_null,
775 false);
776
777 result_datum = (Datum *) palloc(num_percentiles * sizeof(Datum));
778 result_isnull = (bool *) palloc(num_percentiles * sizeof(bool));
779
780
781
782
783
784 for (i = 0; i < num_percentiles; i++)
785 {
787
789 break;
790
791 result_datum[idx] = (Datum) 0;
792 result_isnull[idx] = true;
793 }
794
795
796
797
798
799 if (i < num_percentiles)
800 {
801
803 {
806 }
807 else
809
810 for (; i < num_percentiles; i++)
811 {
814
815
816 if (target_row > rownum)
817 {
819 elog(ERROR, "missing row in percentile_disc");
820
822 &isnull, NULL))
823 elog(ERROR, "missing row in percentile_disc");
824
825 rownum = target_row;
826 }
827
829 result_isnull[idx] = isnull;
830 }
831 }
832
833
842}
843
844
845
846
849 Oid expect_type,
850 int16 typLen, bool typByVal, char typAlign,
852{
855 Datum *percentiles_datum;
856 bool *percentiles_null;
857 int num_percentiles;
859 Datum *result_datum;
860 bool *result_isnull;
861 int64 rownum = 0;
864 bool isnull;
865 int i;
866
868
869
872
874
875
878
880
881
885
887 &percentiles_datum,
888 &percentiles_null,
889 &num_percentiles);
890
891 if (num_percentiles == 0)
893
895 percentiles_datum,
896 percentiles_null,
898 true);
899
900 result_datum = (Datum *) palloc(num_percentiles * sizeof(Datum));
901 result_isnull = (bool *) palloc(num_percentiles * sizeof(bool));
902
903
904
905
906
907 for (i = 0; i < num_percentiles; i++)
908 {
910
912 break;
913
914 result_datum[idx] = (Datum) 0;
915 result_isnull[idx] = true;
916 }
917
918
919
920
921
922 if (i < num_percentiles)
923 {
924
926 {
929 }
930 else
932
933 for (; i < num_percentiles; i++)
934 {
938
939
940
941
942
943
944
946 {
948 elog(ERROR, "missing row in percentile_cont");
949
951 &first_val, &isnull, NULL) || isnull)
952 elog(ERROR, "missing row in percentile_cont");
953
955
956 second_val = first_val;
957 }
959 {
960
961
962
963
964
965 first_val = second_val;
966 }
967
968
970 {
972 &second_val, &isnull, NULL) || isnull)
973 elog(ERROR, "missing row in percentile_cont");
974 rownum++;
975 }
976
978
979
981 result_datum[idx] = lerpfunc(first_val, second_val,
983 else
984 result_datum[idx] = first_val;
985
986 result_isnull[idx] = false;
987 }
988 }
989
990
994 expect_type,
995 typLen,
996 typByVal,
997 typAlign));
998}
999
1000
1001
1002
1005{
1007 FLOAT8OID,
1008
1011 TYPALIGN_DOUBLE,
1013}
1014
1015
1016
1017
1020{
1022 INTERVALOID,
1023
1024 16, false, TYPALIGN_DOUBLE,
1026}
1027
1028
1029
1030
1031
1034{
1037 bool isnull;
1039 int64 mode_freq = 0;
1041 int64 last_val_freq = 0;
1042 bool last_val_is_mode = false;
1046 bool shouldfree;
1047
1049
1050
1053
1055
1056
1059
1060
1065
1067
1068
1070 {
1073 }
1074 else
1076
1077
1079 &abbrev_val))
1080 {
1081
1082 if (isnull)
1083 continue;
1084
1085 if (last_val_freq == 0)
1086 {
1087
1088 mode_val = last_val = val;
1089 mode_freq = last_val_freq = 1;
1090 last_val_is_mode = true;
1091 last_abbrev_val = abbrev_val;
1092 }
1093 else if (abbrev_val == last_abbrev_val &&
1095 {
1096
1097 if (last_val_is_mode)
1098 mode_freq++;
1099 else if (++last_val_freq > mode_freq)
1100 {
1101
1102 if (shouldfree)
1104 mode_val = last_val;
1105 mode_freq = last_val_freq;
1106 last_val_is_mode = true;
1107 }
1108 if (shouldfree)
1110 }
1111 else
1112 {
1113
1114 if (shouldfree && !last_val_is_mode)
1116 last_val = val;
1117
1118 last_abbrev_val = abbrev_val;
1119 last_val_freq = 1;
1120 last_val_is_mode = false;
1121 }
1122
1124 }
1125
1126 if (shouldfree && !last_val_is_mode)
1128
1129 if (mode_freq)
1131 else
1133}
1134
1135
1136
1137
1138
1139
1140
1141static void
1144{
1145 int i;
1146
1147
1148 if (!tupdesc ||
1149 (nargs + 1) != tupdesc->natts ||
1150 TupleDescAttr(tupdesc, nargs)->atttypid != INT4OID)
1151 elog(ERROR, "type mismatch in hypothetical-set function");
1152
1153
1154 for (i = 0; i < nargs; i++)
1155 {
1157
1159 elog(ERROR, "type mismatch in hypothetical-set function");
1160 }
1161}
1162
1163
1164
1165
1166
1167
1168
1169
1172 int64 *number_of_rows)
1173{
1178 int i;
1179
1181
1182
1184 {
1185 *number_of_rows = 0;
1186 return 1;
1187 }
1188
1191
1192
1193 if (nargs % 2 != 0)
1194 elog(ERROR, "wrong number of arguments in hypothetical-set function");
1195 nargs /= 2;
1196
1198
1199
1201
1202
1205 for (i = 0; i < nargs; i++)
1206 {
1209 }
1213
1215
1216
1219
1220
1222 {
1223 bool isnull;
1225
1227 break;
1228
1229 rank++;
1230
1232 }
1233
1235
1236 return rank;
1237}
1238
1239
1240
1241
1242
1245{
1248
1250
1252}
1253
1254
1255
1256
1259{
1262 double result_val;
1263
1265
1266 if (rowcount == 0)
1268
1269 result_val = (double) (rank - 1) / (double) (rowcount);
1270
1272}
1273
1274
1275
1276
1279{
1282 double result_val;
1283
1285
1286 result_val = (double) (rank) / (double) (rowcount + 1);
1287
1289}
1290
1291
1292
1293
1296{
1301 int64 duplicate_count = 0;
1303 int numDistinctCols;
1309 int i;
1310
1312
1313
1316
1319 if (!econtext)
1320 {
1322
1323
1328 }
1329
1330
1331 if (nargs % 2 != 0)
1332 elog(ERROR, "wrong number of arguments in hypothetical-set function");
1333 nargs /= 2;
1334
1336
1337
1338
1339
1340
1342
1343
1345 if (compareTuple == NULL)
1346 {
1349
1352 numDistinctCols,
1353 sortColIdx,
1356 NULL);
1359 }
1360
1361
1363
1364
1367 for (i = 0; i < nargs; i++)
1368 {
1371 }
1375
1377
1378
1381
1382
1383
1384
1385
1386
1389 slot2 = extraslot;
1390
1391
1393 &abbrevVal))
1394 {
1395 bool isnull;
1398
1400 break;
1401
1402
1405
1407 abbrevVal == abbrevOld &&
1409 duplicate_count++;
1410
1411 tmpslot = slot2;
1412 slot2 = slot;
1413 slot = tmpslot;
1414
1415 abbrevOld = abbrevVal;
1416
1417 rank++;
1418
1420 }
1421
1424
1426
1427 rank = rank - duplicate_count;
1428
1430}
Datum idx(PG_FUNCTION_ARGS)
#define PG_GETARG_ARRAYTYPE_P(n)
ArrayType * construct_empty_array(Oid elmtype)
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Datum interval_mi(PG_FUNCTION_ARGS)
Datum interval_pl(PG_FUNCTION_ARGS)
Datum interval_mul(PG_FUNCTION_ARGS)
#define OidIsValid(objectId)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsMinimalTuple
TupleDesc ExecTypeFromTL(List *targetList)
ExprContext * CreateStandaloneExprContext(void)
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Datum Float8GetDatum(float8 X)
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
#define DirectFunctionCall2(func, arg1, arg2)
#define PG_GETARG_FLOAT8(n)
#define PG_RETURN_FLOAT8(x)
#define PG_GETARG_POINTER(n)
#define PG_RETURN_INT64(x)
#define PG_GETARG_DATUM(n)
#define AGG_CONTEXT_AGGREGATE
#define PG_RETURN_DATUM(x)
#define PG_RETURN_POINTER(x)
#define PG_GET_COLLATION()
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
RegProcedure get_opcode(Oid opno)
void pfree(void *pointer)
void * palloc0(Size size)
#define CHECK_FOR_INTERRUPTS()
void AggRegisterCallback(FunctionCallInfo fcinfo, ExprContextCallbackFunction func, Datum arg)
Aggref * AggGetAggref(FunctionCallInfo fcinfo)
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
bool AggStateIsShared(FunctionCallInfo fcinfo)
Oid exprType(const Node *expr)
Oid exprCollation(const Node *expr)
Datum percentile_cont_float8_final(PG_FUNCTION_ARGS)
static OSAPerGroupState * ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
Datum hypothetical_percent_rank_final(PG_FUNCTION_ARGS)
Datum percentile_disc_final(PG_FUNCTION_ARGS)
Datum hypothetical_rank_final(PG_FUNCTION_ARGS)
static Datum percentile_cont_multi_final_common(FunctionCallInfo fcinfo, Oid expect_type, int16 typLen, bool typByVal, char typAlign, LerpFunc lerpfunc)
static struct pct_info * setup_pct_info(int num_percentiles, Datum *percentiles_datum, bool *percentiles_null, int64 rowcount, bool continuous)
struct OSAPerGroupState OSAPerGroupState
static Datum float8_lerp(Datum lo, Datum hi, double pct)
Datum hypothetical_cume_dist_final(PG_FUNCTION_ARGS)
static int64 hypothetical_rank_common(FunctionCallInfo fcinfo, int flag, int64 *number_of_rows)
static Datum interval_lerp(Datum lo, Datum hi, double pct)
Datum ordered_set_transition(PG_FUNCTION_ARGS)
Datum ordered_set_transition_multi(PG_FUNCTION_ARGS)
Datum percentile_disc_multi_final(PG_FUNCTION_ARGS)
Datum hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
static void ordered_set_shutdown(Datum arg)
static Datum percentile_cont_final_common(FunctionCallInfo fcinfo, Oid expect_type, LerpFunc lerpfunc)
Datum percentile_cont_float8_multi_final(PG_FUNCTION_ARGS)
Datum(* LerpFunc)(Datum lo, Datum hi, double pct)
Datum mode_final(PG_FUNCTION_ARGS)
Datum percentile_cont_interval_final(PG_FUNCTION_ARGS)
Datum percentile_cont_interval_multi_final(PG_FUNCTION_ARGS)
struct OSAPerQueryState OSAPerQueryState
static void hypothetical_check_argtypes(FunctionCallInfo fcinfo, int nargs, TupleDesc tupdesc)
static int pct_info_cmp(const void *pa, const void *pb)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
FormData_pg_attribute * Form_pg_attribute
static int list_length(const List *l)
#define qsort(a, b, c, d)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
#define Float8GetDatumFast(X)
static float8 DatumGetFloat8(Datum X)
static Pointer DatumGetPointer(Datum X)
static Datum Int32GetDatum(int32 X)
static int32 DatumGetInt32(Datum X)
TupleTableSlot * ecxt_innertuple
TupleTableSlot * ecxt_outertuple
OSAPerQueryState * qstate
Tuplesortstate * sortstate
TupleDesc tts_tupleDescriptor
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
void FreeTupleDesc(TupleDesc tupdesc)
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
void tuplesort_rescan(Tuplesortstate *state)
void tuplesort_performsort(Tuplesortstate *state)
bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples, bool forward)
void tuplesort_end(Tuplesortstate *state)
#define TUPLESORT_RANDOMACCESS
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, SortCoordinate coordinate, int sortopt)
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy, TupleTableSlot *slot, Datum *abbrev)
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, SortCoordinate coordinate, int sortopt)
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, bool copy, Datum *val, bool *isNull, Datum *abbrev)
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)