1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Add timestamp and timestamptz versions of generate_series().

Hitoshi Harada
This commit is contained in:
Tom Lane
2008-05-04 23:19:24 +00:00
parent 600da67fbe
commit b6d15590f7
5 changed files with 229 additions and 15 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.188 2008/05/04 21:13:35 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.189 2008/05/04 23:19:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -24,6 +24,7 @@
#include "access/hash.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "parser/scansup.h"
@ -45,6 +46,22 @@ TimestampTz PgStartTime;
/* Set at configuration reload */
TimestampTz PgReloadTime;
typedef struct
{
Timestamp current;
Timestamp finish;
Interval step;
int step_sign;
} generate_series_timestamp_fctx;
typedef struct
{
TimestampTz current;
TimestampTz finish;
Interval step;
int step_sign;
} generate_series_timestamptz_fctx;
static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec);
static int EncodeSpecialTimestamp(Timestamp dt, char *str);
@ -4651,3 +4668,165 @@ timestamptz_izone(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMP(result);
}
/* generate_series_timestamp()
* Generate the set of timestamps from start to finish by step
*/
Datum
generate_series_timestamp(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
generate_series_timestamp_fctx *fctx;
Timestamp result;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL())
{
Timestamp start = PG_GETARG_TIMESTAMP(0);
Timestamp finish = PG_GETARG_TIMESTAMP(1);
Interval *step = PG_GETARG_INTERVAL_P(2);
MemoryContext oldcontext;
Interval interval_zero;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
/*
* switch to memory context appropriate for multiple function calls
*/
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* allocate memory for user context */
fctx = (generate_series_timestamp_fctx *)
palloc(sizeof(generate_series_timestamp_fctx));
/*
* Use fctx to keep state from call to call. Seed current with the
* original start value
*/
fctx->current = start;
fctx->finish = finish;
fctx->step = *step;
/* Determine sign of the interval */
MemSet(&interval_zero, 0, sizeof(Interval));
fctx->step_sign = interval_cmp_internal(&fctx->step, &interval_zero);
if (fctx->step_sign == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("step size cannot equal zero")));
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
}
/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();
/*
* get the saved state and use current as the result for this iteration
*/
fctx = funcctx->user_fctx;
result = fctx->current;
if (fctx->step_sign > 0 ?
timestamp_cmp_internal(result, fctx->finish) <= 0 :
timestamp_cmp_internal(result, fctx->finish) >= 0)
{
/* increment current in preparation for next iteration */
fctx->current = DatumGetTimestamp(
DirectFunctionCall2(timestamp_pl_interval,
TimestampGetDatum(fctx->current),
PointerGetDatum(&fctx->step)));
/* do when there is more left to send */
SRF_RETURN_NEXT(funcctx, TimestampGetDatum(result));
}
else
{
/* do when there is no more left */
SRF_RETURN_DONE(funcctx);
}
}
/* generate_series_timestamptz()
* Generate the set of timestamps from start to finish by step
*/
Datum
generate_series_timestamptz(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
generate_series_timestamptz_fctx *fctx;
TimestampTz result;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL())
{
TimestampTz start = PG_GETARG_TIMESTAMPTZ(0);
TimestampTz finish = PG_GETARG_TIMESTAMPTZ(1);
Interval *step = PG_GETARG_INTERVAL_P(2);
MemoryContext oldcontext;
Interval interval_zero;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
/*
* switch to memory context appropriate for multiple function calls
*/
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* allocate memory for user context */
fctx = (generate_series_timestamptz_fctx *)
palloc(sizeof(generate_series_timestamptz_fctx));
/*
* Use fctx to keep state from call to call. Seed current with the
* original start value
*/
fctx->current = start;
fctx->finish = finish;
fctx->step = *step;
/* Determine sign of the interval */
MemSet(&interval_zero, 0, sizeof(Interval));
fctx->step_sign = interval_cmp_internal(&fctx->step, &interval_zero);
if (fctx->step_sign == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("step size cannot equal zero")));
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
}
/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();
/*
* get the saved state and use current as the result for this iteration
*/
fctx = funcctx->user_fctx;
result = fctx->current;
if (fctx->step_sign > 0 ?
timestamp_cmp_internal(result, fctx->finish) <= 0 :
timestamp_cmp_internal(result, fctx->finish) >= 0)
{
/* increment current in preparation for next iteration */
fctx->current = DatumGetTimestampTz(
DirectFunctionCall2(timestamptz_pl_interval,
TimestampTzGetDatum(fctx->current),
PointerGetDatum(&fctx->step)));
/* do when there is more left to send */
SRF_RETURN_NEXT(funcctx, TimestampTzGetDatum(result));
}
else
{
/* do when there is no more left */
SRF_RETURN_DONE(funcctx);
}
}

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.454 2008/05/04 21:13:35 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.455 2008/05/04 23:19:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200805041
#define CATALOG_VERSION_NO 200805042
#endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.495 2008/05/04 21:13:36 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.496 2008/05/04 23:19:23 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -3872,6 +3872,10 @@ DATA(insert OID = 1068 ( generate_series PGNSP PGUID 12 1 1000 f f t t i 3 20 "
DESCR("non-persistent series generator");
DATA(insert OID = 1069 ( generate_series PGNSP PGUID 12 1 1000 f f t t i 2 20 "20 20" _null_ _null_ _null_ generate_series_int8 - _null_ _null_ ));
DESCR("non-persistent series generator");
DATA(insert OID = 938 ( generate_series PGNSP PGUID 12 1 1000 f f t t i 3 1114 "1114 1114 1186" _null_ _null_ _null_ generate_series_timestamp - _null_ _null_ ));
DESCR("non-persistent series generator");
DATA(insert OID = 939 ( generate_series PGNSP PGUID 12 1 1000 f f t t s 3 1184 "1184 1184 1186" _null_ _null_ _null_ generate_series_timestamptz - _null_ _null_ ));
DESCR("non-persistent series generator");
/* boolean aggregates */
DATA(insert OID = 2515 ( booland_statefunc PGNSP PGUID 12 1 0 f f t f i 2 16 "16 16" _null_ _null_ _null_ booland_statefunc - _null_ _null_ ));

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.77 2008/05/04 21:13:36 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.78 2008/05/04 23:19:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -308,6 +308,9 @@ extern Datum clock_timestamp(PG_FUNCTION_ARGS);
extern Datum pg_postmaster_start_time(PG_FUNCTION_ARGS);
extern Datum pg_conf_load_time(PG_FUNCTION_ARGS);
extern Datum generate_series_timestamp(PG_FUNCTION_ARGS);
extern Datum generate_series_timestamptz(PG_FUNCTION_ARGS);
/* Internal routines (not fmgr-callable) */
extern TimestampTz GetCurrentTimestamp(void);