PostgreSQL Source Code  git master
windowfuncs.c File Reference
#include "postgres.h"
#include "nodes/supportnodes.h"
#include "utils/builtins.h"
#include "windowapi.h"
Include dependency graph for windowfuncs.c:

Go to the source code of this file.

Data Structures

struct  rank_context
 
struct  ntile_context
 

Typedefs

typedef struct rank_context rank_context
 

Functions

static bool rank_up (WindowObject winobj)
 
static Datum leadlag_common (FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
 
Datum window_row_number (PG_FUNCTION_ARGS)
 
Datum window_row_number_support (PG_FUNCTION_ARGS)
 
Datum window_rank (PG_FUNCTION_ARGS)
 
Datum window_rank_support (PG_FUNCTION_ARGS)
 
Datum window_dense_rank (PG_FUNCTION_ARGS)
 
Datum window_dense_rank_support (PG_FUNCTION_ARGS)
 
Datum window_percent_rank (PG_FUNCTION_ARGS)
 
Datum window_cume_dist (PG_FUNCTION_ARGS)
 
Datum window_ntile (PG_FUNCTION_ARGS)
 
Datum window_lag (PG_FUNCTION_ARGS)
 
Datum window_lag_with_offset (PG_FUNCTION_ARGS)
 
Datum window_lag_with_offset_and_default (PG_FUNCTION_ARGS)
 
Datum window_lead (PG_FUNCTION_ARGS)
 
Datum window_lead_with_offset (PG_FUNCTION_ARGS)
 
Datum window_lead_with_offset_and_default (PG_FUNCTION_ARGS)
 
Datum window_first_value (PG_FUNCTION_ARGS)
 
Datum window_last_value (PG_FUNCTION_ARGS)
 
Datum window_nth_value (PG_FUNCTION_ARGS)
 

Typedef Documentation

◆ rank_context

typedef struct rank_context rank_context

Function Documentation

◆ leadlag_common()

static Datum leadlag_common ( FunctionCallInfo  fcinfo,
bool  forward,
bool  withoffset,
bool  withdefault 
)
static

Definition at line 349 of file windowfuncs.c.

351 {
352  WindowObject winobj = PG_WINDOW_OBJECT();
353  int32 offset;
354  bool const_offset;
355  Datum result;
356  bool isnull;
357  bool isout;
358 
359  if (withoffset)
360  {
361  offset = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
362  if (isnull)
363  PG_RETURN_NULL();
364  const_offset = get_fn_expr_arg_stable(fcinfo->flinfo, 1);
365  }
366  else
367  {
368  offset = 1;
369  const_offset = true;
370  }
371 
372  result = WinGetFuncArgInPartition(winobj, 0,
373  (forward ? offset : -offset),
375  const_offset,
376  &isnull, &isout);
377 
378  if (isout)
379  {
380  /*
381  * target row is out of the partition; supply default value if
382  * provided. otherwise it'll stay NULL
383  */
384  if (withdefault)
385  result = WinGetFuncArgCurrent(winobj, 2, &isnull);
386  }
387 
388  if (isnull)
389  PG_RETURN_NULL();
390 
391  PG_RETURN_DATUM(result);
392 }
signed int int32
Definition: c.h:440
bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1851
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
Datum WinGetFuncArgInPartition(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
Datum WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetInt32(X)
Definition: postgres.h:516
FmgrInfo * flinfo
Definition: fmgr.h:87
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
#define WINDOW_SEEK_CURRENT
Definition: windowapi.h:32

References DatumGetInt32, FunctionCallInfoBaseData::flinfo, get_fn_expr_arg_stable(), PG_RETURN_DATUM, PG_RETURN_NULL, PG_WINDOW_OBJECT, WINDOW_SEEK_CURRENT, WinGetFuncArgCurrent(), and WinGetFuncArgInPartition().

Referenced by window_lag(), window_lag_with_offset(), window_lag_with_offset_and_default(), window_lead(), window_lead_with_offset(), and window_lead_with_offset_and_default().

◆ rank_up()

static bool rank_up ( WindowObject  winobj)
static

Definition at line 48 of file windowfuncs.c.

49 {
50  bool up = false; /* should rank increase? */
51  int64 curpos = WinGetCurrentPosition(winobj);
52  rank_context *context;
53 
54  context = (rank_context *)
56 
57  if (context->rank == 0)
58  {
59  /* first call: rank of first row is always 1 */
60  Assert(curpos == 0);
61  context->rank = 1;
62  }
63  else
64  {
65  Assert(curpos > 0);
66  /* do current and prior tuples match by ORDER BY clause? */
67  if (!WinRowsArePeers(winobj, curpos - 1, curpos))
68  up = true;
69  }
70 
71  /* We can advance the mark, but only *after* access to prior row */
72  WinSetMarkPosition(winobj, curpos);
73 
74  return up;
75 }
Assert(fmt[strlen(fmt) - 1] !='\n')
int64 WinGetCurrentPosition(WindowObject winobj)
bool WinRowsArePeers(WindowObject winobj, int64 pos1, int64 pos2)
void WinSetMarkPosition(WindowObject winobj, int64 markpos)
void * WinGetPartitionLocalMemory(WindowObject winobj, Size sz)

References Assert(), rank_context::rank, WinGetCurrentPosition(), WinGetPartitionLocalMemory(), WinRowsArePeers(), and WinSetMarkPosition().

Referenced by window_cume_dist(), window_dense_rank(), window_percent_rank(), and window_rank().

◆ window_cume_dist()

Datum window_cume_dist ( PG_FUNCTION_ARGS  )

Definition at line 232 of file windowfuncs.c.

233 {
234  WindowObject winobj = PG_WINDOW_OBJECT();
235  rank_context *context;
236  bool up;
237  int64 totalrows = WinGetPartitionRowCount(winobj);
238 
239  Assert(totalrows > 0);
240 
241  up = rank_up(winobj);
242  context = (rank_context *)
243  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
244  if (up || context->rank == 1)
245  {
246  /*
247  * The current row is not peer to prior row or is just the first, so
248  * count up the number of rows that are peer to the current.
249  */
250  int64 row;
251 
252  context->rank = WinGetCurrentPosition(winobj) + 1;
253 
254  /*
255  * start from current + 1
256  */
257  for (row = context->rank; row < totalrows; row++)
258  {
259  if (!WinRowsArePeers(winobj, row - 1, row))
260  break;
261  context->rank++;
262  }
263  }
264 
265  PG_RETURN_FLOAT8((float8) context->rank / (float8) totalrows);
266 }
double float8
Definition: c.h:576
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
int64 WinGetPartitionRowCount(WindowObject winobj)
static bool rank_up(WindowObject winobj)
Definition: windowfuncs.c:48

References Assert(), PG_RETURN_FLOAT8, PG_WINDOW_OBJECT, rank_context::rank, rank_up(), WinGetCurrentPosition(), WinGetPartitionLocalMemory(), WinGetPartitionRowCount(), and WinRowsArePeers().

◆ window_dense_rank()

Datum window_dense_rank ( PG_FUNCTION_ARGS  )

Definition at line 160 of file windowfuncs.c.

161 {
162  WindowObject winobj = PG_WINDOW_OBJECT();
163  rank_context *context;
164  bool up;
165 
166  up = rank_up(winobj);
167  context = (rank_context *)
168  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
169  if (up)
170  context->rank++;
171 
172  PG_RETURN_INT64(context->rank);
173 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368

References PG_RETURN_INT64, PG_WINDOW_OBJECT, rank_context::rank, rank_up(), and WinGetPartitionLocalMemory().

◆ window_dense_rank_support()

Datum window_dense_rank_support ( PG_FUNCTION_ARGS  )

Definition at line 180 of file windowfuncs.c.

181 {
182  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
183 
184  if (IsA(rawreq, SupportRequestWFuncMonotonic))
185  {
187 
188  /* dense_rank() is monotonically increasing */
190  PG_RETURN_POINTER(req);
191  }
192 
193  PG_RETURN_POINTER(NULL);
194 }
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
@ MONOTONICFUNC_INCREASING
Definition: plannodes.h:1547
Definition: nodes.h:574
MonotonicFunction monotonic
Definition: supportnodes.h:299

References IsA, SupportRequestWFuncMonotonic::monotonic, MONOTONICFUNC_INCREASING, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ window_first_value()

Datum window_first_value ( PG_FUNCTION_ARGS  )

Definition at line 470 of file windowfuncs.c.

471 {
472  WindowObject winobj = PG_WINDOW_OBJECT();
473  Datum result;
474  bool isnull;
475 
476  result = WinGetFuncArgInFrame(winobj, 0,
477  0, WINDOW_SEEK_HEAD, true,
478  &isnull, NULL);
479  if (isnull)
480  PG_RETURN_NULL();
481 
482  PG_RETURN_DATUM(result);
483 }
Datum WinGetFuncArgInFrame(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
#define WINDOW_SEEK_HEAD
Definition: windowapi.h:33

References PG_RETURN_DATUM, PG_RETURN_NULL, PG_WINDOW_OBJECT, WINDOW_SEEK_HEAD, and WinGetFuncArgInFrame().

◆ window_lag()

Datum window_lag ( PG_FUNCTION_ARGS  )

Definition at line 401 of file windowfuncs.c.

402 {
403  return leadlag_common(fcinfo, false, false, false);
404 }
static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
Definition: windowfuncs.c:349

References leadlag_common().

◆ window_lag_with_offset()

Datum window_lag_with_offset ( PG_FUNCTION_ARGS  )

Definition at line 413 of file windowfuncs.c.

414 {
415  return leadlag_common(fcinfo, false, true, false);
416 }

References leadlag_common().

◆ window_lag_with_offset_and_default()

Datum window_lag_with_offset_and_default ( PG_FUNCTION_ARGS  )

Definition at line 424 of file windowfuncs.c.

425 {
426  return leadlag_common(fcinfo, false, true, true);
427 }

References leadlag_common().

◆ window_last_value()

Datum window_last_value ( PG_FUNCTION_ARGS  )

Definition at line 491 of file windowfuncs.c.

492 {
493  WindowObject winobj = PG_WINDOW_OBJECT();
494  Datum result;
495  bool isnull;
496 
497  result = WinGetFuncArgInFrame(winobj, 0,
498  0, WINDOW_SEEK_TAIL, true,
499  &isnull, NULL);
500  if (isnull)
501  PG_RETURN_NULL();
502 
503  PG_RETURN_DATUM(result);
504 }
#define WINDOW_SEEK_TAIL
Definition: windowapi.h:34

References PG_RETURN_DATUM, PG_RETURN_NULL, PG_WINDOW_OBJECT, WINDOW_SEEK_TAIL, and WinGetFuncArgInFrame().

◆ window_lead()

Datum window_lead ( PG_FUNCTION_ARGS  )

Definition at line 436 of file windowfuncs.c.

437 {
438  return leadlag_common(fcinfo, true, false, false);
439 }

References leadlag_common().

◆ window_lead_with_offset()

Datum window_lead_with_offset ( PG_FUNCTION_ARGS  )

Definition at line 448 of file windowfuncs.c.

449 {
450  return leadlag_common(fcinfo, true, true, false);
451 }

References leadlag_common().

◆ window_lead_with_offset_and_default()

Datum window_lead_with_offset_and_default ( PG_FUNCTION_ARGS  )

Definition at line 459 of file windowfuncs.c.

460 {
461  return leadlag_common(fcinfo, true, true, true);
462 }

References leadlag_common().

◆ window_nth_value()

Datum window_nth_value ( PG_FUNCTION_ARGS  )

Definition at line 512 of file windowfuncs.c.

513 {
514  WindowObject winobj = PG_WINDOW_OBJECT();
515  bool const_offset;
516  Datum result;
517  bool isnull;
518  int32 nth;
519 
520  nth = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
521  if (isnull)
522  PG_RETURN_NULL();
523  const_offset = get_fn_expr_arg_stable(fcinfo->flinfo, 1);
524 
525  if (nth <= 0)
526  ereport(ERROR,
527  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_NTH_VALUE),
528  errmsg("argument of nth_value must be greater than zero")));
529 
530  result = WinGetFuncArgInFrame(winobj, 0,
531  nth - 1, WINDOW_SEEK_HEAD, const_offset,
532  &isnull, NULL);
533  if (isnull)
534  PG_RETURN_NULL();
535 
536  PG_RETURN_DATUM(result);
537 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143

References DatumGetInt32, ereport, errcode(), errmsg(), ERROR, get_fn_expr_arg_stable(), PG_RETURN_DATUM, PG_RETURN_NULL, PG_WINDOW_OBJECT, WINDOW_SEEK_HEAD, WinGetFuncArgCurrent(), and WinGetFuncArgInFrame().

◆ window_ntile()

Datum window_ntile ( PG_FUNCTION_ARGS  )

Definition at line 274 of file windowfuncs.c.

275 {
276  WindowObject winobj = PG_WINDOW_OBJECT();
277  ntile_context *context;
278 
279  context = (ntile_context *)
280  WinGetPartitionLocalMemory(winobj, sizeof(ntile_context));
281 
282  if (context->ntile == 0)
283  {
284  /* first call */
285  int64 total;
286  int32 nbuckets;
287  bool isnull;
288 
289  total = WinGetPartitionRowCount(winobj);
290  nbuckets = DatumGetInt32(WinGetFuncArgCurrent(winobj, 0, &isnull));
291 
292  /*
293  * per spec: If NT is the null value, then the result is the null
294  * value.
295  */
296  if (isnull)
297  PG_RETURN_NULL();
298 
299  /*
300  * per spec: If NT is less than or equal to 0 (zero), then an
301  * exception condition is raised.
302  */
303  if (nbuckets <= 0)
304  ereport(ERROR,
305  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_NTILE),
306  errmsg("argument of ntile must be greater than zero")));
307 
308  context->ntile = 1;
309  context->rows_per_bucket = 0;
310  context->boundary = total / nbuckets;
311  if (context->boundary <= 0)
312  context->boundary = 1;
313  else
314  {
315  /*
316  * If the total number is not divisible, add 1 row to leading
317  * buckets.
318  */
319  context->remainder = total % nbuckets;
320  if (context->remainder != 0)
321  context->boundary++;
322  }
323  }
324 
325  context->rows_per_bucket++;
326  if (context->boundary < context->rows_per_bucket)
327  {
328  /* ntile up */
329  if (context->remainder != 0 && context->ntile == context->remainder)
330  {
331  context->remainder = 0;
332  context->boundary -= 1;
333  }
334  context->ntile += 1;
335  context->rows_per_bucket = 1;
336  }
337 
338  PG_RETURN_INT32(context->ntile);
339 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
int64 rows_per_bucket
Definition: windowfuncs.c:34
int64 remainder
Definition: windowfuncs.c:36
int64 boundary
Definition: windowfuncs.c:35

References ntile_context::boundary, DatumGetInt32, ereport, errcode(), errmsg(), ERROR, ntile_context::ntile, PG_RETURN_INT32, PG_RETURN_NULL, PG_WINDOW_OBJECT, ntile_context::remainder, ntile_context::rows_per_bucket, WinGetFuncArgCurrent(), WinGetPartitionLocalMemory(), and WinGetPartitionRowCount().

◆ window_percent_rank()

Datum window_percent_rank ( PG_FUNCTION_ARGS  )

Definition at line 203 of file windowfuncs.c.

204 {
205  WindowObject winobj = PG_WINDOW_OBJECT();
206  rank_context *context;
207  bool up;
208  int64 totalrows = WinGetPartitionRowCount(winobj);
209 
210  Assert(totalrows > 0);
211 
212  up = rank_up(winobj);
213  context = (rank_context *)
214  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
215  if (up)
216  context->rank = WinGetCurrentPosition(winobj) + 1;
217 
218  /* return zero if there's only one row, per spec */
219  if (totalrows <= 1)
220  PG_RETURN_FLOAT8(0.0);
221 
222  PG_RETURN_FLOAT8((float8) (context->rank - 1) / (float8) (totalrows - 1));
223 }

References Assert(), PG_RETURN_FLOAT8, PG_WINDOW_OBJECT, rank_context::rank, rank_up(), WinGetCurrentPosition(), WinGetPartitionLocalMemory(), and WinGetPartitionRowCount().

◆ window_rank()

Datum window_rank ( PG_FUNCTION_ARGS  )

Definition at line 119 of file windowfuncs.c.

120 {
121  WindowObject winobj = PG_WINDOW_OBJECT();
122  rank_context *context;
123  bool up;
124 
125  up = rank_up(winobj);
126  context = (rank_context *)
127  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
128  if (up)
129  context->rank = WinGetCurrentPosition(winobj) + 1;
130 
131  PG_RETURN_INT64(context->rank);
132 }

References PG_RETURN_INT64, PG_WINDOW_OBJECT, rank_context::rank, rank_up(), WinGetCurrentPosition(), and WinGetPartitionLocalMemory().

◆ window_rank_support()

Datum window_rank_support ( PG_FUNCTION_ARGS  )

Definition at line 139 of file windowfuncs.c.

140 {
141  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
142 
143  if (IsA(rawreq, SupportRequestWFuncMonotonic))
144  {
146 
147  /* rank() is monotonically increasing */
149  PG_RETURN_POINTER(req);
150  }
151 
152  PG_RETURN_POINTER(NULL);
153 }

References IsA, SupportRequestWFuncMonotonic::monotonic, MONOTONICFUNC_INCREASING, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ window_row_number()

Datum window_row_number ( PG_FUNCTION_ARGS  )

Definition at line 83 of file windowfuncs.c.

84 {
85  WindowObject winobj = PG_WINDOW_OBJECT();
86  int64 curpos = WinGetCurrentPosition(winobj);
87 
88  WinSetMarkPosition(winobj, curpos);
89  PG_RETURN_INT64(curpos + 1);
90 }

References PG_RETURN_INT64, PG_WINDOW_OBJECT, WinGetCurrentPosition(), and WinSetMarkPosition().

◆ window_row_number_support()

Datum window_row_number_support ( PG_FUNCTION_ARGS  )

Definition at line 97 of file windowfuncs.c.

98 {
99  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
100 
101  if (IsA(rawreq, SupportRequestWFuncMonotonic))
102  {
104 
105  /* row_number() is monotonically increasing */
107  PG_RETURN_POINTER(req);
108  }
109 
110  PG_RETURN_POINTER(NULL);
111 }

References IsA, SupportRequestWFuncMonotonic::monotonic, MONOTONICFUNC_INCREASING, PG_GETARG_POINTER, and PG_RETURN_POINTER.