@ -22,8 +22,10 @@
# include "access/xloginsert.h"
# include "access/xlogutils.h"
# include "catalog/dependency.h"
# include "catalog/indexing.h"
# include "catalog/namespace.h"
# include "catalog/objectaccess.h"
# include "catalog/pg_sequence.h"
# include "catalog/pg_type.h"
# include "commands/defrem.h"
# include "commands/sequence.h"
@ -74,7 +76,7 @@ typedef struct SeqTableData
int64 cached ; /* last value already cached for nextval */
/* if last != cached, we have not used up all the cached values */
int64 increment ; /* copy of sequence's increment field */
/* note that increment is zero until we first do read_seq_tuple () */
/* note that increment is zero until we first do nextval_internal () */
} SeqTableData ;
typedef SeqTableData * SeqTable ;
@ -92,10 +94,11 @@ static int64 nextval_internal(Oid relid);
static Relation open_share_lock ( SeqTable seq ) ;
static void create_seq_hashtable ( void ) ;
static void init_sequence ( Oid relid , SeqTable * p_elm , Relation * p_rel ) ;
static Form_pg_sequence read_seq_tuple ( SeqTable elm , Relation rel ,
Buffer * buf , HeapTuple seqtuple ) ;
static Form_pg_sequence_data read_seq_tuple ( Relation rel ,
Buffer * buf , HeapTuple seqdata tuple ) ;
static void init_params ( ParseState * pstate , List * options , bool isInit ,
Form_pg_sequence new , List * * owned_by ) ;
Form_pg_sequence seqform ,
Form_pg_sequence_data seqdataform , List * * owned_by ) ;
static void do_setval ( Oid relid , int64 next , bool iscalled ) ;
static void process_owned_by ( Relation seqrel , List * owned_by ) ;
@ -107,7 +110,8 @@ static void process_owned_by(Relation seqrel, List *owned_by);
ObjectAddress
DefineSequence ( ParseState * pstate , CreateSeqStmt * seq )
{
FormData_pg_sequence new ;
FormData_pg_sequence seqform ;
FormData_pg_sequence_data seqdataform ;
List * owned_by ;
CreateStmt * stmt = makeNode ( CreateStmt ) ;
Oid seqoid ;
@ -117,8 +121,9 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
TupleDesc tupDesc ;
Datum value [ SEQ_COL_LASTCOL ] ;
bool null [ SEQ_COL_LASTCOL ] ;
Datum pgs_values [ Natts_pg_sequence ] ;
bool pgs_nulls [ Natts_pg_sequence ] ;
int i ;
NameData name ;
/* Unlogged sequences are not implemented -- not clear if useful. */
if ( seq - > sequence - > relpersistence = = RELPERSISTENCE_UNLOGGED )
@ -145,7 +150,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
}
/* Check and set all option values */
init_params ( pstate , seq - > options , true , & new , & owned_by ) ;
init_params ( pstate , seq - > options , true , & seqform , & seqdataform , & owned_by ) ;
/*
* Create relation ( and fill value [ ] and null [ ] for the tuple )
@ -171,52 +176,16 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
switch ( i )
{
case SEQ_COL_NAME :
coldef - > typeName = makeTypeNameFromOid ( NAMEOID , - 1 ) ;
coldef - > colname = " sequence_name " ;
namestrcpy ( & name , seq - > sequence - > relname ) ;
value [ i - 1 ] = NameGetDatum ( & name ) ;
break ;
case SEQ_COL_LASTVAL :
coldef - > typeName = makeTypeNameFromOid ( INT8OID , - 1 ) ;
coldef - > colname = " last_value " ;
value [ i - 1 ] = Int64GetDatumFast ( new . last_value ) ;
break ;
case SEQ_COL_STARTVAL :
coldef - > typeName = makeTypeNameFromOid ( INT8OID , - 1 ) ;
coldef - > colname = " start_value " ;
value [ i - 1 ] = Int64GetDatumFast ( new . start_value ) ;
break ;
case SEQ_COL_INCBY :
coldef - > typeName = makeTypeNameFromOid ( INT8OID , - 1 ) ;
coldef - > colname = " increment_by " ;
value [ i - 1 ] = Int64GetDatumFast ( new . increment_by ) ;
break ;
case SEQ_COL_MAXVALUE :
coldef - > typeName = makeTypeNameFromOid ( INT8OID , - 1 ) ;
coldef - > colname = " max_value " ;
value [ i - 1 ] = Int64GetDatumFast ( new . max_value ) ;
break ;
case SEQ_COL_MINVALUE :
coldef - > typeName = makeTypeNameFromOid ( INT8OID , - 1 ) ;
coldef - > colname = " min_value " ;
value [ i - 1 ] = Int64GetDatumFast ( new . min_value ) ;
break ;
case SEQ_COL_CACHE :
coldef - > typeName = makeTypeNameFromOid ( INT8OID , - 1 ) ;
coldef - > colname = " cache_value " ;
value [ i - 1 ] = Int64GetDatumFast ( new . cache_value ) ;
value [ i - 1 ] = Int64GetDatumFast ( seqdataform . last_value ) ;
break ;
case SEQ_COL_LOG :
coldef - > typeName = makeTypeNameFromOid ( INT8OID , - 1 ) ;
coldef - > colname = " log_cnt " ;
value [ i - 1 ] = Int64GetDatum ( ( int64 ) 0 ) ;
break ;
case SEQ_COL_CYCLE :
coldef - > typeName = makeTypeNameFromOid ( BOOLOID , - 1 ) ;
coldef - > colname = " is_cycled " ;
value [ i - 1 ] = BoolGetDatum ( new . is_cycled ) ;
break ;
case SEQ_COL_CALLED :
coldef - > typeName = makeTypeNameFromOid ( BOOLOID , - 1 ) ;
coldef - > colname = " is_called " ;
@ -251,6 +220,27 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
heap_close ( rel , NoLock ) ;
/* fill in pg_sequence */
rel = heap_open ( SequenceRelationId , RowExclusiveLock ) ;
tupDesc = RelationGetDescr ( rel ) ;
memset ( pgs_nulls , 0 , sizeof ( pgs_nulls ) ) ;
pgs_values [ Anum_pg_sequence_seqrelid - 1 ] = ObjectIdGetDatum ( seqoid ) ;
pgs_values [ Anum_pg_sequence_seqstart - 1 ] = Int64GetDatumFast ( seqform . seqstart ) ;
pgs_values [ Anum_pg_sequence_seqincrement - 1 ] = Int64GetDatumFast ( seqform . seqincrement ) ;
pgs_values [ Anum_pg_sequence_seqmax - 1 ] = Int64GetDatumFast ( seqform . seqmax ) ;
pgs_values [ Anum_pg_sequence_seqmin - 1 ] = Int64GetDatumFast ( seqform . seqmin ) ;
pgs_values [ Anum_pg_sequence_seqcache - 1 ] = Int64GetDatumFast ( seqform . seqcache ) ;
pgs_values [ Anum_pg_sequence_seqcycle - 1 ] = BoolGetDatum ( seqform . seqcycle ) ;
tuple = heap_form_tuple ( tupDesc , pgs_values , pgs_nulls ) ;
simple_heap_insert ( rel , tuple ) ;
CatalogUpdateIndexes ( rel , tuple ) ;
heap_freetuple ( tuple ) ;
heap_close ( rel , RowExclusiveLock ) ;
return address ;
}
@ -271,10 +261,13 @@ ResetSequence(Oid seq_relid)
{
Relation seq_rel ;
SeqTable elm ;
Form_pg_sequence seq ;
Form_pg_sequence_data seq ;
Buffer buf ;
HeapTupleData seqtuple ;
HeapTupleData seqdata tuple ;
HeapTuple tuple ;
HeapTuple pgstuple ;
Form_pg_sequence pgsform ;
int64 startv ;
/*
* Read the old sequence . This does a bit more work than really
@ -282,12 +275,19 @@ ResetSequence(Oid seq_relid)
* indeed a sequence .
*/
init_sequence ( seq_relid , & elm , & seq_rel ) ;
( void ) read_seq_tuple ( elm , seq_rel , & buf , & seqtuple ) ;
( void ) read_seq_tuple ( seq_rel , & buf , & seqdatatuple ) ;
pgstuple = SearchSysCache1 ( SEQRELID , ObjectIdGetDatum ( seq_relid ) ) ;
if ( ! HeapTupleIsValid ( pgstuple ) )
elog ( ERROR , " cache lookup failed for sequence %u " , seq_relid ) ;
pgsform = ( Form_pg_sequence ) GETSTRUCT ( pgstuple ) ;
startv = pgsform - > seqstart ;
ReleaseSysCache ( pgstuple ) ;
/*
* Copy the existing sequence tuple .
*/
tuple = heap_copytuple ( & seqtuple ) ;
tuple = heap_copytuple ( & seqdata tuple ) ;
/* Now we're done with the old page */
UnlockReleaseBuffer ( buf ) ;
@ -296,8 +296,8 @@ ResetSequence(Oid seq_relid)
* Modify the copied tuple to execute the restart ( compare the RESTART
* action in AlterSequence )
*/
seq = ( Form_pg_sequence ) GETSTRUCT ( tuple ) ;
seq - > last_value = seq - > s tart_ value ;
seq = ( Form_pg_sequence_data ) GETSTRUCT ( tuple ) ;
seq - > last_value = startv ;
seq - > is_called = false ;
seq - > log_cnt = 0 ;
@ -410,11 +410,14 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
SeqTable elm ;
Relation seqrel ;
Buffer buf ;
HeapTupleData seqtuple ;
Form_pg_sequence seq ;
FormData_pg_sequence new ;
HeapTupleData seqdatatuple ;
Form_pg_sequence seqform ;
Form_pg_sequence_data seqdata ;
FormData_pg_sequence_data newseqdata ;
List * owned_by ;
ObjectAddress address ;
Relation rel ;
HeapTuple tuple ;
/* Open and lock sequence. */
relid = RangeVarGetRelid ( stmt - > sequence , AccessShareLock , stmt - > missing_ok ) ;
@ -434,13 +437,22 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
stmt - > sequence - > relname ) ;
/* lock page' buffer and read tuple into new sequence structure */
seq = read_seq_tuple ( elm , seqrel , & buf , & seqtuple ) ;
seqdata = read_seq_tuple ( seqrel , & buf , & seqdata tuple ) ;
/* Copy old values of options into workspace */
memcpy ( & new , seq , sizeof ( FormData_pg_sequence ) ) ;
memcpy ( & newseqdata , seqdata , sizeof ( FormData_pg_sequence_data ) ) ;
rel = heap_open ( SequenceRelationId , RowExclusiveLock ) ;
tuple = SearchSysCacheCopy1 ( SEQRELID ,
ObjectIdGetDatum ( relid ) ) ;
if ( ! HeapTupleIsValid ( tuple ) )
elog ( ERROR , " cache lookup failed for sequence %u " ,
relid ) ;
seqform = ( Form_pg_sequence ) GETSTRUCT ( tuple ) ;
/* Check and set new values */
init_params ( pstate , stmt - > options , false , & new , & owned_by ) ;
init_params ( pstate , stmt - > options , false , seqform , & newseqdata , & owned_by ) ;
/* Clear local cache so that we don't think we have cached numbers */
/* Note that we do not change the currval() state */
@ -453,7 +465,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
/* Now okay to update the on-disk tuple */
START_CRIT_SECTION ( ) ;
memcpy ( seq , & new , sizeof ( FormData_pg_sequence ) ) ;
memcpy ( seqdata , & newseqdata , sizeof ( FormData_pg_sequence_data ) ) ;
MarkBufferDirty ( buf ) ;
@ -470,7 +482,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
xlrec . node = seqrel - > rd_node ;
XLogRegisterData ( ( char * ) & xlrec , sizeof ( xl_seq_rec ) ) ;
XLogRegisterData ( ( char * ) seqtuple . t_data , seqtuple . t_len ) ;
XLogRegisterData ( ( char * ) seqdata tuple . t_data , seqdata tuple . t_len ) ;
recptr = XLogInsert ( RM_SEQ_ID , XLOG_SEQ_LOG ) ;
@ -491,9 +503,30 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
relation_close ( seqrel , NoLock ) ;
simple_heap_update ( rel , & tuple - > t_self , tuple ) ;
CatalogUpdateIndexes ( rel , tuple ) ;
heap_close ( rel , RowExclusiveLock ) ;
return address ;
}
void
DeleteSequenceTuple ( Oid relid )
{
Relation rel ;
HeapTuple tuple ;
rel = heap_open ( SequenceRelationId , RowExclusiveLock ) ;
tuple = SearchSysCache1 ( SEQRELID , ObjectIdGetDatum ( relid ) ) ;
if ( ! HeapTupleIsValid ( tuple ) )
elog ( ERROR , " cache lookup failed for sequence %u " , relid ) ;
simple_heap_delete ( rel , & tuple - > t_self ) ;
ReleaseSysCache ( tuple ) ;
heap_close ( rel , RowExclusiveLock ) ;
}
/*
* Note : nextval with a text argument is no longer exported as a pg_proc
@ -537,8 +570,10 @@ nextval_internal(Oid relid)
Relation seqrel ;
Buffer buf ;
Page page ;
HeapTupleData seqtuple ;
Form_pg_sequence seq ;
HeapTuple pgstuple ;
Form_pg_sequence pgsform ;
HeapTupleData seqdatatuple ;
Form_pg_sequence_data seq ;
int64 incby ,
maxv ,
minv ,
@ -549,6 +584,7 @@ nextval_internal(Oid relid)
int64 result ,
next ,
rescnt = 0 ;
bool cycle ;
bool logit = false ;
/* open and AccessShareLock sequence */
@ -582,15 +618,24 @@ nextval_internal(Oid relid)
return elm - > last ;
}
pgstuple = SearchSysCache1 ( SEQRELID , ObjectIdGetDatum ( relid ) ) ;
if ( ! HeapTupleIsValid ( pgstuple ) )
elog ( ERROR , " cache lookup failed for sequence %u " , relid ) ;
pgsform = ( Form_pg_sequence ) GETSTRUCT ( pgstuple ) ;
incby = pgsform - > seqincrement ;
maxv = pgsform - > seqmax ;
minv = pgsform - > seqmin ;
cache = pgsform - > seqcache ;
cycle = pgsform - > seqcycle ;
ReleaseSysCache ( pgstuple ) ;
/* lock page' buffer and read tuple */
seq = read_seq_tuple ( elm , seqrel , & buf , & seqtuple ) ;
seq = read_seq_tuple ( seqrel , & buf , & seqdata tuple ) ;
page = BufferGetPage ( buf ) ;
elm - > increment = incby ;
last = next = result = seq - > last_value ;
incby = seq - > increment_by ;
maxv = seq - > max_value ;
minv = seq - > min_value ;
fetch = cache = seq - > cache_value ;
fetch = cache ;
log = seq - > log_cnt ;
if ( ! seq - > is_called )
@ -641,7 +686,7 @@ nextval_internal(Oid relid)
{
if ( rescnt > 0 )
break ; /* stop fetching */
if ( ! seq - > is_ cycled )
if ( ! cycle )
{
char buf [ 100 ] ;
@ -664,7 +709,7 @@ nextval_internal(Oid relid)
{
if ( rescnt > 0 )
break ; /* stop fetching */
if ( ! seq - > is_ cycled )
if ( ! cycle )
{
char buf [ 100 ] ;
@ -747,7 +792,7 @@ nextval_internal(Oid relid)
xlrec . node = seqrel - > rd_node ;
XLogRegisterData ( ( char * ) & xlrec , sizeof ( xl_seq_rec ) ) ;
XLogRegisterData ( ( char * ) seqtuple . t_data , seqtuple . t_len ) ;
XLogRegisterData ( ( char * ) seqdata tuple . t_data , seqdata tuple . t_len ) ;
recptr = XLogInsert ( RM_SEQ_ID , XLOG_SEQ_LOG ) ;
@ -853,8 +898,12 @@ do_setval(Oid relid, int64 next, bool iscalled)
SeqTable elm ;
Relation seqrel ;
Buffer buf ;
HeapTupleData seqtuple ;
Form_pg_sequence seq ;
HeapTupleData seqdatatuple ;
Form_pg_sequence_data seq ;
HeapTuple pgstuple ;
Form_pg_sequence pgsform ;
int64 maxv ,
minv ;
/* open and AccessShareLock sequence */
init_sequence ( relid , & elm , & seqrel ) ;
@ -865,6 +914,14 @@ do_setval(Oid relid, int64 next, bool iscalled)
errmsg ( " permission denied for sequence %s " ,
RelationGetRelationName ( seqrel ) ) ) ) ;
pgstuple = SearchSysCache1 ( SEQRELID , ObjectIdGetDatum ( relid ) ) ;
if ( ! HeapTupleIsValid ( pgstuple ) )
elog ( ERROR , " cache lookup failed for sequence %u " , relid ) ;
pgsform = ( Form_pg_sequence ) GETSTRUCT ( pgstuple ) ;
maxv = pgsform - > seqmax ;
minv = pgsform - > seqmin ;
ReleaseSysCache ( pgstuple ) ;
/* read-only transactions may only modify temp sequences */
if ( ! seqrel - > rd_islocaltemp )
PreventCommandIfReadOnly ( " setval() " ) ;
@ -877,17 +934,17 @@ do_setval(Oid relid, int64 next, bool iscalled)
PreventCommandIfParallelMode ( " setval() " ) ;
/* lock page' buffer and read tuple */
seq = read_seq_tuple ( elm , seqrel , & buf , & seqtuple ) ;
seq = read_seq_tuple ( seqrel , & buf , & seqdata tuple ) ;
if ( ( next < seq - > min_ value ) | | ( next > seq - > max_ value ) )
if ( ( next < minv ) | | ( next > maxv ) )
{
char bufv [ 100 ] ,
bufm [ 100 ] ,
bufx [ 100 ] ;
snprintf ( bufv , sizeof ( bufv ) , INT64_FORMAT , next ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , seq - > min_ value ) ;
snprintf ( bufx , sizeof ( bufx ) , INT64_FORMAT , seq - > max_ value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , minv ) ;
snprintf ( bufx , sizeof ( bufx ) , INT64_FORMAT , maxv ) ;
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " setval: value %s is out of bounds for sequence \" %s \" (%s..%s) " ,
@ -930,7 +987,7 @@ do_setval(Oid relid, int64 next, bool iscalled)
xlrec . node = seqrel - > rd_node ;
XLogRegisterData ( ( char * ) & xlrec , sizeof ( xl_seq_rec ) ) ;
XLogRegisterData ( ( char * ) seqtuple . t_data , seqtuple . t_len ) ;
XLogRegisterData ( ( char * ) seqdata tuple . t_data , seqdata tuple . t_len ) ;
recptr = XLogInsert ( RM_SEQ_ID , XLOG_SEQ_LOG ) ;
@ -1064,7 +1121,7 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
elm - > filenode = InvalidOid ;
elm - > lxid = InvalidLocalTransactionId ;
elm - > last_valid = false ;
elm - > last = elm - > cached = elm - > increment = 0 ;
elm - > last = elm - > cached = 0 ;
}
/*
@ -1099,18 +1156,18 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
* Given an opened sequence relation , lock the page buffer and find the tuple
*
* * buf receives the reference to the pinned - and - ex - locked buffer
* * seqtuple receives the reference to the sequence tuple proper
* * seqdata tuple receives the reference to the sequence tuple proper
* ( this arg should point to a local variable of type HeapTupleData )
*
* Function ' s return value points to the data payload of the tuple
*/
static Form_pg_sequence
read_seq_tuple ( SeqTable elm , Relation rel , Buffer * buf , HeapTuple seqtuple )
static Form_pg_sequence_data
read_seq_tuple ( Relation rel , Buffer * buf , HeapTuple seqdata tuple )
{
Page page ;
ItemId lp ;
sequence_magic * sm ;
Form_pg_sequence seq ;
Form_pg_sequence_data seq ;
* buf = ReadBuffer ( rel , 0 ) ;
LockBuffer ( * buf , BUFFER_LOCK_EXCLUSIVE ) ;
@ -1125,9 +1182,9 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
lp = PageGetItemId ( page , FirstOffsetNumber ) ;
Assert ( ItemIdIsNormal ( lp ) ) ;
/* Note we currently only bother to set these two fields of *seqtuple */
seqtuple - > t_data = ( HeapTupleHeader ) PageGetItem ( page , lp ) ;
seqtuple - > t_len = ItemIdGetLength ( lp ) ;
/* Note we currently only bother to set these two fields of *seqdata tuple */
seqdata tuple - > t_data = ( HeapTupleHeader ) PageGetItem ( page , lp ) ;
seqdata tuple - > t_len = ItemIdGetLength ( lp ) ;
/*
* Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
@ -1137,19 +1194,16 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
* bit update , ie , don ' t bother to WAL - log it , since we can certainly do
* this again if the update gets lost .
*/
Assert ( ! ( seqtuple - > t_data - > t_infomask & HEAP_XMAX_IS_MULTI ) ) ;
if ( HeapTupleHeaderGetRawXmax ( seqtuple - > t_data ) ! = InvalidTransactionId )
Assert ( ! ( seqdata tuple - > t_data - > t_infomask & HEAP_XMAX_IS_MULTI ) ) ;
if ( HeapTupleHeaderGetRawXmax ( seqdata tuple - > t_data ) ! = InvalidTransactionId )
{
HeapTupleHeaderSetXmax ( seqtuple - > t_data , InvalidTransactionId ) ;
seqtuple - > t_data - > t_infomask & = ~ HEAP_XMAX_COMMITTED ;
seqtuple - > t_data - > t_infomask | = HEAP_XMAX_INVALID ;
HeapTupleHeaderSetXmax ( seqdata tuple - > t_data , InvalidTransactionId ) ;
seqdata tuple - > t_data - > t_infomask & = ~ HEAP_XMAX_COMMITTED ;
seqdata tuple - > t_data - > t_infomask | = HEAP_XMAX_INVALID ;
MarkBufferDirtyHint ( * buf , true ) ;
}
seq = ( Form_pg_sequence ) GETSTRUCT ( seqtuple ) ;
/* this is a handy place to update our copy of the increment */
elm - > increment = seq - > increment_by ;
seq = ( Form_pg_sequence_data ) GETSTRUCT ( seqdatatuple ) ;
return seq ;
}
@ -1164,7 +1218,8 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
*/
static void
init_params ( ParseState * pstate , List * options , bool isInit ,
Form_pg_sequence new , List * * owned_by )
Form_pg_sequence seqform ,
Form_pg_sequence_data seqdataform , List * * owned_by )
{
DefElem * start_value = NULL ;
DefElem * restart_value = NULL ;
@ -1263,69 +1318,69 @@ init_params(ParseState *pstate, List *options, bool isInit,
* would affect future nextval allocations .
*/
if ( isInit )
new - > log_cnt = 0 ;
seqdataform - > log_cnt = 0 ;
/* INCREMENT BY */
if ( increment_by ! = NULL )
{
new - > increment_by = defGetInt64 ( increment_by ) ;
if ( new - > increment_by = = 0 )
seqform - > seq increment = defGetInt64 ( increment_by ) ;
if ( seqform - > seq increment = = 0 )
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " INCREMENT must not be zero " ) ) ) ;
new - > log_cnt = 0 ;
seqdataform - > log_cnt = 0 ;
}
else if ( isInit )
new - > increment_by = 1 ;
seqform - > seq increment = 1 ;
/* CYCLE */
if ( is_cycled ! = NULL )
{
new - > is_cycled = intVal ( is_cycled - > arg ) ;
Assert ( BoolIsValid ( new - > is_cycled ) ) ;
new - > log_cnt = 0 ;
seqform - > seqcycle = intVal ( is_cycled - > arg ) ;
Assert ( BoolIsValid ( seqform - > seqcycle ) ) ;
seqdataform - > log_cnt = 0 ;
}
else if ( isInit )
new - > is_cycled = false ;
seqform - > seqcycle = false ;
/* MAXVALUE (null arg means NO MAXVALUE) */
if ( max_value ! = NULL & & max_value - > arg )
{
new - > max_value = defGetInt64 ( max_value ) ;
new - > log_cnt = 0 ;
seqform - > seq max = defGetInt64 ( max_value ) ;
seqdataform - > log_cnt = 0 ;
}
else if ( isInit | | max_value ! = NULL )
{
if ( new - > increment_by > 0 )
new - > max_value = SEQ_MAXVALUE ; /* ascending seq */
if ( seqform - > seq increment > 0 )
seqform - > seq max = SEQ_MAXVALUE ; /* ascending seq */
else
new - > max_value = - 1 ; /* descending seq */
new - > log_cnt = 0 ;
seqform - > seq max = - 1 ; /* descending seq */
seqdataform - > log_cnt = 0 ;
}
/* MINVALUE (null arg means NO MINVALUE) */
if ( min_value ! = NULL & & min_value - > arg )
{
new - > min_value = defGetInt64 ( min_value ) ;
new - > log_cnt = 0 ;
seqform - > seq min = defGetInt64 ( min_value ) ;
seqdataform - > log_cnt = 0 ;
}
else if ( isInit | | min_value ! = NULL )
{
if ( new - > increment_by > 0 )
new - > min_value = 1 ; /* ascending seq */
if ( seqform - > seq increment > 0 )
seqform - > seq min = 1 ; /* ascending seq */
else
new - > min_value = SEQ_MINVALUE ; /* descending seq */
new - > log_cnt = 0 ;
seqform - > seq min = SEQ_MINVALUE ; /* descending seq */
seqdataform - > log_cnt = 0 ;
}
/* crosscheck min/max */
if ( new - > min_value > = new - > max_value )
if ( seqform - > seq min > = seqform - > seq max)
{
char bufm [ 100 ] ,
bufx [ 100 ] ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , new - > min_value ) ;
snprintf ( bufx , sizeof ( bufx ) , INT64_FORMAT , new - > max_value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , seqform - > seq min) ;
snprintf ( bufx , sizeof ( bufx ) , INT64_FORMAT , seqform - > seq max) ;
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " MINVALUE (%s) must be less than MAXVALUE (%s) " ,
@ -1334,35 +1389,35 @@ init_params(ParseState *pstate, List *options, bool isInit,
/* START WITH */
if ( start_value ! = NULL )
new - > start_value = defGetInt64 ( start_value ) ;
seqform - > seqs tart = defGetInt64 ( start_value ) ;
else if ( isInit )
{
if ( new - > increment_by > 0 )
new - > start_value = new - > min_value ; /* ascending seq */
if ( seqform - > seq increment > 0 )
seqform - > seqstart = seqform - > seq min; /* ascending seq */
else
new - > start_value = new - > max_value ; /* descending seq */
seqform - > seqstart = seqform - > seq max; /* descending seq */
}
/* crosscheck START */
if ( new - > start_value < new - > min_value )
if ( seqform - > seqs tart < seqform - > seq min)
{
char bufs [ 100 ] ,
bufm [ 100 ] ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , new - > start_value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , new - > min_value ) ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , seqform - > seqs tart ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , seqform - > seq min) ;
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " START value (%s) cannot be less than MINVALUE (%s) " ,
bufs , bufm ) ) ) ;
}
if ( new - > start_value > new - > max_value )
if ( seqform - > seqs tart > seqform - > seq max)
{
char bufs [ 100 ] ,
bufm [ 100 ] ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , new - > start_value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , new - > max_value ) ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , seqform - > seqs tart ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , seqform - > seq max) ;
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " START value (%s) cannot be greater than MAXVALUE (%s) " ,
@ -1373,38 +1428,38 @@ init_params(ParseState *pstate, List *options, bool isInit,
if ( restart_value ! = NULL )
{
if ( restart_value - > arg ! = NULL )
new - > last_value = defGetInt64 ( restart_value ) ;
seqdataform - > last_value = defGetInt64 ( restart_value ) ;
else
new - > last_value = new - > start_value ;
new - > is_called = false ;
new - > log_cnt = 0 ;
seqdataform - > last_value = seqform - > seqs tart ;
seqdataform - > is_called = false ;
seqdataform - > log_cnt = 0 ;
}
else if ( isInit )
{
new - > last_value = new - > start_value ;
new - > is_called = false ;
seqdataform - > last_value = seqform - > seqs tart ;
seqdataform - > is_called = false ;
}
/* crosscheck RESTART (or current value, if changing MIN/MAX) */
if ( new - > last_value < new - > min_value )
if ( seqdataform - > last_value < seqform - > seq min)
{
char bufs [ 100 ] ,
bufm [ 100 ] ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , new - > last_value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , new - > min_value ) ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , seqdataform - > last_value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , seqform - > seq min) ;
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " RESTART value (%s) cannot be less than MINVALUE (%s) " ,
bufs , bufm ) ) ) ;
}
if ( new - > last_value > new - > max_value )
if ( seqdataform - > last_value > seqform - > seq max)
{
char bufs [ 100 ] ,
bufm [ 100 ] ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , new - > last_value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , new - > max_value ) ;
snprintf ( bufs , sizeof ( bufs ) , INT64_FORMAT , seqdataform - > last_value ) ;
snprintf ( bufm , sizeof ( bufm ) , INT64_FORMAT , seqform - > seq max) ;
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " RESTART value (%s) cannot be greater than MAXVALUE (%s) " ,
@ -1414,21 +1469,21 @@ init_params(ParseState *pstate, List *options, bool isInit,
/* CACHE */
if ( cache_value ! = NULL )
{
new - > cache_valu e = defGetInt64 ( cache_value ) ;
if ( new - > cache_valu e < = 0 )
seqform - > seq cache = defGetInt64 ( cache_value ) ;
if ( seqform - > seq cache < = 0 )
{
char buf [ 100 ] ;
snprintf ( buf , sizeof ( buf ) , INT64_FORMAT , new - > cache_valu e ) ;
snprintf ( buf , sizeof ( buf ) , INT64_FORMAT , seqform - > seq cache) ;
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " CACHE (%s) must be greater than zero " ,
buf ) ) ) ;
}
new - > log_cnt = 0 ;
seqdataform - > log_cnt = 0 ;
}
else if ( isInit )
new - > cache_valu e = 1 ;
seqform - > seq cache = 1 ;
}
/*
@ -1528,7 +1583,7 @@ process_owned_by(Relation seqrel, List *owned_by)
/*
* Return sequence parameters , for use by information schema
* Return sequence parameters ( formerly for use by information schema )
*/
Datum
pg_sequence_parameters ( PG_FUNCTION_ARGS )
@ -1537,20 +1592,14 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
TupleDesc tupdesc ;
Datum values [ 6 ] ;
bool isnull [ 6 ] ;
SeqTable elm ;
Relation seqrel ;
Buffer buf ;
HeapTupleData seqtuple ;
Form_pg_sequence seq ;
/* open and AccessShareLock sequence */
init_sequence ( relid , & elm , & seqrel ) ;
HeapTuple pgstuple ;
Form_pg_sequence pgsform ;
if ( pg_class_aclcheck ( relid , GetUserId ( ) , ACL_SELECT | ACL_UPDATE | ACL_USAGE ) ! = ACLCHECK_OK )
ereport ( ERROR ,
( errcode ( ERRCODE_INSUFFICIENT_PRIVILEGE ) ,
errmsg ( " permission denied for sequence %s " ,
RelationGetRelationN ame( seq rel) ) ) ) ;
get_rel_name ( relid ) ) ) ) ;
tupdesc = CreateTemplateTupleDesc ( 6 , false ) ;
TupleDescInitEntry ( tupdesc , ( AttrNumber ) 1 , " start_value " ,
@ -1570,17 +1619,19 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
memset ( isnull , 0 , sizeof ( isnull ) ) ;
seq = read_seq_tuple ( elm , seqrel , & buf , & seqtuple ) ;
pgstuple = SearchSysCache1 ( SEQRELID , relid ) ;
if ( ! HeapTupleIsValid ( pgstuple ) )
elog ( ERROR , " cache lookup failed for sequence %u " , relid ) ;
pgsform = ( Form_pg_sequence ) GETSTRUCT ( pgstuple ) ;
values [ 0 ] = Int64GetDatum ( seq - > start_value ) ;
values [ 1 ] = Int64GetDatum ( seq - > min_value ) ;
values [ 2 ] = Int64GetDatum ( seq - > max_value ) ;
values [ 3 ] = Int64GetDatum ( seq - > increment_by ) ;
values [ 4 ] = BoolGetDatum ( seq - > is_cycled ) ;
values [ 5 ] = Int64GetDatum ( seq - > cache_valu e ) ;
values [ 0 ] = Int64GetDatum ( pgsform - > seqs tart ) ;
values [ 1 ] = Int64GetDatum ( pgsform - > seq min) ;
values [ 2 ] = Int64GetDatum ( pgsform - > seq max) ;
values [ 3 ] = Int64GetDatum ( pgsform - > seq increment) ;
values [ 4 ] = BoolGetDatum ( pgsform - > seqcycle ) ;
values [ 5 ] = Int64GetDatum ( pgsform - > seq cache) ;
UnlockReleaseBuffer ( buf ) ;
relation_close ( seqrel , NoLock ) ;
ReleaseSysCache ( pgstuple ) ;
return HeapTupleGetDatum ( heap_form_tuple ( tupdesc , values , isnull ) ) ;
}
@ -1598,7 +1649,7 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
Relation seqrel ;
Buffer buf ;
HeapTupleData seqtuple ;
Form_pg_sequence seq ;
Form_pg_sequence_data seq ;
bool is_called ;
int64 result ;
@ -1611,7 +1662,7 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
errmsg ( " permission denied for sequence %s " ,
RelationGetRelationName ( seqrel ) ) ) ) ;
seq = read_seq_tuple ( elm , seqrel , & buf , & seqtuple ) ;
seq = read_seq_tuple ( seqrel , & buf , & seqtuple ) ;
is_called = seq - > is_called ;
result = seq - > last_value ;