mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Further cleanups for relations in schemas: teach nextval and other
sequence functions how to cope with qualified names. Same code is also used for int4notin, currtid_byrelname, pgstattuple. Also, move TOAST tables into special pg_toast namespace.
This commit is contained in:
parent
25004eec95
commit
5f4745adf4
@ -33,7 +33,7 @@ NOTICE: physical length: 0.08MB live tuples: 20 (0.00MB, 1.17%) dead tuples: 32
|
|||||||
|
|
||||||
pgstattuple can be called as a function:
|
pgstattuple can be called as a function:
|
||||||
|
|
||||||
pgstattuple(NAME) RETURNS FLOAT8
|
pgstattuple(TEXT) RETURNS FLOAT8
|
||||||
|
|
||||||
The argument is the table name. pgstattuple returns the percentage
|
The argument is the table name. pgstattuple returns the percentage
|
||||||
of the "dead" tuples of a table.
|
of the "dead" tuples of a table.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.4 2002/03/06 06:09:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.5 2002/03/30 01:02:41 tgl Exp $
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001 Tatsuo Ishii
|
* Copyright (c) 2001 Tatsuo Ishii
|
||||||
*
|
*
|
||||||
@ -27,6 +27,9 @@
|
|||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "access/transam.h"
|
#include "access/transam.h"
|
||||||
|
#include "catalog/namespace.h"
|
||||||
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(pgstattuple);
|
PG_FUNCTION_INFO_V1(pgstattuple);
|
||||||
|
|
||||||
@ -43,8 +46,8 @@ extern Datum pgstattuple(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
pgstattuple(PG_FUNCTION_ARGS)
|
pgstattuple(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Name p = PG_GETARG_NAME(0);
|
text *relname = PG_GETARG_TEXT_P(0);
|
||||||
|
RangeVar *relrv;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
@ -59,11 +62,13 @@ pgstattuple(PG_FUNCTION_ARGS)
|
|||||||
uint64 dead_tuple_count = 0;
|
uint64 dead_tuple_count = 0;
|
||||||
double tuple_percent;
|
double tuple_percent;
|
||||||
double dead_tuple_percent;
|
double dead_tuple_percent;
|
||||||
|
|
||||||
uint64 free_space = 0; /* free/reusable space in bytes */
|
uint64 free_space = 0; /* free/reusable space in bytes */
|
||||||
double free_percent; /* free/reusable space in % */
|
double free_percent; /* free/reusable space in % */
|
||||||
|
|
||||||
rel = heap_openr(NameStr(*p), AccessShareLock);
|
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
|
||||||
|
"pgstattuple"));
|
||||||
|
rel = heap_openrv(relrv, AccessShareLock);
|
||||||
|
|
||||||
nblocks = RelationGetNumberOfBlocks(rel);
|
nblocks = RelationGetNumberOfBlocks(rel);
|
||||||
scan = heap_beginscan(rel, false, SnapshotAny, 0, NULL);
|
scan = heap_beginscan(rel, false, SnapshotAny, 0, NULL);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
DROP FUNCTION pgstattuple(NAME);
|
DROP FUNCTION pgstattuple(text);
|
||||||
CREATE FUNCTION pgstattuple(NAME) RETURNS FLOAT8
|
CREATE FUNCTION pgstattuple(text) RETURNS float8
|
||||||
AS 'MODULE_PATHNAME', 'pgstattuple'
|
AS 'MODULE_PATHNAME', 'pgstattuple'
|
||||||
LANGUAGE 'c' WITH (isstrict);
|
LANGUAGE 'c' WITH (isstrict);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.2 2002/03/29 19:06:01 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.3 2002/03/30 01:02:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -81,6 +81,10 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
|
|||||||
* RangeVarGetCreationNamespace
|
* RangeVarGetCreationNamespace
|
||||||
* Given a RangeVar describing a to-be-created relation,
|
* Given a RangeVar describing a to-be-created relation,
|
||||||
* choose which namespace to create it in.
|
* choose which namespace to create it in.
|
||||||
|
*
|
||||||
|
* Note: calling this may result in a CommandCounterIncrement operation.
|
||||||
|
* That will happen on the first request for a temp table in any particular
|
||||||
|
* backend run; we will need to either create or clean out the temp schema.
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
RangeVarGetCreationNamespace(const RangeVar *newRelation)
|
RangeVarGetCreationNamespace(const RangeVar *newRelation)
|
||||||
@ -126,6 +130,21 @@ RelnameGetRelid(const char *relname)
|
|||||||
return get_relname_relid(relname, PG_CATALOG_NAMESPACE);
|
return get_relname_relid(relname, PG_CATALOG_NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TypenameGetTypid
|
||||||
|
* Try to resolve an unqualified datatype name.
|
||||||
|
* Returns OID if type found in search path, else InvalidOid.
|
||||||
|
*/
|
||||||
|
Oid
|
||||||
|
TypenameGetTypid(const char *typname)
|
||||||
|
{
|
||||||
|
/* XXX wrong, should use namespace search */
|
||||||
|
return GetSysCacheOid(TYPENAMENSP,
|
||||||
|
PointerGetDatum(typname),
|
||||||
|
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* QualifiedNameGetCreationNamespace
|
* QualifiedNameGetCreationNamespace
|
||||||
* Given a possibly-qualified name for an object (in List-of-Values
|
* Given a possibly-qualified name for an object (in List-of-Values
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.167 2002/03/29 19:06:03 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.168 2002/03/30 01:02:41 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The PerformAddAttribute() code, like most of the relation
|
* The PerformAddAttribute() code, like most of the relation
|
||||||
@ -1755,13 +1755,13 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
|||||||
tupdesc->attrs[2]->attstorage = 'p';
|
tupdesc->attrs[2]->attstorage = 'p';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: the toast relation is considered a "normal" relation even if
|
* Note: the toast relation is placed in the regular pg_toast namespace
|
||||||
* its master relation is a temp table. There cannot be any naming
|
* even if its master relation is a temp table. There cannot be any
|
||||||
* collision, and the toast rel will be destroyed when its master is,
|
* naming collision, and the toast rel will be destroyed when its master
|
||||||
* so there's no need to handle the toast rel as temp.
|
* is, so there's no need to handle the toast rel as temp.
|
||||||
*/
|
*/
|
||||||
toast_relid = heap_create_with_catalog(toast_relname,
|
toast_relid = heap_create_with_catalog(toast_relname,
|
||||||
RelationGetNamespace(rel),
|
PG_TOAST_NAMESPACE,
|
||||||
tupdesc,
|
tupdesc,
|
||||||
RELKIND_TOASTVALUE, false,
|
RELKIND_TOASTVALUE, false,
|
||||||
false, true);
|
false, true);
|
||||||
|
@ -8,15 +8,14 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "postgres.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "commands/creatinh.h"
|
#include "commands/creatinh.h"
|
||||||
#include "commands/sequence.h"
|
#include "commands/sequence.h"
|
||||||
@ -24,9 +23,6 @@
|
|||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/int8.h"
|
#include "utils/int8.h"
|
||||||
#ifdef MULTIBYTE
|
|
||||||
#include "mb/pg_wchar.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define SEQ_MAGIC 0x1717
|
#define SEQ_MAGIC 0x1717
|
||||||
@ -57,7 +53,6 @@ typedef struct sequence_magic
|
|||||||
|
|
||||||
typedef struct SeqTableData
|
typedef struct SeqTableData
|
||||||
{
|
{
|
||||||
char *name;
|
|
||||||
Oid relid;
|
Oid relid;
|
||||||
Relation rel; /* NULL if rel is not open in cur xact */
|
Relation rel; /* NULL if rel is not open in cur xact */
|
||||||
int64 cached;
|
int64 cached;
|
||||||
@ -70,12 +65,11 @@ typedef SeqTableData *SeqTable;
|
|||||||
|
|
||||||
static SeqTable seqtab = NULL;
|
static SeqTable seqtab = NULL;
|
||||||
|
|
||||||
static char *get_seq_name(text *seqin);
|
static SeqTable init_sequence(char *caller, RangeVar *relation);
|
||||||
static SeqTable init_sequence(char *caller, char *name);
|
|
||||||
static Form_pg_sequence read_info(char *caller, SeqTable elm, Buffer *buf);
|
static Form_pg_sequence read_info(char *caller, SeqTable elm, Buffer *buf);
|
||||||
static void init_params(CreateSeqStmt *seq, Form_pg_sequence new);
|
static void init_params(CreateSeqStmt *seq, Form_pg_sequence new);
|
||||||
static int64 get_param(DefElem *def);
|
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
|
* DefineSequence
|
||||||
@ -285,7 +279,7 @@ Datum
|
|||||||
nextval(PG_FUNCTION_ARGS)
|
nextval(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *seqin = PG_GETARG_TEXT_P(0);
|
text *seqin = PG_GETARG_TEXT_P(0);
|
||||||
char *seqname = get_seq_name(seqin);
|
RangeVar *sequence;
|
||||||
SeqTable elm;
|
SeqTable elm;
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
Page page;
|
Page page;
|
||||||
@ -302,14 +296,15 @@ nextval(PG_FUNCTION_ARGS)
|
|||||||
rescnt = 0;
|
rescnt = 0;
|
||||||
bool logit = false;
|
bool logit = false;
|
||||||
|
|
||||||
|
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||||
|
"nextval"));
|
||||||
|
|
||||||
/* open and AccessShareLock sequence */
|
/* 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)
|
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
|
||||||
elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s",
|
elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s",
|
||||||
seqname, seqname);
|
sequence->relname, sequence->relname);
|
||||||
|
|
||||||
pfree(seqname);
|
|
||||||
|
|
||||||
if (elm->last != elm->cached) /* some numbers were cached */
|
if (elm->last != elm->cached) /* some numbers were cached */
|
||||||
{
|
{
|
||||||
@ -379,7 +374,7 @@ nextval(PG_FUNCTION_ARGS)
|
|||||||
break; /* stop fetching */
|
break; /* stop fetching */
|
||||||
if (!seq->is_cycled)
|
if (!seq->is_cycled)
|
||||||
elog(ERROR, "%s.nextval: reached MAXVALUE (" INT64_FORMAT ")",
|
elog(ERROR, "%s.nextval: reached MAXVALUE (" INT64_FORMAT ")",
|
||||||
elm->name, maxv);
|
sequence->relname, maxv);
|
||||||
next = minv;
|
next = minv;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -395,7 +390,7 @@ nextval(PG_FUNCTION_ARGS)
|
|||||||
break; /* stop fetching */
|
break; /* stop fetching */
|
||||||
if (!seq->is_cycled)
|
if (!seq->is_cycled)
|
||||||
elog(ERROR, "%s.nextval: reached MINVALUE (" INT64_FORMAT ")",
|
elog(ERROR, "%s.nextval: reached MINVALUE (" INT64_FORMAT ")",
|
||||||
elm->name, minv);
|
sequence->relname, minv);
|
||||||
next = maxv;
|
next = maxv;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -456,7 +451,7 @@ nextval(PG_FUNCTION_ARGS)
|
|||||||
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
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);
|
PG_RETURN_INT64(result);
|
||||||
}
|
}
|
||||||
@ -465,25 +460,26 @@ Datum
|
|||||||
currval(PG_FUNCTION_ARGS)
|
currval(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *seqin = PG_GETARG_TEXT_P(0);
|
text *seqin = PG_GETARG_TEXT_P(0);
|
||||||
char *seqname = get_seq_name(seqin);
|
RangeVar *sequence;
|
||||||
SeqTable elm;
|
SeqTable elm;
|
||||||
int64 result;
|
int64 result;
|
||||||
|
|
||||||
|
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||||
|
"currval"));
|
||||||
|
|
||||||
/* open and AccessShareLock sequence */
|
/* 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)
|
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
|
||||||
elog(ERROR, "%s.currval: you don't have permissions to read sequence %s",
|
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 */
|
if (elm->increment == 0) /* nextval/read_info were not called */
|
||||||
elog(ERROR, "%s.currval is not yet defined in this session",
|
elog(ERROR, "%s.currval is not yet defined in this session",
|
||||||
seqname);
|
sequence->relname);
|
||||||
|
|
||||||
result = elm->last;
|
result = elm->last;
|
||||||
|
|
||||||
pfree(seqname);
|
|
||||||
|
|
||||||
PG_RETURN_INT64(result);
|
PG_RETURN_INT64(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,25 +497,25 @@ currval(PG_FUNCTION_ARGS)
|
|||||||
* sequence.
|
* sequence.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
do_setval(char *seqname, int64 next, bool iscalled)
|
do_setval(RangeVar *sequence, int64 next, bool iscalled)
|
||||||
{
|
{
|
||||||
SeqTable elm;
|
SeqTable elm;
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
Form_pg_sequence seq;
|
Form_pg_sequence seq;
|
||||||
|
|
||||||
/* open and AccessShareLock sequence */
|
/* 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)
|
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
|
||||||
elog(ERROR, "%s.setval: you don't have permissions to set sequence %s",
|
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 */
|
/* lock page' buffer and read tuple */
|
||||||
seq = read_info("setval", elm, &buf);
|
seq = read_info("setval", elm, &buf);
|
||||||
|
|
||||||
if ((next < seq->min_value) || (next > seq->max_value))
|
if ((next < seq->min_value) || (next > seq->max_value))
|
||||||
elog(ERROR, "%s.setval: value " INT64_FORMAT " is out of bounds (" INT64_FORMAT "," INT64_FORMAT ")",
|
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 */
|
/* save info in local cache */
|
||||||
elm->last = next; /* last returned number */
|
elm->last = next; /* last returned number */
|
||||||
@ -562,9 +558,7 @@ do_setval(char *seqname, int64 next, bool iscalled)
|
|||||||
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
if (WriteBuffer(buf) == STATUS_ERROR)
|
||||||
elog(ERROR, "%s.setval: WriteBuffer failed", seqname);
|
elog(ERROR, "%s.setval: WriteBuffer failed", sequence->relname);
|
||||||
|
|
||||||
pfree(seqname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -576,9 +570,12 @@ setval(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
text *seqin = PG_GETARG_TEXT_P(0);
|
text *seqin = PG_GETARG_TEXT_P(0);
|
||||||
int64 next = PG_GETARG_INT64(1);
|
int64 next = PG_GETARG_INT64(1);
|
||||||
char *seqname = get_seq_name(seqin);
|
RangeVar *sequence;
|
||||||
|
|
||||||
do_setval(seqname, next, true);
|
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||||
|
"setval"));
|
||||||
|
|
||||||
|
do_setval(sequence, next, true);
|
||||||
|
|
||||||
PG_RETURN_INT64(next);
|
PG_RETURN_INT64(next);
|
||||||
}
|
}
|
||||||
@ -593,67 +590,16 @@ setval_and_iscalled(PG_FUNCTION_ARGS)
|
|||||||
text *seqin = PG_GETARG_TEXT_P(0);
|
text *seqin = PG_GETARG_TEXT_P(0);
|
||||||
int64 next = PG_GETARG_INT64(1);
|
int64 next = PG_GETARG_INT64(1);
|
||||||
bool iscalled = PG_GETARG_BOOL(2);
|
bool iscalled = PG_GETARG_BOOL(2);
|
||||||
char *seqname = get_seq_name(seqin);
|
RangeVar *sequence;
|
||||||
|
|
||||||
do_setval(seqname, next, iscalled);
|
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||||
|
"setval"));
|
||||||
|
|
||||||
|
do_setval(sequence, next, iscalled);
|
||||||
|
|
||||||
PG_RETURN_INT64(next);
|
PG_RETURN_INT64(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Form_pg_sequence
|
static Form_pg_sequence
|
||||||
read_info(char *caller, SeqTable elm, Buffer *buf)
|
read_info(char *caller, SeqTable elm, Buffer *buf)
|
||||||
{
|
{
|
||||||
@ -665,11 +611,12 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
|
|||||||
|
|
||||||
if (elm->rel->rd_nblocks > 1)
|
if (elm->rel->rd_nblocks > 1)
|
||||||
elog(ERROR, "%s.%s: invalid number of blocks in sequence",
|
elog(ERROR, "%s.%s: invalid number of blocks in sequence",
|
||||||
elm->name, caller);
|
RelationGetRelationName(elm->rel), caller);
|
||||||
|
|
||||||
*buf = ReadBuffer(elm->rel, 0);
|
*buf = ReadBuffer(elm->rel, 0);
|
||||||
if (!BufferIsValid(*buf))
|
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);
|
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
|
||||||
|
|
||||||
@ -677,7 +624,8 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
|
|||||||
sm = (sequence_magic *) PageGetSpecialPointer(page);
|
sm = (sequence_magic *) PageGetSpecialPointer(page);
|
||||||
|
|
||||||
if (sm->magic != SEQ_MAGIC)
|
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);
|
lp = PageGetItemId(page, FirstOffsetNumber);
|
||||||
Assert(ItemIdIsUsed(lp));
|
Assert(ItemIdIsUsed(lp));
|
||||||
@ -692,16 +640,17 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
|
|||||||
|
|
||||||
|
|
||||||
static SeqTable
|
static SeqTable
|
||||||
init_sequence(char *caller, char *name)
|
init_sequence(char *caller, RangeVar *relation)
|
||||||
{
|
{
|
||||||
|
Oid relid = RangeVarGetRelid(relation, false);
|
||||||
SeqTable elm,
|
SeqTable elm,
|
||||||
prev = (SeqTable) NULL;
|
prev = (SeqTable) NULL;
|
||||||
Relation seqrel;
|
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)
|
for (elm = seqtab; elm != (SeqTable) NULL; elm = elm->next)
|
||||||
{
|
{
|
||||||
if (strcmp(elm->name, name) == 0)
|
if (elm->relid == relid)
|
||||||
break;
|
break;
|
||||||
prev = elm;
|
prev = elm;
|
||||||
}
|
}
|
||||||
@ -711,24 +660,22 @@ init_sequence(char *caller, char *name)
|
|||||||
return elm;
|
return elm;
|
||||||
|
|
||||||
/* Else open and check it */
|
/* Else open and check it */
|
||||||
seqrel = heap_openr(name, AccessShareLock);
|
seqrel = heap_open(relid, AccessShareLock);
|
||||||
if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)
|
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)
|
if (elm != (SeqTable) NULL)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* We are using a seqtable entry left over from a previous xact;
|
|
||||||
* must check for relid change.
|
|
||||||
*/
|
|
||||||
elm->rel = seqrel;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -739,11 +686,8 @@ init_sequence(char *caller, char *name)
|
|||||||
elm = (SeqTable) malloc(sizeof(SeqTableData));
|
elm = (SeqTable) malloc(sizeof(SeqTableData));
|
||||||
if (elm == NULL)
|
if (elm == NULL)
|
||||||
elog(ERROR, "Memory exhausted in init_sequence");
|
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->rel = seqrel;
|
||||||
elm->relid = RelationGetRelid(seqrel);
|
elm->relid = relid;
|
||||||
elm->cached = elm->last = elm->increment = 0;
|
elm->cached = elm->last = elm->increment = 0;
|
||||||
elm->next = (SeqTable) NULL;
|
elm->next = (SeqTable) NULL;
|
||||||
|
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.38 2002/03/29 19:06:12 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.39 2002/03/30 01:02:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_namespace.h"
|
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
@ -132,6 +131,7 @@ LookupTypeName(const TypeName *typename)
|
|||||||
|
|
||||||
if (schemaname)
|
if (schemaname)
|
||||||
{
|
{
|
||||||
|
/* Look in specific schema only */
|
||||||
Oid namespaceId;
|
Oid namespaceId;
|
||||||
|
|
||||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||||
@ -147,11 +147,8 @@ LookupTypeName(const TypeName *typename)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* XXX wrong, should use namespace search */
|
/* Unqualified type name, so search the search path */
|
||||||
restype = GetSysCacheOid(TYPENAMENSP,
|
restype = TypenameGetTypid(typname);
|
||||||
PointerGetDatum(typname),
|
|
||||||
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
|
|
||||||
0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.27 2001/10/25 05:49:45 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.28 2002/03/30 01:02:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -25,7 +25,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
#include "catalog/namespace.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
static int my_varattno(Relation rd, char *a);
|
static int my_varattno(Relation rd, char *a);
|
||||||
@ -39,43 +41,39 @@ int4notin(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
int32 not_in_arg = PG_GETARG_INT32(0);
|
int32 not_in_arg = PG_GETARG_INT32(0);
|
||||||
text *relation_and_attr = PG_GETARG_TEXT_P(1);
|
text *relation_and_attr = PG_GETARG_TEXT_P(1);
|
||||||
|
List *names;
|
||||||
|
int nnames;
|
||||||
|
RangeVar *relrv;
|
||||||
|
char *attribute;
|
||||||
Relation relation_to_scan;
|
Relation relation_to_scan;
|
||||||
int32 integer_value;
|
int32 integer_value;
|
||||||
HeapTuple current_tuple;
|
HeapTuple current_tuple;
|
||||||
HeapScanDesc scan_descriptor;
|
HeapScanDesc scan_descriptor;
|
||||||
bool isNull,
|
bool isNull,
|
||||||
retval;
|
retval;
|
||||||
int attrid,
|
int attrid;
|
||||||
strlength;
|
|
||||||
char *relation,
|
|
||||||
*attribute;
|
|
||||||
char my_copy[NAMEDATALEN * 2 + 2];
|
|
||||||
Datum value;
|
Datum value;
|
||||||
|
|
||||||
/* make a null-terminated copy of text */
|
/* Parse the argument */
|
||||||
strlength = VARSIZE(relation_and_attr) - VARHDRSZ;
|
|
||||||
if (strlength >= sizeof(my_copy))
|
|
||||||
strlength = sizeof(my_copy) - 1;
|
|
||||||
memcpy(my_copy, VARDATA(relation_and_attr), strlength);
|
|
||||||
my_copy[strlength] = '\0';
|
|
||||||
|
|
||||||
relation = (char *) strtok(my_copy, ".");
|
names = textToQualifiedNameList(relation_and_attr, "int4notin");
|
||||||
attribute = (char *) strtok(NULL, ".");
|
nnames = length(names);
|
||||||
if (attribute == NULL)
|
if (nnames < 2)
|
||||||
elog(ERROR, "int4notin: must provide relationname.attributename");
|
elog(ERROR, "int4notin: must provide relationname.attributename");
|
||||||
|
attribute = strVal(nth(nnames-1, names));
|
||||||
|
names = ltruncate(nnames-1, names);
|
||||||
|
relrv = makeRangeVarFromNameList(names);
|
||||||
|
|
||||||
/* Open the relation and get a relation descriptor */
|
/* Open the relation and get a relation descriptor */
|
||||||
|
|
||||||
relation_to_scan = heap_openr(relation, AccessShareLock);
|
relation_to_scan = heap_openrv(relrv, AccessShareLock);
|
||||||
|
|
||||||
/* Find the column to search */
|
/* Find the column to search */
|
||||||
|
|
||||||
attrid = my_varattno(relation_to_scan, attribute);
|
attrid = my_varattno(relation_to_scan, attribute);
|
||||||
if (attrid < 0)
|
if (attrid < 0)
|
||||||
{
|
|
||||||
elog(ERROR, "int4notin: unknown attribute %s for relation %s",
|
elog(ERROR, "int4notin: unknown attribute %s for relation %s",
|
||||||
attribute, relation);
|
attribute, RelationGetRelationName(relation_to_scan));
|
||||||
}
|
|
||||||
|
|
||||||
scan_descriptor = heap_beginscan(relation_to_scan, false, SnapshotNow,
|
scan_descriptor = heap_beginscan(relation_to_scan, false, SnapshotNow,
|
||||||
0, (ScanKey) NULL);
|
0, (ScanKey) NULL);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.28 2001/10/25 05:49:45 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.29 2002/03/30 01:02:41 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* input routine largely stolen from boxin().
|
* input routine largely stolen from boxin().
|
||||||
@ -19,6 +19,7 @@
|
|||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
#include "catalog/namespace.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
#define DatumGetItemPointer(X) ((ItemPointer) DatumGetPointer(X))
|
#define DatumGetItemPointer(X) ((ItemPointer) DatumGetPointer(X))
|
||||||
@ -146,14 +147,13 @@ currtid_byreloid(PG_FUNCTION_ARGS)
|
|||||||
*result = Current_last_tid;
|
*result = Current_last_tid;
|
||||||
PG_RETURN_ITEMPOINTER(result);
|
PG_RETURN_ITEMPOINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rel = heap_open(reloid, AccessShareLock);
|
||||||
|
|
||||||
ItemPointerCopy(tid, result);
|
ItemPointerCopy(tid, result);
|
||||||
if ((rel = heap_open(reloid, AccessShareLock)) != NULL)
|
heap_get_latest_tid(rel, SnapshotNow, result);
|
||||||
{
|
|
||||||
heap_get_latest_tid(rel, SnapshotNow, result);
|
heap_close(rel, AccessShareLock);
|
||||||
heap_close(rel, AccessShareLock);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
elog(ERROR, "Relation %u not found", reloid);
|
|
||||||
|
|
||||||
PG_RETURN_ITEMPOINTER(result);
|
PG_RETURN_ITEMPOINTER(result);
|
||||||
}
|
}
|
||||||
@ -164,23 +164,19 @@ currtid_byrelname(PG_FUNCTION_ARGS)
|
|||||||
text *relname = PG_GETARG_TEXT_P(0);
|
text *relname = PG_GETARG_TEXT_P(0);
|
||||||
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
|
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
|
||||||
ItemPointer result;
|
ItemPointer result;
|
||||||
char *str;
|
RangeVar *relrv;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
|
|
||||||
str = DatumGetCString(DirectFunctionCall1(textout,
|
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
|
||||||
PointerGetDatum(relname)));
|
"currtid_byrelname"));
|
||||||
|
rel = heap_openrv(relrv, AccessShareLock);
|
||||||
|
|
||||||
result = (ItemPointer) palloc(sizeof(ItemPointerData));
|
result = (ItemPointer) palloc(sizeof(ItemPointerData));
|
||||||
ItemPointerCopy(tid, result);
|
ItemPointerCopy(tid, result);
|
||||||
if ((rel = heap_openr(str, AccessShareLock)) != NULL)
|
|
||||||
{
|
|
||||||
heap_get_latest_tid(rel, SnapshotNow, result);
|
|
||||||
heap_close(rel, AccessShareLock);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
elog(ERROR, "Relation %s not found", str);
|
|
||||||
|
|
||||||
pfree(str);
|
heap_get_latest_tid(rel, SnapshotNow, result);
|
||||||
|
|
||||||
|
heap_close(rel, AccessShareLock);
|
||||||
|
|
||||||
PG_RETURN_ITEMPOINTER(result);
|
PG_RETURN_ITEMPOINTER(result);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.79 2002/03/05 05:33:19 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.80 2002/03/30 01:02:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1039,6 +1039,122 @@ name_text(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* textToQualifiedNameList - convert a text object to list of names
|
||||||
|
*
|
||||||
|
* This implements the input parsing needed by nextval() and other
|
||||||
|
* functions that take a text parameter representing a qualified name.
|
||||||
|
* We split the name at dots, downcase if not double-quoted, and
|
||||||
|
* truncate names if they're too long.
|
||||||
|
*
|
||||||
|
* This is a kluge, really, and exists only for historical reasons.
|
||||||
|
* A better notation for such functions would be nextval(relname).
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
textToQualifiedNameList(text *textval, const char *caller)
|
||||||
|
{
|
||||||
|
char *rawname;
|
||||||
|
char *nextp;
|
||||||
|
List *result = NIL;
|
||||||
|
|
||||||
|
/* Convert to C string (handles possible detoasting). */
|
||||||
|
/* Note we rely on being able to modify rawname below. */
|
||||||
|
rawname = DatumGetCString(DirectFunctionCall1(textout,
|
||||||
|
PointerGetDatum(textval)));
|
||||||
|
nextp = rawname;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char *curname;
|
||||||
|
char *endp;
|
||||||
|
char *cp;
|
||||||
|
int curlen;
|
||||||
|
|
||||||
|
if (*nextp == '\"')
|
||||||
|
{
|
||||||
|
/* Quoted name --- collapse quote-quote pairs, no downcasing */
|
||||||
|
curname = nextp + 1;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
endp = strchr(nextp + 1, '\"');
|
||||||
|
if (endp == NULL)
|
||||||
|
elog(ERROR, "%s: invalid quoted name: mismatched quotes",
|
||||||
|
caller);
|
||||||
|
if (endp[1] != '\"')
|
||||||
|
break; /* found end of quoted name */
|
||||||
|
/* Collapse adjacent quotes into one quote, and look again */
|
||||||
|
memmove(endp, endp+1, strlen(endp));
|
||||||
|
nextp = endp;
|
||||||
|
}
|
||||||
|
*endp = '\0';
|
||||||
|
nextp = endp + 1;
|
||||||
|
if (*nextp)
|
||||||
|
{
|
||||||
|
if (*nextp != '.')
|
||||||
|
elog(ERROR, "%s: invalid name syntax",
|
||||||
|
caller);
|
||||||
|
nextp++;
|
||||||
|
if (*nextp == '\0')
|
||||||
|
elog(ERROR, "%s: invalid name syntax",
|
||||||
|
caller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Unquoted name --- extends to next dot */
|
||||||
|
if (*nextp == '\0') /* empty name not okay here */
|
||||||
|
elog(ERROR, "%s: invalid name syntax",
|
||||||
|
caller);
|
||||||
|
curname = nextp;
|
||||||
|
endp = strchr(nextp, '.');
|
||||||
|
if (endp)
|
||||||
|
{
|
||||||
|
*endp = '\0';
|
||||||
|
nextp = endp + 1;
|
||||||
|
if (*nextp == '\0')
|
||||||
|
elog(ERROR, "%s: invalid name syntax",
|
||||||
|
caller);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nextp = nextp + strlen(nextp);
|
||||||
|
/*
|
||||||
|
* It's important that this match the identifier downcasing code
|
||||||
|
* used by backend/parser/scan.l.
|
||||||
|
*/
|
||||||
|
for (cp = curname; *cp; cp++)
|
||||||
|
{
|
||||||
|
if (isupper((unsigned char) *cp))
|
||||||
|
*cp = tolower((unsigned char) *cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Truncate name if it's overlength; again, should match scan.l */
|
||||||
|
curlen = strlen(curname);
|
||||||
|
if (curlen >= NAMEDATALEN)
|
||||||
|
{
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
curlen = pg_mbcliplen(curname, curlen, NAMEDATALEN - 1);
|
||||||
|
curname[curlen] = '\0';
|
||||||
|
#else
|
||||||
|
curname[NAMEDATALEN - 1] = '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finished isolating current name --- add it to list
|
||||||
|
*/
|
||||||
|
result = lappend(result, makeString(pstrdup(curname)));
|
||||||
|
/*
|
||||||
|
* Loop back if we found a dot
|
||||||
|
*/
|
||||||
|
} while (*nextp);
|
||||||
|
|
||||||
|
pfree(rawname);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Comparison Functions used for bytea
|
* Comparison Functions used for bytea
|
||||||
*
|
*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: namespace.h,v 1.2 2002/03/29 19:06:18 tgl Exp $
|
* $Id: namespace.h,v 1.3 2002/03/30 01:02:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -23,6 +23,8 @@ extern Oid RangeVarGetCreationNamespace(const RangeVar *newRelation);
|
|||||||
|
|
||||||
extern Oid RelnameGetRelid(const char *relname);
|
extern Oid RelnameGetRelid(const char *relname);
|
||||||
|
|
||||||
|
extern Oid TypenameGetTypid(const char *typname);
|
||||||
|
|
||||||
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
|
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
|
||||||
|
|
||||||
extern RangeVar *makeRangeVarFromNameList(List *names);
|
extern RangeVar *makeRangeVarFromNameList(List *names);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pg_namespace.h,v 1.1 2002/03/22 21:34:44 tgl Exp $
|
* $Id: pg_namespace.h,v 1.2 2002/03/30 01:02:42 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* the genbki.sh script reads this file and generates .bki
|
* the genbki.sh script reads this file and generates .bki
|
||||||
@ -69,6 +69,12 @@ typedef FormData_pg_namespace *Form_pg_namespace;
|
|||||||
DATA(insert OID = 11 ( "pg_catalog" PGUID "{=r}" ));
|
DATA(insert OID = 11 ( "pg_catalog" PGUID "{=r}" ));
|
||||||
DESCR("System catalog namespace");
|
DESCR("System catalog namespace");
|
||||||
#define PG_CATALOG_NAMESPACE 11
|
#define PG_CATALOG_NAMESPACE 11
|
||||||
|
DATA(insert OID = 99 ( "pg_toast" PGUID "{=r}" ));
|
||||||
|
DESCR("Reserved namespace for TOAST tables");
|
||||||
|
#define PG_TOAST_NAMESPACE 99
|
||||||
|
DATA(insert OID = 2071 ( "pg_public" PGUID "{=rw}" ));
|
||||||
|
DESCR("Standard public namespace");
|
||||||
|
#define PG_PUBLIC_NAMESPACE 2071
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: builtins.h,v 1.173 2002/03/22 02:56:37 tgl Exp $
|
* $Id: builtins.h,v 1.174 2002/03/30 01:02:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -410,6 +410,7 @@ extern Datum text_substr(PG_FUNCTION_ARGS);
|
|||||||
extern Datum name_text(PG_FUNCTION_ARGS);
|
extern Datum name_text(PG_FUNCTION_ARGS);
|
||||||
extern Datum text_name(PG_FUNCTION_ARGS);
|
extern Datum text_name(PG_FUNCTION_ARGS);
|
||||||
extern int varstr_cmp(char *arg1, int len1, char *arg2, int len2);
|
extern int varstr_cmp(char *arg1, int len1, char *arg2, int len2);
|
||||||
|
extern List *textToQualifiedNameList(text *textval, const char *caller);
|
||||||
|
|
||||||
extern Datum byteain(PG_FUNCTION_ARGS);
|
extern Datum byteain(PG_FUNCTION_ARGS);
|
||||||
extern Datum byteaout(PG_FUNCTION_ARGS);
|
extern Datum byteaout(PG_FUNCTION_ARGS);
|
||||||
|
@ -216,7 +216,6 @@ INSERT INTO tmp VALUES (null, 'Y', null);
|
|||||||
INSERT INTO tmp VALUES (5, '!check failed', null);
|
INSERT INTO tmp VALUES (5, '!check failed', null);
|
||||||
INSERT INTO tmp VALUES (null, 'try again', null);
|
INSERT INTO tmp VALUES (null, 'try again', null);
|
||||||
INSERT INTO INSERT_TBL(y) select yd from tmp;
|
INSERT INTO INSERT_TBL(y) select yd from tmp;
|
||||||
WARNING: insert_seq.nextval: sequence was re-created
|
|
||||||
SELECT '' AS three, * FROM INSERT_TBL;
|
SELECT '' AS three, * FROM INSERT_TBL;
|
||||||
three | x | y | z
|
three | x | y | z
|
||||||
-------+---+---------------+----
|
-------+---+---------------+----
|
||||||
|
Loading…
x
Reference in New Issue
Block a user