Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Typedefs | Functions

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

typedef struct rank_context rank_context

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    int32       offset;
    bool        const_offset;
    Datum       result;
    bool        isnull;
    bool        isout;

    if (withoffset)
    {
        offset = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
        if (isnull)
            PG_RETURN_NULL();
        const_offset = get_fn_expr_arg_stable(fcinfo->flinfo, 1);
    }
    else
    {
        offset = 1;
        const_offset = true;
    }

    result = WinGetFuncArgInPartition(winobj, 0,
                                      (forward ? offset : -offset),
                                      WINDOW_SEEK_CURRENT,
                                      const_offset,
                                      &isnull, &isout);

    if (isout)
    {
        /*
         * target row is out of the partition; supply default value if
         * provided.  otherwise it'll stay NULL
         */
        if (withdefault)
            result = WinGetFuncArgCurrent(winobj, 2, &isnull);
    }

    if (isnull)
        PG_RETURN_NULL();

    PG_RETURN_DATUM(result);
}

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

{
    bool        up = false;     /* should rank increase? */
    int64       curpos = WinGetCurrentPosition(winobj);
    rank_context *context;

    context = (rank_context *)
        WinGetPartitionLocalMemory(winobj, sizeof(rank_context));

    if (context->rank == 0)
    {
        /* first call: rank of first row is always 1 */
        Assert(curpos == 0);
        context->rank = 1;
    }
    else
    {
        Assert(curpos > 0);
        /* do current and prior tuples match by ORDER BY clause? */
        if (!WinRowsArePeers(winobj, curpos - 1, curpos))
            up = true;
    }

    /* We can advance the mark, but only *after* acccess to prior row */
    WinSetMarkPosition(winobj, curpos);

    return up;
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    rank_context *context;
    bool        up;
    int64       totalrows = WinGetPartitionRowCount(winobj);

    Assert(totalrows > 0);

    up = rank_up(winobj);
    context = (rank_context *)
        WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
    if (up || context->rank == 1)
    {
        /*
         * The current row is not peer to prior row or is just the first, so
         * count up the number of rows that are peer to the current.
         */
        int64       row;

        context->rank = WinGetCurrentPosition(winobj) + 1;

        /*
         * start from current + 1
         */
        for (row = context->rank; row < totalrows; row++)
        {
            if (!WinRowsArePeers(winobj, row - 1, row))
                break;
            context->rank++;
        }
    }

    PG_RETURN_FLOAT8((float8) context->rank / (float8) totalrows);
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    rank_context *context;
    bool        up;

    up = rank_up(winobj);
    context = (rank_context *)
        WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
    if (up)
        context->rank++;

    PG_RETURN_INT64(context->rank);
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    Datum       result;
    bool        isnull;

    result = WinGetFuncArgInFrame(winobj, 0,
                                  0, WINDOW_SEEK_HEAD, true,
                                  &isnull, NULL);
    if (isnull)
        PG_RETURN_NULL();

    PG_RETURN_DATUM(result);
}

Datum window_lag ( PG_FUNCTION_ARGS   ) 

Definition at line 338 of file windowfuncs.c.

References leadlag_common().

{
    return leadlag_common(fcinfo, false, false, false);
}

Datum window_lag_with_offset ( PG_FUNCTION_ARGS   ) 

Definition at line 350 of file windowfuncs.c.

References leadlag_common().

{
    return leadlag_common(fcinfo, false, true, false);
}

Datum window_lag_with_offset_and_default ( PG_FUNCTION_ARGS   ) 

Definition at line 361 of file windowfuncs.c.

References leadlag_common().

{
    return leadlag_common(fcinfo, false, true, true);
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    Datum       result;
    bool        isnull;

    result = WinGetFuncArgInFrame(winobj, 0,
                                  0, WINDOW_SEEK_TAIL, true,
                                  &isnull, NULL);
    if (isnull)
        PG_RETURN_NULL();

    PG_RETURN_DATUM(result);
}

Datum window_lead ( PG_FUNCTION_ARGS   ) 

Definition at line 373 of file windowfuncs.c.

References leadlag_common().

{
    return leadlag_common(fcinfo, true, false, false);
}

Datum window_lead_with_offset ( PG_FUNCTION_ARGS   ) 

Definition at line 385 of file windowfuncs.c.

References leadlag_common().

{
    return leadlag_common(fcinfo, true, true, false);
}

Datum window_lead_with_offset_and_default ( PG_FUNCTION_ARGS   ) 

Definition at line 396 of file windowfuncs.c.

References leadlag_common().

{
    return leadlag_common(fcinfo, true, true, true);
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    bool        const_offset;
    Datum       result;
    bool        isnull;
    int32       nth;

    nth = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
    if (isnull)
        PG_RETURN_NULL();
    const_offset = get_fn_expr_arg_stable(fcinfo->flinfo, 1);

    if (nth <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_ARGUMENT_FOR_NTH_VALUE),
                 errmsg("argument of nth_value must be greater than zero")));

    result = WinGetFuncArgInFrame(winobj, 0,
                                  nth - 1, WINDOW_SEEK_HEAD, const_offset,
                                  &isnull, NULL);
    if (isnull)
        PG_RETURN_NULL();

    PG_RETURN_DATUM(result);
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    ntile_context *context;

    context = (ntile_context *)
        WinGetPartitionLocalMemory(winobj, sizeof(ntile_context));

    if (context->ntile == 0)
    {
        /* first call */
        int64       total;
        int32       nbuckets;
        bool        isnull;

        total = WinGetPartitionRowCount(winobj);
        nbuckets = DatumGetInt32(WinGetFuncArgCurrent(winobj, 0, &isnull));

        /*
         * per spec: If NT is the null value, then the result is the null
         * value.
         */
        if (isnull)
            PG_RETURN_NULL();

        /*
         * per spec: If NT is less than or equal to 0 (zero), then an
         * exception condition is raised.
         */
        if (nbuckets <= 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_ARGUMENT_FOR_NTILE),
                     errmsg("argument of ntile must be greater than zero")));

        context->ntile = 1;
        context->rows_per_bucket = 0;
        context->boundary = total / nbuckets;
        if (context->boundary <= 0)
            context->boundary = 1;
        else
        {
            /*
             * If the total number is not divisible, add 1 row to leading
             * buckets.
             */
            context->remainder = total % nbuckets;
            if (context->remainder != 0)
                context->boundary++;
        }
    }

    context->rows_per_bucket++;
    if (context->boundary < context->rows_per_bucket)
    {
        /* ntile up */
        if (context->remainder != 0 && context->ntile == context->remainder)
        {
            context->remainder = 0;
            context->boundary -= 1;
        }
        context->ntile += 1;
        context->rows_per_bucket = 1;
    }

    PG_RETURN_INT32(context->ntile);
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    rank_context *context;
    bool        up;
    int64       totalrows = WinGetPartitionRowCount(winobj);

    Assert(totalrows > 0);

    up = rank_up(winobj);
    context = (rank_context *)
        WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
    if (up)
        context->rank = WinGetCurrentPosition(winobj) + 1;

    /* return zero if there's only one row, per spec */
    if (totalrows <= 1)
        PG_RETURN_FLOAT8(0.0);

    PG_RETURN_FLOAT8((float8) (context->rank - 1) / (float8) (totalrows - 1));
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    rank_context *context;
    bool        up;

    up = rank_up(winobj);
    context = (rank_context *)
        WinGetPartitionLocalMemory(winobj, sizeof(rank_context));
    if (up)
        context->rank = WinGetCurrentPosition(winobj) + 1;

    PG_RETURN_INT64(context->rank);
}

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

{
    WindowObject winobj = PG_WINDOW_OBJECT();
    int64       curpos = WinGetCurrentPosition(winobj);

    WinSetMarkPosition(winobj, curpos);
    PG_RETURN_INT64(curpos + 1);
}