Hi, I am newbie in postgresql development, so i took easy item in Todo list " Add generate_series(numeric, numeric)". First, i changed function with analogue funcionality (generate_series_timestamp) and added new object in pg_proc (object id is 6000). My changes successfully was compiled.
I have found some problems when code was tested. (remark step=1.0) 1) STATEMENT: SELECT generate_series(1.0,6.1); 1: generate_series (typeid = 1700, len = -1, typmod = -1, byval = f) ---- 1: generate_series = "1.0" (typeid = 1700, len = -1, typmod = -1, byval = f) ---- 1: generate_series = "2.0" (typeid = 1700, len = -1, typmod = -1, byval = f) ---- 1: generate_series = "3.0" (typeid = 1700, len = -1, typmod = -1, byval = f) ---- 1: generate_series = "4.0" (typeid = 1700, len = -1, typmod = -1, byval = f) ---- 1: generate_series = "5.0" (typeid = 1700, len = -1, typmod = -1, byval = f) ---- 1: generate_series = "6.0" (typeid = 1700, len = -1, typmod = -1, byval = f) ---- Function work. 2) STATEMENT: SELECT * FROM generate_series(1.0, 6.1) 1: generate_series (typeid = 1700, len = -1, typmod = -1, byval = f) ---- make_result(): NUMERIC w=0 d=0 POS 0001 CURRENT:: NUMERIC w=0 d=1 POS 0001 FINISH:: NUMERIC w=0 d=1 POS 0006 1000 STEP:: NUMERIC w=0 d=0 POS 0001 make_result(): NUMERIC w=0 d=1 POS 0002 CURRENT:: NUMERIC w=32639 d=16255 NEG 0000 .... (more 0000) And postgres was crashed. Could you help to find mistakes? Some questions: 1) Is correct using Numeric in generate_series_numeric_fctx instead of NumericVar? 2) How do you determine object id for new function? Maybe you're looking for last object id in catalog directory (src/include/catalog/pg_*.h) and increase by one last object id. P.S. Sorry, I have made mistakes in message, because english isn't native language.
From 916bfe117e464fe9185f294cbf4c9979758e7651 Mon Sep 17 00:00:00 2001 From: Malyugin Platon <malugi...@gmail.com> Date: Mon, 29 Sep 2014 09:40:56 +0700 Subject: [PATCH] Add function generate_series(numeric, numeric) --- src/backend/utils/adt/numeric.c | 73 ++++++++++++++++++++++++++++++++++++++--- src/include/catalog/pg_proc.h | 2 ++ src/include/utils/builtins.h | 1 + 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 19d0bdc..73cd169 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -14,7 +14,7 @@ * Copyright (c) 1998-2014, PostgreSQL Global Development Group * * IDENTIFICATION - * src/backend/utils/adt/numeric.c + * src/backend/utils/adt/numeric.cn * *------------------------------------------------------------------------- */ @@ -35,13 +35,13 @@ #include "utils/builtins.h" #include "utils/int8.h" #include "utils/numeric.h" - +#include "funcapi.h" /* ---------- * Uncomment the following to enable compilation of dump_numeric() * and dump_var() and to get a dump of any result produced by make_result(). - * ---------- + * ---------- */ #define NUMERIC_DEBUG - */ + /* ---------- @@ -260,6 +260,14 @@ typedef struct NumericVar } NumericVar; +typedef struct +{ + Numeric current; + Numeric finish; + Numeric step; + int step_sign; +} generate_series_numeric_fctx; + /* ---------- * Some preinitialized constants * ---------- @@ -1221,6 +1229,63 @@ numeric_floor(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(res); } +Datum +generate_series_numeric(PG_FUNCTION_ARGS) +{ + generate_series_numeric_fctx *fctx; + FuncCallContext *funcctx; + Numeric res; + + if (SRF_IS_FIRSTCALL()) + { + Numeric start = PG_GETARG_NUMERIC(0); + Numeric finish = PG_GETARG_NUMERIC(1); + MemoryContext oldcontext; + + funcctx = SRF_FIRSTCALL_INIT(); + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + fctx = (generate_series_numeric_fctx *)palloc(sizeof(generate_series_numeric_fctx)); + + fctx->current = start; + fctx->finish = finish; + fctx->step = make_result(&const_one); + fctx->step_sign = 1; + + funcctx->user_fctx = fctx; + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + + fctx = funcctx->user_fctx; + dump_numeric("CURRENT:", fctx->current); + dump_numeric("FINISH:", fctx->finish); + dump_numeric("STEP:", fctx->step); + + res = fctx->current; + + if (fctx->step_sign > 0 ? + cmp_numerics(fctx->current, fctx->finish) <= 0 : + cmp_numerics(fctx->current, fctx->finish) >= 0) + { + NumericVar current; + NumericVar step; + NumericVar new; + + init_var_from_num(fctx->current, ¤t); + init_var_from_num(fctx->step, &step); + add_var(¤t, &step, &new); + + fctx->current = make_result(&new); + + SRF_RETURN_NEXT(funcctx, NumericGetDatum(res)); + } + else + { + SRF_RETURN_DONE(funcctx); + } +} + /* * Implements the numeric version of the width_bucket() function * defined by SQL2003. See also width_bucket_float8(). diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 0af1248..7530b64 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3909,6 +3909,8 @@ DATA(insert OID = 1068 ( generate_series PGNSP PGUID 12 1 1000 0 0 f f f f t t DESCR("non-persistent series generator"); DATA(insert OID = 1069 ( generate_series PGNSP PGUID 12 1 1000 0 0 f f f f t t i 2 0 20 "20 20" _null_ _null_ _null_ _null_ generate_series_int8 _null_ _null_ _null_ )); DESCR("non-persistent series generator"); +DATA(insert OID = 6000 ( generate_series PGNSP PGUID 12 1 1000 0 0 f f f f t t i 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ generate_series_numeric _null_ _null_ _null_ )); +DESCR("non-persistent series generator"); DATA(insert OID = 938 ( generate_series PGNSP PGUID 12 1 1000 0 0 f f f f t t i 3 0 1114 "1114 1114 1186" _null_ _null_ _null_ _null_ generate_series_timestamp _null_ _null_ _null_ )); DESCR("non-persistent series generator"); DATA(insert OID = 939 ( generate_series PGNSP PGUID 12 1 1000 0 0 f f f f t t s 3 0 1184 "1184 1184 1186" _null_ _null_ _null_ _null_ generate_series_timestamptz _null_ _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index bbb5d39..341606e 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -1036,6 +1036,7 @@ extern Datum int8_avg(PG_FUNCTION_ARGS); extern Datum int2int4_sum(PG_FUNCTION_ARGS); extern Datum width_bucket_numeric(PG_FUNCTION_ARGS); extern Datum hash_numeric(PG_FUNCTION_ARGS); +extern Datum generate_series_numeric(PG_FUNCTION_ARGS); /* ri_triggers.c */ extern Datum RI_FKey_check_ins(PG_FUNCTION_ARGS); -- 1.9.1
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers