Commit 5f4745ad authored by Tom Lane's avatar Tom Lane

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.
parent 25004eec
......@@ -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(NAME) RETURNS FLOAT8
pgstattuple(TEXT) RETURNS FLOAT8
The argument is the table name. pgstattuple returns the percentage
of the "dead" tuples of a table.
......
/*
* $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
*
......@@ -27,6 +27,9 @@
#include "fmgr.h"
#include "access/heapam.h"
#include "access/transam.h"
#include "catalog/namespace.h"
#include "utils/builtins.h"
PG_FUNCTION_INFO_V1(pgstattuple);
......@@ -43,8 +46,8 @@ extern Datum pgstattuple(PG_FUNCTION_ARGS);
Datum
pgstattuple(PG_FUNCTION_ARGS)
{
Name p = PG_GETARG_NAME(0);
text *relname = PG_GETARG_TEXT_P(0);
RangeVar *relrv;
Relation rel;
HeapScanDesc scan;
HeapTuple tuple;
......@@ -59,11 +62,13 @@ pgstattuple(PG_FUNCTION_ARGS)
uint64 dead_tuple_count = 0;
double tuple_percent;
double dead_tuple_percent;
uint64 free_space = 0; /* free/reusable space in bytes */
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);
scan = heap_beginscan(rel, false, SnapshotAny, 0, NULL);
......
DROP FUNCTION pgstattuple(NAME);
CREATE FUNCTION pgstattuple(NAME) RETURNS FLOAT8
DROP FUNCTION pgstattuple(text);
CREATE FUNCTION pgstattuple(text) RETURNS float8
AS 'MODULE_PATHNAME', 'pgstattuple'
LANGUAGE 'c' WITH (isstrict);
......@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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
* Given a RangeVar describing a to-be-created relation,
* 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
RangeVarGetCreationNamespace(const RangeVar *newRelation)
......@@ -126,6 +130,21 @@ RelnameGetRelid(const char *relname)
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
* Given a possibly-qualified name for an object (in List-of-Values
......
......@@ -8,7 +8,7 @@
*
*
* 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
* The PerformAddAttribute() code, like most of the relation
......@@ -1755,13 +1755,13 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
tupdesc->attrs[2]->attstorage = 'p';
/*
* Note: the toast relation is considered a "normal" relation even if
* its master relation is a temp table. There cannot be any naming
* collision, and the toast rel will be destroyed when its master is,
* so there's no need to handle the toast rel as temp.
* Note: the toast relation is placed in the regular pg_toast namespace
* even if its master relation is a temp table. There cannot be any
* naming collision, and the toast rel will be destroyed when its master
* is, so there's no need to handle the toast rel as temp.
*/
toast_relid = heap_create_with_catalog(toast_relname,
RelationGetNamespace(rel),
PG_TOAST_NAMESPACE,
tupdesc,
RELKIND_TOASTVALUE, false,
false, true);
......
This diff is collapsed.
......@@ -8,14 +8,13 @@
*
*
* 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 "catalog/namespace.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
......@@ -132,6 +131,7 @@ LookupTypeName(const TypeName *typename)
if (schemaname)
{
/* Look in specific schema only */
Oid namespaceId;
namespaceId = GetSysCacheOid(NAMESPACENAME,
......@@ -147,11 +147,8 @@ LookupTypeName(const TypeName *typename)
}
else
{
/* XXX wrong, should use namespace search */
restype = GetSysCacheOid(TYPENAMENSP,
PointerGetDatum(typname),
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
0, 0);
/* Unqualified type name, so search the search path */
restype = TypenameGetTypid(typname);
}
}
......
......@@ -8,7 +8,7 @@
*
*
* 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 "access/heapam.h"
#include "catalog/namespace.h"
#include "utils/builtins.h"
static int my_varattno(Relation rd, char *a);
......@@ -39,43 +41,39 @@ int4notin(PG_FUNCTION_ARGS)
{
int32 not_in_arg = PG_GETARG_INT32(0);
text *relation_and_attr = PG_GETARG_TEXT_P(1);
List *names;
int nnames;
RangeVar *relrv;
char *attribute;
Relation relation_to_scan;
int32 integer_value;
HeapTuple current_tuple;
HeapScanDesc scan_descriptor;
bool isNull,
retval;
int attrid,
strlength;
char *relation,
*attribute;
char my_copy[NAMEDATALEN * 2 + 2];
int attrid;
Datum value;
/* make a null-terminated copy of text */
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';
/* Parse the argument */
relation = (char *) strtok(my_copy, ".");
attribute = (char *) strtok(NULL, ".");
if (attribute == NULL)
names = textToQualifiedNameList(relation_and_attr, "int4notin");
nnames = length(names);
if (nnames < 2)
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 */
relation_to_scan = heap_openr(relation, AccessShareLock);
relation_to_scan = heap_openrv(relrv, AccessShareLock);
/* Find the column to search */
attrid = my_varattno(relation_to_scan, attribute);
if (attrid < 0)
{
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,
0, (ScanKey) NULL);
......
......@@ -8,7 +8,7 @@
*
*
* 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
* input routine largely stolen from boxin().
......@@ -19,6 +19,7 @@
#include "postgres.h"
#include "access/heapam.h"
#include "catalog/namespace.h"
#include "utils/builtins.h"
#define DatumGetItemPointer(X) ((ItemPointer) DatumGetPointer(X))
......@@ -146,14 +147,13 @@ currtid_byreloid(PG_FUNCTION_ARGS)
*result = Current_last_tid;
PG_RETURN_ITEMPOINTER(result);
}
rel = heap_open(reloid, AccessShareLock);
ItemPointerCopy(tid, result);
if ((rel = heap_open(reloid, AccessShareLock)) != NULL)
{
heap_get_latest_tid(rel, SnapshotNow, result);
heap_close(rel, AccessShareLock);
}
else
elog(ERROR, "Relation %u not found", reloid);
heap_get_latest_tid(rel, SnapshotNow, result);
heap_close(rel, AccessShareLock);
PG_RETURN_ITEMPOINTER(result);
}
......@@ -164,23 +164,19 @@ currtid_byrelname(PG_FUNCTION_ARGS)
text *relname = PG_GETARG_TEXT_P(0);
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
ItemPointer result;
char *str;
RangeVar *relrv;
Relation rel;
str = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(relname)));
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
"currtid_byrelname"));
rel = heap_openrv(relrv, AccessShareLock);
result = (ItemPointer) palloc(sizeof(ItemPointerData));
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);
}
......@@ -8,7 +8,7 @@
*
*
* 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
*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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 TypenameGetTypid(const char *typname);
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
extern RangeVar *makeRangeVarFromNameList(List *names);
......
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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
* 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}" ));
DESCR("System catalog namespace");
#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) 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 text_name(PG_FUNCTION_ARGS);
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 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 (null, 'try again', null);
INSERT INTO INSERT_TBL(y) select yd from tmp;
WARNING: insert_seq.nextval: sequence was re-created
SELECT '' AS three, * FROM INSERT_TBL;
three | x | y | z
-------+---+---------------+----
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment