aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/sequence.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/sequence.c')
-rw-r--r--src/backend/commands/sequence.c170
1 files changed, 57 insertions, 113 deletions
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 54ca1d19a10..a7678c5ce38 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -8,15 +8,14 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.75 2002/03/29 19:06:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.76 2002/03/30 01:02:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include <ctype.h>
-
#include "access/heapam.h"
+#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "commands/creatinh.h"
#include "commands/sequence.h"
@@ -24,9 +23,6 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/int8.h"
-#ifdef MULTIBYTE
-#include "mb/pg_wchar.h"
-#endif
#define SEQ_MAGIC 0x1717
@@ -57,7 +53,6 @@ typedef struct sequence_magic
typedef struct SeqTableData
{
- char *name;
Oid relid;
Relation rel; /* NULL if rel is not open in cur xact */
int64 cached;
@@ -70,12 +65,11 @@ typedef SeqTableData *SeqTable;
static SeqTable seqtab = NULL;
-static char *get_seq_name(text *seqin);
-static SeqTable init_sequence(char *caller, char *name);
+static SeqTable init_sequence(char *caller, RangeVar *relation);
static Form_pg_sequence read_info(char *caller, SeqTable elm, Buffer *buf);
static void init_params(CreateSeqStmt *seq, Form_pg_sequence new);
static int64 get_param(DefElem *def);
-static void do_setval(char *seqname, int64 next, bool iscalled);
+static void do_setval(RangeVar *sequence, int64 next, bool iscalled);
/*
* DefineSequence
@@ -285,7 +279,7 @@ Datum
nextval(PG_FUNCTION_ARGS)
{
text *seqin = PG_GETARG_TEXT_P(0);
- char *seqname = get_seq_name(seqin);
+ RangeVar *sequence;
SeqTable elm;
Buffer buf;
Page page;
@@ -302,14 +296,15 @@ nextval(PG_FUNCTION_ARGS)
rescnt = 0;
bool logit = false;
+ sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
+ "nextval"));
+
/* open and AccessShareLock sequence */
- elm = init_sequence("nextval", seqname);
+ elm = init_sequence("nextval", sequence);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s",
- seqname, seqname);
-
- pfree(seqname);
+ sequence->relname, sequence->relname);
if (elm->last != elm->cached) /* some numbers were cached */
{
@@ -379,7 +374,7 @@ nextval(PG_FUNCTION_ARGS)
break; /* stop fetching */
if (!seq->is_cycled)
elog(ERROR, "%s.nextval: reached MAXVALUE (" INT64_FORMAT ")",
- elm->name, maxv);
+ sequence->relname, maxv);
next = minv;
}
else
@@ -395,7 +390,7 @@ nextval(PG_FUNCTION_ARGS)
break; /* stop fetching */
if (!seq->is_cycled)
elog(ERROR, "%s.nextval: reached MINVALUE (" INT64_FORMAT ")",
- elm->name, minv);
+ sequence->relname, minv);
next = maxv;
}
else
@@ -456,7 +451,7 @@ nextval(PG_FUNCTION_ARGS)
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
if (WriteBuffer(buf) == STATUS_ERROR)
- elog(ERROR, "%s.nextval: WriteBuffer failed", elm->name);
+ elog(ERROR, "%s.nextval: WriteBuffer failed", sequence->relname);
PG_RETURN_INT64(result);
}
@@ -465,25 +460,26 @@ Datum
currval(PG_FUNCTION_ARGS)
{
text *seqin = PG_GETARG_TEXT_P(0);
- char *seqname = get_seq_name(seqin);
+ RangeVar *sequence;
SeqTable elm;
int64 result;
+ sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
+ "currval"));
+
/* open and AccessShareLock sequence */
- elm = init_sequence("currval", seqname);
+ elm = init_sequence("currval", sequence);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
elog(ERROR, "%s.currval: you don't have permissions to read sequence %s",
- seqname, seqname);
+ sequence->relname, sequence->relname);
if (elm->increment == 0) /* nextval/read_info were not called */
elog(ERROR, "%s.currval is not yet defined in this session",
- seqname);
+ sequence->relname);
result = elm->last;
- pfree(seqname);
-
PG_RETURN_INT64(result);
}
@@ -501,25 +497,25 @@ currval(PG_FUNCTION_ARGS)
* sequence.
*/
static void
-do_setval(char *seqname, int64 next, bool iscalled)
+do_setval(RangeVar *sequence, int64 next, bool iscalled)
{
SeqTable elm;
Buffer buf;
Form_pg_sequence seq;
/* open and AccessShareLock sequence */
- elm = init_sequence("setval", seqname);
+ elm = init_sequence("setval", sequence);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
elog(ERROR, "%s.setval: you don't have permissions to set sequence %s",
- seqname, seqname);
+ sequence->relname, sequence->relname);
/* lock page' buffer and read tuple */
seq = read_info("setval", elm, &buf);
if ((next < seq->min_value) || (next > seq->max_value))
elog(ERROR, "%s.setval: value " INT64_FORMAT " is out of bounds (" INT64_FORMAT "," INT64_FORMAT ")",
- seqname, next, seq->min_value, seq->max_value);
+ sequence->relname, next, seq->min_value, seq->max_value);
/* save info in local cache */
elm->last = next; /* last returned number */
@@ -562,9 +558,7 @@ do_setval(char *seqname, int64 next, bool iscalled)
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
if (WriteBuffer(buf) == STATUS_ERROR)
- elog(ERROR, "%s.setval: WriteBuffer failed", seqname);
-
- pfree(seqname);
+ elog(ERROR, "%s.setval: WriteBuffer failed", sequence->relname);
}
/*
@@ -576,9 +570,12 @@ setval(PG_FUNCTION_ARGS)
{
text *seqin = PG_GETARG_TEXT_P(0);
int64 next = PG_GETARG_INT64(1);
- char *seqname = get_seq_name(seqin);
+ RangeVar *sequence;
+
+ sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
+ "setval"));
- do_setval(seqname, next, true);
+ do_setval(sequence, next, true);
PG_RETURN_INT64(next);
}
@@ -593,65 +590,14 @@ setval_and_iscalled(PG_FUNCTION_ARGS)
text *seqin = PG_GETARG_TEXT_P(0);
int64 next = PG_GETARG_INT64(1);
bool iscalled = PG_GETARG_BOOL(2);
- char *seqname = get_seq_name(seqin);
+ RangeVar *sequence;
- do_setval(seqname, next, iscalled);
+ sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
+ "setval"));
- PG_RETURN_INT64(next);
-}
+ do_setval(sequence, next, iscalled);
-/*
- * Given a 'text' parameter to a sequence function, extract the actual
- * sequence name. We downcase the name if it's not double-quoted,
- * and truncate it if it's too long.
- *
- * This is a kluge, really --- should be able to write nextval(seqrel).
- */
-static char *
-get_seq_name(text *seqin)
-{
- char *rawname = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(seqin)));
- int rawlen = strlen(rawname);
- char *seqname;
-
- if (rawlen >= 2 &&
- rawname[0] == '\"' && rawname[rawlen - 1] == '\"')
- {
- /* strip off quotes, keep case */
- rawname[rawlen - 1] = '\0';
- seqname = pstrdup(rawname + 1);
- pfree(rawname);
- }
- else
- {
- seqname = rawname;
-
- /*
- * It's important that this match the identifier downcasing code
- * used by backend/parser/scan.l.
- */
- for (; *rawname; rawname++)
- {
- if (isupper((unsigned char) *rawname))
- *rawname = tolower((unsigned char) *rawname);
- }
- }
-
- /* Truncate name if it's overlength; again, should match scan.l */
- if (strlen(seqname) >= NAMEDATALEN)
- {
-#ifdef MULTIBYTE
- int len;
-
- len = pg_mbcliplen(seqname, rawlen, NAMEDATALEN - 1);
- seqname[len] = '\0';
-#else
- seqname[NAMEDATALEN - 1] = '\0';
-#endif
- }
-
- return seqname;
+ PG_RETURN_INT64(next);
}
static Form_pg_sequence
@@ -665,11 +611,12 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
if (elm->rel->rd_nblocks > 1)
elog(ERROR, "%s.%s: invalid number of blocks in sequence",
- elm->name, caller);
+ RelationGetRelationName(elm->rel), caller);
*buf = ReadBuffer(elm->rel, 0);
if (!BufferIsValid(*buf))
- elog(ERROR, "%s.%s: ReadBuffer failed", elm->name, caller);
+ elog(ERROR, "%s.%s: ReadBuffer failed",
+ RelationGetRelationName(elm->rel), caller);
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
@@ -677,7 +624,8 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
sm = (sequence_magic *) PageGetSpecialPointer(page);
if (sm->magic != SEQ_MAGIC)
- elog(ERROR, "%s.%s: bad magic (%08X)", elm->name, caller, sm->magic);
+ elog(ERROR, "%s.%s: bad magic (%08X)",
+ RelationGetRelationName(elm->rel), caller, sm->magic);
lp = PageGetItemId(page, FirstOffsetNumber);
Assert(ItemIdIsUsed(lp));
@@ -692,16 +640,17 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
static SeqTable
-init_sequence(char *caller, char *name)
+init_sequence(char *caller, RangeVar *relation)
{
+ Oid relid = RangeVarGetRelid(relation, false);
SeqTable elm,
prev = (SeqTable) NULL;
Relation seqrel;
-
- /* Look to see if we already have a seqtable entry for name */
+
+ /* Look to see if we already have a seqtable entry for relation */
for (elm = seqtab; elm != (SeqTable) NULL; elm = elm->next)
{
- if (strcmp(elm->name, name) == 0)
+ if (elm->relid == relid)
break;
prev = elm;
}
@@ -711,24 +660,22 @@ init_sequence(char *caller, char *name)
return elm;
/* Else open and check it */
- seqrel = heap_openr(name, AccessShareLock);
+ seqrel = heap_open(relid, AccessShareLock);
if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)
- elog(ERROR, "%s.%s: %s is not a sequence", name, caller, name);
+ elog(ERROR, "%s.%s: %s is not a sequence",
+ relation->relname, caller, relation->relname);
+ /*
+ * If elm exists but elm->rel is NULL, the seqtable entry is left over
+ * from a previous xact -- update the entry and reuse it.
+ *
+ * NOTE: seqtable entries remain in the list for the life of a backend.
+ * If the sequence itself is deleted then the entry becomes wasted memory,
+ * but it's small enough that this should not matter.
+ */
if (elm != (SeqTable) NULL)
{
- /*
- * We are using a seqtable entry left over from a previous xact;
- * must check for relid change.
- */
elm->rel = seqrel;
- if (RelationGetRelid(seqrel) != elm->relid)
- {
- elog(WARNING, "%s.%s: sequence was re-created",
- name, caller);
- elm->relid = RelationGetRelid(seqrel);
- elm->cached = elm->last = elm->increment = 0;
- }
}
else
{
@@ -739,11 +686,8 @@ init_sequence(char *caller, char *name)
elm = (SeqTable) malloc(sizeof(SeqTableData));
if (elm == NULL)
elog(ERROR, "Memory exhausted in init_sequence");
- elm->name = strdup(name);
- if (elm->name == NULL)
- elog(ERROR, "Memory exhausted in init_sequence");
elm->rel = seqrel;
- elm->relid = RelationGetRelid(seqrel);
+ elm->relid = relid;
elm->cached = elm->last = elm->increment = 0;
elm->next = (SeqTable) NULL;