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

211 Assert(i == numSortCols);

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{

639 int idx;

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

828 result_datum[idx] = val;

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)