PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
orderedsetaggs.c File Reference
#include "postgres.h"
#include <float.h>
#include <math.h>
#include "catalog/pg_aggregate.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/tlist.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/timestamp.h"
#include "utils/tuplesort.h"
Include dependency graph for orderedsetaggs.c:

Go to the source code of this file.

Data Structures

struct  OSAPerQueryState
 
struct  OSAPerGroupState
 
struct  pct_info
 

Typedefs

typedef struct OSAPerQueryState OSAPerQueryState
 
typedef struct OSAPerGroupState OSAPerGroupState
 
typedef Datum(* LerpFunc )(Datum lo, Datum hi, double pct)
 

Functions

static void ordered_set_shutdown (Datum arg)
 
static OSAPerGroupStateordered_set_startup (FunctionCallInfo fcinfo, bool use_tuples)
 
Datum ordered_set_transition (PG_FUNCTION_ARGS)
 
Datum ordered_set_transition_multi (PG_FUNCTION_ARGS)
 
Datum percentile_disc_final (PG_FUNCTION_ARGS)
 
static Datum float8_lerp (Datum lo, Datum hi, double pct)
 
static Datum interval_lerp (Datum lo, Datum hi, double pct)
 
static Datum percentile_cont_final_common (FunctionCallInfo fcinfo, Oid expect_type, LerpFunc lerpfunc)
 
Datum percentile_cont_float8_final (PG_FUNCTION_ARGS)
 
Datum percentile_cont_interval_final (PG_FUNCTION_ARGS)
 
static int pct_info_cmp (const void *pa, const void *pb)
 
static struct pct_infosetup_pct_info (int num_percentiles, Datum *percentiles_datum, bool *percentiles_null, int64 rowcount, bool continuous)
 
Datum percentile_disc_multi_final (PG_FUNCTION_ARGS)
 
static Datum percentile_cont_multi_final_common (FunctionCallInfo fcinfo, Oid expect_type, int16 typLen, bool typByVal, char typAlign, LerpFunc lerpfunc)
 
Datum percentile_cont_float8_multi_final (PG_FUNCTION_ARGS)
 
Datum percentile_cont_interval_multi_final (PG_FUNCTION_ARGS)
 
Datum mode_final (PG_FUNCTION_ARGS)
 
static void hypothetical_check_argtypes (FunctionCallInfo fcinfo, int nargs, TupleDesc tupdesc)
 
static int64 hypothetical_rank_common (FunctionCallInfo fcinfo, int flag, int64 *number_of_rows)
 
Datum hypothetical_rank_final (PG_FUNCTION_ARGS)
 
Datum hypothetical_percent_rank_final (PG_FUNCTION_ARGS)
 
Datum hypothetical_cume_dist_final (PG_FUNCTION_ARGS)
 
Datum hypothetical_dense_rank_final (PG_FUNCTION_ARGS)
 

Typedef Documentation

typedef Datum(* LerpFunc)(Datum lo, Datum hi, double pct)

Definition at line 480 of file orderedsetaggs.c.

Function Documentation

static Datum float8_lerp ( Datum  lo,
Datum  hi,
double  pct 
)
static

Definition at line 483 of file orderedsetaggs.c.

References DatumGetFloat8, and Float8GetDatum().

Referenced by percentile_cont_float8_final(), and percentile_cont_float8_multi_final().

484 {
485  double loval = DatumGetFloat8(lo);
486  double hival = DatumGetFloat8(hi);
487 
488  return Float8GetDatum(loval + (pct * (hival - loval)));
489 }
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1815
#define DatumGetFloat8(X)
Definition: postgres.h:734
static void hypothetical_check_argtypes ( FunctionCallInfo  fcinfo,
int  nargs,
TupleDesc  tupdesc 
)
static

Definition at line 1120 of file orderedsetaggs.c.

References tupleDesc::attrs, elog, ERROR, FunctionCallInfoData::flinfo, get_fn_expr_argtype(), i, INT4OID, and tupleDesc::natts.

Referenced by hypothetical_dense_rank_final(), and hypothetical_rank_common().

1122 {
1123  int i;
1124 
1125  /* check that we have an int4 flag column */
1126  if (!tupdesc ||
1127  (nargs + 1) != tupdesc->natts ||
1128  tupdesc->attrs[nargs]->atttypid != INT4OID)
1129  elog(ERROR, "type mismatch in hypothetical-set function");
1130 
1131  /* check that direct args match in type with aggregated args */
1132  for (i = 0; i < nargs; i++)
1133  {
1134  if (get_fn_expr_argtype(fcinfo->flinfo, i + 1) != tupdesc->attrs[i]->atttypid)
1135  elog(ERROR, "type mismatch in hypothetical-set function");
1136  }
1137 }
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define INT4OID
Definition: pg_type.h:316
int natts
Definition: tupdesc.h:73
FmgrInfo * flinfo
Definition: fmgr.h:79
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1909
int i
#define elog
Definition: elog.h:219
Datum hypothetical_cume_dist_final ( PG_FUNCTION_ARGS  )

Definition at line 1254 of file orderedsetaggs.c.

References hypothetical_rank_common(), and PG_RETURN_FLOAT8.

1255 {
1256  int64 rank;
1257  int64 rowcount;
1258  double result_val;
1259 
1260  rank = hypothetical_rank_common(fcinfo, 1, &rowcount);
1261 
1262  result_val = (double) (rank) / (double) (rowcount + 1);
1263 
1264  PG_RETURN_FLOAT8(result_val);
1265 }
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
static int64 hypothetical_rank_common(FunctionCallInfo fcinfo, int flag, int64 *number_of_rows)
Datum hypothetical_dense_rank_final ( PG_FUNCTION_ARGS  )

Definition at line 1271 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), AggGetTempMemoryContext(), Assert, CHECK_FOR_INTERRUPTS, DatumGetInt32, elog, OSAPerQueryState::eqOperators, OSAPerQueryState::equalfns, ERROR, ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), execTuplesMatch(), fmgr_info_cxt(), get_opcode(), hypothetical_check_argtypes(), i, Int32GetDatum, MakeSingleTupleTableSlot(), MemoryContextAlloc(), NULL, OSAPerQueryState::numSortCols, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_NARGS, PG_RETURN_INT64, OSAPerQueryState::qcontext, OSAPerGroupState::qstate, slot_getattr(), OSAPerQueryState::sortColIdx, OSAPerGroupState::sortstate, TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, OSAPerQueryState::tupdesc, TupIsNull, tuplesort_end(), tuplesort_gettupleslot(), tuplesort_performsort(), tuplesort_puttupleslot(), and OSAPerQueryState::tupslot.

1272 {
1273  int nargs = PG_NARGS() - 1;
1274  int64 rank = 1;
1275  int64 duplicate_count = 0;
1276  OSAPerGroupState *osastate;
1277  int numDistinctCols;
1278  Datum abbrevVal = (Datum) 0;
1279  Datum abbrevOld = (Datum) 0;
1280  AttrNumber *sortColIdx;
1281  FmgrInfo *equalfns;
1282  TupleTableSlot *slot;
1283  TupleTableSlot *extraslot;
1284  TupleTableSlot *slot2;
1285  MemoryContext tmpcontext;
1286  int i;
1287 
1289 
1290  /* If there were no regular rows, the rank is always 1 */
1291  if (PG_ARGISNULL(0))
1292  PG_RETURN_INT64(rank);
1293 
1294  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
1295 
1296  /* Adjust nargs to be the number of direct (or aggregated) args */
1297  if (nargs % 2 != 0)
1298  elog(ERROR, "wrong number of arguments in hypothetical-set function");
1299  nargs /= 2;
1300 
1301  hypothetical_check_argtypes(fcinfo, nargs, osastate->qstate->tupdesc);
1302 
1303  /*
1304  * When comparing tuples, we can omit the flag column since we will only
1305  * compare rows with flag == 0.
1306  */
1307  numDistinctCols = osastate->qstate->numSortCols - 1;
1308 
1309  /* Look up the equality function(s), if we didn't already */
1310  equalfns = osastate->qstate->equalfns;
1311  if (equalfns == NULL)
1312  {
1313  MemoryContext qcontext = osastate->qstate->qcontext;
1314 
1315  equalfns = (FmgrInfo *)
1316  MemoryContextAlloc(qcontext, numDistinctCols * sizeof(FmgrInfo));
1317  for (i = 0; i < numDistinctCols; i++)
1318  {
1319  fmgr_info_cxt(get_opcode(osastate->qstate->eqOperators[i]),
1320  &equalfns[i],
1321  qcontext);
1322  }
1323  osastate->qstate->equalfns = equalfns;
1324  }
1325  sortColIdx = osastate->qstate->sortColIdx;
1326 
1327  /* Get short-term context we can use for execTuplesMatch */
1328  tmpcontext = AggGetTempMemoryContext(fcinfo);
1329 
1330  /* insert the hypothetical row into the sort */
1331  slot = osastate->qstate->tupslot;
1332  ExecClearTuple(slot);
1333  for (i = 0; i < nargs; i++)
1334  {
1335  slot->tts_values[i] = PG_GETARG_DATUM(i + 1);
1336  slot->tts_isnull[i] = PG_ARGISNULL(i + 1);
1337  }
1338  slot->tts_values[i] = Int32GetDatum(-1);
1339  slot->tts_isnull[i] = false;
1340  ExecStoreVirtualTuple(slot);
1341 
1342  tuplesort_puttupleslot(osastate->sortstate, slot);
1343 
1344  /* finish the sort */
1345  tuplesort_performsort(osastate->sortstate);
1346 
1347  /*
1348  * We alternate fetching into tupslot and extraslot so that we have the
1349  * previous row available for comparisons. This is accomplished by
1350  * swapping the slot pointer variables after each row.
1351  */
1352  extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc);
1353  slot2 = extraslot;
1354 
1355  /* iterate till we find the hypothetical row */
1356  while (tuplesort_gettupleslot(osastate->sortstate, true, true, slot,
1357  &abbrevVal))
1358  {
1359  bool isnull;
1360  Datum d = slot_getattr(slot, nargs + 1, &isnull);
1361  TupleTableSlot *tmpslot;
1362 
1363  if (!isnull && DatumGetInt32(d) != 0)
1364  break;
1365 
1366  /* count non-distinct tuples */
1367  if (!TupIsNull(slot2) &&
1368  abbrevVal == abbrevOld &&
1369  execTuplesMatch(slot, slot2,
1370  numDistinctCols,
1371  sortColIdx,
1372  equalfns,
1373  tmpcontext))
1374  duplicate_count++;
1375 
1376  tmpslot = slot2;
1377  slot2 = slot;
1378  slot = tmpslot;
1379  /* avoid execTuplesMatch() calls by reusing abbreviated keys */
1380  abbrevOld = abbrevVal;
1381 
1382  rank++;
1383 
1385  }
1386 
1387  ExecClearTuple(slot);
1388  ExecClearTuple(slot2);
1389 
1390  ExecDropSingleTupleTableSlot(extraslot);
1391 
1392  /* Might as well clean up the tuplesort object immediately */
1393  tuplesort_end(osastate->sortstate);
1394  osastate->sortstate = NULL;
1395 
1396  rank = rank - duplicate_count;
1397 
1398  PG_RETURN_INT64(rank);
1399 }
Definition: fmgr.h:56
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
OSAPerQueryState * qstate
#define DatumGetInt32(X)
Definition: postgres.h:478
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
TupleTableSlot * tupslot
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
bool execTuplesMatch(TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
Definition: execGrouping.c:69
Datum * tts_values
Definition: tuptable.h:125
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
MemoryContext qcontext
#define ERROR
Definition: elog.h:43
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy, TupleTableSlot *slot, Datum *abbrev)
Definition: tuplesort.c:2113
bool * tts_isnull
Definition: tuptable.h:126
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
#define TupIsNull(slot)
Definition: tuptable.h:138
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
MemoryContext AggGetTempMemoryContext(FunctionCallInfo fcinfo)
Definition: nodeAgg.c:4080
uintptr_t Datum
Definition: postgres.h:372
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
#define PG_NARGS()
Definition: fmgr.h:168
FmgrInfo * equalfns
#define Int32GetDatum(X)
Definition: postgres.h:485
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
int i
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1143
static void hypothetical_check_argtypes(FunctionCallInfo fcinfo, int nargs, TupleDesc tupdesc)
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define elog
Definition: elog.h:219
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1167
AttrNumber * sortColIdx
int16 AttrNumber
Definition: attnum.h:21
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Definition: tuplesort.c:1364
Datum hypothetical_percent_rank_final ( PG_FUNCTION_ARGS  )

Definition at line 1234 of file orderedsetaggs.c.

References hypothetical_rank_common(), and PG_RETURN_FLOAT8.

1235 {
1236  int64 rank;
1237  int64 rowcount;
1238  double result_val;
1239 
1240  rank = hypothetical_rank_common(fcinfo, -1, &rowcount);
1241 
1242  if (rowcount == 0)
1243  PG_RETURN_FLOAT8(0);
1244 
1245  result_val = (double) (rank - 1) / (double) (rowcount);
1246 
1247  PG_RETURN_FLOAT8(result_val);
1248 }
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
static int64 hypothetical_rank_common(FunctionCallInfo fcinfo, int flag, int64 *number_of_rows)
static int64 hypothetical_rank_common ( FunctionCallInfo  fcinfo,
int  flag,
int64 *  number_of_rows 
)
static

Definition at line 1147 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), Assert, CHECK_FOR_INTERRUPTS, DatumGetInt32, elog, ERROR, ExecClearTuple(), ExecStoreVirtualTuple(), hypothetical_check_argtypes(), i, Int32GetDatum, NULL, OSAPerGroupState::number_of_rows, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_NARGS, OSAPerGroupState::qstate, slot_getattr(), OSAPerGroupState::sortstate, TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, OSAPerQueryState::tupdesc, tuplesort_end(), tuplesort_gettupleslot(), tuplesort_performsort(), tuplesort_puttupleslot(), and OSAPerQueryState::tupslot.

Referenced by hypothetical_cume_dist_final(), hypothetical_percent_rank_final(), and hypothetical_rank_final().

1149 {
1150  int nargs = PG_NARGS() - 1;
1151  int64 rank = 1;
1152  OSAPerGroupState *osastate;
1153  TupleTableSlot *slot;
1154  int i;
1155 
1157 
1158  /* If there were no regular rows, the rank is always 1 */
1159  if (PG_ARGISNULL(0))
1160  {
1161  *number_of_rows = 0;
1162  return 1;
1163  }
1164 
1165  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
1166  *number_of_rows = osastate->number_of_rows;
1167 
1168  /* Adjust nargs to be the number of direct (or aggregated) args */
1169  if (nargs % 2 != 0)
1170  elog(ERROR, "wrong number of arguments in hypothetical-set function");
1171  nargs /= 2;
1172 
1173  hypothetical_check_argtypes(fcinfo, nargs, osastate->qstate->tupdesc);
1174 
1175  /* insert the hypothetical row into the sort */
1176  slot = osastate->qstate->tupslot;
1177  ExecClearTuple(slot);
1178  for (i = 0; i < nargs; i++)
1179  {
1180  slot->tts_values[i] = PG_GETARG_DATUM(i + 1);
1181  slot->tts_isnull[i] = PG_ARGISNULL(i + 1);
1182  }
1183  slot->tts_values[i] = Int32GetDatum(flag);
1184  slot->tts_isnull[i] = false;
1185  ExecStoreVirtualTuple(slot);
1186 
1187  tuplesort_puttupleslot(osastate->sortstate, slot);
1188 
1189  /* finish the sort */
1190  tuplesort_performsort(osastate->sortstate);
1191 
1192  /* iterate till we find the hypothetical row */
1193  while (tuplesort_gettupleslot(osastate->sortstate, true, true, slot, NULL))
1194  {
1195  bool isnull;
1196  Datum d = slot_getattr(slot, nargs + 1, &isnull);
1197 
1198  if (!isnull && DatumGetInt32(d) != 0)
1199  break;
1200 
1201  rank++;
1202 
1204  }
1205 
1206  ExecClearTuple(slot);
1207 
1208  /* Might as well clean up the tuplesort object immediately */
1209  tuplesort_end(osastate->sortstate);
1210  osastate->sortstate = NULL;
1211 
1212  return rank;
1213 }
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
OSAPerQueryState * qstate
#define DatumGetInt32(X)
Definition: postgres.h:478
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
TupleTableSlot * tupslot
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
Datum * tts_values
Definition: tuptable.h:125
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define ERROR
Definition: elog.h:43
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy, TupleTableSlot *slot, Datum *abbrev)
Definition: tuplesort.c:2113
bool * tts_isnull
Definition: tuptable.h:126
char * flag(int b)
Definition: test-ctype.c:33
uintptr_t Datum
Definition: postgres.h:372
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
#define PG_NARGS()
Definition: fmgr.h:168
#define Int32GetDatum(X)
Definition: postgres.h:485
int i
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1143
static void hypothetical_check_argtypes(FunctionCallInfo fcinfo, int nargs, TupleDesc tupdesc)
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define elog
Definition: elog.h:219
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1167
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Definition: tuplesort.c:1364
Datum hypothetical_rank_final ( PG_FUNCTION_ARGS  )

Definition at line 1220 of file orderedsetaggs.c.

References hypothetical_rank_common(), and PG_RETURN_INT64.

1221 {
1222  int64 rank;
1223  int64 rowcount;
1224 
1225  rank = hypothetical_rank_common(fcinfo, -1, &rowcount);
1226 
1227  PG_RETURN_INT64(rank);
1228 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
static int64 hypothetical_rank_common(FunctionCallInfo fcinfo, int flag, int64 *number_of_rows)
static Datum interval_lerp ( Datum  lo,
Datum  hi,
double  pct 
)
static

Definition at line 492 of file orderedsetaggs.c.

References DirectFunctionCall2, Float8GetDatumFast, interval_mi(), interval_mul(), and interval_pl().

Referenced by percentile_cont_interval_final(), and percentile_cont_interval_multi_final().

493 {
494  Datum diff_result = DirectFunctionCall2(interval_mi, hi, lo);
496  diff_result,
497  Float8GetDatumFast(pct));
498 
499  return DirectFunctionCall2(interval_pl, mul_result, lo);
500 }
Datum interval_mi(PG_FUNCTION_ARGS)
Definition: timestamp.c:3074
Datum interval_pl(PG_FUNCTION_ARGS)
Definition: timestamp.c:3040
uintptr_t Datum
Definition: postgres.h:372
#define Float8GetDatumFast(X)
Definition: postgres.h:782
Datum interval_mul(PG_FUNCTION_ARGS)
Definition: timestamp.c:3114
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:586
Datum mode_final ( PG_FUNCTION_ARGS  )

Definition at line 1011 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), Assert, CHECK_FOR_INTERRUPTS, DatumGetBool, DatumGetPointer, OSAPerQueryState::eqOperator, OSAPerQueryState::equalfn, fmgr_info_cxt(), FmgrInfo::fn_oid, FunctionCall2, get_opcode(), NULL, OSAPerGroupState::number_of_rows, OidIsValid, pfree(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_DATUM, PG_RETURN_NULL, OSAPerQueryState::qcontext, OSAPerGroupState::qstate, OSAPerGroupState::sortstate, tuplesort_getdatum(), tuplesort_performsort(), OSAPerQueryState::typByVal, and val.

1012 {
1013  OSAPerGroupState *osastate;
1014  Datum val;
1015  bool isnull;
1016  Datum mode_val = (Datum) 0;
1017  int64 mode_freq = 0;
1018  Datum last_val = (Datum) 0;
1019  int64 last_val_freq = 0;
1020  bool last_val_is_mode = false;
1021  FmgrInfo *equalfn;
1022  Datum abbrev_val = (Datum) 0;
1023  Datum last_abbrev_val = (Datum) 0;
1024  bool shouldfree;
1025 
1027 
1028  /* If there were no regular rows, the result is NULL */
1029  if (PG_ARGISNULL(0))
1030  PG_RETURN_NULL();
1031 
1032  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
1033 
1034  /* number_of_rows could be zero if we only saw NULL input values */
1035  if (osastate->number_of_rows == 0)
1036  PG_RETURN_NULL();
1037 
1038  /* Look up the equality function for the datatype, if we didn't already */
1039  equalfn = &(osastate->qstate->equalfn);
1040  if (!OidIsValid(equalfn->fn_oid))
1041  fmgr_info_cxt(get_opcode(osastate->qstate->eqOperator), equalfn,
1042  osastate->qstate->qcontext);
1043 
1044  shouldfree = !(osastate->qstate->typByVal);
1045 
1046  /* Finish the sort */
1047  tuplesort_performsort(osastate->sortstate);
1048 
1049  /* Scan tuples and count frequencies */
1050  while (tuplesort_getdatum(osastate->sortstate, true, &val, &isnull, &abbrev_val))
1051  {
1052  /* we don't expect any nulls, but ignore them if found */
1053  if (isnull)
1054  continue;
1055 
1056  if (last_val_freq == 0)
1057  {
1058  /* first nonnull value - it's the mode for now */
1059  mode_val = last_val = val;
1060  mode_freq = last_val_freq = 1;
1061  last_val_is_mode = true;
1062  last_abbrev_val = abbrev_val;
1063  }
1064  else if (abbrev_val == last_abbrev_val &&
1065  DatumGetBool(FunctionCall2(equalfn, val, last_val)))
1066  {
1067  /* value equal to previous value, count it */
1068  if (last_val_is_mode)
1069  mode_freq++; /* needn't maintain last_val_freq */
1070  else if (++last_val_freq > mode_freq)
1071  {
1072  /* last_val becomes new mode */
1073  if (shouldfree)
1074  pfree(DatumGetPointer(mode_val));
1075  mode_val = last_val;
1076  mode_freq = last_val_freq;
1077  last_val_is_mode = true;
1078  }
1079  if (shouldfree)
1080  pfree(DatumGetPointer(val));
1081  }
1082  else
1083  {
1084  /* val should replace last_val */
1085  if (shouldfree && !last_val_is_mode)
1086  pfree(DatumGetPointer(last_val));
1087  last_val = val;
1088  /* avoid equality function calls by reusing abbreviated keys */
1089  last_abbrev_val = abbrev_val;
1090  last_val_freq = 1;
1091  last_val_is_mode = false;
1092  }
1093 
1095  }
1096 
1097  if (shouldfree && !last_val_is_mode)
1098  pfree(DatumGetPointer(last_val));
1099 
1100  /*
1101  * Note: we *cannot* clean up the tuplesort object here, because the value
1102  * to be returned is allocated inside its sortcontext. We could use
1103  * datumCopy to copy it out of there, but it doesn't seem worth the
1104  * trouble, since the cleanup callback will clear the tuplesort later.
1105  */
1106 
1107  if (mode_freq)
1108  PG_RETURN_DATUM(mode_val);
1109  else
1110  PG_RETURN_NULL();
1111 }
Definition: fmgr.h:56
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2199
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
OSAPerQueryState * qstate
#define FunctionCall2(flinfo, arg1, arg2)
Definition: fmgr.h:604
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define OidIsValid(objectId)
Definition: c.h:538
MemoryContext qcontext
void pfree(void *pointer)
Definition: mcxt.c:950
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
#define DatumGetBool(X)
Definition: postgres.h:399
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
Oid fn_oid
Definition: fmgr.h:59
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
#define DatumGetPointer(X)
Definition: postgres.h:555
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
static void ordered_set_shutdown ( Datum  arg)
static

Definition at line 319 of file orderedsetaggs.c.

References DatumGetPointer, ExecClearTuple(), NULL, OSAPerGroupState::qstate, OSAPerGroupState::sortstate, tuplesort_end(), and OSAPerQueryState::tupslot.

Referenced by ordered_set_startup().

320 {
322 
323  /* Tuplesort object might have temp files. */
324  if (osastate->sortstate)
325  tuplesort_end(osastate->sortstate);
326  osastate->sortstate = NULL;
327  /* The tupleslot probably can't be holding a pin, but let's be safe. */
328  if (osastate->qstate->tupslot)
329  ExecClearTuple(osastate->qstate->tupslot);
330 }
OSAPerQueryState * qstate
TupleTableSlot * tupslot
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define NULL
Definition: c.h:229
Tuplesortstate * sortstate
#define DatumGetPointer(X)
Definition: postgres.h:555
void * arg
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1167
static OSAPerGroupState* ordered_set_startup ( FunctionCallInfo  fcinfo,
bool  use_tuples 
)
static

Definition at line 103 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), AggGetAggref(), Aggref::aggkind, AGGKIND_HYPOTHETICAL, AGGKIND_IS_ORDERED_SET, Aggref::aggorder, OSAPerQueryState::aggref, AggRegisterCallback(), Aggref::args, Assert, CreateTemplateTupleDesc(), elog, SortGroupClause::eqop, OSAPerQueryState::eqOperator, OSAPerQueryState::eqOperators, ERROR, ExecTypeFromTL(), TargetEntry::expr, exprCollation(), exprType(), FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, FreeTupleDesc(), OSAPerGroupState::gcontext, get_sortgroupclause_tle(), get_typlenbyvalalign(), i, Int4EqualOperator, Int4LessOperator, INT4OID, InvalidOid, lfirst, linitial, list_length(), MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), tupleDesc::natts, NULL, SortGroupClause::nulls_first, OSAPerGroupState::number_of_rows, OSAPerQueryState::numSortCols, OidIsValid, ordered_set_shutdown(), palloc(), palloc0(), PointerGetDatum, OSAPerQueryState::qcontext, OSAPerGroupState::qstate, TargetEntry::resno, OSAPerQueryState::sortColIdx, OSAPerQueryState::sortCollation, OSAPerQueryState::sortCollations, OSAPerQueryState::sortColType, OSAPerQueryState::sortNullsFirst, OSAPerQueryState::sortNullsFirsts, SortGroupClause::sortop, OSAPerQueryState::sortOperator, OSAPerQueryState::sortOperators, OSAPerGroupState::sortstate, OSAPerQueryState::tupdesc, TupleDescCopyEntry(), TupleDescInitEntry(), tuplesort_begin_datum(), tuplesort_begin_heap(), OSAPerQueryState::tupslot, OSAPerQueryState::typAlign, OSAPerQueryState::typByVal, OSAPerQueryState::typLen, and work_mem.

Referenced by ordered_set_transition(), and ordered_set_transition_multi().

104 {
105  OSAPerGroupState *osastate;
106  OSAPerQueryState *qstate;
107  MemoryContext gcontext;
108  MemoryContext oldcontext;
109 
110  /*
111  * Check we're called as aggregate (and not a window function), and get
112  * the Agg node's group-lifespan context (which might change from group to
113  * group, so we shouldn't cache it in the per-query state).
114  */
115  if (AggCheckCallContext(fcinfo, &gcontext) != AGG_CONTEXT_AGGREGATE)
116  elog(ERROR, "ordered-set aggregate called in non-aggregate context");
117 
118  /*
119  * We keep a link to the per-query state in fn_extra; if it's not there,
120  * create it, and do the per-query setup we need.
121  */
122  qstate = (OSAPerQueryState *) fcinfo->flinfo->fn_extra;
123  if (qstate == NULL)
124  {
125  Aggref *aggref;
126  MemoryContext qcontext;
127  List *sortlist;
128  int numSortCols;
129 
130  /* Get the Aggref so we can examine aggregate's arguments */
131  aggref = AggGetAggref(fcinfo);
132  if (!aggref)
133  elog(ERROR, "ordered-set aggregate called in non-aggregate context");
134  if (!AGGKIND_IS_ORDERED_SET(aggref->aggkind))
135  elog(ERROR, "ordered-set aggregate support function called for non-ordered-set aggregate");
136 
137  /*
138  * Prepare per-query structures in the fn_mcxt, which we assume is the
139  * executor's per-query context; in any case it's the right place to
140  * keep anything found via fn_extra.
141  */
142  qcontext = fcinfo->flinfo->fn_mcxt;
143  oldcontext = MemoryContextSwitchTo(qcontext);
144 
145  qstate = (OSAPerQueryState *) palloc0(sizeof(OSAPerQueryState));
146  qstate->aggref = aggref;
147  qstate->qcontext = qcontext;
148 
149  /* Extract the sort information */
150  sortlist = aggref->aggorder;
151  numSortCols = list_length(sortlist);
152 
153  if (use_tuples)
154  {
155  bool ishypothetical = (aggref->aggkind == AGGKIND_HYPOTHETICAL);
156  ListCell *lc;
157  int i;
158 
159  if (ishypothetical)
160  numSortCols++; /* make space for flag column */
161  qstate->numSortCols = numSortCols;
162  qstate->sortColIdx = (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
163  qstate->sortOperators = (Oid *) palloc(numSortCols * sizeof(Oid));
164  qstate->eqOperators = (Oid *) palloc(numSortCols * sizeof(Oid));
165  qstate->sortCollations = (Oid *) palloc(numSortCols * sizeof(Oid));
166  qstate->sortNullsFirsts = (bool *) palloc(numSortCols * sizeof(bool));
167 
168  i = 0;
169  foreach(lc, sortlist)
170  {
171  SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
172  TargetEntry *tle = get_sortgroupclause_tle(sortcl,
173  aggref->args);
174 
175  /* the parser should have made sure of this */
176  Assert(OidIsValid(sortcl->sortop));
177 
178  qstate->sortColIdx[i] = tle->resno;
179  qstate->sortOperators[i] = sortcl->sortop;
180  qstate->eqOperators[i] = sortcl->eqop;
181  qstate->sortCollations[i] = exprCollation((Node *) tle->expr);
182  qstate->sortNullsFirsts[i] = sortcl->nulls_first;
183  i++;
184  }
185 
186  if (ishypothetical)
187  {
188  /* Add an integer flag column as the last sort column */
189  qstate->sortColIdx[i] = list_length(aggref->args) + 1;
190  qstate->sortOperators[i] = Int4LessOperator;
191  qstate->eqOperators[i] = Int4EqualOperator;
192  qstate->sortCollations[i] = InvalidOid;
193  qstate->sortNullsFirsts[i] = false;
194  i++;
195  }
196 
197  Assert(i == numSortCols);
198 
199  /*
200  * Get a tupledesc corresponding to the aggregated inputs
201  * (including sort expressions) of the agg.
202  */
203  qstate->tupdesc = ExecTypeFromTL(aggref->args, false);
204 
205  /* If we need a flag column, hack the tupledesc to include that */
206  if (ishypothetical)
207  {
208  TupleDesc newdesc;
209  int natts = qstate->tupdesc->natts;
210 
211  newdesc = CreateTemplateTupleDesc(natts + 1, false);
212  for (i = 1; i <= natts; i++)
213  TupleDescCopyEntry(newdesc, i, qstate->tupdesc, i);
214 
215  TupleDescInitEntry(newdesc,
216  (AttrNumber) ++natts,
217  "flag",
218  INT4OID,
219  -1,
220  0);
221 
222  FreeTupleDesc(qstate->tupdesc);
223  qstate->tupdesc = newdesc;
224  }
225 
226  /* Create slot we'll use to store/retrieve rows */
227  qstate->tupslot = MakeSingleTupleTableSlot(qstate->tupdesc);
228  }
229  else
230  {
231  /* Sort single datums */
232  SortGroupClause *sortcl;
233  TargetEntry *tle;
234 
235  if (numSortCols != 1 || aggref->aggkind == AGGKIND_HYPOTHETICAL)
236  elog(ERROR, "ordered-set aggregate support function does not support multiple aggregated columns");
237 
238  sortcl = (SortGroupClause *) linitial(sortlist);
239  tle = get_sortgroupclause_tle(sortcl, aggref->args);
240 
241  /* the parser should have made sure of this */
242  Assert(OidIsValid(sortcl->sortop));
243 
244  /* Save sort ordering info */
245  qstate->sortColType = exprType((Node *) tle->expr);
246  qstate->sortOperator = sortcl->sortop;
247  qstate->eqOperator = sortcl->eqop;
248  qstate->sortCollation = exprCollation((Node *) tle->expr);
249  qstate->sortNullsFirst = sortcl->nulls_first;
250 
251  /* Save datatype info */
253  &qstate->typLen,
254  &qstate->typByVal,
255  &qstate->typAlign);
256  }
257 
258  fcinfo->flinfo->fn_extra = (void *) qstate;
259 
260  MemoryContextSwitchTo(oldcontext);
261  }
262 
263  /* Now build the stuff we need in group-lifespan context */
264  oldcontext = MemoryContextSwitchTo(gcontext);
265 
266  osastate = (OSAPerGroupState *) palloc(sizeof(OSAPerGroupState));
267  osastate->qstate = qstate;
268  osastate->gcontext = gcontext;
269 
270  /*
271  * Initialize tuplesort object.
272  */
273  if (use_tuples)
274  osastate->sortstate = tuplesort_begin_heap(qstate->tupdesc,
275  qstate->numSortCols,
276  qstate->sortColIdx,
277  qstate->sortOperators,
278  qstate->sortCollations,
279  qstate->sortNullsFirsts,
280  work_mem, false);
281  else
282  osastate->sortstate = tuplesort_begin_datum(qstate->sortColType,
283  qstate->sortOperator,
284  qstate->sortCollation,
285  qstate->sortNullsFirst,
286  work_mem, false);
287 
288  osastate->number_of_rows = 0;
289 
290  /* Now register a shutdown callback to clean things up at end of group */
291  AggRegisterCallback(fcinfo,
293  PointerGetDatum(osastate));
294 
295  MemoryContextSwitchTo(oldcontext);
296 
297  return osastate;
298 }
MemoryContext gcontext
OSAPerQueryState * qstate
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:370
MemoryContext fn_mcxt
Definition: fmgr.h:65
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
#define PointerGetDatum(X)
Definition: postgres.h:562
TupleTableSlot * tupslot
#define Int4LessOperator
Definition: pg_operator.h:133
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define INT4OID
Definition: pg_type.h:316
Definition: nodes.h:509
List * args
Definition: primnodes.h:301
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
int natts
Definition: tupdesc.h:73
#define AGGKIND_IS_ORDERED_SET(kind)
Definition: pg_aggregate.h:129
MemoryContext qcontext
FmgrInfo * flinfo
Definition: fmgr.h:79
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
static void ordered_set_shutdown(Datum arg)
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
Definition: tupdesc.c:230
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, bool randomAccess)
Definition: tuplesort.c:1038
List * aggorder
Definition: primnodes.h:302
AttrNumber resno
Definition: primnodes.h:1368
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:497
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
void * palloc0(Size size)
Definition: mcxt.c:878
int work_mem
Definition: globals.c:112
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1367
Tuplesortstate * sortstate
#define Int4EqualOperator
Definition: pg_operator.h:130
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:748
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
void * fn_extra
Definition: fmgr.h:64
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:268
void AggRegisterCallback(FunctionCallInfo fcinfo, ExprContextCallbackFunction func, Datum arg)
Definition: nodeAgg.c:4107
Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, bool randomAccess)
Definition: tuplesort.c:756
void * palloc(Size size)
Definition: mcxt.c:849
int i
char aggkind
Definition: primnodes.h:308
#define elog
Definition: elog.h:219
#define AGGKIND_HYPOTHETICAL
Definition: pg_aggregate.h:126
Definition: pg_list.h:45
AttrNumber * sortColIdx
int16 AttrNumber
Definition: attnum.h:21
Aggref * AggGetAggref(FunctionCallInfo fcinfo)
Definition: nodeAgg.c:4055
Datum ordered_set_transition ( PG_FUNCTION_ARGS  )

Definition at line 338 of file orderedsetaggs.c.

References OSAPerGroupState::number_of_rows, ordered_set_startup(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, OSAPerGroupState::sortstate, and tuplesort_putdatum().

339 {
340  OSAPerGroupState *osastate;
341 
342  /* If first call, create the transition state workspace */
343  if (PG_ARGISNULL(0))
344  osastate = ordered_set_startup(fcinfo, false);
345  else
346  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
347 
348  /* Load the datum into the tuplesort object, but only if it's not null */
349  if (!PG_ARGISNULL(1))
350  {
351  tuplesort_putdatum(osastate->sortstate, PG_GETARG_DATUM(1), false);
352  osastate->number_of_rows++;
353  }
354 
355  PG_RETURN_POINTER(osastate);
356 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
Definition: tuplesort.c:1485
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
static OSAPerGroupState * ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
Tuplesortstate * sortstate
Datum ordered_set_transition_multi ( PG_FUNCTION_ARGS  )

Definition at line 363 of file orderedsetaggs.c.

References Aggref::aggkind, AGGKIND_HYPOTHETICAL, OSAPerQueryState::aggref, Assert, ExecClearTuple(), ExecStoreVirtualTuple(), i, Int32GetDatum, tupleDesc::natts, OSAPerGroupState::number_of_rows, ordered_set_startup(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_NARGS, PG_RETURN_POINTER, OSAPerGroupState::qstate, OSAPerGroupState::sortstate, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, TupleTableSlot::tts_values, tuplesort_puttupleslot(), and OSAPerQueryState::tupslot.

364 {
365  OSAPerGroupState *osastate;
366  TupleTableSlot *slot;
367  int nargs;
368  int i;
369 
370  /* If first call, create the transition state workspace */
371  if (PG_ARGISNULL(0))
372  osastate = ordered_set_startup(fcinfo, true);
373  else
374  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
375 
376  /* Form a tuple from all the other inputs besides the transition value */
377  slot = osastate->qstate->tupslot;
378  ExecClearTuple(slot);
379  nargs = PG_NARGS() - 1;
380  for (i = 0; i < nargs; i++)
381  {
382  slot->tts_values[i] = PG_GETARG_DATUM(i + 1);
383  slot->tts_isnull[i] = PG_ARGISNULL(i + 1);
384  }
385  if (osastate->qstate->aggref->aggkind == AGGKIND_HYPOTHETICAL)
386  {
387  /* Add a zero flag value to mark this row as a normal input row */
388  slot->tts_values[i] = Int32GetDatum(0);
389  slot->tts_isnull[i] = false;
390  i++;
391  }
392  Assert(i == slot->tts_tupleDescriptor->natts);
393  ExecStoreVirtualTuple(slot);
394 
395  /* Load the row into the tuplesort object */
396  tuplesort_puttupleslot(osastate->sortstate, slot);
397  osastate->number_of_rows++;
398 
399  PG_RETURN_POINTER(osastate);
400 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
OSAPerQueryState * qstate
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
TupleTableSlot * tupslot
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
Datum * tts_values
Definition: tuptable.h:125
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
int natts
Definition: tupdesc.h:73
static OSAPerGroupState * ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
bool * tts_isnull
Definition: tuptable.h:126
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
#define PG_NARGS()
Definition: fmgr.h:168
#define Int32GetDatum(X)
Definition: postgres.h:485
int i
char aggkind
Definition: primnodes.h:308
#define AGGKIND_HYPOTHETICAL
Definition: pg_aggregate.h:126
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Definition: tuplesort.c:1364
static int pct_info_cmp ( const void *  pa,
const void *  pb 
)
static

Definition at line 625 of file orderedsetaggs.c.

References pct_info::first_row, and pct_info::second_row.

Referenced by setup_pct_info().

626 {
627  const struct pct_info *a = (const struct pct_info *) pa;
628  const struct pct_info *b = (const struct pct_info *) pb;
629 
630  if (a->first_row != b->first_row)
631  return (a->first_row < b->first_row) ? -1 : 1;
632  if (a->second_row != b->second_row)
633  return (a->second_row < b->second_row) ? -1 : 1;
634  return 0;
635 }
int64 second_row
int64 first_row
static Datum percentile_cont_final_common ( FunctionCallInfo  fcinfo,
Oid  expect_type,
LerpFunc  lerpfunc 
)
static

Definition at line 506 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), Assert, elog, ereport, errcode(), errmsg(), ERROR, NULL, OSAPerGroupState::number_of_rows, PG_ARGISNULL, PG_GETARG_FLOAT8, PG_GETARG_POINTER, PG_RETURN_DATUM, PG_RETURN_NULL, OSAPerGroupState::qstate, OSAPerQueryState::sortColType, OSAPerGroupState::sortstate, tuplesort_getdatum(), tuplesort_performsort(), tuplesort_skiptuples(), and val.

Referenced by percentile_cont_float8_final(), and percentile_cont_interval_final().

509 {
510  OSAPerGroupState *osastate;
511  double percentile;
512  int64 first_row = 0;
513  int64 second_row = 0;
514  Datum val;
515  Datum first_val;
516  Datum second_val;
517  double proportion;
518  bool isnull;
519 
521 
522  /* Get and check the percentile argument */
523  if (PG_ARGISNULL(1))
524  PG_RETURN_NULL();
525 
526  percentile = PG_GETARG_FLOAT8(1);
527 
528  if (percentile < 0 || percentile > 1 || isnan(percentile))
529  ereport(ERROR,
530  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
531  errmsg("percentile value %g is not between 0 and 1",
532  percentile)));
533 
534  /* If there were no regular rows, the result is NULL */
535  if (PG_ARGISNULL(0))
536  PG_RETURN_NULL();
537 
538  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
539 
540  /* number_of_rows could be zero if we only saw NULL input values */
541  if (osastate->number_of_rows == 0)
542  PG_RETURN_NULL();
543 
544  Assert(expect_type == osastate->qstate->sortColType);
545 
546  /* Finish the sort */
547  tuplesort_performsort(osastate->sortstate);
548 
549  first_row = floor(percentile * (osastate->number_of_rows - 1));
550  second_row = ceil(percentile * (osastate->number_of_rows - 1));
551 
552  Assert(first_row < osastate->number_of_rows);
553 
554  if (!tuplesort_skiptuples(osastate->sortstate, first_row, true))
555  elog(ERROR, "missing row in percentile_cont");
556 
557  if (!tuplesort_getdatum(osastate->sortstate, true, &first_val, &isnull, NULL))
558  elog(ERROR, "missing row in percentile_cont");
559  if (isnull)
560  PG_RETURN_NULL();
561 
562  if (first_row == second_row)
563  {
564  val = first_val;
565  }
566  else
567  {
568  if (!tuplesort_getdatum(osastate->sortstate, true, &second_val, &isnull, NULL))
569  elog(ERROR, "missing row in percentile_cont");
570 
571  if (isnull)
572  PG_RETURN_NULL();
573 
574  proportion = (percentile * (osastate->number_of_rows - 1)) - first_row;
575  val = lerpfunc(first_val, second_val, proportion);
576  }
577 
578  /*
579  * Note: we *cannot* clean up the tuplesort object here, because the value
580  * to be returned may be allocated inside its sortcontext. We could use
581  * datumCopy to copy it out of there, but it doesn't seem worth the
582  * trouble, since the cleanup callback will clear the tuplesort later.
583  */
584 
585  PG_RETURN_DATUM(val);
586 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:246
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2199
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
OSAPerQueryState * qstate
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
int64 second_row
#define ERROR
Definition: elog.h:43
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
#define ereport(elevel, rest)
Definition: elog.h:122
int64 first_row
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
double proportion
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples, bool forward)
Definition: tuplesort.c:2238
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum percentile_cont_float8_final ( PG_FUNCTION_ARGS  )

Definition at line 592 of file orderedsetaggs.c.

References float8_lerp(), FLOAT8OID, and percentile_cont_final_common().

593 {
595 }
#define FLOAT8OID
Definition: pg_type.h:419
static Datum percentile_cont_final_common(FunctionCallInfo fcinfo, Oid expect_type, LerpFunc lerpfunc)
static Datum float8_lerp(Datum lo, Datum hi, double pct)
Datum percentile_cont_float8_multi_final ( PG_FUNCTION_ARGS  )

Definition at line 984 of file orderedsetaggs.c.

References float8_lerp(), FLOAT8OID, and percentile_cont_multi_final_common().

985 {
987  FLOAT8OID,
988  /* hard-wired info on type float8 */
989  8, FLOAT8PASSBYVAL, 'd',
990  float8_lerp);
991 }
#define FLOAT8OID
Definition: pg_type.h:419
static Datum percentile_cont_multi_final_common(FunctionCallInfo fcinfo, Oid expect_type, int16 typLen, bool typByVal, char typAlign, LerpFunc lerpfunc)
static Datum float8_lerp(Datum lo, Datum hi, double pct)
Datum percentile_cont_interval_final ( PG_FUNCTION_ARGS  )

Definition at line 601 of file orderedsetaggs.c.

References interval_lerp(), INTERVALOID, and percentile_cont_final_common().

602 {
604 }
static Datum interval_lerp(Datum lo, Datum hi, double pct)
#define INTERVALOID
Definition: pg_type.h:529
static Datum percentile_cont_final_common(FunctionCallInfo fcinfo, Oid expect_type, LerpFunc lerpfunc)
Datum percentile_cont_interval_multi_final ( PG_FUNCTION_ARGS  )

Definition at line 997 of file orderedsetaggs.c.

References interval_lerp(), INTERVALOID, and percentile_cont_multi_final_common().

998 {
1000  INTERVALOID,
1001  /* hard-wired info on type interval */
1002  16, false, 'd',
1003  interval_lerp);
1004 }
static Datum interval_lerp(Datum lo, Datum hi, double pct)
#define INTERVALOID
Definition: pg_type.h:529
static Datum percentile_cont_multi_final_common(FunctionCallInfo fcinfo, Oid expect_type, int16 typLen, bool typByVal, char typAlign, LerpFunc lerpfunc)
static Datum percentile_cont_multi_final_common ( FunctionCallInfo  fcinfo,
Oid  expect_type,
int16  typLen,
bool  typByVal,
char  typAlign,
LerpFunc  lerpfunc 
)
static

Definition at line 827 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), ARR_DIMS, ARR_LBOUND, ARR_NDIM, Assert, construct_empty_array(), construct_md_array(), deconstruct_array(), elog, ERROR, pct_info::first_row, FLOAT8OID, i, idx(), pct_info::idx, NULL, OSAPerGroupState::number_of_rows, palloc(), PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_POINTER, pct_info::proportion, OSAPerGroupState::qstate, pct_info::second_row, setup_pct_info(), OSAPerQueryState::sortColType, OSAPerGroupState::sortstate, tuplesort_getdatum(), tuplesort_performsort(), and tuplesort_skiptuples().

Referenced by percentile_cont_float8_multi_final(), and percentile_cont_interval_multi_final().

831 {
832  OSAPerGroupState *osastate;
833  ArrayType *param;
834  Datum *percentiles_datum;
835  bool *percentiles_null;
836  int num_percentiles;
837  struct pct_info *pct_info;
838  Datum *result_datum;
839  bool *result_isnull;
840  int64 rownum = 0;
841  Datum first_val = (Datum) 0;
842  Datum second_val = (Datum) 0;
843  bool isnull;
844  int i;
845 
847 
848  /* If there were no regular rows, the result is NULL */
849  if (PG_ARGISNULL(0))
850  PG_RETURN_NULL();
851 
852  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
853 
854  /* number_of_rows could be zero if we only saw NULL input values */
855  if (osastate->number_of_rows == 0)
856  PG_RETURN_NULL();
857 
858  Assert(expect_type == osastate->qstate->sortColType);
859 
860  /* Deconstruct the percentile-array input */
861  if (PG_ARGISNULL(1))
862  PG_RETURN_NULL();
863  param = PG_GETARG_ARRAYTYPE_P(1);
864 
866  /* hard-wired info on type float8 */
867  8, FLOAT8PASSBYVAL, 'd',
868  &percentiles_datum,
869  &percentiles_null,
870  &num_percentiles);
871 
872  if (num_percentiles == 0)
874 
875  pct_info = setup_pct_info(num_percentiles,
876  percentiles_datum,
877  percentiles_null,
878  osastate->number_of_rows,
879  true);
880 
881  result_datum = (Datum *) palloc(num_percentiles * sizeof(Datum));
882  result_isnull = (bool *) palloc(num_percentiles * sizeof(bool));
883 
884  /*
885  * Start by dealing with any nulls in the param array - those are sorted
886  * to the front on row=0, so set the corresponding result indexes to null
887  */
888  for (i = 0; i < num_percentiles; i++)
889  {
890  int idx = pct_info[i].idx;
891 
892  if (pct_info[i].first_row > 0)
893  break;
894 
895  result_datum[idx] = (Datum) 0;
896  result_isnull[idx] = true;
897  }
898 
899  /*
900  * If there's anything left after doing the nulls, then grind the input
901  * and extract the needed values
902  */
903  if (i < num_percentiles)
904  {
905  /* Finish the sort */
906  tuplesort_performsort(osastate->sortstate);
907 
908  for (; i < num_percentiles; i++)
909  {
910  int64 first_row = pct_info[i].first_row;
911  int64 second_row = pct_info[i].second_row;
912  int idx = pct_info[i].idx;
913 
914  /*
915  * Advance to first_row, if not already there. Note that we might
916  * already have rownum beyond first_row, in which case first_val
917  * is already correct. (This occurs when interpolating between
918  * the same two input rows as for the previous percentile.)
919  */
920  if (first_row > rownum)
921  {
922  if (!tuplesort_skiptuples(osastate->sortstate, first_row - rownum - 1, true))
923  elog(ERROR, "missing row in percentile_cont");
924 
925  if (!tuplesort_getdatum(osastate->sortstate, true, &first_val,
926  &isnull, NULL) || isnull)
927  elog(ERROR, "missing row in percentile_cont");
928 
929  rownum = first_row;
930  /* Always advance second_val to be latest input value */
931  second_val = first_val;
932  }
933  else if (first_row == rownum)
934  {
935  /*
936  * We are already at the desired row, so we must previously
937  * have read its value into second_val (and perhaps first_val
938  * as well, but this assignment is harmless in that case).
939  */
940  first_val = second_val;
941  }
942 
943  /* Fetch second_row if needed */
944  if (second_row > rownum)
945  {
946  if (!tuplesort_getdatum(osastate->sortstate, true, &second_val,
947  &isnull, NULL) || isnull)
948  elog(ERROR, "missing row in percentile_cont");
949  rownum++;
950  }
951  /* We should now certainly be on second_row exactly */
952  Assert(second_row == rownum);
953 
954  /* Compute appropriate result */
955  if (second_row > first_row)
956  result_datum[idx] = lerpfunc(first_val, second_val,
957  pct_info[i].proportion);
958  else
959  result_datum[idx] = first_val;
960 
961  result_isnull[idx] = false;
962  }
963  }
964 
965  /*
966  * We could clean up the tuplesort object after forming the array, but
967  * probably not worth the trouble.
968  */
969 
970  /* We make the output array the same shape as the input */
971  PG_RETURN_POINTER(construct_md_array(result_datum, result_isnull,
972  ARR_NDIM(param),
973  ARR_DIMS(param), ARR_LBOUND(param),
974  expect_type,
975  typLen,
976  typByVal,
977  typAlign));
978 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2199
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
OSAPerQueryState * qstate
static struct pct_info * setup_pct_info(int num_percentiles, Datum *percentiles_datum, bool *percentiles_null, int64 rowcount, bool continuous)
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3424
#define ARR_LBOUND(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
int64 second_row
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:275
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
int64 first_row
uintptr_t Datum
Definition: postgres.h:372
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
#define FLOAT8OID
Definition: pg_type.h:419
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
#define ARR_NDIM(a)
Definition: array.h:271
double proportion
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define elog
Definition: elog.h:219
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3340
bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples, bool forward)
Definition: tuplesort.c:2238
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum percentile_disc_final ( PG_FUNCTION_ARGS  )

Definition at line 407 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), Assert, elog, ereport, errcode(), errmsg(), ERROR, NULL, OSAPerGroupState::number_of_rows, PG_ARGISNULL, PG_GETARG_FLOAT8, PG_GETARG_POINTER, PG_RETURN_DATUM, PG_RETURN_NULL, OSAPerGroupState::sortstate, tuplesort_getdatum(), tuplesort_performsort(), tuplesort_skiptuples(), and val.

408 {
409  OSAPerGroupState *osastate;
410  double percentile;
411  Datum val;
412  bool isnull;
413  int64 rownum;
414 
416 
417  /* Get and check the percentile argument */
418  if (PG_ARGISNULL(1))
419  PG_RETURN_NULL();
420 
421  percentile = PG_GETARG_FLOAT8(1);
422 
423  if (percentile < 0 || percentile > 1 || isnan(percentile))
424  ereport(ERROR,
425  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
426  errmsg("percentile value %g is not between 0 and 1",
427  percentile)));
428 
429  /* If there were no regular rows, the result is NULL */
430  if (PG_ARGISNULL(0))
431  PG_RETURN_NULL();
432 
433  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
434 
435  /* number_of_rows could be zero if we only saw NULL input values */
436  if (osastate->number_of_rows == 0)
437  PG_RETURN_NULL();
438 
439  /* Finish the sort */
440  tuplesort_performsort(osastate->sortstate);
441 
442  /*----------
443  * We need the smallest K such that (K/N) >= percentile.
444  * N>0, therefore K >= N*percentile, therefore K = ceil(N*percentile).
445  * So we skip K-1 rows (if K>0) and return the next row fetched.
446  *----------
447  */
448  rownum = (int64) ceil(percentile * osastate->number_of_rows);
449  Assert(rownum <= osastate->number_of_rows);
450 
451  if (rownum > 1)
452  {
453  if (!tuplesort_skiptuples(osastate->sortstate, rownum - 1, true))
454  elog(ERROR, "missing row in percentile_disc");
455  }
456 
457  if (!tuplesort_getdatum(osastate->sortstate, true, &val, &isnull, NULL))
458  elog(ERROR, "missing row in percentile_disc");
459 
460  /*
461  * Note: we *cannot* clean up the tuplesort object here, because the value
462  * to be returned is allocated inside its sortcontext. We could use
463  * datumCopy to copy it out of there, but it doesn't seem worth the
464  * trouble, since the cleanup callback will clear the tuplesort later.
465  */
466 
467  /* We shouldn't have stored any nulls, but do the right thing anyway */
468  if (isnull)
469  PG_RETURN_NULL();
470  else
471  PG_RETURN_DATUM(val);
472 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:246
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2199
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define ERROR
Definition: elog.h:43
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples, bool forward)
Definition: tuplesort.c:2238
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum percentile_disc_multi_final ( PG_FUNCTION_ARGS  )

Definition at line 710 of file orderedsetaggs.c.

References AGG_CONTEXT_AGGREGATE, AggCheckCallContext(), ARR_DIMS, ARR_LBOUND, ARR_NDIM, Assert, construct_empty_array(), construct_md_array(), deconstruct_array(), elog, ERROR, pct_info::first_row, FLOAT8OID, i, idx(), pct_info::idx, NULL, OSAPerGroupState::number_of_rows, palloc(), PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_POINTER, OSAPerGroupState::qstate, setup_pct_info(), OSAPerQueryState::sortColType, OSAPerGroupState::sortstate, tuplesort_getdatum(), tuplesort_performsort(), tuplesort_skiptuples(), OSAPerQueryState::typAlign, OSAPerQueryState::typByVal, OSAPerQueryState::typLen, and val.

711 {
712  OSAPerGroupState *osastate;
713  ArrayType *param;
714  Datum *percentiles_datum;
715  bool *percentiles_null;
716  int num_percentiles;
717  struct pct_info *pct_info;
718  Datum *result_datum;
719  bool *result_isnull;
720  int64 rownum = 0;
721  Datum val = (Datum) 0;
722  bool isnull = true;
723  int i;
724 
726 
727  /* If there were no regular rows, the result is NULL */
728  if (PG_ARGISNULL(0))
729  PG_RETURN_NULL();
730 
731  osastate = (OSAPerGroupState *) PG_GETARG_POINTER(0);
732 
733  /* number_of_rows could be zero if we only saw NULL input values */
734  if (osastate->number_of_rows == 0)
735  PG_RETURN_NULL();
736 
737  /* Deconstruct the percentile-array input */
738  if (PG_ARGISNULL(1))
739  PG_RETURN_NULL();
740  param = PG_GETARG_ARRAYTYPE_P(1);
741 
743  /* hard-wired info on type float8 */
744  8, FLOAT8PASSBYVAL, 'd',
745  &percentiles_datum,
746  &percentiles_null,
747  &num_percentiles);
748 
749  if (num_percentiles == 0)
751 
752  pct_info = setup_pct_info(num_percentiles,
753  percentiles_datum,
754  percentiles_null,
755  osastate->number_of_rows,
756  false);
757 
758  result_datum = (Datum *) palloc(num_percentiles * sizeof(Datum));
759  result_isnull = (bool *) palloc(num_percentiles * sizeof(bool));
760 
761  /*
762  * Start by dealing with any nulls in the param array - those are sorted
763  * to the front on row=0, so set the corresponding result indexes to null
764  */
765  for (i = 0; i < num_percentiles; i++)
766  {
767  int idx = pct_info[i].idx;
768 
769  if (pct_info[i].first_row > 0)
770  break;
771 
772  result_datum[idx] = (Datum) 0;
773  result_isnull[idx] = true;
774  }
775 
776  /*
777  * If there's anything left after doing the nulls, then grind the input
778  * and extract the needed values
779  */
780  if (i < num_percentiles)
781  {
782  /* Finish the sort */
783  tuplesort_performsort(osastate->sortstate);
784 
785  for (; i < num_percentiles; i++)
786  {
787  int64 target_row = pct_info[i].first_row;
788  int idx = pct_info[i].idx;
789 
790  /* Advance to target row, if not already there */
791  if (target_row > rownum)
792  {
793  if (!tuplesort_skiptuples(osastate->sortstate, target_row - rownum - 1, true))
794  elog(ERROR, "missing row in percentile_disc");
795 
796  if (!tuplesort_getdatum(osastate->sortstate, true, &val, &isnull, NULL))
797  elog(ERROR, "missing row in percentile_disc");
798 
799  rownum = target_row;
800  }
801 
802  result_datum[idx] = val;
803  result_isnull[idx] = isnull;
804  }
805  }
806 
807  /*
808  * We could clean up the tuplesort object after forming the array, but
809  * probably not worth the trouble.
810  */
811 
812  /* We make the output array the same shape as the input */
813  PG_RETURN_POINTER(construct_md_array(result_datum, result_isnull,
814  ARR_NDIM(param),
815  ARR_DIMS(param),
816  ARR_LBOUND(param),
817  osastate->qstate->sortColType,
818  osastate->qstate->typLen,
819  osastate->qstate->typByVal,
820  osastate->qstate->typAlign));
821 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2199
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1773
OSAPerQueryState * qstate
static struct pct_info * setup_pct_info(int num_percentiles, Datum *percentiles_datum, bool *percentiles_null, int64 rowcount, bool continuous)
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3424
#define ARR_LBOUND(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:275
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:693
int64 first_row
uintptr_t Datum
Definition: postgres.h:372
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Tuplesortstate * sortstate
#define FLOAT8OID
Definition: pg_type.h:419
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4018
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define elog
Definition: elog.h:219
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3340
bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples, bool forward)
Definition: tuplesort.c:2238
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
static struct pct_info* setup_pct_info ( int  num_percentiles,
Datum percentiles_datum,
bool percentiles_null,
int64  rowcount,
bool  continuous 
)
static

Definition at line 641 of file orderedsetaggs.c.

References DatumGetFloat8, ereport, errcode(), errmsg(), ERROR, pct_info::first_row, i, pct_info::idx, Max, palloc(), pct_info_cmp(), pct_info::proportion, qsort, and pct_info::second_row.

Referenced by percentile_cont_multi_final_common(), and percentile_disc_multi_final().

646 {
647  struct pct_info *pct_info;
648  int i;
649 
650  pct_info = (struct pct_info *) palloc(num_percentiles * sizeof(struct pct_info));
651 
652  for (i = 0; i < num_percentiles; i++)
653  {
654  pct_info[i].idx = i;
655 
656  if (percentiles_null[i])
657  {
658  /* dummy entry for any NULL in array */
659  pct_info[i].first_row = 0;
660  pct_info[i].second_row = 0;
661  pct_info[i].proportion = 0;
662  }
663  else
664  {
665  double p = DatumGetFloat8(percentiles_datum[i]);
666 
667  if (p < 0 || p > 1 || isnan(p))
668  ereport(ERROR,
669  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
670  errmsg("percentile value %g is not between 0 and 1",
671  p)));
672 
673  if (continuous)
674  {
675  pct_info[i].first_row = 1 + floor(p * (rowcount - 1));
676  pct_info[i].second_row = 1 + ceil(p * (rowcount - 1));
677  pct_info[i].proportion = (p * (rowcount - 1)) - floor(p * (rowcount - 1));
678  }
679  else
680  {
681  /*----------
682  * We need the smallest K such that (K/N) >= percentile.
683  * N>0, therefore K >= N*percentile, therefore
684  * K = ceil(N*percentile); but not less than 1.
685  *----------
686  */
687  int64 row = (int64) ceil(p * rowcount);
688 
689  row = Max(1, row);
690  pct_info[i].first_row = row;
691  pct_info[i].second_row = row;
692  pct_info[i].proportion = 0;
693  }
694  }
695  }
696 
697  /*
698  * The parameter array wasn't necessarily in sorted order, but we need to
699  * visit the rows in order, so sort by first_row/second_row.
700  */
701  qsort(pct_info, num_percentiles, sizeof(struct pct_info), pct_info_cmp);
702 
703  return pct_info;
704 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int64 second_row
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int64 first_row
#define DatumGetFloat8(X)
Definition: postgres.h:734
#define Max(x, y)
Definition: c.h:800
double proportion
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define qsort(a, b, c, d)
Definition: port.h:440
static int pct_info_cmp(const void *pa, const void *pb)