1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-12 05:01:15 +03:00

Add function (actually an int4 and an int8 version) that generates

a series of numbers, optionally using an explicit step size other
than the default value (one). Use function in the information_schema
to replace hard-wired knowledge of INDEX_MAX_KEYS. initdb forced due
to pg_proc change. Documentation update still needed -- will be
committed separately.
This commit is contained in:
Joe Conway
2004-02-03 08:29:57 +00:00
parent 9dac52649d
commit 12661642c8
7 changed files with 205 additions and 19 deletions

View File

@@ -4,7 +4,7 @@
*
* Copyright 2003, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.22 2004/01/24 23:45:13 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.23 2004/02/03 08:29:56 joe Exp $
*/
/*
@@ -399,17 +399,9 @@ GRANT SELECT ON columns TO PUBLIC;
CREATE FUNCTION _pg_keypositions() RETURNS SETOF integer
LANGUAGE sql
IMMUTABLE
AS 'select 1 union all select 2 union all select 3 union all
select 4 union all select 5 union all select 6 union all
select 7 union all select 8 union all select 9 union all
select 10 union all select 11 union all select 12 union all
select 13 union all select 14 union all select 15 union all
select 16 union all select 17 union all select 18 union all
select 19 union all select 20 union all select 21 union all
select 22 union all select 23 union all select 24 union all
select 25 union all select 26 union all select 27 union all
select 28 union all select 29 union all select 30 union all
select 31 union all select 32';
AS 'select g.s
from generate_series(1,current_setting(''max_index_keys'')::int,1)
as g(s)';
CREATE VIEW constraint_column_usage AS
SELECT CAST(current_database() AS sql_identifier) AS table_catalog,

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.59 2003/12/01 21:52:37 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.60 2004/02/03 08:29:56 joe Exp $
*
*-------------------------------------------------------------------------
*/
@@ -34,6 +34,7 @@
#include <ctype.h>
#include <limits.h>
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
@@ -44,6 +45,13 @@
#define SHRT_MIN (-0x8000)
#endif
typedef struct
{
int32 current;
int32 finish;
int32 step;
} generate_series_fctx;
/*****************************************************************************
* USER I/O ROUTINES *
*****************************************************************************/
@@ -1021,3 +1029,84 @@ int2shr(PG_FUNCTION_ARGS)
PG_RETURN_INT16(arg1 >> arg2);
}
/*
* non-persistent numeric series generator
*/
Datum
generate_series_int4(PG_FUNCTION_ARGS)
{
return generate_series_step_int4(fcinfo);
}
Datum
generate_series_step_int4(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
generate_series_fctx *fctx;
int32 result;
MemoryContext oldcontext;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL())
{
int32 start = PG_GETARG_INT32(0);
int32 finish = PG_GETARG_INT32(1);
int32 step = 1;
/* see if we were given an explicit step size */
if (PG_NARGS() == 3)
step = PG_GETARG_INT32(2);
if (step == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("step size may not equal 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_fctx *) palloc(sizeof(generate_series_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;
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 > 0 && fctx->current <= fctx->finish) ||
(fctx->step < 0 && fctx->current >= fctx->finish))
{
/* increment current in preparation for next iteration */
fctx->current += fctx->step;
/* do when there is more left to send */
SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
}
else
/* do when there is no more left */
SRF_RETURN_DONE(funcctx);
}

View File

@@ -7,21 +7,29 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.50 2003/12/01 21:52:37 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.51 2004/02/03 08:29:56 joe Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/int8.h"
#define MAXINT8LEN 25
typedef struct
{
int64 current;
int64 finish;
int64 step;
} generate_series_fctx;
/***********************************************************************
**
@@ -936,3 +944,84 @@ int8_text(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(result);
}
/*
* non-persistent numeric series generator
*/
Datum
generate_series_int8(PG_FUNCTION_ARGS)
{
return generate_series_step_int8(fcinfo);
}
Datum
generate_series_step_int8(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
generate_series_fctx *fctx;
int64 result;
MemoryContext oldcontext;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL())
{
int64 start = PG_GETARG_INT64(0);
int64 finish = PG_GETARG_INT64(1);
int64 step = 1;
/* see if we were given an explicit step size */
if (PG_NARGS() == 3)
step = PG_GETARG_INT64(2);
if (step == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("step size may not equal 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_fctx *) palloc(sizeof(generate_series_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;
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 > 0 && fctx->current <= fctx->finish) ||
(fctx->step < 0 && fctx->current >= fctx->finish))
{
/* increment current in preparation for next iteration */
fctx->current += fctx->step;
/* do when there is more left to send */
SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
}
else
/* do when there is no more left */
SRF_RETURN_DONE(funcctx);
}