PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
windowfuncs.c File Reference
#include "postgres.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_rank (PG_FUNCTION_ARGS)
 
Datum window_dense_rank (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

Function Documentation

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

Definition at line 286 of file windowfuncs.c.

References DatumGetInt32, FunctionCallInfoData::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().

288 {
289  WindowObject winobj = PG_WINDOW_OBJECT();
290  int32 offset;
291  bool const_offset;
292  Datum result;
293  bool isnull;
294  bool isout;
295 
296  if (withoffset)
297  {
298  offset = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
299  if (isnull)
300  PG_RETURN_NULL();
301  const_offset = get_fn_expr_arg_stable(fcinfo->flinfo, 1);
302  }
303  else
304  {
305  offset = 1;
306  const_offset = true;
307  }
308 
309  result = WinGetFuncArgInPartition(winobj, 0,
310  (forward ? offset : -offset),
312  const_offset,
313  &isnull, &isout);
314 
315  if (isout)
316  {
317  /*
318  * target row is out of the partition; supply default value if
319  * provided. otherwise it'll stay NULL
320  */
321  if (withdefault)
322  result = WinGetFuncArgCurrent(winobj, 2, &isnull);
323  }
324 
325  if (isnull)
326  PG_RETURN_NULL();
327 
328  PG_RETURN_DATUM(result);
329 }
Datum WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)
bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2291
#define DatumGetInt32(X)
Definition: postgres.h:480
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
signed int int32
Definition: c.h:253
FmgrInfo * flinfo
Definition: fmgr.h:71
Datum WinGetFuncArgInPartition(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define WINDOW_SEEK_CURRENT
Definition: windowapi.h:32
#define PG_RETURN_NULL()
Definition: fmgr.h:289
static bool rank_up ( WindowObject  winobj)
static

Definition at line 47 of file windowfuncs.c.

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

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

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

Definition at line 169 of file windowfuncs.c.

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

170 {
171  WindowObject winobj = PG_WINDOW_OBJECT();
172  rank_context *context;
173  bool up;
174  int64 totalrows = WinGetPartitionRowCount(winobj);
175 
176  Assert(totalrows > 0);
177 
178  up = rank_up(winobj);
179  context = (rank_context *)
180  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
181  if (up || context->rank == 1)
182  {
183  /*
184  * The current row is not peer to prior row or is just the first, so
185  * count up the number of rows that are peer to the current.
186  */
187  int64 row;
188 
189  context->rank = WinGetCurrentPosition(winobj) + 1;
190 
191  /*
192  * start from current + 1
193  */
194  for (row = context->rank; row < totalrows; row++)
195  {
196  if (!WinRowsArePeers(winobj, row - 1, row))
197  break;
198  context->rank++;
199  }
200  }
201 
202  PG_RETURN_FLOAT8((float8) context->rank / (float8) totalrows);
203 }
bool WinRowsArePeers(WindowObject winobj, int64 pos1, int64 pos2)
void * WinGetPartitionLocalMemory(WindowObject winobj, Size sz)
int64 WinGetPartitionRowCount(WindowObject winobj)
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:310
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
double float8
Definition: c.h:378
static bool rank_up(WindowObject winobj)
Definition: windowfuncs.c:47
int64 WinGetCurrentPosition(WindowObject winobj)
#define Assert(condition)
Definition: c.h:671
Datum window_dense_rank ( PG_FUNCTION_ARGS  )

Definition at line 118 of file windowfuncs.c.

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

119 {
120  WindowObject winobj = PG_WINDOW_OBJECT();
121  rank_context *context;
122  bool up;
123 
124  up = rank_up(winobj);
125  context = (rank_context *)
126  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
127  if (up)
128  context->rank++;
129 
130  PG_RETURN_INT64(context->rank);
131 }
void * WinGetPartitionLocalMemory(WindowObject winobj, Size sz)
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
static bool rank_up(WindowObject winobj)
Definition: windowfuncs.c:47
Datum window_first_value ( PG_FUNCTION_ARGS  )

Definition at line 407 of file windowfuncs.c.

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

408 {
409  WindowObject winobj = PG_WINDOW_OBJECT();
410  Datum result;
411  bool isnull;
412 
413  result = WinGetFuncArgInFrame(winobj, 0,
414  0, WINDOW_SEEK_HEAD, true,
415  &isnull, NULL);
416  if (isnull)
417  PG_RETURN_NULL();
418 
419  PG_RETURN_DATUM(result);
420 }
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
#define WINDOW_SEEK_HEAD
Definition: windowapi.h:33
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define NULL
Definition: c.h:226
Datum WinGetFuncArgInFrame(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum window_lag ( PG_FUNCTION_ARGS  )

Definition at line 338 of file windowfuncs.c.

References leadlag_common().

339 {
340  return leadlag_common(fcinfo, false, false, false);
341 }
static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
Definition: windowfuncs.c:286
Datum window_lag_with_offset ( PG_FUNCTION_ARGS  )

Definition at line 350 of file windowfuncs.c.

References leadlag_common().

351 {
352  return leadlag_common(fcinfo, false, true, false);
353 }
static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
Definition: windowfuncs.c:286
Datum window_lag_with_offset_and_default ( PG_FUNCTION_ARGS  )

Definition at line 361 of file windowfuncs.c.

References leadlag_common().

362 {
363  return leadlag_common(fcinfo, false, true, true);
364 }
static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
Definition: windowfuncs.c:286
Datum window_last_value ( PG_FUNCTION_ARGS  )

Definition at line 428 of file windowfuncs.c.

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

429 {
430  WindowObject winobj = PG_WINDOW_OBJECT();
431  Datum result;
432  bool isnull;
433 
434  result = WinGetFuncArgInFrame(winobj, 0,
435  0, WINDOW_SEEK_TAIL, true,
436  &isnull, NULL);
437  if (isnull)
438  PG_RETURN_NULL();
439 
440  PG_RETURN_DATUM(result);
441 }
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
#define WINDOW_SEEK_TAIL
Definition: windowapi.h:34
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define NULL
Definition: c.h:226
Datum WinGetFuncArgInFrame(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum window_lead ( PG_FUNCTION_ARGS  )

Definition at line 373 of file windowfuncs.c.

References leadlag_common().

374 {
375  return leadlag_common(fcinfo, true, false, false);
376 }
static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
Definition: windowfuncs.c:286
Datum window_lead_with_offset ( PG_FUNCTION_ARGS  )

Definition at line 385 of file windowfuncs.c.

References leadlag_common().

386 {
387  return leadlag_common(fcinfo, true, true, false);
388 }
static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
Definition: windowfuncs.c:286
Datum window_lead_with_offset_and_default ( PG_FUNCTION_ARGS  )

Definition at line 396 of file windowfuncs.c.

References leadlag_common().

397 {
398  return leadlag_common(fcinfo, true, true, true);
399 }
static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault)
Definition: windowfuncs.c:286
Datum window_nth_value ( PG_FUNCTION_ARGS  )

Definition at line 449 of file windowfuncs.c.

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

450 {
451  WindowObject winobj = PG_WINDOW_OBJECT();
452  bool const_offset;
453  Datum result;
454  bool isnull;
455  int32 nth;
456 
457  nth = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
458  if (isnull)
459  PG_RETURN_NULL();
460  const_offset = get_fn_expr_arg_stable(fcinfo->flinfo, 1);
461 
462  if (nth <= 0)
463  ereport(ERROR,
464  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_NTH_VALUE),
465  errmsg("argument of nth_value must be greater than zero")));
466 
467  result = WinGetFuncArgInFrame(winobj, 0,
468  nth - 1, WINDOW_SEEK_HEAD, const_offset,
469  &isnull, NULL);
470  if (isnull)
471  PG_RETURN_NULL();
472 
473  PG_RETURN_DATUM(result);
474 }
Datum WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)
bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2291
#define DatumGetInt32(X)
Definition: postgres.h:480
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
signed int int32
Definition: c.h:253
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define WINDOW_SEEK_HEAD
Definition: windowapi.h:33
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define NULL
Definition: c.h:226
Datum WinGetFuncArgInFrame(WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum window_ntile ( PG_FUNCTION_ARGS  )

Definition at line 211 of file windowfuncs.c.

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().

212 {
213  WindowObject winobj = PG_WINDOW_OBJECT();
214  ntile_context *context;
215 
216  context = (ntile_context *)
217  WinGetPartitionLocalMemory(winobj, sizeof(ntile_context));
218 
219  if (context->ntile == 0)
220  {
221  /* first call */
222  int64 total;
223  int32 nbuckets;
224  bool isnull;
225 
226  total = WinGetPartitionRowCount(winobj);
227  nbuckets = DatumGetInt32(WinGetFuncArgCurrent(winobj, 0, &isnull));
228 
229  /*
230  * per spec: If NT is the null value, then the result is the null
231  * value.
232  */
233  if (isnull)
234  PG_RETURN_NULL();
235 
236  /*
237  * per spec: If NT is less than or equal to 0 (zero), then an
238  * exception condition is raised.
239  */
240  if (nbuckets <= 0)
241  ereport(ERROR,
242  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_NTILE),
243  errmsg("argument of ntile must be greater than zero")));
244 
245  context->ntile = 1;
246  context->rows_per_bucket = 0;
247  context->boundary = total / nbuckets;
248  if (context->boundary <= 0)
249  context->boundary = 1;
250  else
251  {
252  /*
253  * If the total number is not divisible, add 1 row to leading
254  * buckets.
255  */
256  context->remainder = total % nbuckets;
257  if (context->remainder != 0)
258  context->boundary++;
259  }
260  }
261 
262  context->rows_per_bucket++;
263  if (context->boundary < context->rows_per_bucket)
264  {
265  /* ntile up */
266  if (context->remainder != 0 && context->ntile == context->remainder)
267  {
268  context->remainder = 0;
269  context->boundary -= 1;
270  }
271  context->ntile += 1;
272  context->rows_per_bucket = 1;
273  }
274 
275  PG_RETURN_INT32(context->ntile);
276 }
Datum WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)
void * WinGetPartitionLocalMemory(WindowObject winobj, Size sz)
int64 WinGetPartitionRowCount(WindowObject winobj)
#define DatumGetInt32(X)
Definition: postgres.h:480
int64 remainder
Definition: windowfuncs.c:35
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
signed int int32
Definition: c.h:253
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int64 rows_per_bucket
Definition: windowfuncs.c:33
int errmsg(const char *fmt,...)
Definition: elog.c:797
int64 boundary
Definition: windowfuncs.c:34
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum window_percent_rank ( PG_FUNCTION_ARGS  )

Definition at line 140 of file windowfuncs.c.

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

141 {
142  WindowObject winobj = PG_WINDOW_OBJECT();
143  rank_context *context;
144  bool up;
145  int64 totalrows = WinGetPartitionRowCount(winobj);
146 
147  Assert(totalrows > 0);
148 
149  up = rank_up(winobj);
150  context = (rank_context *)
151  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
152  if (up)
153  context->rank = WinGetCurrentPosition(winobj) + 1;
154 
155  /* return zero if there's only one row, per spec */
156  if (totalrows <= 1)
157  PG_RETURN_FLOAT8(0.0);
158 
159  PG_RETURN_FLOAT8((float8) (context->rank - 1) / (float8) (totalrows - 1));
160 }
void * WinGetPartitionLocalMemory(WindowObject winobj, Size sz)
int64 WinGetPartitionRowCount(WindowObject winobj)
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:310
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
double float8
Definition: c.h:378
static bool rank_up(WindowObject winobj)
Definition: windowfuncs.c:47
int64 WinGetCurrentPosition(WindowObject winobj)
#define Assert(condition)
Definition: c.h:671
Datum window_rank ( PG_FUNCTION_ARGS  )

Definition at line 98 of file windowfuncs.c.

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

99 {
100  WindowObject winobj = PG_WINDOW_OBJECT();
101  rank_context *context;
102  bool up;
103 
104  up = rank_up(winobj);
105  context = (rank_context *)
106  WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
107  if (up)
108  context->rank = WinGetCurrentPosition(winobj) + 1;
109 
110  PG_RETURN_INT64(context->rank);
111 }
void * WinGetPartitionLocalMemory(WindowObject winobj, Size sz)
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
static bool rank_up(WindowObject winobj)
Definition: windowfuncs.c:47
int64 WinGetCurrentPosition(WindowObject winobj)
Datum window_row_number ( PG_FUNCTION_ARGS  )

Definition at line 82 of file windowfuncs.c.

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

83 {
84  WindowObject winobj = PG_WINDOW_OBJECT();
85  int64 curpos = WinGetCurrentPosition(winobj);
86 
87  WinSetMarkPosition(winobj, curpos);
88  PG_RETURN_INT64(curpos + 1);
89 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
#define PG_WINDOW_OBJECT()
Definition: windowapi.h:39
int64 WinGetCurrentPosition(WindowObject winobj)
void WinSetMarkPosition(WindowObject winobj, int64 markpos)