mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
pgindent run.
This commit is contained in:
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.4 2002/08/22 00:01:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.5 2002/09/04 20:31:14 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -110,8 +110,8 @@ DefineAggregate(List *names, List *parameters)
|
||||
* We have historically allowed the command to look like basetype = 'ANY'
|
||||
* so we must do a case-insensitive comparison for the name ANY. Ugh.
|
||||
*
|
||||
* basetype can be a pseudo-type, but transtype can't, since we need
|
||||
* to be able to store values of the transtype.
|
||||
* basetype can be a pseudo-type, but transtype can't, since we need to
|
||||
* be able to store values of the transtype.
|
||||
*/
|
||||
if (strcasecmp(TypeNameToString(baseType), "ANY") == 0)
|
||||
baseTypeId = ANYOID;
|
||||
@ -127,10 +127,10 @@ DefineAggregate(List *names, List *parameters)
|
||||
* Most of the argument-checking is done inside of AggregateCreate
|
||||
*/
|
||||
AggregateCreate(aggName, /* aggregate name */
|
||||
aggNamespace, /* namespace */
|
||||
aggNamespace, /* namespace */
|
||||
transfuncName, /* step function name */
|
||||
finalfuncName, /* final function name */
|
||||
baseTypeId, /* type of data being aggregated */
|
||||
baseTypeId, /* type of data being aggregated */
|
||||
transTypeId, /* transition data type */
|
||||
initval); /* initial condition */
|
||||
}
|
||||
@ -154,8 +154,8 @@ RemoveAggregate(RemoveAggrStmt *stmt)
|
||||
* if a basetype is passed in, then attempt to find an aggregate for
|
||||
* that specific type.
|
||||
*
|
||||
* else attempt to find an aggregate with a basetype of ANYOID.
|
||||
* This means that the aggregate is to apply to all basetypes (eg, COUNT).
|
||||
* else attempt to find an aggregate with a basetype of ANYOID. This
|
||||
* means that the aggregate is to apply to all basetypes (eg, COUNT).
|
||||
*/
|
||||
if (aggType)
|
||||
basetypeID = typenameTypeId(aggType);
|
||||
@ -170,7 +170,7 @@ RemoveAggregate(RemoveAggrStmt *stmt)
|
||||
tup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(procOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveAggregate: couldn't find pg_proc tuple for %s",
|
||||
NameListToString(aggName));
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.45 2002/08/26 18:45:57 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.46 2002/09/04 20:31:14 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -110,10 +110,10 @@ typedef struct
|
||||
|
||||
|
||||
/* Default statistics target (GUC parameter) */
|
||||
int default_statistics_target = 10;
|
||||
int default_statistics_target = 10;
|
||||
|
||||
|
||||
static int elevel = -1;
|
||||
static int elevel = -1;
|
||||
|
||||
static MemoryContext anl_context = NULL;
|
||||
|
||||
@ -163,9 +163,9 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
|
||||
elevel = DEBUG1;
|
||||
|
||||
/*
|
||||
* Use the current context for storing analysis info. vacuum.c ensures
|
||||
* that this context will be cleared when I return, thus releasing the
|
||||
* memory allocated here.
|
||||
* Use the current context for storing analysis info. vacuum.c
|
||||
* ensures that this context will be cleared when I return, thus
|
||||
* releasing the memory allocated here.
|
||||
*/
|
||||
anl_context = CurrentMemoryContext;
|
||||
|
||||
@ -219,7 +219,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
|
||||
* We can ANALYZE any table except pg_statistic. See update_attstats
|
||||
*/
|
||||
if (IsSystemNamespace(RelationGetNamespace(onerel)) &&
|
||||
strcmp(RelationGetRelationName(onerel), StatisticRelationName) == 0)
|
||||
strcmp(RelationGetRelationName(onerel), StatisticRelationName) == 0)
|
||||
{
|
||||
relation_close(onerel, AccessShareLock);
|
||||
return;
|
||||
@ -1042,11 +1042,15 @@ compute_minimal_stats(VacAttrStats *stats,
|
||||
*/
|
||||
int f1 = nonnull_cnt - summultiple;
|
||||
int d = f1 + nmultiple;
|
||||
double numer, denom, stadistinct;
|
||||
double numer,
|
||||
denom,
|
||||
stadistinct;
|
||||
|
||||
numer = (double) numrows *(double) d;
|
||||
|
||||
numer = (double) numrows * (double) d;
|
||||
denom = (double) (numrows - f1) +
|
||||
(double) f1 * (double) numrows / totalrows;
|
||||
(double) f1 *(double) numrows / totalrows;
|
||||
|
||||
stadistinct = numer / denom;
|
||||
/* Clamp to sane range in case of roundoff error */
|
||||
if (stadistinct < (double) d)
|
||||
@ -1361,11 +1365,15 @@ compute_scalar_stats(VacAttrStats *stats,
|
||||
*/
|
||||
int f1 = ndistinct - nmultiple + toowide_cnt;
|
||||
int d = f1 + nmultiple;
|
||||
double numer, denom, stadistinct;
|
||||
double numer,
|
||||
denom,
|
||||
stadistinct;
|
||||
|
||||
numer = (double) numrows *(double) d;
|
||||
|
||||
numer = (double) numrows * (double) d;
|
||||
denom = (double) (numrows - f1) +
|
||||
(double) f1 * (double) numrows / totalrows;
|
||||
(double) f1 *(double) numrows / totalrows;
|
||||
|
||||
stadistinct = numer / denom;
|
||||
/* Clamp to sane range in case of roundoff error */
|
||||
if (stadistinct < (double) d)
|
||||
@ -1666,7 +1674,7 @@ compare_mcvs(const void *a, const void *b)
|
||||
* relation for ANALYZE (ie, ShareUpdateExclusiveLock instead
|
||||
* of AccessShareLock); but that cure seems worse than the disease,
|
||||
* especially now that ANALYZE doesn't start a new transaction
|
||||
* for each relation. The lock could be held for a long time...
|
||||
* for each relation. The lock could be held for a long time...
|
||||
*/
|
||||
static void
|
||||
update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.89 2002/09/03 01:04:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.90 2002/09/04 20:31:14 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -60,7 +60,7 @@ static void swap_relfilenodes(Oid r1, Oid r2);
|
||||
*
|
||||
* This clusters the table by creating a new, clustered table and
|
||||
* swapping the relfilenodes of the new table and the old table, so
|
||||
* the OID of the original table is preserved. Thus we do not lose
|
||||
* the OID of the original table is preserved. Thus we do not lose
|
||||
* GRANT, inheritance nor references to this table (this was a bug
|
||||
* in releases thru 7.3).
|
||||
*
|
||||
@ -111,11 +111,11 @@ cluster(RangeVar *oldrelation, char *oldindexname)
|
||||
RelationGetRelationName(OldHeap));
|
||||
|
||||
/*
|
||||
* Disallow clustering system relations. This will definitely NOT work
|
||||
* for shared relations (we have no way to update pg_class rows in other
|
||||
* databases), nor for nailed-in-cache relations (the relfilenode values
|
||||
* for those are hardwired, see relcache.c). It might work for other
|
||||
* system relations, but I ain't gonna risk it.
|
||||
* Disallow clustering system relations. This will definitely NOT
|
||||
* work for shared relations (we have no way to update pg_class rows
|
||||
* in other databases), nor for nailed-in-cache relations (the
|
||||
* relfilenode values for those are hardwired, see relcache.c). It
|
||||
* might work for other system relations, but I ain't gonna risk it.
|
||||
*/
|
||||
if (IsSystemRelation(OldHeap))
|
||||
elog(ERROR, "CLUSTER: cannot cluster system relation \"%s\"",
|
||||
@ -130,16 +130,20 @@ cluster(RangeVar *oldrelation, char *oldindexname)
|
||||
|
||||
/*
|
||||
* Create the new heap, using a temporary name in the same namespace
|
||||
* as the existing table. NOTE: there is some risk of collision with user
|
||||
* relnames. Working around this seems more trouble than it's worth; in
|
||||
* particular, we can't create the new heap in a different namespace from
|
||||
* the old, or we will have problems with the TEMP status of temp tables.
|
||||
* as the existing table. NOTE: there is some risk of collision with
|
||||
* user relnames. Working around this seems more trouble than it's
|
||||
* worth; in particular, we can't create the new heap in a different
|
||||
* namespace from the old, or we will have problems with the TEMP
|
||||
* status of temp tables.
|
||||
*/
|
||||
snprintf(NewHeapName, NAMEDATALEN, "pg_temp_%u", OIDOldHeap);
|
||||
|
||||
OIDNewHeap = make_new_heap(OIDOldHeap, NewHeapName);
|
||||
|
||||
/* We don't need CommandCounterIncrement() because make_new_heap did it. */
|
||||
/*
|
||||
* We don't need CommandCounterIncrement() because make_new_heap did
|
||||
* it.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copy the heap data into the new table in the desired order.
|
||||
@ -244,14 +248,14 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
|
||||
while ((tuple = index_getnext(scan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
/*
|
||||
* We must copy the tuple because heap_insert() will overwrite
|
||||
* the commit-status fields of the tuple it's handed, and the
|
||||
* retrieved tuple will actually be in a disk buffer! Thus,
|
||||
* the source relation would get trashed, which is bad news if
|
||||
* we abort later on. (This was a bug in releases thru 7.0)
|
||||
* We must copy the tuple because heap_insert() will overwrite the
|
||||
* commit-status fields of the tuple it's handed, and the
|
||||
* retrieved tuple will actually be in a disk buffer! Thus, the
|
||||
* source relation would get trashed, which is bad news if we
|
||||
* abort later on. (This was a bug in releases thru 7.0)
|
||||
*
|
||||
* Note that the copied tuple will have the original OID, if any,
|
||||
* so this does preserve OIDs.
|
||||
* Note that the copied tuple will have the original OID, if any, so
|
||||
* this does preserve OIDs.
|
||||
*/
|
||||
HeapTuple copiedTuple = heap_copytuple(tuple);
|
||||
|
||||
@ -276,15 +280,15 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
|
||||
static List *
|
||||
get_indexattr_list(Relation OldHeap, Oid OldIndex)
|
||||
{
|
||||
List *indexes = NIL;
|
||||
List *indexes = NIL;
|
||||
List *indlist;
|
||||
|
||||
/* Ask the relcache to produce a list of the indexes of the old rel */
|
||||
foreach(indlist, RelationGetIndexList(OldHeap))
|
||||
{
|
||||
Oid indexOID = (Oid) lfirsti(indlist);
|
||||
HeapTuple indexTuple;
|
||||
HeapTuple classTuple;
|
||||
Oid indexOID = (Oid) lfirsti(indlist);
|
||||
HeapTuple indexTuple;
|
||||
HeapTuple classTuple;
|
||||
Form_pg_index indexForm;
|
||||
Form_pg_class classForm;
|
||||
IndexAttrs *attrs;
|
||||
@ -320,7 +324,8 @@ get_indexattr_list(Relation OldHeap, Oid OldIndex)
|
||||
ReleaseSysCache(classTuple);
|
||||
ReleaseSysCache(indexTuple);
|
||||
|
||||
/* Cons the gathered data into the list. We do not care about
|
||||
/*
|
||||
* Cons the gathered data into the list. We do not care about
|
||||
* ordering, and this is more efficient than append.
|
||||
*/
|
||||
indexes = lcons(attrs, indexes);
|
||||
@ -330,13 +335,13 @@ get_indexattr_list(Relation OldHeap, Oid OldIndex)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create new indexes and swap the filenodes with old indexes. Then drop
|
||||
* Create new indexes and swap the filenodes with old indexes. Then drop
|
||||
* the new index (carrying the old index filenode along).
|
||||
*/
|
||||
static void
|
||||
recreate_indexattr(Oid OIDOldHeap, List *indexes)
|
||||
{
|
||||
List *elem;
|
||||
List *elem;
|
||||
|
||||
foreach(elem, indexes)
|
||||
{
|
||||
@ -352,13 +357,13 @@ recreate_indexattr(Oid OIDOldHeap, List *indexes)
|
||||
snprintf(newIndexName, NAMEDATALEN, "pg_temp_%u", attrs->indexOID);
|
||||
|
||||
/*
|
||||
* The new index will have primary and constraint status set to false,
|
||||
* but since we will only use its filenode it doesn't matter:
|
||||
* after the filenode swap the index will keep the constraint
|
||||
* status of the old index.
|
||||
* The new index will have primary and constraint status set to
|
||||
* false, but since we will only use its filenode it doesn't
|
||||
* matter: after the filenode swap the index will keep the
|
||||
* constraint status of the old index.
|
||||
*/
|
||||
newIndexOID = index_create(OIDOldHeap, newIndexName,
|
||||
attrs->indexInfo, attrs->accessMethodOID,
|
||||
attrs->indexInfo, attrs->accessMethodOID,
|
||||
attrs->classOID, false,
|
||||
false, allowSystemTableMods);
|
||||
CommandCounterIncrement();
|
||||
@ -369,8 +374,8 @@ recreate_indexattr(Oid OIDOldHeap, List *indexes)
|
||||
CommandCounterIncrement();
|
||||
|
||||
/*
|
||||
* Make sure that indisclustered is correct: it should be set
|
||||
* only for the index we just clustered on.
|
||||
* Make sure that indisclustered is correct: it should be set only
|
||||
* for the index we just clustered on.
|
||||
*/
|
||||
pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
|
||||
tuple = SearchSysCacheCopy(INDEXRELID,
|
||||
@ -392,13 +397,13 @@ recreate_indexattr(Oid OIDOldHeap, List *indexes)
|
||||
object.classId = RelOid_pg_class;
|
||||
object.objectId = newIndexOID;
|
||||
object.objectSubId = 0;
|
||||
|
||||
|
||||
/*
|
||||
* The relation is local to our transaction and we know
|
||||
* nothing depends on it, so DROP_RESTRICT should be OK.
|
||||
* The relation is local to our transaction and we know nothing
|
||||
* depends on it, so DROP_RESTRICT should be OK.
|
||||
*/
|
||||
performDeletion(&object, DROP_RESTRICT);
|
||||
|
||||
|
||||
/* performDeletion does CommandCounterIncrement() at its end */
|
||||
}
|
||||
}
|
||||
@ -473,7 +478,7 @@ swap_relfilenodes(Oid r1, Oid r2)
|
||||
/* Update the tuples in pg_class */
|
||||
simple_heap_update(relRelation, &reltup1->t_self, reltup1);
|
||||
simple_heap_update(relRelation, &reltup2->t_self, reltup2);
|
||||
|
||||
|
||||
/* Keep system catalogs current */
|
||||
indstate = CatalogOpenIndexes(relRelation);
|
||||
CatalogIndexInsert(indstate, reltup1);
|
||||
@ -481,16 +486,17 @@ swap_relfilenodes(Oid r1, Oid r2)
|
||||
CatalogCloseIndexes(indstate);
|
||||
|
||||
/*
|
||||
* If we have toast tables associated with the relations being swapped,
|
||||
* change their dependency links to re-associate them with their new
|
||||
* owning relations. Otherwise the wrong one will get dropped ...
|
||||
* If we have toast tables associated with the relations being
|
||||
* swapped, change their dependency links to re-associate them with
|
||||
* their new owning relations. Otherwise the wrong one will get
|
||||
* dropped ...
|
||||
*
|
||||
* NOTE: for now, we can assume the new table will have a TOAST table
|
||||
* if and only if the old one does. This logic might need work if we
|
||||
* get smarter about dropped columns.
|
||||
* NOTE: for now, we can assume the new table will have a TOAST table if
|
||||
* and only if the old one does. This logic might need work if we get
|
||||
* smarter about dropped columns.
|
||||
*
|
||||
* NOTE: at present, a TOAST table's only dependency is the one on
|
||||
* its owning table. If more are ever created, we'd need to use something
|
||||
* NOTE: at present, a TOAST table's only dependency is the one on its
|
||||
* owning table. If more are ever created, we'd need to use something
|
||||
* more selective than deleteDependencyRecordsFor() to get rid of only
|
||||
* the link we want.
|
||||
*/
|
||||
@ -532,12 +538,12 @@ swap_relfilenodes(Oid r1, Oid r2)
|
||||
}
|
||||
|
||||
/*
|
||||
* Blow away the old relcache entries now. We need this kluge because
|
||||
* relcache.c indexes relcache entries by rd_node as well as OID.
|
||||
* It will get confused if it is asked to (re)build an entry with a new
|
||||
* Blow away the old relcache entries now. We need this kluge because
|
||||
* relcache.c indexes relcache entries by rd_node as well as OID. It
|
||||
* will get confused if it is asked to (re)build an entry with a new
|
||||
* rd_node value when there is still another entry laying about with
|
||||
* that same rd_node value. (Fortunately, since one of the entries
|
||||
* is local in our transaction, it's sufficient to clear out our own
|
||||
* that same rd_node value. (Fortunately, since one of the entries is
|
||||
* local in our transaction, it's sufficient to clear out our own
|
||||
* relcache this way; the problem cannot arise for other backends when
|
||||
* they see our update on the non-local relation.)
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.59 2002/09/02 01:05:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.60 2002/09/04 20:31:14 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -231,7 +231,7 @@ DeleteComments(Oid oid, Oid classoid, int32 subid)
|
||||
Relation description;
|
||||
ScanKeyData skey[3];
|
||||
int nkeys;
|
||||
SysScanDesc sd;
|
||||
SysScanDesc sd;
|
||||
HeapTuple oldtuple;
|
||||
|
||||
/* Use the index to search for all matching old tuples */
|
||||
@ -260,9 +260,7 @@ DeleteComments(Oid oid, Oid classoid, int32 subid)
|
||||
SnapshotNow, nkeys, skey);
|
||||
|
||||
while ((oldtuple = systable_getnext(sd)) != NULL)
|
||||
{
|
||||
simple_heap_delete(description, &oldtuple->t_self);
|
||||
}
|
||||
|
||||
/* Done */
|
||||
|
||||
@ -357,8 +355,8 @@ CommentAttribute(List *qualname, char *comment)
|
||||
nnames = length(qualname);
|
||||
if (nnames < 2)
|
||||
elog(ERROR, "CommentAttribute: must specify relation.attribute");
|
||||
relname = ltruncate(nnames-1, listCopy(qualname));
|
||||
attrname = strVal(nth(nnames-1, qualname));
|
||||
relname = ltruncate(nnames - 1, listCopy(qualname));
|
||||
attrname = strVal(nth(nnames - 1, qualname));
|
||||
|
||||
/* Open the containing relation to ensure it won't go away meanwhile */
|
||||
rel = makeRangeVarFromNameList(relname);
|
||||
@ -521,13 +519,13 @@ CommentRule(List *qualname, char *comment)
|
||||
else
|
||||
{
|
||||
elog(ERROR, "rule \"%s\" does not exist", rulename);
|
||||
reloid = ruleoid = 0; /* keep compiler quiet */
|
||||
reloid = ruleoid = 0; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
if (HeapTupleIsValid(tuple = heap_getnext(scanDesc,
|
||||
ForwardScanDirection)))
|
||||
elog(ERROR, "There are multiple rules \"%s\""
|
||||
"\n\tPlease specify a relation name as well as a rule name",
|
||||
"\n\tPlease specify a relation name as well as a rule name",
|
||||
rulename);
|
||||
|
||||
heap_endscan(scanDesc);
|
||||
@ -540,8 +538,8 @@ CommentRule(List *qualname, char *comment)
|
||||
{
|
||||
/* New-style: rule and relname both provided */
|
||||
Assert(nnames >= 2);
|
||||
relname = ltruncate(nnames-1, listCopy(qualname));
|
||||
rulename = strVal(nth(nnames-1, qualname));
|
||||
relname = ltruncate(nnames - 1, listCopy(qualname));
|
||||
rulename = strVal(nth(nnames - 1, qualname));
|
||||
|
||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||
rel = makeRangeVarFromNameList(relname);
|
||||
@ -724,7 +722,7 @@ CommentTrigger(List *qualname, char *comment)
|
||||
Relation pg_trigger,
|
||||
relation;
|
||||
HeapTuple triggertuple;
|
||||
SysScanDesc scan;
|
||||
SysScanDesc scan;
|
||||
ScanKeyData entry[2];
|
||||
Oid oid;
|
||||
|
||||
@ -732,8 +730,8 @@ CommentTrigger(List *qualname, char *comment)
|
||||
nnames = length(qualname);
|
||||
if (nnames < 2)
|
||||
elog(ERROR, "CommentTrigger: must specify relation and trigger");
|
||||
relname = ltruncate(nnames-1, listCopy(qualname));
|
||||
trigname = strVal(nth(nnames-1, qualname));
|
||||
relname = ltruncate(nnames - 1, listCopy(qualname));
|
||||
trigname = strVal(nth(nnames - 1, qualname));
|
||||
|
||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||
rel = makeRangeVarFromNameList(relname);
|
||||
@ -799,7 +797,7 @@ CommentConstraint(List *qualname, char *comment)
|
||||
Relation pg_constraint,
|
||||
relation;
|
||||
HeapTuple tuple;
|
||||
SysScanDesc scan;
|
||||
SysScanDesc scan;
|
||||
ScanKeyData skey[1];
|
||||
Oid conOid = InvalidOid;
|
||||
|
||||
@ -807,8 +805,8 @@ CommentConstraint(List *qualname, char *comment)
|
||||
nnames = length(qualname);
|
||||
if (nnames < 2)
|
||||
elog(ERROR, "CommentConstraint: must specify relation and constraint");
|
||||
relName = ltruncate(nnames-1, listCopy(qualname));
|
||||
conName = strVal(nth(nnames-1, qualname));
|
||||
relName = ltruncate(nnames - 1, listCopy(qualname));
|
||||
conName = strVal(nth(nnames - 1, qualname));
|
||||
|
||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||
rel = makeRangeVarFromNameList(relName);
|
||||
@ -820,9 +818,9 @@ CommentConstraint(List *qualname, char *comment)
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation));
|
||||
|
||||
/*
|
||||
* Fetch the constraint tuple from pg_constraint. There may be more than
|
||||
* one match, because constraints are not required to have unique names;
|
||||
* if so, error out.
|
||||
* Fetch the constraint tuple from pg_constraint. There may be more
|
||||
* than one match, because constraints are not required to have unique
|
||||
* names; if so, error out.
|
||||
*/
|
||||
pg_constraint = heap_openr(ConstraintRelationName, AccessShareLock);
|
||||
|
||||
@ -835,7 +833,7 @@ CommentConstraint(List *qualname, char *comment)
|
||||
|
||||
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
|
||||
{
|
||||
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
|
||||
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
|
||||
|
||||
if (strcmp(NameStr(con->conname), conName) == 0)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.3 2002/08/22 00:01:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.4 2002/09/04 20:31:14 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -33,19 +33,19 @@ void
|
||||
CreateConversionCommand(CreateConversionStmt *stmt)
|
||||
{
|
||||
Oid namespaceId;
|
||||
char *conversion_name;
|
||||
char *conversion_name;
|
||||
AclResult aclresult;
|
||||
int for_encoding;
|
||||
int to_encoding;
|
||||
Oid funcoid;
|
||||
Oid funcnamespace;
|
||||
char *dummy;
|
||||
char *dummy;
|
||||
|
||||
const char *for_encoding_name = stmt->for_encoding_name;
|
||||
const char *to_encoding_name = stmt->to_encoding_name;
|
||||
List *func_name = stmt->func_name;
|
||||
List *func_name = stmt->func_name;
|
||||
|
||||
static Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, CSTRINGOID, INT4OID};
|
||||
static Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, CSTRINGOID, INT4OID};
|
||||
|
||||
/* Convert list of names to a name and namespace */
|
||||
namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name, &conversion_name);
|
||||
@ -64,10 +64,11 @@ CreateConversionCommand(CreateConversionStmt *stmt)
|
||||
if (to_encoding < 0)
|
||||
elog(ERROR, "Invalid to encoding name: %s", to_encoding_name);
|
||||
|
||||
/* Check the existence of the conversion function.
|
||||
* Function name could be a qualified name.
|
||||
/*
|
||||
* Check the existence of the conversion function. Function name could
|
||||
* be a qualified name.
|
||||
*/
|
||||
funcoid = LookupFuncName(func_name, sizeof(funcargs)/sizeof(Oid), funcargs);
|
||||
funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid), funcargs);
|
||||
if (!OidIsValid(funcoid))
|
||||
elog(ERROR, "Function %s does not exist", NameListToString(func_name));
|
||||
|
||||
@ -80,8 +81,11 @@ CreateConversionCommand(CreateConversionStmt *stmt)
|
||||
aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(funcnamespace));
|
||||
|
||||
/* All seem ok, go ahead (possible failure would be a duplicate conversion name) */
|
||||
|
||||
/*
|
||||
* All seem ok, go ahead (possible failure would be a duplicate
|
||||
* conversion name)
|
||||
*/
|
||||
ConversionCreate(conversion_name, namespaceId, GetUserId(),
|
||||
for_encoding, to_encoding, funcoid, stmt->def);
|
||||
}
|
||||
@ -93,7 +97,7 @@ void
|
||||
DropConversionCommand(List *name, DropBehavior behavior)
|
||||
{
|
||||
Oid namespaceId;
|
||||
char *conversion_name;
|
||||
char *conversion_name;
|
||||
AclResult aclresult;
|
||||
|
||||
/* Convert list of names to a name and namespace */
|
||||
@ -104,9 +108,9 @@ DropConversionCommand(List *name, DropBehavior behavior)
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceId));
|
||||
|
||||
/* Go ahead (possible failure would be:
|
||||
* none existing conversion
|
||||
* not ower of this conversion
|
||||
/*
|
||||
* Go ahead (possible failure would be: none existing conversion not
|
||||
* ower of this conversion
|
||||
*/
|
||||
ConversionDrop(conversion_name, namespaceId, GetUserId(), behavior);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.170 2002/09/02 01:05:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.171 2002/09/04 20:31:14 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,9 +53,9 @@ typedef enum CopyReadResult
|
||||
|
||||
/* non-export function prototypes */
|
||||
static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
FILE *fp, char *delim, char *null_print);
|
||||
FILE *fp, char *delim, char *null_print);
|
||||
static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
FILE *fp, char *delim, char *null_print);
|
||||
FILE *fp, char *delim, char *null_print);
|
||||
static Oid GetInputFunction(Oid type);
|
||||
static Oid GetTypeElement(Oid type);
|
||||
static char *CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result);
|
||||
@ -268,17 +268,17 @@ CopyDonePeek(FILE *fp, int c, bool pickup)
|
||||
void
|
||||
DoCopy(const CopyStmt *stmt)
|
||||
{
|
||||
RangeVar *relation = stmt->relation;
|
||||
char *filename = stmt->filename;
|
||||
bool is_from = stmt->is_from;
|
||||
bool pipe = (stmt->filename == NULL);
|
||||
List *option;
|
||||
List *attnamelist = stmt->attlist;
|
||||
List *attnumlist;
|
||||
bool binary = false;
|
||||
bool oids = false;
|
||||
char *delim = NULL;
|
||||
char *null_print = NULL;
|
||||
RangeVar *relation = stmt->relation;
|
||||
char *filename = stmt->filename;
|
||||
bool is_from = stmt->is_from;
|
||||
bool pipe = (stmt->filename == NULL);
|
||||
List *option;
|
||||
List *attnamelist = stmt->attlist;
|
||||
List *attnumlist;
|
||||
bool binary = false;
|
||||
bool oids = false;
|
||||
char *delim = NULL;
|
||||
char *null_print = NULL;
|
||||
FILE *fp;
|
||||
Relation rel;
|
||||
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
|
||||
@ -336,7 +336,7 @@ DoCopy(const CopyStmt *stmt)
|
||||
|
||||
if (!null_print)
|
||||
null_print = "\\N";
|
||||
|
||||
|
||||
/*
|
||||
* Open and lock the relation, using the appropriate lock type.
|
||||
*/
|
||||
@ -512,8 +512,8 @@ DoCopy(const CopyStmt *stmt)
|
||||
* Copy from relation TO file.
|
||||
*/
|
||||
static void
|
||||
CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
FILE *fp, char *delim, char *null_print)
|
||||
CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
FILE *fp, char *delim, char *null_print)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
TupleDesc tupDesc;
|
||||
@ -537,24 +537,23 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
/*
|
||||
* Get info about the columns we need to process.
|
||||
*
|
||||
* For binary copy we really only need isvarlena, but compute it
|
||||
* all...
|
||||
* For binary copy we really only need isvarlena, but compute it all...
|
||||
*/
|
||||
out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
|
||||
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
|
||||
isvarlena = (bool *) palloc(num_phys_attrs * sizeof(bool));
|
||||
foreach(cur, attnumlist)
|
||||
{
|
||||
int attnum = lfirsti(cur);
|
||||
int attnum = lfirsti(cur);
|
||||
Oid out_func_oid;
|
||||
|
||||
if (!getTypeOutputInfo(attr[attnum-1]->atttypid,
|
||||
&out_func_oid, &elements[attnum-1],
|
||||
&isvarlena[attnum-1]))
|
||||
if (!getTypeOutputInfo(attr[attnum - 1]->atttypid,
|
||||
&out_func_oid, &elements[attnum - 1],
|
||||
&isvarlena[attnum - 1]))
|
||||
elog(ERROR, "COPY: couldn't lookup info for type %u",
|
||||
attr[attnum-1]->atttypid);
|
||||
fmgr_info(out_func_oid, &out_functions[attnum-1]);
|
||||
if (binary && attr[attnum-1]->attlen == -2)
|
||||
attr[attnum - 1]->atttypid);
|
||||
fmgr_info(out_func_oid, &out_functions[attnum - 1]);
|
||||
if (binary && attr[attnum - 1]->attlen == -2)
|
||||
elog(ERROR, "COPY BINARY: cstring not supported");
|
||||
}
|
||||
|
||||
@ -597,7 +596,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
/* Send OID if wanted --- note fld_count doesn't include it */
|
||||
if (oids)
|
||||
{
|
||||
Oid oid = HeapTupleGetOid(tuple);
|
||||
Oid oid = HeapTupleGetOid(tuple);
|
||||
|
||||
fld_size = sizeof(Oid);
|
||||
CopySendData(&fld_size, sizeof(int16), fp);
|
||||
@ -610,7 +609,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
if (oids)
|
||||
{
|
||||
string = DatumGetCString(DirectFunctionCall1(oidout,
|
||||
ObjectIdGetDatum(HeapTupleGetOid(tuple))));
|
||||
ObjectIdGetDatum(HeapTupleGetOid(tuple))));
|
||||
CopySendString(string, fp);
|
||||
pfree(string);
|
||||
need_delim = true;
|
||||
@ -619,7 +618,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
|
||||
foreach(cur, attnumlist)
|
||||
{
|
||||
int attnum = lfirsti(cur);
|
||||
int attnum = lfirsti(cur);
|
||||
Datum origvalue,
|
||||
value;
|
||||
bool isnull;
|
||||
@ -653,25 +652,25 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
* (or for binary case, becase we must output untoasted
|
||||
* value).
|
||||
*/
|
||||
if (isvarlena[attnum-1])
|
||||
if (isvarlena[attnum - 1])
|
||||
value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
|
||||
else
|
||||
value = origvalue;
|
||||
|
||||
if (!binary)
|
||||
{
|
||||
string = DatumGetCString(FunctionCall3(&out_functions[attnum-1],
|
||||
string = DatumGetCString(FunctionCall3(&out_functions[attnum - 1],
|
||||
value,
|
||||
ObjectIdGetDatum(elements[attnum-1]),
|
||||
Int32GetDatum(attr[attnum-1]->atttypmod)));
|
||||
ObjectIdGetDatum(elements[attnum - 1]),
|
||||
Int32GetDatum(attr[attnum - 1]->atttypmod)));
|
||||
CopyAttributeOut(fp, string, delim);
|
||||
pfree(string);
|
||||
}
|
||||
else
|
||||
{
|
||||
fld_size = attr[attnum-1]->attlen;
|
||||
fld_size = attr[attnum - 1]->attlen;
|
||||
CopySendData(&fld_size, sizeof(int16), fp);
|
||||
if (isvarlena[attnum-1])
|
||||
if (isvarlena[attnum - 1])
|
||||
{
|
||||
/* varlena */
|
||||
Assert(fld_size == -1);
|
||||
@ -679,7 +678,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
VARSIZE(value),
|
||||
fp);
|
||||
}
|
||||
else if (!attr[attnum-1]->attbyval)
|
||||
else if (!attr[attnum - 1]->attbyval)
|
||||
{
|
||||
/* fixed-length pass-by-reference */
|
||||
Assert(fld_size > 0);
|
||||
@ -734,13 +733,15 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
* Copy FROM file to relation.
|
||||
*/
|
||||
static void
|
||||
CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
FILE *fp, char *delim, char *null_print)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
TupleDesc tupDesc;
|
||||
Form_pg_attribute *attr;
|
||||
AttrNumber num_phys_attrs, attr_count, num_defaults;
|
||||
AttrNumber num_phys_attrs,
|
||||
attr_count,
|
||||
num_defaults;
|
||||
FmgrInfo *in_functions;
|
||||
Oid *elements;
|
||||
int i;
|
||||
@ -755,8 +756,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
TupleTableSlot *slot;
|
||||
bool file_has_oids;
|
||||
int *defmap;
|
||||
Node **defexprs; /* array of default att expressions */
|
||||
ExprContext *econtext; /* used for ExecEvalExpr for default atts */
|
||||
Node **defexprs; /* array of default att expressions */
|
||||
ExprContext *econtext; /* used for ExecEvalExpr for default atts */
|
||||
MemoryContext oldcontext = CurrentMemoryContext;
|
||||
|
||||
tupDesc = RelationGetDescr(rel);
|
||||
@ -787,9 +788,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
ExecSetSlotDescriptor(slot, tupDesc, false);
|
||||
|
||||
/*
|
||||
* pick up the input function and default expression (if any) for
|
||||
* each attribute in the relation. (We don't actually use the
|
||||
* input function if it's a binary copy.)
|
||||
* pick up the input function and default expression (if any) for each
|
||||
* attribute in the relation. (We don't actually use the input
|
||||
* function if it's a binary copy.)
|
||||
*/
|
||||
defmap = (int *) palloc(sizeof(int) * num_phys_attrs);
|
||||
defexprs = (Node **) palloc(sizeof(Node *) * num_phys_attrs);
|
||||
@ -874,13 +875,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
|
||||
while (!done)
|
||||
{
|
||||
bool skip_tuple;
|
||||
Oid loaded_oid = InvalidOid;
|
||||
bool skip_tuple;
|
||||
Oid loaded_oid = InvalidOid;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
copy_lineno++;
|
||||
|
||||
|
||||
/* Reset the per-tuple exprcontext */
|
||||
ResetPerTupleExprContext(estate);
|
||||
|
||||
@ -894,8 +895,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
|
||||
if (!binary)
|
||||
{
|
||||
CopyReadResult result = NORMAL_ATTR;
|
||||
char *string;
|
||||
CopyReadResult result = NORMAL_ATTR;
|
||||
char *string;
|
||||
|
||||
if (file_has_oids)
|
||||
{
|
||||
@ -918,14 +919,14 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
elog(ERROR, "Invalid Oid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Loop to read the user attributes on the line.
|
||||
*/
|
||||
foreach(cur, attnumlist)
|
||||
{
|
||||
int attnum = lfirsti(cur);
|
||||
int m = attnum - 1;
|
||||
int attnum = lfirsti(cur);
|
||||
int m = attnum - 1;
|
||||
|
||||
/*
|
||||
* If prior attr on this line was ended by newline or EOF,
|
||||
@ -953,8 +954,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
{
|
||||
values[m] = FunctionCall3(&in_functions[m],
|
||||
CStringGetDatum(string),
|
||||
ObjectIdGetDatum(elements[m]),
|
||||
Int32GetDatum(attr[m]->atttypmod));
|
||||
ObjectIdGetDatum(elements[m]),
|
||||
Int32GetDatum(attr[m]->atttypmod));
|
||||
nulls[m] = ' ';
|
||||
}
|
||||
}
|
||||
@ -1009,7 +1010,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
i = 0;
|
||||
foreach(cur, attnumlist)
|
||||
{
|
||||
int attnum = lfirsti(cur);
|
||||
int attnum = lfirsti(cur);
|
||||
|
||||
i++;
|
||||
|
||||
@ -1018,9 +1019,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
||||
if (fld_size == 0)
|
||||
continue; /* it's NULL; nulls[attnum-1] already set */
|
||||
if (fld_size != attr[attnum-1]->attlen)
|
||||
if (fld_size != attr[attnum - 1]->attlen)
|
||||
elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d",
|
||||
i, (int) fld_size, (int) attr[attnum-1]->attlen);
|
||||
i, (int) fld_size, (int) attr[attnum - 1]->attlen);
|
||||
if (fld_size == -1)
|
||||
{
|
||||
/* varlena field */
|
||||
@ -1039,9 +1040,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
fp);
|
||||
if (CopyGetEof(fp))
|
||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
||||
values[attnum-1] = PointerGetDatum(varlena_ptr);
|
||||
values[attnum - 1] = PointerGetDatum(varlena_ptr);
|
||||
}
|
||||
else if (!attr[attnum-1]->attbyval)
|
||||
else if (!attr[attnum - 1]->attbyval)
|
||||
{
|
||||
/* fixed-length pass-by-reference */
|
||||
Pointer refval_ptr;
|
||||
@ -1051,7 +1052,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
CopyGetData(refval_ptr, fld_size, fp);
|
||||
if (CopyGetEof(fp))
|
||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
||||
values[attnum-1] = PointerGetDatum(refval_ptr);
|
||||
values[attnum - 1] = PointerGetDatum(refval_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1059,29 +1060,28 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
Datum datumBuf;
|
||||
|
||||
/*
|
||||
* We need this horsing around because we don't
|
||||
* know how shorter data values are aligned within
|
||||
* a Datum.
|
||||
* We need this horsing around because we don't know
|
||||
* how shorter data values are aligned within a Datum.
|
||||
*/
|
||||
Assert(fld_size > 0 && fld_size <= sizeof(Datum));
|
||||
CopyGetData(&datumBuf, fld_size, fp);
|
||||
if (CopyGetEof(fp))
|
||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
||||
values[attnum-1] = fetch_att(&datumBuf, true, fld_size);
|
||||
values[attnum - 1] = fetch_att(&datumBuf, true, fld_size);
|
||||
}
|
||||
|
||||
nulls[attnum-1] = ' ';
|
||||
nulls[attnum - 1] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now compute and insert any defaults available for the
|
||||
* columns not provided by the input data. Anything not
|
||||
* processed here or above will remain NULL.
|
||||
* Now compute and insert any defaults available for the columns
|
||||
* not provided by the input data. Anything not processed here or
|
||||
* above will remain NULL.
|
||||
*/
|
||||
for (i = 0; i < num_defaults; i++)
|
||||
{
|
||||
bool isnull;
|
||||
bool isnull;
|
||||
|
||||
values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
|
||||
&isnull, NULL);
|
||||
@ -1093,7 +1093,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
* And now we can form the input tuple.
|
||||
*/
|
||||
tuple = heap_formtuple(tupDesc, values, nulls);
|
||||
|
||||
|
||||
if (oids && file_has_oids)
|
||||
HeapTupleSetOid(tuple, loaded_oid);
|
||||
|
||||
@ -1464,14 +1464,14 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
|
||||
static List *
|
||||
CopyGetAttnums(Relation rel, List *attnamelist)
|
||||
{
|
||||
List *attnums = NIL;
|
||||
List *attnums = NIL;
|
||||
|
||||
if (attnamelist == NIL)
|
||||
{
|
||||
/* Generate default column list */
|
||||
TupleDesc tupDesc = RelationGetDescr(rel);
|
||||
TupleDesc tupDesc = RelationGetDescr(rel);
|
||||
Form_pg_attribute *attr = tupDesc->attrs;
|
||||
int attr_count = tupDesc->natts;
|
||||
int attr_count = tupDesc->natts;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < attr_count; i++)
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.104 2002/09/03 22:17:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.105 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -79,14 +79,14 @@ createdb(const CreatedbStmt *stmt)
|
||||
int32 datdba;
|
||||
List *option;
|
||||
DefElem *downer = NULL;
|
||||
DefElem *dpath = NULL;
|
||||
DefElem *dtemplate = NULL;
|
||||
DefElem *dencoding = NULL;
|
||||
DefElem *dpath = NULL;
|
||||
DefElem *dtemplate = NULL;
|
||||
DefElem *dencoding = NULL;
|
||||
char *dbname = stmt->dbname;
|
||||
char *dbowner = NULL;
|
||||
char *dbpath = NULL;
|
||||
char *dbtemplate = NULL;
|
||||
int encoding = -1;
|
||||
int encoding = -1;
|
||||
|
||||
/* Extract options from the statement node tree */
|
||||
foreach(option, stmt->options)
|
||||
@ -133,7 +133,7 @@ createdb(const CreatedbStmt *stmt)
|
||||
|
||||
/* obtain sysid of proposed owner */
|
||||
if (dbowner)
|
||||
datdba = get_usesysid(dbowner); /* will elog if no such user */
|
||||
datdba = get_usesysid(dbowner); /* will elog if no such user */
|
||||
else
|
||||
datdba = GetUserId();
|
||||
|
||||
@ -185,7 +185,7 @@ createdb(const CreatedbStmt *stmt)
|
||||
*/
|
||||
if (!src_istemplate)
|
||||
{
|
||||
if (!superuser() && GetUserId() != src_owner )
|
||||
if (!superuser() && GetUserId() != src_owner)
|
||||
elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied",
|
||||
dbtemplate);
|
||||
}
|
||||
@ -226,10 +226,10 @@ createdb(const CreatedbStmt *stmt)
|
||||
* database), and resolve alternate physical location if one is
|
||||
* specified.
|
||||
*
|
||||
* If an alternate location is specified but is the same as the
|
||||
* normal path, just drop the alternate-location spec (this seems
|
||||
* friendlier than erroring out). We must test this case to avoid
|
||||
* creating a circular symlink below.
|
||||
* If an alternate location is specified but is the same as the normal
|
||||
* path, just drop the alternate-location spec (this seems friendlier
|
||||
* than erroring out). We must test this case to avoid creating a
|
||||
* circular symlink below.
|
||||
*/
|
||||
nominal_loc = GetDatabasePath(dboid);
|
||||
alt_loc = resolve_alt_dbpath(dbpath, dboid);
|
||||
@ -328,11 +328,12 @@ createdb(const CreatedbStmt *stmt)
|
||||
/* do not set datpath to null, GetRawDatabaseInfo won't cope */
|
||||
new_record[Anum_pg_database_datpath - 1] =
|
||||
DirectFunctionCall1(textin, CStringGetDatum(dbpath ? dbpath : ""));
|
||||
|
||||
/*
|
||||
* We deliberately set datconfig and datacl to defaults (NULL), rather
|
||||
* than copying them from the template database. Copying datacl would
|
||||
* be a bad idea when the owner is not the same as the template's owner.
|
||||
* It's more debatable whether datconfig should be copied.
|
||||
* be a bad idea when the owner is not the same as the template's
|
||||
* owner. It's more debatable whether datconfig should be copied.
|
||||
*/
|
||||
new_record_nulls[Anum_pg_database_datconfig - 1] = 'n';
|
||||
new_record_nulls[Anum_pg_database_datacl - 1] = 'n';
|
||||
@ -495,7 +496,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
||||
HeapTuple tuple,
|
||||
newtuple;
|
||||
Relation rel;
|
||||
ScanKeyData scankey;
|
||||
ScanKeyData scankey;
|
||||
HeapScanDesc scan;
|
||||
Datum repl_val[Natts_pg_database];
|
||||
char repl_null[Natts_pg_database];
|
||||
@ -512,25 +513,25 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
||||
elog(ERROR, "database \"%s\" does not exist", stmt->dbname);
|
||||
|
||||
if (!(superuser()
|
||||
|| ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId()))
|
||||
|| ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId()))
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
MemSet(repl_repl, ' ', sizeof(repl_repl));
|
||||
repl_repl[Anum_pg_database_datconfig-1] = 'r';
|
||||
repl_repl[Anum_pg_database_datconfig - 1] = 'r';
|
||||
|
||||
if (strcmp(stmt->variable, "all")==0 && valuestr == NULL)
|
||||
if (strcmp(stmt->variable, "all") == 0 && valuestr == NULL)
|
||||
{
|
||||
/* RESET ALL */
|
||||
repl_null[Anum_pg_database_datconfig-1] = 'n';
|
||||
repl_val[Anum_pg_database_datconfig-1] = (Datum) 0;
|
||||
repl_null[Anum_pg_database_datconfig - 1] = 'n';
|
||||
repl_val[Anum_pg_database_datconfig - 1] = (Datum) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
ArrayType *a;
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
ArrayType *a;
|
||||
|
||||
repl_null[Anum_pg_database_datconfig-1] = ' ';
|
||||
repl_null[Anum_pg_database_datconfig - 1] = ' ';
|
||||
|
||||
datum = heap_getattr(tuple, Anum_pg_database_datconfig,
|
||||
RelationGetDescr(rel), &isnull);
|
||||
@ -542,7 +543,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
||||
else
|
||||
a = GUCArrayDelete(a, stmt->variable);
|
||||
|
||||
repl_val[Anum_pg_database_datconfig-1] = PointerGetDatum(a);
|
||||
repl_val[Anum_pg_database_datconfig - 1] = PointerGetDatum(a);
|
||||
}
|
||||
|
||||
newtuple = heap_modifytuple(tuple, rel, repl_val, repl_null, repl_repl);
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.79 2002/08/10 19:01:53 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.80 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -132,10 +132,11 @@ defGetInt64(DefElem *def)
|
||||
case T_Integer:
|
||||
return (int64) intVal(def->arg);
|
||||
case T_Float:
|
||||
|
||||
/*
|
||||
* Values too large for int4 will be represented as Float
|
||||
* constants by the lexer. Accept these if they are valid int8
|
||||
* strings.
|
||||
* constants by the lexer. Accept these if they are valid
|
||||
* int8 strings.
|
||||
*/
|
||||
return DatumGetInt64(DirectFunctionCall1(int8in,
|
||||
CStringGetDatum(strVal(def->arg))));
|
||||
@ -188,14 +189,14 @@ defGetTypeName(DefElem *def)
|
||||
case T_TypeName:
|
||||
return (TypeName *) def->arg;
|
||||
case T_String:
|
||||
{
|
||||
/* Allow quoted typename for backwards compatibility */
|
||||
TypeName *n = makeNode(TypeName);
|
||||
{
|
||||
/* Allow quoted typename for backwards compatibility */
|
||||
TypeName *n = makeNode(TypeName);
|
||||
|
||||
n->names = makeList1(def->arg);
|
||||
n->typmod = -1;
|
||||
return n;
|
||||
}
|
||||
n->names = makeList1(def->arg);
|
||||
n->typmod = -1;
|
||||
return n;
|
||||
}
|
||||
default:
|
||||
elog(ERROR, "Define: argument of \"%s\" must be a type name",
|
||||
def->defname);
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.86 2002/09/02 01:05:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.87 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -41,18 +41,18 @@ typedef struct ExplainState
|
||||
|
||||
static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es);
|
||||
static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
|
||||
TupOutputState *tstate);
|
||||
TupOutputState *tstate);
|
||||
static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
|
||||
int indent, ExplainState *es);
|
||||
int indent, ExplainState *es);
|
||||
static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel,
|
||||
int scanrelid, Plan *outer_plan,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
int scanrelid, Plan *outer_plan,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
static void show_upper_qual(List *qual, const char *qlabel,
|
||||
const char *outer_name, int outer_varno, Plan *outer_plan,
|
||||
const char *inner_name, int inner_varno, Plan *inner_plan,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
const char *outer_name, int outer_varno, Plan *outer_plan,
|
||||
const char *inner_name, int inner_varno, Plan *inner_plan,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
static void show_sort_keys(List *tlist, int nkeys, const char *qlabel,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
static Node *make_ors_ands_explicit(List *orclauses);
|
||||
|
||||
/*
|
||||
@ -189,7 +189,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
|
||||
do_text_output_multiline(tstate, f);
|
||||
pfree(f);
|
||||
if (es->printCost)
|
||||
do_text_output_oneline(tstate, ""); /* separator line */
|
||||
do_text_output_oneline(tstate, ""); /* separator line */
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +325,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
|
||||
relation = index_open(lfirsti(l));
|
||||
appendStringInfo(str, "%s%s",
|
||||
(++i > 1) ? ", " : "",
|
||||
quote_identifier(RelationGetRelationName(relation)));
|
||||
quote_identifier(RelationGetRelationName(relation)));
|
||||
index_close(relation);
|
||||
}
|
||||
/* FALL THRU */
|
||||
@ -335,7 +335,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
|
||||
{
|
||||
RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
|
||||
es->rtable);
|
||||
char *relname;
|
||||
char *relname;
|
||||
|
||||
/* Assume it's on a real relation */
|
||||
Assert(rte->rtekind == RTE_RELATION);
|
||||
@ -347,7 +347,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
|
||||
quote_identifier(relname));
|
||||
if (strcmp(rte->eref->aliasname, relname) != 0)
|
||||
appendStringInfo(str, " %s",
|
||||
quote_identifier(rte->eref->aliasname));
|
||||
quote_identifier(rte->eref->aliasname));
|
||||
}
|
||||
break;
|
||||
case T_SubqueryScan:
|
||||
@ -365,10 +365,10 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
|
||||
{
|
||||
RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
|
||||
es->rtable);
|
||||
Expr *expr;
|
||||
Func *funcnode;
|
||||
Oid funcid;
|
||||
char *proname;
|
||||
Expr *expr;
|
||||
Func *funcnode;
|
||||
Oid funcid;
|
||||
char *proname;
|
||||
|
||||
/* Assert it's on a RangeFunction */
|
||||
Assert(rte->rtekind == RTE_FUNCTION);
|
||||
@ -384,7 +384,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
|
||||
quote_identifier(proname));
|
||||
if (strcmp(rte->eref->aliasname, proname) != 0)
|
||||
appendStringInfo(str, " %s",
|
||||
quote_identifier(rte->eref->aliasname));
|
||||
quote_identifier(rte->eref->aliasname));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -482,7 +482,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
|
||||
case T_SubqueryScan:
|
||||
show_upper_qual(plan->qual,
|
||||
"Filter",
|
||||
"subplan", 1, ((SubqueryScan *) plan)->subplan,
|
||||
"subplan", 1, ((SubqueryScan *) plan)->subplan,
|
||||
"", 0, NULL,
|
||||
str, indent, es);
|
||||
break;
|
||||
@ -662,14 +662,14 @@ show_scan_qual(List *qual, bool is_or_qual, const char *qlabel,
|
||||
|
||||
/*
|
||||
* If we have an outer plan that is referenced by the qual, add it to
|
||||
* the deparse context. If not, don't (so that we don't force prefixes
|
||||
* unnecessarily).
|
||||
* the deparse context. If not, don't (so that we don't force
|
||||
* prefixes unnecessarily).
|
||||
*/
|
||||
if (outer_plan)
|
||||
{
|
||||
if (intMember(OUTER, pull_varnos(node)))
|
||||
outercontext = deparse_context_for_subplan("outer",
|
||||
outer_plan->targetlist,
|
||||
outer_plan->targetlist,
|
||||
es->rtable);
|
||||
else
|
||||
outercontext = NULL;
|
||||
@ -760,10 +760,11 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel,
|
||||
|
||||
/*
|
||||
* In this routine we expect that the plan node's tlist has not been
|
||||
* processed by set_plan_references(). Normally, any Vars will contain
|
||||
* valid varnos referencing the actual rtable. But we might instead be
|
||||
* looking at a dummy tlist generated by prepunion.c; if there are
|
||||
* Vars with zero varno, use the tlist itself to determine their names.
|
||||
* processed by set_plan_references(). Normally, any Vars will
|
||||
* contain valid varnos referencing the actual rtable. But we might
|
||||
* instead be looking at a dummy tlist generated by prepunion.c; if
|
||||
* there are Vars with zero varno, use the tlist itself to determine
|
||||
* their names.
|
||||
*/
|
||||
if (intMember(0, pull_varnos((Node *) tlist)))
|
||||
{
|
||||
@ -811,7 +812,7 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel,
|
||||
}
|
||||
|
||||
/*
|
||||
* Indexscan qual lists have an implicit OR-of-ANDs structure. Make it
|
||||
* Indexscan qual lists have an implicit OR-of-ANDs structure. Make it
|
||||
* explicit so deparsing works properly.
|
||||
*/
|
||||
static Node *
|
||||
@ -823,13 +824,11 @@ make_ors_ands_explicit(List *orclauses)
|
||||
return (Node *) make_ands_explicit(lfirst(orclauses));
|
||||
else
|
||||
{
|
||||
List *args = NIL;
|
||||
List *orptr;
|
||||
List *args = NIL;
|
||||
List *orptr;
|
||||
|
||||
foreach(orptr, orclauses)
|
||||
{
|
||||
args = lappend(args, make_ands_explicit(lfirst(orptr)));
|
||||
}
|
||||
|
||||
return (Node *) make_orclause(args);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.18 2002/08/22 00:01:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.19 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* These routines take the parse tree and pick out the
|
||||
@ -61,7 +61,7 @@
|
||||
* allow a shell type to be used, or even created if the specified return type
|
||||
* doesn't exist yet. (Without this, there's no way to define the I/O procs
|
||||
* for a new type.) But SQL function creation won't cope, so error out if
|
||||
* the target language is SQL. (We do this here, not in the SQL-function
|
||||
* the target language is SQL. (We do this here, not in the SQL-function
|
||||
* validator, so as not to produce a WARNING and then an ERROR for the same
|
||||
* condition.)
|
||||
*/
|
||||
@ -69,7 +69,7 @@ static void
|
||||
compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
Oid *prorettype_p, bool *returnsSet_p)
|
||||
{
|
||||
Oid rettype;
|
||||
Oid rettype;
|
||||
|
||||
rettype = LookupTypeName(returnType);
|
||||
|
||||
@ -87,7 +87,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
}
|
||||
else
|
||||
{
|
||||
char *typnam = TypeNameToString(returnType);
|
||||
char *typnam = TypeNameToString(returnType);
|
||||
Oid namespaceId;
|
||||
AclResult aclresult;
|
||||
char *typname;
|
||||
@ -184,41 +184,41 @@ compute_attributes_sql_style(const List *options,
|
||||
bool *security_definer)
|
||||
{
|
||||
const List *option;
|
||||
DefElem *as_item = NULL;
|
||||
DefElem *language_item = NULL;
|
||||
DefElem *volatility_item = NULL;
|
||||
DefElem *strict_item = NULL;
|
||||
DefElem *security_item = NULL;
|
||||
DefElem *as_item = NULL;
|
||||
DefElem *language_item = NULL;
|
||||
DefElem *volatility_item = NULL;
|
||||
DefElem *strict_item = NULL;
|
||||
DefElem *security_item = NULL;
|
||||
|
||||
foreach(option, options)
|
||||
{
|
||||
DefElem *defel = (DefElem *) lfirst(option);
|
||||
|
||||
if (strcmp(defel->defname, "as")==0)
|
||||
if (strcmp(defel->defname, "as") == 0)
|
||||
{
|
||||
if (as_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
as_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "language")==0)
|
||||
else if (strcmp(defel->defname, "language") == 0)
|
||||
{
|
||||
if (language_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
language_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "volatility")==0)
|
||||
else if (strcmp(defel->defname, "volatility") == 0)
|
||||
{
|
||||
if (volatility_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
volatility_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "strict")==0)
|
||||
else if (strcmp(defel->defname, "strict") == 0)
|
||||
{
|
||||
if (strict_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
strict_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "security")==0)
|
||||
else if (strcmp(defel->defname, "security") == 0)
|
||||
{
|
||||
if (security_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
@ -229,7 +229,7 @@ compute_attributes_sql_style(const List *options,
|
||||
}
|
||||
|
||||
if (as_item)
|
||||
*as = (List *)as_item->arg;
|
||||
*as = (List *) as_item->arg;
|
||||
else
|
||||
elog(ERROR, "no function body specified");
|
||||
|
||||
@ -240,11 +240,11 @@ compute_attributes_sql_style(const List *options,
|
||||
|
||||
if (volatility_item)
|
||||
{
|
||||
if (strcmp(strVal(volatility_item->arg), "immutable")==0)
|
||||
if (strcmp(strVal(volatility_item->arg), "immutable") == 0)
|
||||
*volatility_p = PROVOLATILE_IMMUTABLE;
|
||||
else if (strcmp(strVal(volatility_item->arg), "stable")==0)
|
||||
else if (strcmp(strVal(volatility_item->arg), "stable") == 0)
|
||||
*volatility_p = PROVOLATILE_STABLE;
|
||||
else if (strcmp(strVal(volatility_item->arg), "volatile")==0)
|
||||
else if (strcmp(strVal(volatility_item->arg), "volatile") == 0)
|
||||
*volatility_p = PROVOLATILE_VOLATILE;
|
||||
else
|
||||
elog(ERROR, "invalid volatility");
|
||||
@ -386,7 +386,7 @@ CreateFunction(CreateFunctionStmt *stmt)
|
||||
|
||||
/* override attributes from explicit list */
|
||||
compute_attributes_sql_style(stmt->options,
|
||||
&as_clause, &language, &volatility, &isStrict, &security);
|
||||
&as_clause, &language, &volatility, &isStrict, &security);
|
||||
|
||||
/* Convert language name to canonical case */
|
||||
case_translate_language_name(language, languageName);
|
||||
@ -439,13 +439,12 @@ CreateFunction(CreateFunctionStmt *stmt)
|
||||
if (languageOid == INTERNALlanguageId)
|
||||
{
|
||||
/*
|
||||
* In PostgreSQL versions before 6.5, the SQL name of the
|
||||
* created function could not be different from the internal
|
||||
* name, and "prosrc" wasn't used. So there is code out there
|
||||
* that does CREATE FUNCTION xyz AS '' LANGUAGE 'internal'.
|
||||
* To preserve some modicum of backwards compatibility, accept
|
||||
* an empty "prosrc" value as meaning the supplied SQL
|
||||
* function name.
|
||||
* In PostgreSQL versions before 6.5, the SQL name of the created
|
||||
* function could not be different from the internal name, and
|
||||
* "prosrc" wasn't used. So there is code out there that does
|
||||
* CREATE FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some
|
||||
* modicum of backwards compatibility, accept an empty "prosrc"
|
||||
* value as meaning the supplied SQL function name.
|
||||
*/
|
||||
if (strlen(prosrc_str) == 0)
|
||||
prosrc_str = funcname;
|
||||
@ -488,7 +487,7 @@ void
|
||||
RemoveFunction(RemoveFuncStmt *stmt)
|
||||
{
|
||||
List *functionName = stmt->funcname;
|
||||
List *argTypes = stmt->args; /* list of TypeName nodes */
|
||||
List *argTypes = stmt->args; /* list of TypeName nodes */
|
||||
Oid funcOid;
|
||||
HeapTuple tup;
|
||||
ObjectAddress object;
|
||||
@ -496,13 +495,13 @@ RemoveFunction(RemoveFuncStmt *stmt)
|
||||
/*
|
||||
* Find the function, do permissions and validity checks
|
||||
*/
|
||||
funcOid = LookupFuncNameTypeNames(functionName, argTypes,
|
||||
funcOid = LookupFuncNameTypeNames(functionName, argTypes,
|
||||
"RemoveFunction");
|
||||
|
||||
tup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveFunction: couldn't find tuple for function %s",
|
||||
NameListToString(functionName));
|
||||
|
||||
@ -557,7 +556,7 @@ RemoveFunctionById(Oid funcOid)
|
||||
tup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveFunctionById: couldn't find tuple for function %u",
|
||||
funcOid);
|
||||
|
||||
@ -579,7 +578,7 @@ RemoveFunctionById(Oid funcOid)
|
||||
tup = SearchSysCache(AGGFNOID,
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveFunctionById: couldn't find pg_aggregate tuple for %u",
|
||||
funcOid);
|
||||
|
||||
@ -611,7 +610,7 @@ CreateCast(CreateCastStmt *stmt)
|
||||
int i;
|
||||
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
referenced;
|
||||
|
||||
sourcetypeid = LookupTypeName(stmt->sourcetype);
|
||||
if (!OidIsValid(sourcetypeid))
|
||||
@ -693,10 +692,10 @@ CreateCast(CreateCastStmt *stmt)
|
||||
}
|
||||
|
||||
/* ready to go */
|
||||
values[Anum_pg_cast_castsource-1] = ObjectIdGetDatum(sourcetypeid);
|
||||
values[Anum_pg_cast_casttarget-1] = ObjectIdGetDatum(targettypeid);
|
||||
values[Anum_pg_cast_castfunc-1] = ObjectIdGetDatum(funcid);
|
||||
values[Anum_pg_cast_castimplicit-1] = BoolGetDatum(stmt->implicit);
|
||||
values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
|
||||
values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
|
||||
values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
|
||||
values[Anum_pg_cast_castimplicit - 1] = BoolGetDatum(stmt->implicit);
|
||||
|
||||
for (i = 0; i < Natts_pg_cast; ++i)
|
||||
nulls[i] = ' ';
|
||||
@ -760,9 +759,9 @@ DropCast(DropCastStmt *stmt)
|
||||
TypeNameToString(stmt->targettype));
|
||||
|
||||
tuple = SearchSysCache(CASTSOURCETARGET,
|
||||
ObjectIdGetDatum(sourcetypeid),
|
||||
ObjectIdGetDatum(targettypeid),
|
||||
0, 0);
|
||||
ObjectIdGetDatum(sourcetypeid),
|
||||
ObjectIdGetDatum(targettypeid),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cast from type %s to type %s does not exist",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.86 2002/08/30 22:18:05 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.87 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -117,9 +117,9 @@ DefineIndex(RangeVar *heapRelation,
|
||||
|
||||
/*
|
||||
* Verify we (still) have CREATE rights in the rel's namespace.
|
||||
* (Presumably we did when the rel was created, but maybe not anymore.)
|
||||
* Skip check if bootstrapping, since permissions machinery may not
|
||||
* be working yet.
|
||||
* (Presumably we did when the rel was created, but maybe not
|
||||
* anymore.) Skip check if bootstrapping, since permissions machinery
|
||||
* may not be working yet.
|
||||
*/
|
||||
if (!IsBootstrapProcessingMode())
|
||||
{
|
||||
@ -254,8 +254,8 @@ CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid)
|
||||
elog(ERROR, "Cannot use aggregate in index predicate");
|
||||
|
||||
/*
|
||||
* A predicate using mutable functions is probably wrong, for the
|
||||
* same reasons that we don't allow a functional index to use one.
|
||||
* A predicate using mutable functions is probably wrong, for the same
|
||||
* reasons that we don't allow a functional index to use one.
|
||||
*/
|
||||
if (contain_mutable_functions((Node *) predList))
|
||||
elog(ERROR, "Functions in index predicate must be marked isImmutable");
|
||||
@ -432,7 +432,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
if (schemaname)
|
||||
{
|
||||
/* Look in specific schema only */
|
||||
Oid namespaceId;
|
||||
Oid namespaceId;
|
||||
|
||||
namespaceId = LookupExplicitNamespace(schemaname);
|
||||
tuple = SearchSysCache(CLAAMNAMENSP,
|
||||
@ -458,15 +458,15 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
NameListToString(attribute->opclass), accessMethodName);
|
||||
|
||||
/*
|
||||
* Verify that the index operator class accepts this
|
||||
* datatype. Note we will accept binary compatibility.
|
||||
* Verify that the index operator class accepts this datatype. Note
|
||||
* we will accept binary compatibility.
|
||||
*/
|
||||
opClassId = HeapTupleGetOid(tuple);
|
||||
opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
|
||||
|
||||
if (!IsBinaryCompatible(attrType, opInputType))
|
||||
elog(ERROR, "operator class \"%s\" does not accept data type %s",
|
||||
NameListToString(attribute->opclass), format_type_be(attrType));
|
||||
NameListToString(attribute->opclass), format_type_be(attrType));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
@ -547,7 +547,7 @@ RemoveIndex(RangeVar *relation, DropBehavior behavior)
|
||||
|
||||
if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
|
||||
elog(ERROR, "relation \"%s\" is of type \"%c\"",
|
||||
relation->relname, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
|
||||
relation->relname, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
@ -704,7 +704,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
|
||||
relcnt = relalc = 0;
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
char relkind;
|
||||
char relkind;
|
||||
|
||||
if (!all)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/lockcmds.c,v 1.3 2002/06/20 20:29:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/lockcmds.c,v 1.4 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -43,8 +43,8 @@ LockTableCommand(LockStmt *lockstmt)
|
||||
Relation rel;
|
||||
|
||||
/*
|
||||
* We don't want to open the relation until we've checked privilege.
|
||||
* So, manually get the relation OID.
|
||||
* We don't want to open the relation until we've checked
|
||||
* privilege. So, manually get the relation OID.
|
||||
*/
|
||||
reloid = RangeVarGetRelid(relation, false);
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.4 2002/08/22 00:01:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.5 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
|
||||
static void storeOperators(Oid opclassoid, int numOperators,
|
||||
Oid *operators, bool *recheck);
|
||||
Oid *operators, bool *recheck);
|
||||
static void storeProcedures(Oid opclassoid, int numProcs, Oid *procedures);
|
||||
|
||||
|
||||
@ -68,8 +68,8 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
AclResult aclresult;
|
||||
NameData opcName;
|
||||
int i;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
|
||||
/* Convert list of names to a name and namespace */
|
||||
namespaceoid = QualifiedNameGetCreationNamespace(stmt->opclassname,
|
||||
@ -107,9 +107,9 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
storageoid = InvalidOid;
|
||||
|
||||
/*
|
||||
* Create work arrays to hold info about operators and procedures.
|
||||
* We do this mainly so that we can detect duplicate strategy
|
||||
* numbers and support-proc numbers.
|
||||
* Create work arrays to hold info about operators and procedures. We
|
||||
* do this mainly so that we can detect duplicate strategy numbers and
|
||||
* support-proc numbers.
|
||||
*/
|
||||
operators = (Oid *) palloc(sizeof(Oid) * numOperators);
|
||||
MemSet(operators, 0, sizeof(Oid) * numOperators);
|
||||
@ -141,11 +141,11 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
item->number);
|
||||
if (item->args != NIL)
|
||||
{
|
||||
TypeName *typeName1 = (TypeName *) lfirst(item->args);
|
||||
TypeName *typeName2 = (TypeName *) lsecond(item->args);
|
||||
TypeName *typeName1 = (TypeName *) lfirst(item->args);
|
||||
TypeName *typeName2 = (TypeName *) lsecond(item->args);
|
||||
|
||||
operOid = LookupOperNameTypeNames(item->name,
|
||||
typeName1, typeName2,
|
||||
typeName1, typeName2,
|
||||
"DefineOpClass");
|
||||
/* No need to check for error */
|
||||
}
|
||||
@ -221,8 +221,8 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
rel = heap_openr(OperatorClassRelationName, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Make sure there is no existing opclass of this name (this is
|
||||
* just to give a more friendly error message than "duplicate key").
|
||||
* Make sure there is no existing opclass of this name (this is just
|
||||
* to give a more friendly error message than "duplicate key").
|
||||
*/
|
||||
if (SearchSysCacheExists(CLAAMNAMENSP,
|
||||
ObjectIdGetDatum(amoid),
|
||||
@ -233,12 +233,12 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
opcname, stmt->amname);
|
||||
|
||||
/*
|
||||
* If we are creating a default opclass, check there isn't one already.
|
||||
* (XXX should we restrict this test to visible opclasses?)
|
||||
* If we are creating a default opclass, check there isn't one
|
||||
* already. (XXX should we restrict this test to visible opclasses?)
|
||||
*/
|
||||
if (stmt->isDefault)
|
||||
{
|
||||
ScanKeyData skey[1];
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc scan;
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
@ -276,11 +276,11 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
values[i++] = ObjectIdGetDatum(amoid); /* opcamid */
|
||||
namestrcpy(&opcName, opcname);
|
||||
values[i++] = NameGetDatum(&opcName); /* opcname */
|
||||
values[i++] = ObjectIdGetDatum(namespaceoid); /* opcnamespace */
|
||||
values[i++] = ObjectIdGetDatum(namespaceoid); /* opcnamespace */
|
||||
values[i++] = Int32GetDatum(GetUserId()); /* opcowner */
|
||||
values[i++] = ObjectIdGetDatum(typeoid); /* opcintype */
|
||||
values[i++] = BoolGetDatum(stmt->isDefault); /* opcdefault */
|
||||
values[i++] = ObjectIdGetDatum(storageoid); /* opckeytype */
|
||||
values[i++] = BoolGetDatum(stmt->isDefault); /* opcdefault */
|
||||
values[i++] = ObjectIdGetDatum(storageoid); /* opckeytype */
|
||||
|
||||
tup = heap_formtuple(rel->rd_att, values, nulls);
|
||||
|
||||
@ -291,8 +291,8 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
heap_freetuple(tup);
|
||||
|
||||
/*
|
||||
* Now add tuples to pg_amop and pg_amproc tying in the
|
||||
* operators and functions.
|
||||
* Now add tuples to pg_amop and pg_amproc tying in the operators and
|
||||
* functions.
|
||||
*/
|
||||
storeOperators(opclassoid, numOperators, operators, recheck);
|
||||
storeProcedures(opclassoid, numProcs, procedures);
|
||||
@ -358,11 +358,12 @@ static void
|
||||
storeOperators(Oid opclassoid, int numOperators,
|
||||
Oid *operators, bool *recheck)
|
||||
{
|
||||
Relation rel;
|
||||
Datum values[Natts_pg_amop];
|
||||
char nulls[Natts_pg_amop];
|
||||
HeapTuple tup;
|
||||
int i, j;
|
||||
Relation rel;
|
||||
Datum values[Natts_pg_amop];
|
||||
char nulls[Natts_pg_amop];
|
||||
HeapTuple tup;
|
||||
int i,
|
||||
j;
|
||||
|
||||
rel = heap_openr(AccessMethodOperatorRelationName, RowExclusiveLock);
|
||||
|
||||
@ -378,9 +379,9 @@ storeOperators(Oid opclassoid, int numOperators,
|
||||
}
|
||||
|
||||
i = 0;
|
||||
values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */
|
||||
values[i++] = Int16GetDatum(j + 1); /* amopstrategy */
|
||||
values[i++] = BoolGetDatum(recheck[j]); /* amopreqcheck */
|
||||
values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */
|
||||
values[i++] = Int16GetDatum(j + 1); /* amopstrategy */
|
||||
values[i++] = BoolGetDatum(recheck[j]); /* amopreqcheck */
|
||||
values[i++] = ObjectIdGetDatum(operators[j]); /* amopopr */
|
||||
|
||||
tup = heap_formtuple(rel->rd_att, values, nulls);
|
||||
@ -401,11 +402,12 @@ storeOperators(Oid opclassoid, int numOperators,
|
||||
static void
|
||||
storeProcedures(Oid opclassoid, int numProcs, Oid *procedures)
|
||||
{
|
||||
Relation rel;
|
||||
Datum values[Natts_pg_amproc];
|
||||
char nulls[Natts_pg_amproc];
|
||||
HeapTuple tup;
|
||||
int i, j;
|
||||
Relation rel;
|
||||
Datum values[Natts_pg_amproc];
|
||||
char nulls[Natts_pg_amproc];
|
||||
HeapTuple tup;
|
||||
int i,
|
||||
j;
|
||||
|
||||
rel = heap_openr(AccessMethodProcedureRelationName, RowExclusiveLock);
|
||||
|
||||
@ -421,9 +423,9 @@ storeProcedures(Oid opclassoid, int numProcs, Oid *procedures)
|
||||
}
|
||||
|
||||
i = 0;
|
||||
values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */
|
||||
values[i++] = Int16GetDatum(j + 1); /* amprocnum */
|
||||
values[i++] = ObjectIdGetDatum(procedures[j]); /* amproc */
|
||||
values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */
|
||||
values[i++] = Int16GetDatum(j + 1); /* amprocnum */
|
||||
values[i++] = ObjectIdGetDatum(procedures[j]); /* amproc */
|
||||
|
||||
tup = heap_formtuple(rel->rd_att, values, nulls);
|
||||
|
||||
@ -445,14 +447,15 @@ storeProcedures(Oid opclassoid, int numProcs, Oid *procedures)
|
||||
void
|
||||
RemoveOpClass(RemoveOpClassStmt *stmt)
|
||||
{
|
||||
Oid amID, opcID;
|
||||
Oid amID,
|
||||
opcID;
|
||||
char *schemaname;
|
||||
char *opcname;
|
||||
HeapTuple tuple;
|
||||
ObjectAddress object;
|
||||
|
||||
/*
|
||||
* Get the access method's OID.
|
||||
* Get the access method's OID.
|
||||
*/
|
||||
amID = GetSysCacheOid(AMNAME,
|
||||
CStringGetDatum(stmt->amname),
|
||||
@ -471,7 +474,7 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
|
||||
if (schemaname)
|
||||
{
|
||||
/* Look in specific schema only */
|
||||
Oid namespaceId;
|
||||
Oid namespaceId;
|
||||
|
||||
namespaceId = LookupExplicitNamespace(schemaname);
|
||||
tuple = SearchSysCache(CLAAMNAMENSP,
|
||||
@ -523,10 +526,10 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
|
||||
void
|
||||
RemoveOpClassById(Oid opclassOid)
|
||||
{
|
||||
Relation rel;
|
||||
HeapTuple tup;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc scan;
|
||||
Relation rel;
|
||||
HeapTuple tup;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc scan;
|
||||
|
||||
/*
|
||||
* First remove the pg_opclass entry itself.
|
||||
@ -536,7 +539,7 @@ RemoveOpClassById(Oid opclassOid)
|
||||
tup = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opclassOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveOpClassById: couldn't find pg_class entry %u",
|
||||
opclassOid);
|
||||
|
||||
@ -559,9 +562,7 @@ RemoveOpClassById(Oid opclassOid)
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||
{
|
||||
simple_heap_delete(rel, &tup->t_self);
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
@ -579,9 +580,7 @@ RemoveOpClassById(Oid opclassOid)
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||
{
|
||||
simple_heap_delete(rel, &tup->t_self);
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.6 2002/07/24 19:11:09 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.7 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -62,7 +62,7 @@ DefineOperator(List *names, List *parameters)
|
||||
char *oprName;
|
||||
Oid oprNamespace;
|
||||
AclResult aclresult;
|
||||
bool canHash = false; /* operator hashes */
|
||||
bool canHash = false; /* operator hashes */
|
||||
bool canMerge = false; /* operator merges */
|
||||
List *functionName = NIL; /* function for operator */
|
||||
TypeName *typeName1 = NULL; /* first type name */
|
||||
@ -74,7 +74,7 @@ DefineOperator(List *names, List *parameters)
|
||||
List *negatorName = NIL; /* optional negator operator name */
|
||||
List *restrictionName = NIL; /* optional restrict. sel.
|
||||
* procedure */
|
||||
List *joinName = NIL; /* optional join sel. procedure */
|
||||
List *joinName = NIL; /* optional join sel. procedure */
|
||||
List *leftSortName = NIL; /* optional left sort operator */
|
||||
List *rightSortName = NIL; /* optional right sort operator */
|
||||
List *ltCompareName = NIL; /* optional < compare operator */
|
||||
@ -173,7 +173,7 @@ DefineOperator(List *names, List *parameters)
|
||||
* now have OperatorCreate do all the work..
|
||||
*/
|
||||
OperatorCreate(oprName, /* operator name */
|
||||
oprNamespace, /* namespace */
|
||||
oprNamespace, /* namespace */
|
||||
typeId1, /* left type id */
|
||||
typeId2, /* right type id */
|
||||
functionName, /* function for operator */
|
||||
@ -185,9 +185,9 @@ DefineOperator(List *names, List *parameters)
|
||||
joinName, /* optional join sel. procedure name */
|
||||
canHash, /* operator hashes */
|
||||
leftSortName, /* optional left sort operator */
|
||||
rightSortName, /* optional right sort operator */
|
||||
ltCompareName, /* optional < comparison op */
|
||||
gtCompareName); /* optional < comparison op */
|
||||
rightSortName, /* optional right sort operator */
|
||||
ltCompareName, /* optional < comparison op */
|
||||
gtCompareName); /* optional < comparison op */
|
||||
}
|
||||
|
||||
|
||||
@ -198,9 +198,9 @@ DefineOperator(List *names, List *parameters)
|
||||
void
|
||||
RemoveOperator(RemoveOperStmt *stmt)
|
||||
{
|
||||
List *operatorName = stmt->opname;
|
||||
TypeName *typeName1 = (TypeName *) lfirst(stmt->args);
|
||||
TypeName *typeName2 = (TypeName *) lsecond(stmt->args);
|
||||
List *operatorName = stmt->opname;
|
||||
TypeName *typeName1 = (TypeName *) lfirst(stmt->args);
|
||||
TypeName *typeName2 = (TypeName *) lsecond(stmt->args);
|
||||
Oid operOid;
|
||||
HeapTuple tup;
|
||||
ObjectAddress object;
|
||||
@ -211,7 +211,7 @@ RemoveOperator(RemoveOperStmt *stmt)
|
||||
tup = SearchSysCache(OPEROID,
|
||||
ObjectIdGetDatum(operOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'",
|
||||
NameListToString(operatorName));
|
||||
|
||||
@ -247,7 +247,7 @@ RemoveOperatorById(Oid operOid)
|
||||
tup = SearchSysCache(OPEROID,
|
||||
ObjectIdGetDatum(operOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveOperatorById: failed to find tuple for operator %u",
|
||||
operOid);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.2 2002/05/21 22:05:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.3 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -134,12 +134,12 @@ PerformPortalFetch(char *name,
|
||||
* Determine which direction to go in, and check to see if we're
|
||||
* already at the end of the available tuples in that direction. If
|
||||
* so, set the direction to NoMovement to avoid trying to fetch any
|
||||
* tuples. (This check exists because not all plan node types
|
||||
* are robust about being called again if they've already returned
|
||||
* NULL once.) Then call the executor (we must not skip this, because
|
||||
* the destination needs to see a setup and shutdown even if no tuples
|
||||
* are available). Finally, update the atStart/atEnd state depending
|
||||
* on the number of tuples that were retrieved.
|
||||
* tuples. (This check exists because not all plan node types are
|
||||
* robust about being called again if they've already returned NULL
|
||||
* once.) Then call the executor (we must not skip this, because the
|
||||
* destination needs to see a setup and shutdown even if no tuples are
|
||||
* available). Finally, update the atStart/atEnd state depending on
|
||||
* the number of tuples that were retrieved.
|
||||
*/
|
||||
if (forward)
|
||||
{
|
||||
@ -151,9 +151,9 @@ PerformPortalFetch(char *name,
|
||||
ExecutorRun(queryDesc, estate, direction, (long) count);
|
||||
|
||||
if (estate->es_processed > 0)
|
||||
portal->atStart = false; /* OK to back up now */
|
||||
portal->atStart = false; /* OK to back up now */
|
||||
if (count <= 0 || (int) estate->es_processed < count)
|
||||
portal->atEnd = true; /* we retrieved 'em all */
|
||||
portal->atEnd = true; /* we retrieved 'em all */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -165,9 +165,9 @@ PerformPortalFetch(char *name,
|
||||
ExecutorRun(queryDesc, estate, direction, (long) count);
|
||||
|
||||
if (estate->es_processed > 0)
|
||||
portal->atEnd = false; /* OK to go forward now */
|
||||
portal->atEnd = false; /* OK to go forward now */
|
||||
if (count <= 0 || (int) estate->es_processed < count)
|
||||
portal->atStart = true; /* we retrieved 'em all */
|
||||
portal->atStart = true; /* we retrieved 'em all */
|
||||
}
|
||||
|
||||
/* Return command status if wanted */
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright (c) 2002, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.1 2002/08/27 04:55:07 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.2 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -34,7 +34,7 @@ typedef struct
|
||||
List *query_list; /* list of queries */
|
||||
List *plan_list; /* list of plans */
|
||||
List *argtype_list; /* list of parameter type OIDs */
|
||||
MemoryContext context; /* context containing this query */
|
||||
MemoryContext context; /* context containing this query */
|
||||
} QueryHashEntry;
|
||||
|
||||
/*
|
||||
@ -47,7 +47,7 @@ static HTAB *prepared_queries = NULL;
|
||||
|
||||
static void InitQueryHashTable(void);
|
||||
static void StoreQuery(const char *stmt_name, List *query_list,
|
||||
List *plan_list, List *argtype_list);
|
||||
List *plan_list, List *argtype_list);
|
||||
static QueryHashEntry *FetchQuery(const char *plan_name);
|
||||
static void RunQuery(QueryDesc *qdesc, EState *state);
|
||||
|
||||
@ -58,9 +58,9 @@ static void RunQuery(QueryDesc *qdesc, EState *state);
|
||||
void
|
||||
PrepareQuery(PrepareStmt *stmt)
|
||||
{
|
||||
List *plan_list = NIL;
|
||||
List *query_list,
|
||||
*query_list_item;
|
||||
List *plan_list = NIL;
|
||||
List *query_list,
|
||||
*query_list_item;
|
||||
|
||||
if (!stmt->name)
|
||||
elog(ERROR, "No statement name given");
|
||||
@ -73,8 +73,8 @@ PrepareQuery(PrepareStmt *stmt)
|
||||
|
||||
foreach(query_list_item, query_list)
|
||||
{
|
||||
Query *query = (Query *) lfirst(query_list_item);
|
||||
Plan *plan;
|
||||
Query *query = (Query *) lfirst(query_list_item);
|
||||
Plan *plan;
|
||||
|
||||
/* We can't generate plans for utility statements. */
|
||||
if (query->commandType == CMD_UTILITY)
|
||||
@ -97,10 +97,10 @@ PrepareQuery(PrepareStmt *stmt)
|
||||
void
|
||||
ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
|
||||
{
|
||||
QueryHashEntry *entry;
|
||||
List *l,
|
||||
*query_list,
|
||||
*plan_list;
|
||||
QueryHashEntry *entry;
|
||||
List *l,
|
||||
*query_list,
|
||||
*plan_list;
|
||||
ParamListInfo paramLI = NULL;
|
||||
|
||||
/* Look it up in the hash table */
|
||||
@ -115,8 +115,8 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
|
||||
/* Evaluate parameters, if any */
|
||||
if (entry->argtype_list != NIL)
|
||||
{
|
||||
int nargs = length(entry->argtype_list);
|
||||
int i = 0;
|
||||
int nargs = length(entry->argtype_list);
|
||||
int i = 0;
|
||||
ExprContext *econtext = MakeExprContext(NULL, CurrentMemoryContext);
|
||||
|
||||
/* Parser should have caught this error, but check */
|
||||
@ -126,10 +126,10 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
|
||||
paramLI = (ParamListInfo) palloc((nargs + 1) * sizeof(ParamListInfoData));
|
||||
MemSet(paramLI, 0, (nargs + 1) * sizeof(ParamListInfoData));
|
||||
|
||||
foreach (l, stmt->params)
|
||||
foreach(l, stmt->params)
|
||||
{
|
||||
Node *n = lfirst(l);
|
||||
bool isNull;
|
||||
Node *n = lfirst(l);
|
||||
bool isNull;
|
||||
|
||||
paramLI[i].value = ExecEvalExprSwitchContext(n,
|
||||
econtext,
|
||||
@ -147,9 +147,9 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
|
||||
/* Execute each query */
|
||||
foreach(l, query_list)
|
||||
{
|
||||
Query *query = lfirst(l);
|
||||
Plan *plan = lfirst(plan_list);
|
||||
bool is_last_query;
|
||||
Query *query = lfirst(l);
|
||||
Plan *plan = lfirst(plan_list);
|
||||
bool is_last_query;
|
||||
|
||||
plan_list = lnext(plan_list);
|
||||
is_last_query = (plan_list == NIL);
|
||||
@ -158,8 +158,8 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
|
||||
ProcessUtility(query->utilityStmt, outputDest, NULL);
|
||||
else
|
||||
{
|
||||
QueryDesc *qdesc;
|
||||
EState *state;
|
||||
QueryDesc *qdesc;
|
||||
EState *state;
|
||||
|
||||
if (Show_executor_stats)
|
||||
ResetUsage();
|
||||
@ -185,11 +185,11 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're processing multiple queries, we need to increment
|
||||
* the command counter between them. For the last query,
|
||||
* there's no need to do this, it's done automatically.
|
||||
* If we're processing multiple queries, we need to increment the
|
||||
* command counter between them. For the last query, there's no
|
||||
* need to do this, it's done automatically.
|
||||
*/
|
||||
if (! is_last_query)
|
||||
if (!is_last_query)
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
|
||||
static void
|
||||
InitQueryHashTable(void)
|
||||
{
|
||||
HASHCTL hash_ctl;
|
||||
HASHCTL hash_ctl;
|
||||
|
||||
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
|
||||
|
||||
@ -229,9 +229,9 @@ StoreQuery(const char *stmt_name, List *query_list, List *plan_list,
|
||||
{
|
||||
QueryHashEntry *entry;
|
||||
MemoryContext oldcxt,
|
||||
entrycxt;
|
||||
char key[HASH_KEY_LEN];
|
||||
bool found;
|
||||
entrycxt;
|
||||
char key[HASH_KEY_LEN];
|
||||
bool found;
|
||||
|
||||
/* Initialize the hash table, if necessary */
|
||||
if (!prepared_queries)
|
||||
@ -258,10 +258,10 @@ StoreQuery(const char *stmt_name, List *query_list, List *plan_list,
|
||||
oldcxt = MemoryContextSwitchTo(entrycxt);
|
||||
|
||||
/*
|
||||
* We need to copy the data so that it is stored in the correct
|
||||
* memory context. Do this before making hashtable entry, so that
|
||||
* an out-of-memory failure only wastes memory and doesn't leave us
|
||||
* with an incomplete (ie corrupt) hashtable entry.
|
||||
* We need to copy the data so that it is stored in the correct memory
|
||||
* context. Do this before making hashtable entry, so that an
|
||||
* out-of-memory failure only wastes memory and doesn't leave us with
|
||||
* an incomplete (ie corrupt) hashtable entry.
|
||||
*/
|
||||
query_list = (List *) copyObject(query_list);
|
||||
plan_list = (List *) copyObject(plan_list);
|
||||
@ -293,7 +293,7 @@ StoreQuery(const char *stmt_name, List *query_list, List *plan_list,
|
||||
static QueryHashEntry *
|
||||
FetchQuery(const char *plan_name)
|
||||
{
|
||||
char key[HASH_KEY_LEN];
|
||||
char key[HASH_KEY_LEN];
|
||||
QueryHashEntry *entry;
|
||||
|
||||
/*
|
||||
@ -306,8 +306,8 @@ FetchQuery(const char *plan_name)
|
||||
|
||||
/*
|
||||
* We can't just use the statement name as supplied by the user: the
|
||||
* hash package is picky enough that it needs to be NULL-padded out
|
||||
* to the appropriate length to work correctly.
|
||||
* hash package is picky enough that it needs to be NULL-padded out to
|
||||
* the appropriate length to work correctly.
|
||||
*/
|
||||
MemSet(key, 0, sizeof(key));
|
||||
strncpy(key, plan_name, sizeof(key));
|
||||
@ -344,7 +344,7 @@ FetchQueryParams(const char *plan_name)
|
||||
static void
|
||||
RunQuery(QueryDesc *qdesc, EState *state)
|
||||
{
|
||||
TupleDesc tupdesc;
|
||||
TupleDesc tupdesc;
|
||||
|
||||
tupdesc = ExecutorStart(qdesc, state);
|
||||
|
||||
@ -363,7 +363,7 @@ RunQuery(QueryDesc *qdesc, EState *state)
|
||||
void
|
||||
DeallocateQuery(DeallocateStmt *stmt)
|
||||
{
|
||||
char key[HASH_KEY_LEN];
|
||||
char key[HASH_KEY_LEN];
|
||||
QueryHashEntry *entry;
|
||||
|
||||
/*
|
||||
@ -376,18 +376,18 @@ DeallocateQuery(DeallocateStmt *stmt)
|
||||
|
||||
/*
|
||||
* We can't just use the statement name as supplied by the user: the
|
||||
* hash package is picky enough that it needs to be NULL-padded out
|
||||
* to the appropriate length to work correctly.
|
||||
* hash package is picky enough that it needs to be NULL-padded out to
|
||||
* the appropriate length to work correctly.
|
||||
*/
|
||||
MemSet(key, 0, sizeof(key));
|
||||
strncpy(key, stmt->name, sizeof(key));
|
||||
|
||||
/*
|
||||
* First lookup the entry, so we can release all the subsidiary memory
|
||||
* it has allocated (when it's removed, hash_search() will return
|
||||
* a dangling pointer, so it needs to be done prior to HASH_REMOVE).
|
||||
* This requires an extra hash-table lookup, but DEALLOCATE
|
||||
* isn't exactly a performance bottleneck.
|
||||
* it has allocated (when it's removed, hash_search() will return a
|
||||
* dangling pointer, so it needs to be done prior to HASH_REMOVE).
|
||||
* This requires an extra hash-table lookup, but DEALLOCATE isn't
|
||||
* exactly a performance bottleneck.
|
||||
*/
|
||||
entry = (QueryHashEntry *) hash_search(prepared_queries,
|
||||
key,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.41 2002/08/22 00:01:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.42 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -41,7 +41,8 @@ void
|
||||
CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
{
|
||||
char languageName[NAMEDATALEN];
|
||||
Oid procOid, valProcOid;
|
||||
Oid procOid,
|
||||
valProcOid;
|
||||
Oid typev[FUNC_MAX_ARGS];
|
||||
char nulls[Natts_pg_language];
|
||||
Datum values[Natts_pg_language];
|
||||
@ -49,8 +50,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
HeapTuple tup;
|
||||
TupleDesc tupDesc;
|
||||
int i;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
|
||||
/*
|
||||
* Check permission
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.5 2002/07/18 16:47:24 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.6 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -61,15 +61,17 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
owner_name = authId;
|
||||
/* The following will error out if user does not exist */
|
||||
owner_userid = get_usesysid(owner_name);
|
||||
|
||||
/*
|
||||
* Set the current user to the requested authorization so
|
||||
* that objects created in the statement have the requested
|
||||
* owner. (This will revert to session user on error or at
|
||||
* the end of this routine.)
|
||||
* Set the current user to the requested authorization so that
|
||||
* objects created in the statement have the requested owner.
|
||||
* (This will revert to session user on error or at the end of
|
||||
* this routine.)
|
||||
*/
|
||||
SetUserId(owner_userid);
|
||||
}
|
||||
else /* not superuser */
|
||||
else
|
||||
/* not superuser */
|
||||
{
|
||||
owner_userid = saved_userid;
|
||||
owner_name = GetUserNameFromId(owner_userid);
|
||||
@ -98,17 +100,17 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
|
||||
/*
|
||||
* Temporarily make the new namespace be the front of the search path,
|
||||
* as well as the default creation target namespace. This will be undone
|
||||
* at the end of this routine, or upon error.
|
||||
* as well as the default creation target namespace. This will be
|
||||
* undone at the end of this routine, or upon error.
|
||||
*/
|
||||
PushSpecialNamespace(namespaceId);
|
||||
|
||||
/*
|
||||
* Examine the list of commands embedded in the CREATE SCHEMA command,
|
||||
* and reorganize them into a sequentially executable order with no
|
||||
* forward references. Note that the result is still a list of raw
|
||||
* parsetrees in need of parse analysis --- we cannot, in general,
|
||||
* run analyze.c on one statement until we have actually executed the
|
||||
* forward references. Note that the result is still a list of raw
|
||||
* parsetrees in need of parse analysis --- we cannot, in general, run
|
||||
* analyze.c on one statement until we have actually executed the
|
||||
* prior ones.
|
||||
*/
|
||||
parsetree_list = analyzeCreateSchemaStmt(stmt);
|
||||
@ -171,12 +173,12 @@ RemoveSchema(List *names, DropBehavior behavior)
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, namespaceName);
|
||||
|
||||
/*
|
||||
* Do the deletion. Objects contained in the schema are removed
|
||||
* by means of their dependency links to the schema.
|
||||
* Do the deletion. Objects contained in the schema are removed by
|
||||
* means of their dependency links to the schema.
|
||||
*
|
||||
* XXX currently, index opclasses don't have creation/deletion
|
||||
* commands, so they will not get removed when the containing
|
||||
* schema is removed. This is annoying but not fatal.
|
||||
* XXX currently, index opclasses don't have creation/deletion commands,
|
||||
* so they will not get removed when the containing schema is removed.
|
||||
* This is annoying but not fatal.
|
||||
*/
|
||||
object.classId = get_system_catalog_relid(NamespaceRelationName);
|
||||
object.objectId = namespaceId;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.86 2002/09/03 18:50:54 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.87 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -60,7 +60,7 @@ typedef struct sequence_magic
|
||||
* rely on the relcache, since it's only, well, a cache, and may decide to
|
||||
* discard entries.)
|
||||
*
|
||||
* XXX We use linear search to find pre-existing SeqTable entries. This is
|
||||
* XXX We use linear search to find pre-existing SeqTable entries. This is
|
||||
* good when only a small number of sequences are touched in a session, but
|
||||
* would suck with many different sequences. Perhaps use a hashtable someday.
|
||||
*/
|
||||
@ -81,9 +81,9 @@ static SeqTable seqtab = NULL; /* Head of list of SeqTable items */
|
||||
|
||||
|
||||
static void init_sequence(const char *caller, RangeVar *relation,
|
||||
SeqTable *p_elm, Relation *p_rel);
|
||||
SeqTable *p_elm, Relation *p_rel);
|
||||
static Form_pg_sequence read_info(const char *caller, SeqTable elm,
|
||||
Relation rel, Buffer *buf);
|
||||
Relation rel, Buffer *buf);
|
||||
static void init_params(CreateSeqStmt *seq, Form_pg_sequence new);
|
||||
static void do_setval(RangeVar *sequence, int64 next, bool iscalled);
|
||||
|
||||
@ -226,15 +226,15 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
* Two special hacks here:
|
||||
*
|
||||
* 1. Since VACUUM does not process sequences, we have to force the tuple
|
||||
* to have xmin = FrozenTransactionId now. Otherwise it would become
|
||||
* invisible to SELECTs after 2G transactions. It is okay to do this
|
||||
* to have xmin = FrozenTransactionId now. Otherwise it would become
|
||||
* invisible to SELECTs after 2G transactions. It is okay to do this
|
||||
* because if the current transaction aborts, no other xact will ever
|
||||
* examine the sequence tuple anyway.
|
||||
*
|
||||
* 2. Even though heap_insert emitted a WAL log record, we have to emit
|
||||
* an XLOG_SEQ_LOG record too, since (a) the heap_insert record will
|
||||
* not have the right xmin, and (b) REDO of the heap_insert record
|
||||
* would re-init page and sequence magic number would be lost. This
|
||||
* would re-init page and sequence magic number would be lost. This
|
||||
* means two log records instead of one :-(
|
||||
*/
|
||||
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
|
||||
@ -243,11 +243,12 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
|
||||
{
|
||||
/*
|
||||
* Note that the "tuple" structure is still just a local tuple record
|
||||
* created by heap_formtuple; its t_data pointer doesn't point at the
|
||||
* disk buffer. To scribble on the disk buffer we need to fetch the
|
||||
* item pointer. But do the same to the local tuple, since that will
|
||||
* be the source for the WAL log record, below.
|
||||
* Note that the "tuple" structure is still just a local tuple
|
||||
* record created by heap_formtuple; its t_data pointer doesn't
|
||||
* point at the disk buffer. To scribble on the disk buffer we
|
||||
* need to fetch the item pointer. But do the same to the local
|
||||
* tuple, since that will be the source for the WAL log record,
|
||||
* below.
|
||||
*/
|
||||
ItemId itemId;
|
||||
Item item;
|
||||
@ -323,7 +324,7 @@ nextval(PG_FUNCTION_ARGS)
|
||||
bool logit = false;
|
||||
|
||||
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||
"nextval"));
|
||||
"nextval"));
|
||||
|
||||
/* open and AccessShareLock sequence */
|
||||
init_sequence("nextval", sequence, &elm, &seqrel);
|
||||
@ -358,14 +359,14 @@ nextval(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide whether we should emit a WAL log record. If so, force up
|
||||
* Decide whether we should emit a WAL log record. If so, force up
|
||||
* the fetch count to grab SEQ_LOG_VALS more values than we actually
|
||||
* need to cache. (These will then be usable without logging.)
|
||||
*
|
||||
* If this is the first nextval after a checkpoint, we must force
|
||||
* a new WAL record to be written anyway, else replay starting from the
|
||||
* If this is the first nextval after a checkpoint, we must force a new
|
||||
* WAL record to be written anyway, else replay starting from the
|
||||
* checkpoint would fail to advance the sequence past the logged
|
||||
* values. In this case we may as well fetch extra values.
|
||||
* values. In this case we may as well fetch extra values.
|
||||
*/
|
||||
if (log < fetch)
|
||||
{
|
||||
@ -401,7 +402,8 @@ nextval(PG_FUNCTION_ARGS)
|
||||
break; /* stop fetching */
|
||||
if (!seq->is_cycled)
|
||||
{
|
||||
char buf[100];
|
||||
char buf[100];
|
||||
|
||||
snprintf(buf, 100, INT64_FORMAT, maxv);
|
||||
elog(ERROR, "%s.nextval: reached MAXVALUE (%s)",
|
||||
sequence->relname, buf);
|
||||
@ -421,7 +423,8 @@ nextval(PG_FUNCTION_ARGS)
|
||||
break; /* stop fetching */
|
||||
if (!seq->is_cycled)
|
||||
{
|
||||
char buf[100];
|
||||
char buf[100];
|
||||
|
||||
snprintf(buf, 100, INT64_FORMAT, minv);
|
||||
elog(ERROR, "%s.nextval: reached MINVALUE (%s)",
|
||||
sequence->relname, buf);
|
||||
@ -507,7 +510,7 @@ currval(PG_FUNCTION_ARGS)
|
||||
int64 result;
|
||||
|
||||
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||
"currval"));
|
||||
"currval"));
|
||||
|
||||
/* open and AccessShareLock sequence */
|
||||
init_sequence("currval", sequence, &elm, &seqrel);
|
||||
@ -560,7 +563,10 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
|
||||
|
||||
if ((next < seq->min_value) || (next > seq->max_value))
|
||||
{
|
||||
char bufv[100], bufm[100], bufx[100];
|
||||
char bufv[100],
|
||||
bufm[100],
|
||||
bufx[100];
|
||||
|
||||
snprintf(bufv, 100, INT64_FORMAT, next);
|
||||
snprintf(bufm, 100, INT64_FORMAT, seq->min_value);
|
||||
snprintf(bufx, 100, INT64_FORMAT, seq->max_value);
|
||||
@ -632,7 +638,7 @@ setval(PG_FUNCTION_ARGS)
|
||||
RangeVar *sequence;
|
||||
|
||||
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||
"setval"));
|
||||
"setval"));
|
||||
|
||||
do_setval(sequence, next, true);
|
||||
|
||||
@ -652,7 +658,7 @@ setval_and_iscalled(PG_FUNCTION_ARGS)
|
||||
RangeVar *sequence;
|
||||
|
||||
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
|
||||
"setval"));
|
||||
"setval"));
|
||||
|
||||
do_setval(sequence, next, iscalled);
|
||||
|
||||
@ -672,7 +678,7 @@ init_sequence(const char *caller, RangeVar *relation,
|
||||
TransactionId thisxid = GetCurrentTransactionId();
|
||||
SeqTable elm;
|
||||
Relation seqrel;
|
||||
|
||||
|
||||
/* Look to see if we already have a seqtable entry for relation */
|
||||
for (elm = seqtab; elm != NULL; elm = elm->next)
|
||||
{
|
||||
@ -697,9 +703,9 @@ init_sequence(const char *caller, RangeVar *relation,
|
||||
* Allocate new seqtable entry if we didn't find one.
|
||||
*
|
||||
* 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 the sequence itself is deleted then the entry becomes wasted
|
||||
* memory, but it's small enough that this should not matter.
|
||||
*/
|
||||
if (elm == NULL)
|
||||
{
|
||||
/*
|
||||
@ -828,7 +834,9 @@ init_params(CreateSeqStmt *seq, Form_pg_sequence new)
|
||||
|
||||
if (new->min_value >= new->max_value)
|
||||
{
|
||||
char bufm[100], bufx[100];
|
||||
char bufm[100],
|
||||
bufx[100];
|
||||
|
||||
snprintf(bufm, 100, INT64_FORMAT, new->min_value);
|
||||
snprintf(bufx, 100, INT64_FORMAT, new->max_value);
|
||||
elog(ERROR, "DefineSequence: MINVALUE (%s) must be less than MAXVALUE (%s)",
|
||||
@ -847,7 +855,9 @@ init_params(CreateSeqStmt *seq, Form_pg_sequence new)
|
||||
|
||||
if (new->last_value < new->min_value)
|
||||
{
|
||||
char bufs[100], bufm[100];
|
||||
char bufs[100],
|
||||
bufm[100];
|
||||
|
||||
snprintf(bufs, 100, INT64_FORMAT, new->last_value);
|
||||
snprintf(bufm, 100, INT64_FORMAT, new->min_value);
|
||||
elog(ERROR, "DefineSequence: START value (%s) can't be less than MINVALUE (%s)",
|
||||
@ -855,7 +865,9 @@ init_params(CreateSeqStmt *seq, Form_pg_sequence new)
|
||||
}
|
||||
if (new->last_value > new->max_value)
|
||||
{
|
||||
char bufs[100], bufm[100];
|
||||
char bufs[100],
|
||||
bufm[100];
|
||||
|
||||
snprintf(bufs, 100, INT64_FORMAT, new->last_value);
|
||||
snprintf(bufm, 100, INT64_FORMAT, new->max_value);
|
||||
elog(ERROR, "DefineSequence: START value (%s) can't be greater than MAXVALUE (%s)",
|
||||
@ -866,7 +878,8 @@ init_params(CreateSeqStmt *seq, Form_pg_sequence new)
|
||||
new->cache_value = 1;
|
||||
else if ((new->cache_value = defGetInt64(cache_value)) <= 0)
|
||||
{
|
||||
char buf[100];
|
||||
char buf[100];
|
||||
|
||||
snprintf(buf, 100, INT64_FORMAT, new->cache_value);
|
||||
elog(ERROR, "DefineSequence: CACHE (%s) can't be <= 0",
|
||||
buf);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.38 2002/09/02 01:05:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.39 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -60,11 +60,11 @@ static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
|
||||
static void CheckTupleType(Form_pg_class tuple_class);
|
||||
static bool needs_toast_table(Relation rel);
|
||||
static void validateForeignKeyConstraint(FkConstraint *fkconstraint,
|
||||
Relation rel, Relation pkrel);
|
||||
static Oid createForeignKeyConstraint(Relation rel, Relation pkrel,
|
||||
FkConstraint *fkconstraint);
|
||||
Relation rel, Relation pkrel);
|
||||
static Oid createForeignKeyConstraint(Relation rel, Relation pkrel,
|
||||
FkConstraint *fkconstraint);
|
||||
static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
Oid constrOid);
|
||||
Oid constrOid);
|
||||
static char *fkMatchTypeToString(char match_type);
|
||||
|
||||
/* Used by attribute and relation renaming routines: */
|
||||
@ -114,9 +114,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
|
||||
/*
|
||||
* Look up the namespace in which we are supposed to create the
|
||||
* relation. Check we have permission to create there.
|
||||
* Skip check if bootstrapping, since permissions machinery may not
|
||||
* be working yet.
|
||||
* relation. Check we have permission to create there. Skip check if
|
||||
* bootstrapping, since permissions machinery may not be working yet.
|
||||
*/
|
||||
namespaceId = RangeVarGetCreationNamespace(stmt->relation);
|
||||
|
||||
@ -136,7 +135,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
*/
|
||||
schema = MergeAttributes(schema, stmt->inhRelations,
|
||||
stmt->relation->istemp,
|
||||
&inheritOids, &old_constraints, &parentHasOids);
|
||||
&inheritOids, &old_constraints, &parentHasOids);
|
||||
|
||||
numberOfAttributes = length(schema);
|
||||
if (numberOfAttributes <= 0)
|
||||
@ -180,10 +179,10 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Generate a constraint name. NB: this should match the
|
||||
* Generate a constraint name. NB: this should match the
|
||||
* form of names that GenerateConstraintName() may produce
|
||||
* for names added later. We are assured that there is
|
||||
* no name conflict, because MergeAttributes() did not pass
|
||||
* for names added later. We are assured that there is no
|
||||
* name conflict, because MergeAttributes() did not pass
|
||||
* back any names of this form.
|
||||
*/
|
||||
check[ncheck].ccname = (char *) palloc(NAMEDATALEN);
|
||||
@ -242,8 +241,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
* CREATE TABLE.
|
||||
*
|
||||
* Another task that's conveniently done at this step is to add
|
||||
* dependency links between columns and supporting relations (such
|
||||
* as SERIAL sequences).
|
||||
* dependency links between columns and supporting relations (such as
|
||||
* SERIAL sequences).
|
||||
*
|
||||
* First, scan schema to find new column defaults.
|
||||
*/
|
||||
@ -271,7 +270,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
if (colDef->support != NULL)
|
||||
{
|
||||
/* Create dependency for supporting relation for this column */
|
||||
ObjectAddress colobject,
|
||||
ObjectAddress colobject,
|
||||
suppobject;
|
||||
|
||||
colobject.classId = RelOid_pg_class;
|
||||
@ -334,9 +333,9 @@ TruncateRelation(const RangeVar *relation)
|
||||
Relation rel;
|
||||
Oid relid;
|
||||
Oid toastrelid;
|
||||
ScanKeyData key;
|
||||
Relation fkeyRel;
|
||||
SysScanDesc fkeyScan;
|
||||
ScanKeyData key;
|
||||
Relation fkeyRel;
|
||||
SysScanDesc fkeyScan;
|
||||
HeapTuple tuple;
|
||||
|
||||
/* Grab exclusive lock in preparation for truncate */
|
||||
@ -366,8 +365,7 @@ TruncateRelation(const RangeVar *relation)
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Don't allow truncate on tables which are referenced
|
||||
* by foreign keys
|
||||
* Don't allow truncate on tables which are referenced by foreign keys
|
||||
*/
|
||||
fkeyRel = heap_openr(ConstraintRelationName, AccessShareLock);
|
||||
|
||||
@ -380,8 +378,8 @@ TruncateRelation(const RangeVar *relation)
|
||||
SnapshotNow, 1, &key);
|
||||
|
||||
/*
|
||||
* First foreign key found with us as the reference
|
||||
* should throw an error.
|
||||
* First foreign key found with us as the reference should throw an
|
||||
* error.
|
||||
*/
|
||||
while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
|
||||
{
|
||||
@ -554,7 +552,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
/*
|
||||
* newattno[] will contain the child-table attribute numbers for
|
||||
* the attributes of this parent table. (They are not the same
|
||||
* for parents after the first one, nor if we have dropped columns.)
|
||||
* for parents after the first one, nor if we have dropped
|
||||
* columns.)
|
||||
*/
|
||||
newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
|
||||
|
||||
@ -572,9 +571,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
*/
|
||||
if (attribute->attisdropped)
|
||||
{
|
||||
/*
|
||||
* change_varattnos_of_a_node asserts that this is greater than
|
||||
* zero, so if anything tries to use it, we should find out.
|
||||
/*
|
||||
* change_varattnos_of_a_node asserts that this is greater
|
||||
* than zero, so if anything tries to use it, we should
|
||||
* find out.
|
||||
*/
|
||||
newattno[parent_attno - 1] = 0;
|
||||
continue;
|
||||
@ -684,6 +684,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
Node *expr;
|
||||
|
||||
cdef->contype = CONSTR_CHECK;
|
||||
|
||||
/*
|
||||
* Do not inherit generated constraint names, since they
|
||||
* might conflict across multiple inheritance parents.
|
||||
@ -857,8 +858,8 @@ StoreCatalogInheritance(Oid relationId, List *supers)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Store INHERITS information in pg_inherits using direct ancestors only.
|
||||
* Also enter dependencies on the direct ancestors.
|
||||
* Store INHERITS information in pg_inherits using direct ancestors
|
||||
* only. Also enter dependencies on the direct ancestors.
|
||||
*/
|
||||
relation = heap_openr(InheritsRelationName, RowExclusiveLock);
|
||||
desc = RelationGetDescr(relation);
|
||||
@ -1076,7 +1077,7 @@ renameatt(Oid myrelid,
|
||||
*
|
||||
* normally, only the owner of a class can change its schema.
|
||||
*/
|
||||
if (!allowSystemTableMods
|
||||
if (!allowSystemTableMods
|
||||
&& IsSystemRelation(targetrelation))
|
||||
elog(ERROR, "renameatt: class \"%s\" is a system catalog",
|
||||
RelationGetRelationName(targetrelation));
|
||||
@ -1141,8 +1142,8 @@ renameatt(Oid myrelid,
|
||||
oldattname);
|
||||
|
||||
/*
|
||||
* if the attribute is inherited, forbid the renaming, unless we
|
||||
* are already inside a recursive rename.
|
||||
* if the attribute is inherited, forbid the renaming, unless we are
|
||||
* already inside a recursive rename.
|
||||
*/
|
||||
if (attform->attisinherited && !recursing)
|
||||
elog(ERROR, "renameatt: inherited attribute \"%s\" may not be renamed",
|
||||
@ -1233,7 +1234,8 @@ renameatt(Oid myrelid,
|
||||
true, false);
|
||||
}
|
||||
|
||||
relation_close(targetrelation, NoLock); /* close rel but keep lock! */
|
||||
relation_close(targetrelation, NoLock); /* close rel but keep
|
||||
* lock! */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1382,7 +1384,7 @@ update_ri_trigger_args(Oid relid,
|
||||
{
|
||||
Relation tgrel;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc trigscan;
|
||||
SysScanDesc trigscan;
|
||||
HeapTuple tuple;
|
||||
Datum values[Natts_pg_trigger];
|
||||
char nulls[Natts_pg_trigger];
|
||||
@ -1577,8 +1579,8 @@ AlterTableAddColumn(Oid myrelid,
|
||||
HeapTuple typeTuple;
|
||||
Form_pg_type tform;
|
||||
int attndims;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
|
||||
/*
|
||||
* Grab an exclusive lock on the target table, which we will NOT
|
||||
@ -1666,7 +1668,7 @@ AlterTableAddColumn(Oid myrelid,
|
||||
|
||||
if (colDef->is_not_null)
|
||||
elog(ERROR, "Adding NOT NULL columns is not implemented."
|
||||
"\n\tAdd the column, then use ALTER TABLE ... SET NOT NULL.");
|
||||
"\n\tAdd the column, then use ALTER TABLE ... SET NOT NULL.");
|
||||
|
||||
pgclass = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||
|
||||
@ -1678,8 +1680,9 @@ AlterTableAddColumn(Oid myrelid,
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* this test is deliberately not attisdropped-aware, since if one tries
|
||||
* to add a column matching a dropped column name, it's gonna fail anyway.
|
||||
* this test is deliberately not attisdropped-aware, since if one
|
||||
* tries to add a column matching a dropped column name, it's gonna
|
||||
* fail anyway.
|
||||
*/
|
||||
if (SearchSysCacheExists(ATTNAME,
|
||||
ObjectIdGetDatum(myrelid),
|
||||
@ -1706,7 +1709,7 @@ AlterTableAddColumn(Oid myrelid,
|
||||
tform = (Form_pg_type) GETSTRUCT(typeTuple);
|
||||
|
||||
attributeTuple = heap_addheader(Natts_pg_attribute,
|
||||
false,
|
||||
false,
|
||||
ATTRIBUTE_TUPLE_SIZE,
|
||||
(void *) &attributeD);
|
||||
|
||||
@ -1806,8 +1809,8 @@ AlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse,
|
||||
HeapTuple tuple;
|
||||
AttrNumber attnum;
|
||||
Relation attr_rel;
|
||||
List *indexoidlist;
|
||||
List *indexoidscan;
|
||||
List *indexoidlist;
|
||||
List *indexoidscan;
|
||||
|
||||
rel = heap_open(myrelid, AccessExclusiveLock);
|
||||
|
||||
@ -1874,10 +1877,10 @@ AlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse,
|
||||
|
||||
foreach(indexoidscan, indexoidlist)
|
||||
{
|
||||
Oid indexoid = lfirsti(indexoidscan);
|
||||
Oid indexoid = lfirsti(indexoidscan);
|
||||
HeapTuple indexTuple;
|
||||
Form_pg_index indexStruct;
|
||||
int i;
|
||||
Form_pg_index indexStruct;
|
||||
int i;
|
||||
|
||||
indexTuple = SearchSysCache(INDEXRELID,
|
||||
ObjectIdGetDatum(indexoid),
|
||||
@ -1891,11 +1894,11 @@ AlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse,
|
||||
if (indexStruct->indisprimary)
|
||||
{
|
||||
/*
|
||||
* Loop over each attribute in the primary key and
|
||||
* see if it matches the to-be-altered attribute
|
||||
* Loop over each attribute in the primary key and see if it
|
||||
* matches the to-be-altered attribute
|
||||
*/
|
||||
for (i = 0; i < INDEX_MAX_KEYS &&
|
||||
indexStruct->indkey[i] != InvalidAttrNumber; i++)
|
||||
indexStruct->indkey[i] != InvalidAttrNumber; i++)
|
||||
{
|
||||
if (indexStruct->indkey[i] == attnum)
|
||||
elog(ERROR, "ALTER TABLE: Attribute \"%s\" is in a primary key", colName);
|
||||
@ -1913,7 +1916,7 @@ AlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse,
|
||||
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
|
||||
|
||||
tuple = SearchSysCacheCopyAttName(myrelid, colName);
|
||||
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
|
||||
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
|
||||
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
|
||||
RelationGetRelationName(rel), colName);
|
||||
|
||||
@ -1940,7 +1943,7 @@ AlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse,
|
||||
HeapTuple tuple;
|
||||
AttrNumber attnum;
|
||||
Relation attr_rel;
|
||||
HeapScanDesc scan;
|
||||
HeapScanDesc scan;
|
||||
TupleDesc tupdesc;
|
||||
|
||||
rel = heap_open(myrelid, AccessExclusiveLock);
|
||||
@ -2000,8 +2003,8 @@ AlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse,
|
||||
colName);
|
||||
|
||||
/*
|
||||
* Perform a scan to ensure that there are no NULL
|
||||
* values already in the relation
|
||||
* Perform a scan to ensure that there are no NULL values already in
|
||||
* the relation
|
||||
*/
|
||||
tupdesc = RelationGetDescr(rel);
|
||||
|
||||
@ -2009,7 +2012,7 @@ AlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse,
|
||||
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
Datum d;
|
||||
Datum d;
|
||||
bool isnull;
|
||||
|
||||
d = heap_getattr(tuple, attnum, tupdesc, &isnull);
|
||||
@ -2027,7 +2030,7 @@ AlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse,
|
||||
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
|
||||
|
||||
tuple = SearchSysCacheCopyAttName(myrelid, colName);
|
||||
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
|
||||
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
|
||||
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
|
||||
RelationGetRelationName(rel), colName);
|
||||
|
||||
@ -2153,7 +2156,7 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse,
|
||||
{
|
||||
Relation rel;
|
||||
int newtarget = 1;
|
||||
char newstorage = 'p';
|
||||
char newstorage = 'p';
|
||||
Relation attrelation;
|
||||
HeapTuple tuple;
|
||||
Form_pg_attribute attrtuple;
|
||||
@ -2200,7 +2203,7 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse,
|
||||
else if (*flagType == 'M')
|
||||
{
|
||||
/* STORAGE */
|
||||
char *storagemode;
|
||||
char *storagemode;
|
||||
|
||||
Assert(IsA(flagValue, String));
|
||||
storagemode = strVal(flagValue);
|
||||
@ -2246,7 +2249,7 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse,
|
||||
if (childrelid == myrelid)
|
||||
continue;
|
||||
AlterTableAlterColumnFlags(childrelid,
|
||||
false, colName, flagValue, flagType);
|
||||
false, colName, flagValue, flagType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2263,6 +2266,7 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse,
|
||||
if (attrtuple->attnum < 0)
|
||||
elog(ERROR, "ALTER TABLE: cannot change system attribute \"%s\"",
|
||||
colName);
|
||||
|
||||
/*
|
||||
* Now change the appropriate field
|
||||
*/
|
||||
@ -2306,7 +2310,7 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
|
||||
AttrNumber n;
|
||||
TupleDesc tupleDesc;
|
||||
bool success;
|
||||
ObjectAddress object;
|
||||
ObjectAddress object;
|
||||
|
||||
rel = heap_open(myrelid, AccessExclusiveLock);
|
||||
|
||||
@ -2336,8 +2340,9 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
|
||||
colName);
|
||||
|
||||
/*
|
||||
* Make sure there will be at least one user column left in the relation
|
||||
* after we drop this one. Zero-length tuples tend to confuse us.
|
||||
* Make sure there will be at least one user column left in the
|
||||
* relation after we drop this one. Zero-length tuples tend to
|
||||
* confuse us.
|
||||
*/
|
||||
tupleDesc = RelationGetDescr(rel);
|
||||
|
||||
@ -2355,7 +2360,7 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
|
||||
|
||||
if (!success)
|
||||
elog(ERROR, "ALTER TABLE: Cannot drop last column from table \"%s\"",
|
||||
RelationGetRelationName(rel));
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
/* Don't drop inherited columns */
|
||||
if (tupleDesc->attrs[attnum - 1]->attisinherited && !recursing)
|
||||
@ -2363,8 +2368,8 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
|
||||
colName);
|
||||
|
||||
/*
|
||||
* If we are asked to drop ONLY in this table (no recursion),
|
||||
* we need to mark the inheritors' attribute as non-inherited.
|
||||
* If we are asked to drop ONLY in this table (no recursion), we need
|
||||
* to mark the inheritors' attribute as non-inherited.
|
||||
*/
|
||||
if (!recurse && !recursing)
|
||||
{
|
||||
@ -2378,14 +2383,14 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
|
||||
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
|
||||
foreach(child, children)
|
||||
{
|
||||
Oid childrelid = lfirsti(child);
|
||||
Relation childrel;
|
||||
Oid childrelid = lfirsti(child);
|
||||
Relation childrel;
|
||||
HeapTuple tuple;
|
||||
|
||||
childrel = heap_open(childrelid, AccessExclusiveLock);
|
||||
|
||||
tuple = SearchSysCacheCopyAttName(childrelid, colName);
|
||||
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
|
||||
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
|
||||
elog(ERROR, "ALTER TABLE: relation %u has no column \"%s\"",
|
||||
childrelid, colName);
|
||||
|
||||
@ -2407,7 +2412,7 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
|
||||
if (recurse)
|
||||
{
|
||||
List *child,
|
||||
*children;
|
||||
*children;
|
||||
|
||||
/* this routine is actually in the planner */
|
||||
children = find_all_inheritors(myrelid);
|
||||
@ -2495,8 +2500,8 @@ AlterTableAddConstraint(Oid myrelid, bool recurse,
|
||||
foreach(listptr, newConstraints)
|
||||
{
|
||||
/*
|
||||
* copy is because we may destructively alter the node below
|
||||
* by inserting a generated name; this name is not necessarily
|
||||
* copy is because we may destructively alter the node below by
|
||||
* inserting a generated name; this name is not necessarily
|
||||
* correct for children or parents.
|
||||
*/
|
||||
Node *newConstraint = copyObject(lfirst(listptr));
|
||||
@ -2533,16 +2538,16 @@ AlterTableAddConstraint(Oid myrelid, bool recurse,
|
||||
if (constr->name)
|
||||
{
|
||||
if (ConstraintNameIsUsed(RelationGetRelid(rel),
|
||||
RelationGetNamespace(rel),
|
||||
constr->name))
|
||||
RelationGetNamespace(rel),
|
||||
constr->name))
|
||||
elog(ERROR, "constraint \"%s\" already exists for relation \"%s\"",
|
||||
constr->name,
|
||||
RelationGetRelationName(rel));
|
||||
RelationGetRelationName(rel));
|
||||
}
|
||||
else
|
||||
constr->name = GenerateConstraintName(RelationGetRelid(rel),
|
||||
RelationGetNamespace(rel),
|
||||
&counter);
|
||||
RelationGetNamespace(rel),
|
||||
&counter);
|
||||
|
||||
/*
|
||||
* We need to make a parse state and range
|
||||
@ -2552,8 +2557,8 @@ AlterTableAddConstraint(Oid myrelid, bool recurse,
|
||||
*/
|
||||
pstate = make_parsestate(NULL);
|
||||
rte = addRangeTableEntryForRelation(pstate,
|
||||
myrelid,
|
||||
makeAlias(RelationGetRelationName(rel), NIL),
|
||||
myrelid,
|
||||
makeAlias(RelationGetRelationName(rel), NIL),
|
||||
false,
|
||||
true);
|
||||
addRTEtoQuery(pstate, rte, true, true);
|
||||
@ -2657,23 +2662,23 @@ AlterTableAddConstraint(Oid myrelid, bool recurse,
|
||||
if (fkconstraint->constr_name)
|
||||
{
|
||||
if (ConstraintNameIsUsed(RelationGetRelid(rel),
|
||||
RelationGetNamespace(rel),
|
||||
fkconstraint->constr_name))
|
||||
RelationGetNamespace(rel),
|
||||
fkconstraint->constr_name))
|
||||
elog(ERROR, "constraint \"%s\" already exists for relation \"%s\"",
|
||||
fkconstraint->constr_name,
|
||||
RelationGetRelationName(rel));
|
||||
}
|
||||
else
|
||||
fkconstraint->constr_name = GenerateConstraintName(RelationGetRelid(rel),
|
||||
RelationGetNamespace(rel),
|
||||
&counter);
|
||||
RelationGetNamespace(rel),
|
||||
&counter);
|
||||
|
||||
/*
|
||||
* Grab an exclusive lock on the pk table, so that
|
||||
* someone doesn't delete rows out from under us.
|
||||
* (Although a lesser lock would do for that purpose,
|
||||
* we'll need exclusive lock anyway to add triggers
|
||||
* to the pk table; trying to start with a lesser lock
|
||||
* we'll need exclusive lock anyway to add triggers to
|
||||
* the pk table; trying to start with a lesser lock
|
||||
* will just create a risk of deadlock.)
|
||||
*/
|
||||
pkrel = heap_openrv(fkconstraint->pktable,
|
||||
@ -2716,12 +2721,14 @@ AlterTableAddConstraint(Oid myrelid, bool recurse,
|
||||
fkconstraint);
|
||||
|
||||
/*
|
||||
* Create the triggers that will enforce the constraint.
|
||||
* Create the triggers that will enforce the
|
||||
* constraint.
|
||||
*/
|
||||
createForeignKeyTriggers(rel, fkconstraint, constrOid);
|
||||
|
||||
/*
|
||||
* Close pk table, but keep lock until we've committed.
|
||||
* Close pk table, but keep lock until we've
|
||||
* committed.
|
||||
*/
|
||||
heap_close(pkrel, NoLock);
|
||||
|
||||
@ -2754,10 +2761,9 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint,
|
||||
int count;
|
||||
|
||||
/*
|
||||
* Scan through each tuple, calling RI_FKey_check_ins
|
||||
* (insert trigger) as if that tuple had just been
|
||||
* inserted. If any of those fail, it should
|
||||
* elog(ERROR) and that's that.
|
||||
* Scan through each tuple, calling RI_FKey_check_ins (insert trigger)
|
||||
* as if that tuple had just been inserted. If any of those fail, it
|
||||
* should elog(ERROR) and that's that.
|
||||
*/
|
||||
MemSet(&trig, 0, sizeof(trig));
|
||||
trig.tgoid = InvalidOid;
|
||||
@ -2848,7 +2854,7 @@ createForeignKeyConstraint(Relation rel, Relation pkrel,
|
||||
i = 0;
|
||||
foreach(l, fkconstraint->fk_attrs)
|
||||
{
|
||||
char *id = strVal(lfirst(l));
|
||||
char *id = strVal(lfirst(l));
|
||||
AttrNumber attno;
|
||||
|
||||
attno = get_attnum(RelationGetRelid(rel), id);
|
||||
@ -2864,7 +2870,7 @@ createForeignKeyConstraint(Relation rel, Relation pkrel,
|
||||
i = 0;
|
||||
foreach(l, fkconstraint->pk_attrs)
|
||||
{
|
||||
char *id = strVal(lfirst(l));
|
||||
char *id = strVal(lfirst(l));
|
||||
AttrNumber attno;
|
||||
|
||||
attno = get_attnum(RelationGetRelid(pkrel), id);
|
||||
@ -2883,14 +2889,14 @@ createForeignKeyConstraint(Relation rel, Relation pkrel,
|
||||
RelationGetRelid(rel),
|
||||
fkattr,
|
||||
fkcount,
|
||||
InvalidOid, /* not a domain constraint */
|
||||
InvalidOid, /* not a domain constraint */
|
||||
RelationGetRelid(pkrel),
|
||||
pkattr,
|
||||
pkcount,
|
||||
fkconstraint->fk_upd_action,
|
||||
fkconstraint->fk_del_action,
|
||||
fkconstraint->fk_matchtype,
|
||||
NULL, /* no check constraint */
|
||||
NULL, /* no check constraint */
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
@ -2910,7 +2916,8 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
constrobj;
|
||||
|
||||
/*
|
||||
* Reconstruct a RangeVar for my relation (not passed in, unfortunately).
|
||||
* Reconstruct a RangeVar for my relation (not passed in,
|
||||
* unfortunately).
|
||||
*/
|
||||
myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
|
||||
RelationGetRelationName(rel));
|
||||
@ -2956,9 +2963,9 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(myRel->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
|
||||
makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
pk_attr = fkconstraint->pk_attrs;
|
||||
if (length(fk_attr) != length(pk_attr))
|
||||
@ -2983,8 +2990,8 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
CommandCounterIncrement();
|
||||
|
||||
/*
|
||||
* Build and execute a CREATE CONSTRAINT TRIGGER statement for the
|
||||
* ON DELETE action on the referenced table.
|
||||
* Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
|
||||
* DELETE action on the referenced table.
|
||||
*/
|
||||
fk_trigger = makeNode(CreateTrigStmt);
|
||||
fk_trigger->trigname = fkconstraint->constr_name;
|
||||
@ -3032,9 +3039,9 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(myRel->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
|
||||
makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
pk_attr = fkconstraint->pk_attrs;
|
||||
while (fk_attr != NIL)
|
||||
@ -3054,8 +3061,8 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
CommandCounterIncrement();
|
||||
|
||||
/*
|
||||
* Build and execute a CREATE CONSTRAINT TRIGGER statement for the
|
||||
* ON UPDATE action on the referenced table.
|
||||
* Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
|
||||
* UPDATE action on the referenced table.
|
||||
*/
|
||||
fk_trigger = makeNode(CreateTrigStmt);
|
||||
fk_trigger->trigname = fkconstraint->constr_name;
|
||||
@ -3103,9 +3110,9 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(myRel->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
makeString(fkconstraint->pktable->relname));
|
||||
fk_trigger->args = lappend(fk_trigger->args,
|
||||
makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
|
||||
makeString(fkMatchTypeToString(fkconstraint->fk_matchtype)));
|
||||
fk_attr = fkconstraint->fk_attrs;
|
||||
pk_attr = fkconstraint->pk_attrs;
|
||||
while (fk_attr != NIL)
|
||||
@ -3129,7 +3136,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
||||
static char *
|
||||
fkMatchTypeToString(char match_type)
|
||||
{
|
||||
switch (match_type)
|
||||
switch (match_type)
|
||||
{
|
||||
case FKCONSTR_MATCH_FULL:
|
||||
return pstrdup("FULL");
|
||||
@ -3227,10 +3234,10 @@ AlterTableDropConstraint(Oid myrelid, bool recurse,
|
||||
void
|
||||
AlterTableOwner(Oid relationOid, int32 newOwnerSysId)
|
||||
{
|
||||
Relation target_rel;
|
||||
Relation class_rel;
|
||||
HeapTuple tuple;
|
||||
Form_pg_class tuple_class;
|
||||
Relation target_rel;
|
||||
Relation class_rel;
|
||||
HeapTuple tuple;
|
||||
Form_pg_class tuple_class;
|
||||
|
||||
/* Get exclusive lock till end of transaction on the target table */
|
||||
/* Use relation_open here so that we work on indexes... */
|
||||
@ -3250,8 +3257,8 @@ AlterTableOwner(Oid relationOid, int32 newOwnerSysId)
|
||||
CheckTupleType(tuple_class);
|
||||
|
||||
/*
|
||||
* Okay, this is a valid tuple: change its ownership and
|
||||
* write to the heap.
|
||||
* Okay, this is a valid tuple: change its ownership and write to the
|
||||
* heap.
|
||||
*/
|
||||
tuple_class->relowner = newOwnerSysId;
|
||||
simple_heap_update(class_rel, &tuple->t_self, tuple);
|
||||
@ -3267,16 +3274,15 @@ AlterTableOwner(Oid relationOid, int32 newOwnerSysId)
|
||||
if (tuple_class->relkind == RELKIND_RELATION ||
|
||||
tuple_class->relkind == RELKIND_TOASTVALUE)
|
||||
{
|
||||
List *index_oid_list, *i;
|
||||
List *index_oid_list,
|
||||
*i;
|
||||
|
||||
/* Find all the indexes belonging to this relation */
|
||||
index_oid_list = RelationGetIndexList(target_rel);
|
||||
|
||||
/* For each index, recursively change its ownership */
|
||||
foreach(i, index_oid_list)
|
||||
{
|
||||
AlterTableOwner(lfirsti(i), newOwnerSysId);
|
||||
}
|
||||
|
||||
freeList(index_oid_list);
|
||||
}
|
||||
@ -3285,9 +3291,7 @@ AlterTableOwner(Oid relationOid, int32 newOwnerSysId)
|
||||
{
|
||||
/* If it has a toast table, recurse to change its ownership */
|
||||
if (tuple_class->reltoastrelid != InvalidOid)
|
||||
{
|
||||
AlterTableOwner(tuple_class->reltoastrelid, newOwnerSysId);
|
||||
}
|
||||
}
|
||||
|
||||
heap_freetuple(tuple);
|
||||
@ -3355,7 +3359,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
* We cannot allow toasting a shared relation after initdb (because
|
||||
* there's no way to mark it toasted in other databases' pg_class).
|
||||
* Unfortunately we can't distinguish initdb from a manually started
|
||||
* standalone backend. However, we can at least prevent this mistake
|
||||
* standalone backend. However, we can at least prevent this mistake
|
||||
* under normal multi-user operation.
|
||||
*/
|
||||
shared_relation = rel->rd_rel->relisshared;
|
||||
@ -3453,10 +3457,11 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
tupdesc->attrs[2]->attstorage = 'p';
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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,
|
||||
PG_TOAST_NAMESPACE,
|
||||
@ -3471,12 +3476,12 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
/*
|
||||
* Create unique index on chunk_id, chunk_seq.
|
||||
*
|
||||
* NOTE: the normal TOAST access routines could actually function with
|
||||
* a single-column index on chunk_id only. However, the slice access
|
||||
* NOTE: the normal TOAST access routines could actually function with a
|
||||
* single-column index on chunk_id only. However, the slice access
|
||||
* routines use both columns for faster access to an individual chunk.
|
||||
* In addition, we want it to be unique as a check against the
|
||||
* In addition, we want it to be unique as a check against the
|
||||
* possibility of duplicate TOAST chunk OIDs. The index might also be
|
||||
* a little more efficient this way, since btree isn't all that happy
|
||||
* a little more efficient this way, since btree isn't all that happy
|
||||
* with large numbers of equal keys.
|
||||
*/
|
||||
|
||||
@ -3516,8 +3521,8 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
heap_freetuple(reltup);
|
||||
|
||||
/*
|
||||
* Register dependency from the toast table to the master, so that
|
||||
* the toast table will be deleted if the master is.
|
||||
* Register dependency from the toast table to the master, so that the
|
||||
* toast table will be deleted if the master is.
|
||||
*/
|
||||
baseobject.classId = RelOid_pg_class;
|
||||
baseobject.objectId = relOid;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.130 2002/09/02 01:05:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.131 2002/09/04 20:31:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -55,7 +55,7 @@ static void DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
|
||||
* Create a trigger. Returns the OID of the created trigger.
|
||||
*
|
||||
* forConstraint, if true, says that this trigger is being created to
|
||||
* implement a constraint. The caller will then be expected to make
|
||||
* implement a constraint. The caller will then be expected to make
|
||||
* a pg_depend entry linking the trigger to that constraint (and thereby
|
||||
* to the owning relation(s)).
|
||||
*/
|
||||
@ -69,7 +69,7 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
Relation rel;
|
||||
AclResult aclresult;
|
||||
Relation tgrel;
|
||||
SysScanDesc tgscan;
|
||||
SysScanDesc tgscan;
|
||||
ScanKeyData key;
|
||||
Relation pgrel;
|
||||
HeapTuple tuple;
|
||||
@ -82,8 +82,8 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
char *trigname;
|
||||
char *constrname;
|
||||
Oid constrrelid;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
|
||||
rel = heap_openrv(stmt->relation, AccessExclusiveLock);
|
||||
|
||||
@ -98,7 +98,7 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
|
||||
if (!allowSystemTableMods && IsSystemRelation(rel))
|
||||
elog(ERROR, "CreateTrigger: can't create trigger for system relation %s",
|
||||
stmt->relation->relname);
|
||||
stmt->relation->relname);
|
||||
|
||||
/* permission checks */
|
||||
|
||||
@ -132,9 +132,9 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
|
||||
/*
|
||||
* If trigger is an RI constraint, use specified trigger name as
|
||||
* constraint name and build a unique trigger name instead.
|
||||
* This is mainly for backwards compatibility with CREATE CONSTRAINT
|
||||
* TRIGGER commands.
|
||||
* constraint name and build a unique trigger name instead. This is
|
||||
* mainly for backwards compatibility with CREATE CONSTRAINT TRIGGER
|
||||
* commands.
|
||||
*/
|
||||
if (stmt->isconstraint)
|
||||
{
|
||||
@ -183,10 +183,10 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan pg_trigger for existing triggers on relation. We do this mainly
|
||||
* because we must count them; a secondary benefit is to give a nice
|
||||
* error message if there's already a trigger of the same name. (The
|
||||
* unique index on tgrelid/tgname would complain anyway.)
|
||||
* Scan pg_trigger for existing triggers on relation. We do this
|
||||
* mainly because we must count them; a secondary benefit is to give a
|
||||
* nice error message if there's already a trigger of the same name.
|
||||
* (The unique index on tgrelid/tgname would complain anyway.)
|
||||
*
|
||||
* NOTE that this is cool only because we have AccessExclusiveLock on the
|
||||
* relation, so the trigger set won't be changing underneath us.
|
||||
@ -241,13 +241,13 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
|
||||
values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
|
||||
values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
|
||||
CStringGetDatum(trigname));
|
||||
CStringGetDatum(trigname));
|
||||
values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
|
||||
values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
|
||||
values[Anum_pg_trigger_tgenabled - 1] = BoolGetDatum(true);
|
||||
values[Anum_pg_trigger_tgisconstraint - 1] = BoolGetDatum(stmt->isconstraint);
|
||||
values[Anum_pg_trigger_tgconstrname - 1] = DirectFunctionCall1(namein,
|
||||
CStringGetDatum(constrname));
|
||||
CStringGetDatum(constrname));
|
||||
values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
|
||||
values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
|
||||
values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
|
||||
@ -354,8 +354,9 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
* CREATE TRIGGER command, also make trigger be auto-dropped if its
|
||||
* relation is dropped or if the FK relation is dropped. (Auto drop
|
||||
* is compatible with our pre-7.3 behavior.) If the trigger is being
|
||||
* made for a constraint, we can skip the relation links; the dependency
|
||||
* on the constraint will indirectly depend on the relations.
|
||||
* made for a constraint, we can skip the relation links; the
|
||||
* dependency on the constraint will indirectly depend on the
|
||||
* relations.
|
||||
*/
|
||||
referenced.classId = RelOid_pg_proc;
|
||||
referenced.objectId = funcoid;
|
||||
@ -389,10 +390,10 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
|
||||
void
|
||||
DropTrigger(Oid relid, const char *trigname, DropBehavior behavior)
|
||||
{
|
||||
Relation tgrel;
|
||||
ScanKeyData skey[2];
|
||||
SysScanDesc tgscan;
|
||||
HeapTuple tup;
|
||||
Relation tgrel;
|
||||
ScanKeyData skey[2];
|
||||
SysScanDesc tgscan;
|
||||
HeapTuple tup;
|
||||
ObjectAddress object;
|
||||
|
||||
/*
|
||||
@ -440,14 +441,14 @@ void
|
||||
RemoveTriggerById(Oid trigOid)
|
||||
{
|
||||
Relation tgrel;
|
||||
SysScanDesc tgscan;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc tgscan;
|
||||
ScanKeyData skey[1];
|
||||
HeapTuple tup;
|
||||
Oid relid;
|
||||
Relation rel;
|
||||
Relation pgrel;
|
||||
HeapTuple tuple;
|
||||
Form_pg_class classForm;
|
||||
Form_pg_class classForm;
|
||||
|
||||
tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
|
||||
|
||||
@ -495,8 +496,8 @@ RemoveTriggerById(Oid trigOid)
|
||||
* rebuild relcache entries.
|
||||
*
|
||||
* Note this is OK only because we have AccessExclusiveLock on the rel,
|
||||
* so no one else is creating/deleting triggers on this rel at the same
|
||||
* time.
|
||||
* so no one else is creating/deleting triggers on this rel at the
|
||||
* same time.
|
||||
*/
|
||||
pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||
tuple = SearchSysCacheCopy(RELOID,
|
||||
@ -545,7 +546,7 @@ renametrig(Oid relid,
|
||||
Relation targetrel;
|
||||
Relation tgrel;
|
||||
HeapTuple tuple;
|
||||
SysScanDesc tgscan;
|
||||
SysScanDesc tgscan;
|
||||
ScanKeyData key[2];
|
||||
|
||||
/*
|
||||
@ -555,10 +556,10 @@ renametrig(Oid relid,
|
||||
targetrel = heap_open(relid, AccessExclusiveLock);
|
||||
|
||||
/*
|
||||
* Scan pg_trigger twice for existing triggers on relation. We do this in
|
||||
* order to ensure a trigger does not exist with newname (The unique index
|
||||
* on tgrelid/tgname would complain anyway) and to ensure a trigger does
|
||||
* exist with oldname.
|
||||
* Scan pg_trigger twice for existing triggers on relation. We do
|
||||
* this in order to ensure a trigger does not exist with newname (The
|
||||
* unique index on tgrelid/tgname would complain anyway) and to ensure
|
||||
* a trigger does exist with oldname.
|
||||
*
|
||||
* NOTE that this is cool only because we have AccessExclusiveLock on the
|
||||
* relation, so the trigger set won't be changing underneath us.
|
||||
@ -601,7 +602,7 @@ renametrig(Oid relid,
|
||||
/*
|
||||
* Update pg_trigger tuple with new tgname.
|
||||
*/
|
||||
tuple = heap_copytuple(tuple); /* need a modifiable copy */
|
||||
tuple = heap_copytuple(tuple); /* need a modifiable copy */
|
||||
|
||||
namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname, newname);
|
||||
|
||||
@ -611,9 +612,10 @@ renametrig(Oid relid,
|
||||
CatalogUpdateIndexes(tgrel, tuple);
|
||||
|
||||
/*
|
||||
* Invalidate relation's relcache entry so that other backends (and
|
||||
* this one too!) are sent SI message to make them rebuild relcache
|
||||
* entries. (Ideally this should happen automatically...)
|
||||
* Invalidate relation's relcache entry so that other backends
|
||||
* (and this one too!) are sent SI message to make them rebuild
|
||||
* relcache entries. (Ideally this should happen
|
||||
* automatically...)
|
||||
*/
|
||||
CacheInvalidateRelcache(relid);
|
||||
}
|
||||
@ -649,17 +651,17 @@ RelationBuildTriggers(Relation relation)
|
||||
int found = 0;
|
||||
Relation tgrel;
|
||||
ScanKeyData skey;
|
||||
SysScanDesc tgscan;
|
||||
SysScanDesc tgscan;
|
||||
HeapTuple htup;
|
||||
|
||||
triggers = (Trigger *) MemoryContextAlloc(CacheMemoryContext,
|
||||
ntrigs * sizeof(Trigger));
|
||||
|
||||
/*
|
||||
* Note: since we scan the triggers using TriggerRelidNameIndex,
|
||||
* we will be reading the triggers in name order, except possibly
|
||||
* during emergency-recovery operations (ie, IsIgnoringSystemIndexes).
|
||||
* This in turn ensures that triggers will be fired in name order.
|
||||
* Note: since we scan the triggers using TriggerRelidNameIndex, we
|
||||
* will be reading the triggers in name order, except possibly during
|
||||
* emergency-recovery operations (ie, IsIgnoringSystemIndexes). This
|
||||
* in turn ensures that triggers will be fired in name order.
|
||||
*/
|
||||
ScanKeyEntryInitialize(&skey,
|
||||
(bits16) 0x0,
|
||||
@ -1528,17 +1530,17 @@ deferredTriggerInvokeEvents(bool immediate_only)
|
||||
|
||||
/*
|
||||
* If immediate_only is true, we remove fully-processed events from
|
||||
* the event queue to recycle space. If immediate_only is false,
|
||||
* we are going to discard the whole event queue on return anyway,
|
||||
* so no need to bother with "retail" pfree's.
|
||||
* the event queue to recycle space. If immediate_only is false, we
|
||||
* are going to discard the whole event queue on return anyway, so no
|
||||
* need to bother with "retail" pfree's.
|
||||
*
|
||||
* In a scenario with many commands in a transaction and many
|
||||
* deferred-to-end-of-transaction triggers, it could get annoying
|
||||
* to rescan all the deferred triggers at each command end.
|
||||
* To speed this up, we could remember the actual end of the queue at
|
||||
* EndQuery and examine only events that are newer. On state changes
|
||||
* we simply reset the saved position to the beginning of the queue
|
||||
* and process all events once with the new states.
|
||||
* deferred-to-end-of-transaction triggers, it could get annoying to
|
||||
* rescan all the deferred triggers at each command end. To speed this
|
||||
* up, we could remember the actual end of the queue at EndQuery and
|
||||
* examine only events that are newer. On state changes we simply
|
||||
* reset the saved position to the beginning of the queue and process
|
||||
* all events once with the new states.
|
||||
*/
|
||||
|
||||
/* Make a per-tuple memory context for trigger function calls */
|
||||
@ -1559,8 +1561,8 @@ deferredTriggerInvokeEvents(bool immediate_only)
|
||||
/*
|
||||
* Check if event is already completely done.
|
||||
*/
|
||||
if (! (event->dte_event & (TRIGGER_DEFERRED_DONE |
|
||||
TRIGGER_DEFERRED_CANCELED)))
|
||||
if (!(event->dte_event & (TRIGGER_DEFERRED_DONE |
|
||||
TRIGGER_DEFERRED_CANCELED)))
|
||||
{
|
||||
MemoryContextReset(per_tuple_context);
|
||||
|
||||
@ -1577,16 +1579,16 @@ deferredTriggerInvokeEvents(bool immediate_only)
|
||||
* should call it now.
|
||||
*/
|
||||
if (immediate_only &&
|
||||
deferredTriggerCheckState(event->dte_item[i].dti_tgoid,
|
||||
event->dte_item[i].dti_state))
|
||||
deferredTriggerCheckState(event->dte_item[i].dti_tgoid,
|
||||
event->dte_item[i].dti_state))
|
||||
{
|
||||
still_deferred_ones = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* So let's fire it... but first, open the correct relation
|
||||
* if this is not the same relation as before.
|
||||
* So let's fire it... but first, open the correct
|
||||
* relation if this is not the same relation as before.
|
||||
*/
|
||||
if (rel == NULL || rel->rd_id != event->dte_relid)
|
||||
{
|
||||
@ -1596,14 +1598,14 @@ deferredTriggerInvokeEvents(bool immediate_only)
|
||||
pfree(finfo);
|
||||
|
||||
/*
|
||||
* We assume that an appropriate lock is still held by the
|
||||
* executor, so grab no new lock here.
|
||||
* We assume that an appropriate lock is still held by
|
||||
* the executor, so grab no new lock here.
|
||||
*/
|
||||
rel = heap_open(event->dte_relid, NoLock);
|
||||
|
||||
/*
|
||||
* Allocate space to cache fmgr lookup info for triggers
|
||||
* of this relation.
|
||||
* Allocate space to cache fmgr lookup info for
|
||||
* triggers of this relation.
|
||||
*/
|
||||
finfo = (FmgrInfo *)
|
||||
palloc(rel->trigdesc->numtriggers * sizeof(FmgrInfo));
|
||||
@ -1615,15 +1617,15 @@ deferredTriggerInvokeEvents(bool immediate_only)
|
||||
per_tuple_context);
|
||||
|
||||
event->dte_item[i].dti_state |= TRIGGER_DEFERRED_DONE;
|
||||
} /* end loop over items within event */
|
||||
} /* end loop over items within event */
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's now completely done, throw it away.
|
||||
*
|
||||
* NB: it's possible the trigger calls above added more events to the
|
||||
* queue, or that calls we will do later will want to add more,
|
||||
* so we have to be careful about maintaining list validity here.
|
||||
* queue, or that calls we will do later will want to add more, so
|
||||
* we have to be careful about maintaining list validity here.
|
||||
*/
|
||||
next_event = event->dte_next;
|
||||
|
||||
@ -1724,6 +1726,7 @@ DeferredTriggerBeginXact(void)
|
||||
oldcxt = MemoryContextSwitchTo(deftrig_cxt);
|
||||
|
||||
deftrig_all_isset = false;
|
||||
|
||||
/*
|
||||
* If unspecified, constraints default to IMMEDIATE, per SQL
|
||||
*/
|
||||
@ -1827,8 +1830,8 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||
|
||||
/*
|
||||
* If called outside a transaction block, we can safely return: this
|
||||
* command cannot effect any subsequent transactions, and there
|
||||
* are no "session-level" trigger settings.
|
||||
* command cannot effect any subsequent transactions, and there are no
|
||||
* "session-level" trigger settings.
|
||||
*/
|
||||
if (!IsTransactionBlock())
|
||||
return;
|
||||
@ -1879,7 +1882,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||
{
|
||||
char *cname = strVal(lfirst(l));
|
||||
ScanKeyData skey;
|
||||
SysScanDesc tgscan;
|
||||
SysScanDesc tgscan;
|
||||
HeapTuple htup;
|
||||
|
||||
/*
|
||||
@ -1892,7 +1895,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||
* Setup to scan pg_trigger by tgconstrname ...
|
||||
*/
|
||||
ScanKeyEntryInitialize(&skey, (bits16) 0x0,
|
||||
(AttrNumber) Anum_pg_trigger_tgconstrname,
|
||||
(AttrNumber) Anum_pg_trigger_tgconstrname,
|
||||
(RegProcedure) F_NAMEEQ,
|
||||
PointerGetDatum(cname));
|
||||
|
||||
@ -1910,9 +1913,9 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||
Oid constr_oid;
|
||||
|
||||
/*
|
||||
* If we found some, check that they fit the deferrability but
|
||||
* skip ON <event> RESTRICT ones, since they are silently
|
||||
* never deferrable.
|
||||
* If we found some, check that they fit the deferrability
|
||||
* but skip ON <event> RESTRICT ones, since they are
|
||||
* silently never deferrable.
|
||||
*/
|
||||
if (stmt->deferred && !pg_trigger->tgdeferrable &&
|
||||
pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_UPD &&
|
||||
@ -1971,11 +1974,11 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||
|
||||
/*
|
||||
* SQL99 requires that when a constraint is set to IMMEDIATE, any
|
||||
* deferred checks against that constraint must be made when the
|
||||
* SET CONSTRAINTS command is executed -- i.e. the effects of the
|
||||
* SET CONSTRAINTS command applies retroactively. This happens "for
|
||||
* free" since we have already made the necessary modifications to
|
||||
* the constraints, and deferredTriggerEndQuery() is called by
|
||||
* deferred checks against that constraint must be made when the SET
|
||||
* CONSTRAINTS command is executed -- i.e. the effects of the SET
|
||||
* CONSTRAINTS command applies retroactively. This happens "for free"
|
||||
* since we have already made the necessary modifications to the
|
||||
* constraints, and deferredTriggerEndQuery() is called by
|
||||
* finish_xact_command().
|
||||
*/
|
||||
}
|
||||
@ -2062,6 +2065,7 @@ DeferredTriggerSaveEvent(ResultRelInfo *relinfo, int event,
|
||||
break;
|
||||
|
||||
case TRIGGER_EVENT_UPDATE:
|
||||
|
||||
/*
|
||||
* Check if one of the referenced keys is changed.
|
||||
*/
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.12 2002/08/29 00:17:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.13 2002/09/04 20:31:16 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -49,7 +49,7 @@
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
static Oid findTypeIOFunction(List *procname, Oid typeOid, bool isOutput);
|
||||
static Oid findTypeIOFunction(List *procname, Oid typeOid, bool isOutput);
|
||||
|
||||
/*
|
||||
* DefineType
|
||||
@ -101,15 +101,15 @@ DefineType(List *names, List *parameters)
|
||||
if (strcasecmp(defel->defname, "internallength") == 0)
|
||||
internalLength = defGetTypeLength(defel);
|
||||
else if (strcasecmp(defel->defname, "externallength") == 0)
|
||||
; /* ignored -- remove after 7.3 */
|
||||
; /* ignored -- remove after 7.3 */
|
||||
else if (strcasecmp(defel->defname, "input") == 0)
|
||||
inputName = defGetQualifiedName(defel);
|
||||
else if (strcasecmp(defel->defname, "output") == 0)
|
||||
outputName = defGetQualifiedName(defel);
|
||||
else if (strcasecmp(defel->defname, "send") == 0)
|
||||
; /* ignored -- remove after 7.3 */
|
||||
; /* ignored -- remove after 7.3 */
|
||||
else if (strcasecmp(defel->defname, "receive") == 0)
|
||||
; /* ignored -- remove after 7.3 */
|
||||
; /* ignored -- remove after 7.3 */
|
||||
else if (strcasecmp(defel->defname, "delimiter") == 0)
|
||||
{
|
||||
char *p = defGetString(defel);
|
||||
@ -203,8 +203,9 @@ DefineType(List *names, List *parameters)
|
||||
outputOid = findTypeIOFunction(outputName, typoid, true);
|
||||
|
||||
/*
|
||||
* Verify that I/O procs return the expected thing. OPAQUE is an allowed,
|
||||
* but deprecated, alternative to the fully type-safe choices.
|
||||
* Verify that I/O procs return the expected thing. OPAQUE is an
|
||||
* allowed, but deprecated, alternative to the fully type-safe
|
||||
* choices.
|
||||
*/
|
||||
resulttype = get_func_rettype(inputOid);
|
||||
if (!(OidIsValid(typoid) && resulttype == typoid))
|
||||
@ -229,26 +230,26 @@ DefineType(List *names, List *parameters)
|
||||
* now have TypeCreate do all the real work.
|
||||
*/
|
||||
typoid =
|
||||
TypeCreate(typeName, /* type name */
|
||||
typeNamespace, /* namespace */
|
||||
InvalidOid, /* preassigned type oid (not done here) */
|
||||
InvalidOid, /* relation oid (n/a here) */
|
||||
0, /* relation kind (ditto) */
|
||||
internalLength, /* internal size */
|
||||
'b', /* type-type (base type) */
|
||||
delimiter, /* array element delimiter */
|
||||
inputOid, /* input procedure */
|
||||
outputOid, /* output procedure */
|
||||
elemType, /* element type ID */
|
||||
InvalidOid, /* base type ID (only for domains) */
|
||||
TypeCreate(typeName, /* type name */
|
||||
typeNamespace, /* namespace */
|
||||
InvalidOid, /* preassigned type oid (not done here) */
|
||||
InvalidOid, /* relation oid (n/a here) */
|
||||
0, /* relation kind (ditto) */
|
||||
internalLength, /* internal size */
|
||||
'b', /* type-type (base type) */
|
||||
delimiter, /* array element delimiter */
|
||||
inputOid, /* input procedure */
|
||||
outputOid, /* output procedure */
|
||||
elemType, /* element type ID */
|
||||
InvalidOid, /* base type ID (only for domains) */
|
||||
defaultValue, /* default type value */
|
||||
NULL, /* no binary form available */
|
||||
byValue, /* passed by value */
|
||||
alignment, /* required alignment */
|
||||
storage, /* TOAST strategy */
|
||||
-1, /* typMod (Domains only) */
|
||||
0, /* Array Dimensions of typbasetype */
|
||||
false); /* Type NOT NULL */
|
||||
NULL, /* no binary form available */
|
||||
byValue, /* passed by value */
|
||||
alignment, /* required alignment */
|
||||
storage, /* TOAST strategy */
|
||||
-1, /* typMod (Domains only) */
|
||||
0, /* Array Dimensions of typbasetype */
|
||||
false); /* Type NOT NULL */
|
||||
|
||||
/*
|
||||
* When we create a base type (as opposed to a complex type) we need
|
||||
@ -392,7 +393,7 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
List *listptr;
|
||||
Oid basetypeoid;
|
||||
Oid domainoid;
|
||||
Form_pg_type baseType;
|
||||
Form_pg_type baseType;
|
||||
|
||||
/* Convert list of names to a name and namespace */
|
||||
domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
|
||||
@ -406,7 +407,7 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
|
||||
/*
|
||||
* Domainnames, unlike typenames don't need to account for the '_'
|
||||
* prefix. So they can be one character longer.
|
||||
* prefix. So they can be one character longer.
|
||||
*/
|
||||
if (strlen(domainName) > (NAMEDATALEN - 1))
|
||||
elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
|
||||
@ -421,9 +422,10 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
basetypeoid = HeapTupleGetOid(typeTup);
|
||||
|
||||
/*
|
||||
* Base type must be a plain base type. Domains over pseudo types would
|
||||
* create a security hole. Domains of domains might be made to work in
|
||||
* the future, but not today. Ditto for domains over complex types.
|
||||
* Base type must be a plain base type. Domains over pseudo types
|
||||
* would create a security hole. Domains of domains might be made to
|
||||
* work in the future, but not today. Ditto for domains over complex
|
||||
* types.
|
||||
*/
|
||||
typtype = baseType->typtype;
|
||||
if (typtype != 'b')
|
||||
@ -450,13 +452,13 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
outputProcedure = baseType->typoutput;
|
||||
|
||||
/* Inherited default value */
|
||||
datum = SysCacheGetAttr(TYPEOID, typeTup,
|
||||
datum = SysCacheGetAttr(TYPEOID, typeTup,
|
||||
Anum_pg_type_typdefault, &isnull);
|
||||
if (!isnull)
|
||||
defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
|
||||
|
||||
/* Inherited default binary value */
|
||||
datum = SysCacheGetAttr(TYPEOID, typeTup,
|
||||
datum = SysCacheGetAttr(TYPEOID, typeTup,
|
||||
Anum_pg_type_typdefaultbin, &isnull);
|
||||
if (!isnull)
|
||||
defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
|
||||
@ -469,11 +471,11 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
basetypelem = baseType->typelem;
|
||||
|
||||
/*
|
||||
* Run through constraints manually to avoid the additional
|
||||
* processing conducted by DefineRelation() and friends.
|
||||
* Run through constraints manually to avoid the additional processing
|
||||
* conducted by DefineRelation() and friends.
|
||||
*
|
||||
* Besides, we don't want any constraints to be cooked. We'll
|
||||
* do that when the table is created via MergeDomainAttributes().
|
||||
* Besides, we don't want any constraints to be cooked. We'll do that
|
||||
* when the table is created via MergeDomainAttributes().
|
||||
*/
|
||||
foreach(listptr, schema)
|
||||
{
|
||||
@ -482,77 +484,79 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
|
||||
switch (colDef->contype)
|
||||
{
|
||||
/*
|
||||
* The inherited default value may be overridden by the user
|
||||
* with the DEFAULT <expr> statement.
|
||||
*
|
||||
* We have to search the entire constraint tree returned as we
|
||||
* don't want to cook or fiddle too much.
|
||||
*/
|
||||
/*
|
||||
* The inherited default value may be overridden by the
|
||||
* user with the DEFAULT <expr> statement.
|
||||
*
|
||||
* We have to search the entire constraint tree returned as
|
||||
* we don't want to cook or fiddle too much.
|
||||
*/
|
||||
case CONSTR_DEFAULT:
|
||||
if (defaultExpr)
|
||||
elog(ERROR, "CREATE DOMAIN has multiple DEFAULT expressions");
|
||||
/* Create a dummy ParseState for transformExpr */
|
||||
pstate = make_parsestate(NULL);
|
||||
|
||||
/*
|
||||
* Cook the colDef->raw_expr into an expression.
|
||||
* Note: Name is strictly for error message
|
||||
* Cook the colDef->raw_expr into an expression. Note:
|
||||
* Name is strictly for error message
|
||||
*/
|
||||
defaultExpr = cookDefault(pstate, colDef->raw_expr,
|
||||
basetypeoid,
|
||||
stmt->typename->typmod,
|
||||
domainName);
|
||||
|
||||
/*
|
||||
* Expression must be stored as a nodeToString result,
|
||||
* but we also require a valid textual representation
|
||||
* (mainly to make life easier for pg_dump).
|
||||
* Expression must be stored as a nodeToString result, but
|
||||
* we also require a valid textual representation (mainly
|
||||
* to make life easier for pg_dump).
|
||||
*/
|
||||
defaultValue = deparse_expression(defaultExpr,
|
||||
deparse_context_for(domainName,
|
||||
InvalidOid),
|
||||
false);
|
||||
deparse_context_for(domainName,
|
||||
InvalidOid),
|
||||
false);
|
||||
defaultValueBin = nodeToString(defaultExpr);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Find the NULL constraint.
|
||||
*/
|
||||
/*
|
||||
* Find the NULL constraint.
|
||||
*/
|
||||
case CONSTR_NOTNULL:
|
||||
if (nullDefined)
|
||||
elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
|
||||
typNotNull = true;
|
||||
nullDefined = true;
|
||||
break;
|
||||
break;
|
||||
|
||||
case CONSTR_NULL:
|
||||
if (nullDefined)
|
||||
elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
|
||||
typNotNull = false;
|
||||
nullDefined = true;
|
||||
break;
|
||||
break;
|
||||
|
||||
case CONSTR_UNIQUE:
|
||||
elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported");
|
||||
break;
|
||||
case CONSTR_UNIQUE:
|
||||
elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported");
|
||||
break;
|
||||
|
||||
case CONSTR_PRIMARY:
|
||||
elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported");
|
||||
break;
|
||||
case CONSTR_PRIMARY:
|
||||
elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported");
|
||||
break;
|
||||
|
||||
case CONSTR_CHECK:
|
||||
elog(ERROR, "DefineDomain: CHECK Constraints not supported");
|
||||
break;
|
||||
case CONSTR_CHECK:
|
||||
elog(ERROR, "DefineDomain: CHECK Constraints not supported");
|
||||
break;
|
||||
|
||||
case CONSTR_ATTR_DEFERRABLE:
|
||||
case CONSTR_ATTR_NOT_DEFERRABLE:
|
||||
case CONSTR_ATTR_DEFERRED:
|
||||
case CONSTR_ATTR_IMMEDIATE:
|
||||
elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
|
||||
break;
|
||||
case CONSTR_ATTR_DEFERRABLE:
|
||||
case CONSTR_ATTR_NOT_DEFERRABLE:
|
||||
case CONSTR_ATTR_DEFERRED:
|
||||
case CONSTR_ATTR_IMMEDIATE:
|
||||
elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "DefineDomain: unrecognized constraint node type");
|
||||
break;
|
||||
elog(ERROR, "DefineDomain: unrecognized constraint node type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,33 +564,33 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
* Have TypeCreate do all the real work.
|
||||
*/
|
||||
domainoid =
|
||||
TypeCreate(domainName, /* type name */
|
||||
TypeCreate(domainName, /* type name */
|
||||
domainNamespace, /* namespace */
|
||||
InvalidOid, /* preassigned type oid (none here) */
|
||||
InvalidOid, /* relation oid (n/a here) */
|
||||
0, /* relation kind (ditto) */
|
||||
InvalidOid, /* preassigned type oid (none here) */
|
||||
InvalidOid, /* relation oid (n/a here) */
|
||||
0, /* relation kind (ditto) */
|
||||
internalLength, /* internal size */
|
||||
'd', /* type-type (domain type) */
|
||||
delimiter, /* array element delimiter */
|
||||
'd', /* type-type (domain type) */
|
||||
delimiter, /* array element delimiter */
|
||||
inputProcedure, /* input procedure */
|
||||
outputProcedure, /* output procedure */
|
||||
basetypelem, /* element type ID */
|
||||
basetypeoid, /* base type ID */
|
||||
defaultValue, /* default type value (text) */
|
||||
basetypelem, /* element type ID */
|
||||
basetypeoid, /* base type ID */
|
||||
defaultValue, /* default type value (text) */
|
||||
defaultValueBin, /* default type value (binary) */
|
||||
byValue, /* passed by value */
|
||||
alignment, /* required alignment */
|
||||
storage, /* TOAST strategy */
|
||||
stmt->typename->typmod, /* typeMod value */
|
||||
typNDims, /* Array dimensions for base type */
|
||||
typNotNull); /* Type NOT NULL */
|
||||
byValue, /* passed by value */
|
||||
alignment, /* required alignment */
|
||||
storage, /* TOAST strategy */
|
||||
stmt->typename->typmod, /* typeMod value */
|
||||
typNDims, /* Array dimensions for base type */
|
||||
typNotNull); /* Type NOT NULL */
|
||||
|
||||
/*
|
||||
* Add any dependencies needed for the default expression.
|
||||
*/
|
||||
if (defaultExpr)
|
||||
{
|
||||
ObjectAddress domobject;
|
||||
ObjectAddress domobject;
|
||||
|
||||
domobject.classId = RelOid_pg_type;
|
||||
domobject.objectId = domainoid;
|
||||
@ -678,10 +682,10 @@ findTypeIOFunction(List *procname, Oid typeOid, bool isOutput)
|
||||
if (isOutput)
|
||||
{
|
||||
/*
|
||||
* Output functions can take a single argument of the type,
|
||||
* or two arguments (data value, element OID). The signature
|
||||
* may use OPAQUE in place of the actual type name; this is the
|
||||
* only possibility if the type doesn't yet exist as a shell.
|
||||
* Output functions can take a single argument of the type, or two
|
||||
* arguments (data value, element OID). The signature may use
|
||||
* OPAQUE in place of the actual type name; this is the only
|
||||
* possibility if the type doesn't yet exist as a shell.
|
||||
*
|
||||
* Note: although we could throw a NOTICE in this routine if OPAQUE
|
||||
* is used, we do not because of the probability that it'd be
|
||||
@ -728,8 +732,8 @@ findTypeIOFunction(List *procname, Oid typeOid, bool isOutput)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Input functions can take a single argument of type CSTRING,
|
||||
* or three arguments (string, element OID, typmod). The signature
|
||||
* Input functions can take a single argument of type CSTRING, or
|
||||
* three arguments (string, element OID, typmod). The signature
|
||||
* may use OPAQUE in place of CSTRING.
|
||||
*/
|
||||
MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
||||
@ -793,7 +797,7 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
|
||||
|
||||
if (coldeflist == NIL)
|
||||
elog(ERROR, "attempted to define composite type relation with"
|
||||
" no attrs");
|
||||
" no attrs");
|
||||
|
||||
/*
|
||||
* now create the parameters for keys/inheritance etc. All of them are
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.110 2002/09/02 02:47:01 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.111 2002/09/04 20:31:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -41,7 +41,7 @@ extern bool Password_encryption;
|
||||
|
||||
static void CheckPgUserAclNotNull(void);
|
||||
static void UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple,
|
||||
List *members);
|
||||
List *members);
|
||||
static IdList *IdListToArray(List *members);
|
||||
static List *IdArrayToList(IdList *oldarray);
|
||||
|
||||
@ -52,7 +52,8 @@ static List *IdArrayToList(IdList *oldarray);
|
||||
* Outputs string in quotes, with double-quotes duplicated.
|
||||
* We could use quote_ident(), but that expects a TEXT argument.
|
||||
*/
|
||||
static void fputs_quote(char *str, FILE *fp)
|
||||
static void
|
||||
fputs_quote(char *str, FILE *fp)
|
||||
{
|
||||
fputc('"', fp);
|
||||
while (*str)
|
||||
@ -79,7 +80,7 @@ group_getfilename(void)
|
||||
char *pfnam;
|
||||
|
||||
bufsize = strlen(DataDir) + strlen("/global/") +
|
||||
strlen(USER_GROUP_FILE) + 1;
|
||||
strlen(USER_GROUP_FILE) + 1;
|
||||
pfnam = (char *) palloc(bufsize);
|
||||
snprintf(pfnam, bufsize, "%s/global/%s", DataDir, USER_GROUP_FILE);
|
||||
|
||||
@ -99,7 +100,7 @@ user_getfilename(void)
|
||||
char *pfnam;
|
||||
|
||||
bufsize = strlen(DataDir) + strlen("/global/") +
|
||||
strlen(PWD_FILE) + 1;
|
||||
strlen(PWD_FILE) + 1;
|
||||
pfnam = (char *) palloc(bufsize);
|
||||
snprintf(pfnam, bufsize, "%s/global/%s", DataDir, PWD_FILE);
|
||||
|
||||
@ -125,8 +126,8 @@ write_group_file(Relation urel, Relation grel)
|
||||
|
||||
/*
|
||||
* Create a temporary filename to be renamed later. This prevents the
|
||||
* backend from clobbering the pg_group file while the postmaster might
|
||||
* be reading from it.
|
||||
* backend from clobbering the pg_group file while the postmaster
|
||||
* might be reading from it.
|
||||
*/
|
||||
filename = group_getfilename();
|
||||
bufsize = strlen(filename) + 12;
|
||||
@ -143,14 +144,16 @@ write_group_file(Relation urel, Relation grel)
|
||||
scan = heap_beginscan(grel, SnapshotSelf, 0, NULL);
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
Datum datum, grolist_datum;
|
||||
Datum datum,
|
||||
grolist_datum;
|
||||
bool isnull;
|
||||
char *groname;
|
||||
IdList *grolist_p;
|
||||
AclId *aidp;
|
||||
int i, j,
|
||||
int i,
|
||||
j,
|
||||
num;
|
||||
char *usename;
|
||||
char *usename;
|
||||
bool first_user = true;
|
||||
|
||||
datum = heap_getattr(tuple, Anum_pg_group_groname, dsc, &isnull);
|
||||
@ -199,8 +202,8 @@ write_group_file(Relation urel, Relation grel)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* File format is:
|
||||
* "dbname" "user1" "user2" "user3"
|
||||
/*
|
||||
* File format is: "dbname" "user1" "user2" "user3"
|
||||
*/
|
||||
if (first_user)
|
||||
{
|
||||
@ -833,8 +836,8 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
||||
valuestr = flatten_set_variable_args(stmt->variable, stmt->value);
|
||||
|
||||
/*
|
||||
* RowExclusiveLock is sufficient, because we don't need to update
|
||||
* the flat password file.
|
||||
* RowExclusiveLock is sufficient, because we don't need to update the
|
||||
* flat password file.
|
||||
*/
|
||||
rel = heap_openr(ShadowRelationName, RowExclusiveLock);
|
||||
oldtuple = SearchSysCache(SHADOWNAME,
|
||||
@ -844,23 +847,23 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
||||
elog(ERROR, "user \"%s\" does not exist", stmt->user);
|
||||
|
||||
if (!(superuser()
|
||||
|| ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId()))
|
||||
|| ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId()))
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
for (i = 0; i < Natts_pg_shadow; i++)
|
||||
repl_repl[i] = ' ';
|
||||
|
||||
repl_repl[Anum_pg_shadow_useconfig-1] = 'r';
|
||||
if (strcmp(stmt->variable, "all")==0 && valuestr == NULL)
|
||||
repl_repl[Anum_pg_shadow_useconfig - 1] = 'r';
|
||||
if (strcmp(stmt->variable, "all") == 0 && valuestr == NULL)
|
||||
/* RESET ALL */
|
||||
repl_null[Anum_pg_shadow_useconfig-1] = 'n';
|
||||
repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
|
||||
else
|
||||
{
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
ArrayType *array;
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
ArrayType *array;
|
||||
|
||||
repl_null[Anum_pg_shadow_useconfig-1] = ' ';
|
||||
repl_null[Anum_pg_shadow_useconfig - 1] = ' ';
|
||||
|
||||
datum = SysCacheGetAttr(SHADOWNAME, oldtuple,
|
||||
Anum_pg_shadow_useconfig, &isnull);
|
||||
@ -872,7 +875,7 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
||||
else
|
||||
array = GUCArrayDelete(array, stmt->variable);
|
||||
|
||||
repl_val[Anum_pg_shadow_useconfig-1] = PointerGetDatum(array);
|
||||
repl_val[Anum_pg_shadow_useconfig - 1] = PointerGetDatum(array);
|
||||
}
|
||||
|
||||
newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl);
|
||||
@ -1253,12 +1256,12 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
* create user */
|
||||
{
|
||||
/*
|
||||
* convert the to be added usernames to sysids and add them to
|
||||
* the list
|
||||
* convert the to be added usernames to sysids and add them to the
|
||||
* list
|
||||
*/
|
||||
foreach(item, stmt->listUsers)
|
||||
{
|
||||
int32 sysid;
|
||||
int32 sysid;
|
||||
|
||||
if (strcmp(tag, "ALTER GROUP") == 0)
|
||||
{
|
||||
@ -1282,6 +1285,7 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
if (!intMember(sysid, newlist))
|
||||
newlist = lappendi(newlist, sysid);
|
||||
else
|
||||
|
||||
/*
|
||||
* we silently assume here that this error will only come
|
||||
* up in a ALTER GROUP statement
|
||||
@ -1306,8 +1310,8 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* convert the to be dropped usernames to sysids and
|
||||
* remove them from the list
|
||||
* convert the to be dropped usernames to sysids and remove
|
||||
* them from the list
|
||||
*/
|
||||
foreach(item, stmt->listUsers)
|
||||
{
|
||||
@ -1375,7 +1379,7 @@ UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple,
|
||||
new_record_repl[Anum_pg_group_grolist - 1] = 'r';
|
||||
|
||||
tuple = heap_modifytuple(group_tuple, group_rel,
|
||||
new_record, new_record_nulls, new_record_repl);
|
||||
new_record, new_record_nulls, new_record_repl);
|
||||
|
||||
simple_heap_update(group_rel, &group_tuple->t_self, tuple);
|
||||
|
||||
@ -1401,12 +1405,10 @@ IdListToArray(List *members)
|
||||
newarray->elemtype = INT4OID;
|
||||
ARR_NDIM(newarray) = 1; /* one dimensional array */
|
||||
ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */
|
||||
ARR_DIMS(newarray)[0] = nmembers; /* axis is this long */
|
||||
ARR_DIMS(newarray)[0] = nmembers; /* axis is this long */
|
||||
i = 0;
|
||||
foreach(item, members)
|
||||
{
|
||||
((int *) ARR_DATA_PTR(newarray))[i++] = lfirsti(item);
|
||||
}
|
||||
|
||||
return newarray;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.236 2002/09/02 01:05:04 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.237 2002/09/04 20:31:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -100,7 +100,7 @@ typedef struct VRelStats
|
||||
|
||||
static MemoryContext vac_context = NULL;
|
||||
|
||||
static int elevel = -1;
|
||||
static int elevel = -1;
|
||||
|
||||
static TransactionId OldestXmin;
|
||||
static TransactionId FreezeLimit;
|
||||
@ -204,8 +204,9 @@ vacuum(VacuumStmt *vacstmt)
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
/*
|
||||
* If we are running only ANALYZE, we don't need per-table transactions,
|
||||
* but we still need a memory context with table lifetime.
|
||||
* If we are running only ANALYZE, we don't need per-table
|
||||
* transactions, but we still need a memory context with table
|
||||
* lifetime.
|
||||
*/
|
||||
if (vacstmt->analyze && !vacstmt->vacuum)
|
||||
anl_context = AllocSetContextCreate(QueryContext,
|
||||
@ -221,29 +222,29 @@ vacuum(VacuumStmt *vacstmt)
|
||||
* Formerly, there was code here to prevent more than one VACUUM from
|
||||
* executing concurrently in the same database. However, there's no
|
||||
* good reason to prevent that, and manually removing lockfiles after
|
||||
* a vacuum crash was a pain for dbadmins. So, forget about lockfiles,
|
||||
* and just rely on the locks we grab on each target table
|
||||
* a vacuum crash was a pain for dbadmins. So, forget about
|
||||
* lockfiles, and just rely on the locks we grab on each target table
|
||||
* to ensure that there aren't two VACUUMs running on the same table
|
||||
* at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The strangeness with committing and starting transactions here is due
|
||||
* to wanting to run each table's VACUUM as a separate transaction, so
|
||||
* that we don't hold locks unnecessarily long. Also, if we are doing
|
||||
* VACUUM ANALYZE, the ANALYZE part runs as a separate transaction from
|
||||
* the VACUUM to further reduce locking.
|
||||
* The strangeness with committing and starting transactions here is
|
||||
* due to wanting to run each table's VACUUM as a separate
|
||||
* transaction, so that we don't hold locks unnecessarily long. Also,
|
||||
* if we are doing VACUUM ANALYZE, the ANALYZE part runs as a separate
|
||||
* transaction from the VACUUM to further reduce locking.
|
||||
*
|
||||
* vacuum_rel expects to be entered with no transaction active; it will
|
||||
* start and commit its own transaction. But we are called by an SQL
|
||||
* command, and so we are executing inside a transaction already. We
|
||||
* commit the transaction started in PostgresMain() here, and start
|
||||
* another one before exiting to match the commit waiting for us back in
|
||||
* PostgresMain().
|
||||
* another one before exiting to match the commit waiting for us back
|
||||
* in PostgresMain().
|
||||
*
|
||||
* In the case of an ANALYZE statement (no vacuum, just analyze) it's
|
||||
* okay to run the whole thing in the outer transaction, and so we skip
|
||||
* transaction start/stop operations.
|
||||
* okay to run the whole thing in the outer transaction, and so we
|
||||
* skip transaction start/stop operations.
|
||||
*/
|
||||
if (vacstmt->vacuum)
|
||||
{
|
||||
@ -254,22 +255,23 @@ vacuum(VacuumStmt *vacstmt)
|
||||
*
|
||||
* Compute the initially applicable OldestXmin and FreezeLimit
|
||||
* XIDs, so that we can record these values at the end of the
|
||||
* VACUUM. Note that individual tables may well be processed with
|
||||
* newer values, but we can guarantee that no (non-shared)
|
||||
* relations are processed with older ones.
|
||||
* VACUUM. Note that individual tables may well be processed
|
||||
* with newer values, but we can guarantee that no
|
||||
* (non-shared) relations are processed with older ones.
|
||||
*
|
||||
* It is okay to record non-shared values in pg_database, even though
|
||||
* we may vacuum shared relations with older cutoffs, because only
|
||||
* the minimum of the values present in pg_database matters. We
|
||||
* can be sure that shared relations have at some time been
|
||||
* vacuumed with cutoffs no worse than the global minimum; for, if
|
||||
* there is a backend in some other DB with xmin = OLDXMIN that's
|
||||
* determining the cutoff with which we vacuum shared relations,
|
||||
* it is not possible for that database to have a cutoff newer
|
||||
* than OLDXMIN recorded in pg_database.
|
||||
* It is okay to record non-shared values in pg_database, even
|
||||
* though we may vacuum shared relations with older cutoffs,
|
||||
* because only the minimum of the values present in
|
||||
* pg_database matters. We can be sure that shared relations
|
||||
* have at some time been vacuumed with cutoffs no worse than
|
||||
* the global minimum; for, if there is a backend in some
|
||||
* other DB with xmin = OLDXMIN that's determining the cutoff
|
||||
* with which we vacuum shared relations, it is not possible
|
||||
* for that database to have a cutoff newer than OLDXMIN
|
||||
* recorded in pg_database.
|
||||
*/
|
||||
vacuum_set_xid_limits(vacstmt, false,
|
||||
&initialOldestXmin, &initialFreezeLimit);
|
||||
&initialOldestXmin, &initialFreezeLimit);
|
||||
}
|
||||
|
||||
/* matches the StartTransaction in PostgresMain() */
|
||||
@ -281,7 +283,7 @@ vacuum(VacuumStmt *vacstmt)
|
||||
*/
|
||||
foreach(cur, vrl)
|
||||
{
|
||||
Oid relid = (Oid) lfirsti(cur);
|
||||
Oid relid = (Oid) lfirsti(cur);
|
||||
|
||||
if (vacstmt->vacuum)
|
||||
vacuum_rel(relid, vacstmt, RELKIND_RELATION);
|
||||
@ -290,10 +292,11 @@ vacuum(VacuumStmt *vacstmt)
|
||||
MemoryContext old_context = NULL;
|
||||
|
||||
/*
|
||||
* If we vacuumed, use new transaction for analyze. Otherwise,
|
||||
* we can use the outer transaction, but we still need to call
|
||||
* analyze_rel in a memory context that will be cleaned up on
|
||||
* return (else we leak memory while processing multiple tables).
|
||||
* If we vacuumed, use new transaction for analyze.
|
||||
* Otherwise, we can use the outer transaction, but we still
|
||||
* need to call analyze_rel in a memory context that will be
|
||||
* cleaned up on return (else we leak memory while processing
|
||||
* multiple tables).
|
||||
*/
|
||||
if (vacstmt->vacuum)
|
||||
StartTransactionCommand(true);
|
||||
@ -320,16 +323,17 @@ vacuum(VacuumStmt *vacstmt)
|
||||
/* here, we are not in a transaction */
|
||||
|
||||
/*
|
||||
* This matches the CommitTransaction waiting for us in PostgresMain().
|
||||
* We tell xact.c not to chain the upcoming commit, so that a VACUUM
|
||||
* doesn't start a transaction block, even when autocommit is off.
|
||||
* This matches the CommitTransaction waiting for us in
|
||||
* PostgresMain(). We tell xact.c not to chain the upcoming
|
||||
* commit, so that a VACUUM doesn't start a transaction block,
|
||||
* even when autocommit is off.
|
||||
*/
|
||||
StartTransactionCommand(true);
|
||||
|
||||
/*
|
||||
* If we did a database-wide VACUUM, update the database's pg_database
|
||||
* row with info about the transaction IDs used, and try to truncate
|
||||
* pg_clog.
|
||||
* If we did a database-wide VACUUM, update the database's
|
||||
* pg_database row with info about the transaction IDs used, and
|
||||
* try to truncate pg_clog.
|
||||
*/
|
||||
if (vacstmt->relation == NULL)
|
||||
{
|
||||
@ -366,7 +370,7 @@ getrels(const RangeVar *vacrel, const char *stmttype)
|
||||
if (vacrel)
|
||||
{
|
||||
/* Process specific relation */
|
||||
Oid relid;
|
||||
Oid relid;
|
||||
|
||||
relid = RangeVarGetRelid(vacrel, false);
|
||||
|
||||
@ -517,9 +521,9 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
|
||||
|
||||
/*
|
||||
* Invalidate the tuple in the catcaches; this also arranges to flush
|
||||
* the relation's relcache entry. (If we fail to commit for some reason,
|
||||
* no flush will occur, but no great harm is done since there are no
|
||||
* noncritical state updates here.)
|
||||
* the relation's relcache entry. (If we fail to commit for some
|
||||
* reason, no flush will occur, but no great harm is done since there
|
||||
* are no noncritical state updates here.)
|
||||
*/
|
||||
CacheInvalidateHeapTuple(rd, &rtup);
|
||||
|
||||
@ -647,8 +651,8 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
|
||||
heap_close(relation, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Do not truncate CLOG if we seem to have suffered wraparound already;
|
||||
* the computed minimum XID might be bogus.
|
||||
* Do not truncate CLOG if we seem to have suffered wraparound
|
||||
* already; the computed minimum XID might be bogus.
|
||||
*/
|
||||
if (vacuumAlreadyWrapped)
|
||||
{
|
||||
@ -740,7 +744,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
|
||||
*
|
||||
* We allow the user to vacuum a table if he is superuser, the table
|
||||
* owner, or the database owner (but in the latter case, only if it's
|
||||
* not a shared relation). pg_class_ownercheck includes the superuser case.
|
||||
* not a shared relation). pg_class_ownercheck includes the superuser
|
||||
* case.
|
||||
*
|
||||
* Note we choose to treat permissions failure as a WARNING and keep
|
||||
* trying to vacuum the rest of the DB --- is this appropriate?
|
||||
@ -1581,21 +1586,23 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
* by "recent" transactions then we have to move all chain of
|
||||
* tuples to another places.
|
||||
*
|
||||
* NOTE: this test is not 100% accurate: it is possible for
|
||||
* a tuple to be an updated one with recent xmin, and yet not
|
||||
* have a corresponding tuple in the vtlinks list. Presumably
|
||||
* NOTE: this test is not 100% accurate: it is possible for a
|
||||
* tuple to be an updated one with recent xmin, and yet not
|
||||
* have a corresponding tuple in the vtlinks list. Presumably
|
||||
* there was once a parent tuple with xmax matching the xmin,
|
||||
* but it's possible that that tuple has been removed --- for
|
||||
* example, if it had xmin = xmax then HeapTupleSatisfiesVacuum
|
||||
* would deem it removable as soon as the xmin xact completes.
|
||||
* example, if it had xmin = xmax then
|
||||
* HeapTupleSatisfiesVacuum would deem it removable as soon as
|
||||
* the xmin xact completes.
|
||||
*
|
||||
* To be on the safe side, we abandon the repair_frag process if
|
||||
* we cannot find the parent tuple in vtlinks. This may be overly
|
||||
* conservative; AFAICS it would be safe to move the chain.
|
||||
* we cannot find the parent tuple in vtlinks. This may be
|
||||
* overly conservative; AFAICS it would be safe to move the
|
||||
* chain.
|
||||
*/
|
||||
if (((tuple.t_data->t_infomask & HEAP_UPDATED) &&
|
||||
!TransactionIdPrecedes(HeapTupleHeaderGetXmin(tuple.t_data),
|
||||
OldestXmin)) ||
|
||||
OldestXmin)) ||
|
||||
(!(tuple.t_data->t_infomask & (HEAP_XMAX_INVALID |
|
||||
HEAP_MARKED_FOR_UPDATE)) &&
|
||||
!(ItemPointerEquals(&(tuple.t_self),
|
||||
@ -1626,7 +1633,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
if (vacrelstats->vtlinks == NULL)
|
||||
{
|
||||
elog(WARNING, "Parent item in update-chain not found - can't continue repair_frag");
|
||||
break; /* out of walk-along-page loop */
|
||||
break; /* out of walk-along-page loop */
|
||||
}
|
||||
|
||||
vtmove = (VTupleMove) palloc(100 * sizeof(VTupleMoveData));
|
||||
@ -1638,7 +1645,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
* we have to move to the end of chain.
|
||||
*/
|
||||
while (!(tp.t_data->t_infomask & (HEAP_XMAX_INVALID |
|
||||
HEAP_MARKED_FOR_UPDATE)) &&
|
||||
HEAP_MARKED_FOR_UPDATE)) &&
|
||||
!(ItemPointerEquals(&(tp.t_self),
|
||||
&(tp.t_data->t_ctid))))
|
||||
{
|
||||
@ -1704,7 +1711,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
{
|
||||
/* can't move item anywhere */
|
||||
chain_move_failed = true;
|
||||
break; /* out of check-all-items loop */
|
||||
break; /* out of check-all-items loop */
|
||||
}
|
||||
to_item = i;
|
||||
to_vacpage = fraged_pages->pagedesc[to_item];
|
||||
@ -1732,8 +1739,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
|
||||
/* At beginning of chain? */
|
||||
if (!(tp.t_data->t_infomask & HEAP_UPDATED) ||
|
||||
TransactionIdPrecedes(HeapTupleHeaderGetXmin(tp.t_data),
|
||||
OldestXmin))
|
||||
TransactionIdPrecedes(HeapTupleHeaderGetXmin(tp.t_data),
|
||||
OldestXmin))
|
||||
break;
|
||||
|
||||
/* No, move to tuple with prior row version */
|
||||
@ -1749,14 +1756,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
/* see discussion above */
|
||||
elog(WARNING, "Parent item in update-chain not found - can't continue repair_frag");
|
||||
chain_move_failed = true;
|
||||
break; /* out of check-all-items loop */
|
||||
break; /* out of check-all-items loop */
|
||||
}
|
||||
tp.t_self = vtlp->this_tid;
|
||||
Pbuf = ReadBuffer(onerel,
|
||||
ItemPointerGetBlockNumber(&(tp.t_self)));
|
||||
ItemPointerGetBlockNumber(&(tp.t_self)));
|
||||
Ppage = BufferGetPage(Pbuf);
|
||||
Pitemid = PageGetItemId(Ppage,
|
||||
ItemPointerGetOffsetNumber(&(tp.t_self)));
|
||||
ItemPointerGetOffsetNumber(&(tp.t_self)));
|
||||
/* this can't happen since we saw tuple earlier: */
|
||||
if (!ItemIdIsUsed(Pitemid))
|
||||
elog(ERROR, "Parent itemid marked as unused");
|
||||
@ -1768,25 +1775,24 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
&(Ptp.t_data->t_ctid)));
|
||||
|
||||
/*
|
||||
* Read above about cases when
|
||||
* !ItemIdIsUsed(Citemid) (child item is
|
||||
* removed)... Due to the fact that at the moment
|
||||
* we don't remove unuseful part of update-chain,
|
||||
* it's possible to get too old parent row here.
|
||||
* Like as in the case which caused this problem,
|
||||
* we stop shrinking here. I could try to find
|
||||
* real parent row but want not to do it because
|
||||
* of real solution will be implemented anyway,
|
||||
* later, and we are too close to 6.5 release. -
|
||||
* vadim 06/11/99
|
||||
* Read above about cases when !ItemIdIsUsed(Citemid)
|
||||
* (child item is removed)... Due to the fact that at
|
||||
* the moment we don't remove unuseful part of
|
||||
* update-chain, it's possible to get too old parent
|
||||
* row here. Like as in the case which caused this
|
||||
* problem, we stop shrinking here. I could try to
|
||||
* find real parent row but want not to do it because
|
||||
* of real solution will be implemented anyway, later,
|
||||
* and we are too close to 6.5 release. - vadim
|
||||
* 06/11/99
|
||||
*/
|
||||
if (!(TransactionIdEquals(HeapTupleHeaderGetXmax(Ptp.t_data),
|
||||
HeapTupleHeaderGetXmin(tp.t_data))))
|
||||
HeapTupleHeaderGetXmin(tp.t_data))))
|
||||
{
|
||||
ReleaseBuffer(Pbuf);
|
||||
elog(WARNING, "Too old parent tuple found - can't continue repair_frag");
|
||||
chain_move_failed = true;
|
||||
break; /* out of check-all-items loop */
|
||||
break; /* out of check-all-items loop */
|
||||
}
|
||||
tp.t_datamcxt = Ptp.t_datamcxt;
|
||||
tp.t_data = Ptp.t_data;
|
||||
@ -1795,7 +1801,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
ReleaseBuffer(Cbuf);
|
||||
Cbuf = Pbuf;
|
||||
freeCbuf = true;
|
||||
} /* end of check-all-items loop */
|
||||
} /* end of check-all-items loop */
|
||||
|
||||
if (freeCbuf)
|
||||
ReleaseBuffer(Cbuf);
|
||||
@ -1804,9 +1810,9 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
if (chain_move_failed)
|
||||
{
|
||||
/*
|
||||
* Undo changes to offsets_used state. We don't bother
|
||||
* cleaning up the amount-free state, since we're not
|
||||
* going to do any further tuple motion.
|
||||
* Undo changes to offsets_used state. We don't
|
||||
* bother cleaning up the amount-free state, since
|
||||
* we're not going to do any further tuple motion.
|
||||
*/
|
||||
for (i = 0; i < num_vtmove; i++)
|
||||
{
|
||||
@ -1939,7 +1945,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No XLOG record, but still need to flag that XID exists on disk */
|
||||
/*
|
||||
* No XLOG record, but still need to flag that XID
|
||||
* exists on disk
|
||||
*/
|
||||
MyXactMadeTempRelUpdate = true;
|
||||
}
|
||||
|
||||
@ -1985,7 +1994,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
|
||||
WriteBuffer(cur_buffer);
|
||||
WriteBuffer(Cbuf);
|
||||
} /* end of move-the-tuple-chain loop */
|
||||
} /* end of move-the-tuple-chain loop */
|
||||
|
||||
cur_buffer = InvalidBuffer;
|
||||
pfree(vtmove);
|
||||
@ -1993,7 +2002,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
|
||||
/* advance to next tuple in walk-along-page loop */
|
||||
continue;
|
||||
} /* end of is-tuple-in-chain test */
|
||||
} /* end of is-tuple-in-chain test */
|
||||
|
||||
/* try to find new page for this tuple */
|
||||
if (cur_buffer == InvalidBuffer ||
|
||||
@ -2031,10 +2040,9 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
/*
|
||||
* register invalidation of source tuple in catcaches.
|
||||
*
|
||||
* (Note: we do not need to register the copied tuple,
|
||||
* because we are not changing the tuple contents and
|
||||
* so there cannot be any need to flush negative
|
||||
* catcache entries.)
|
||||
* (Note: we do not need to register the copied tuple, because we
|
||||
* are not changing the tuple contents and so there cannot be
|
||||
* any need to flush negative catcache entries.)
|
||||
*/
|
||||
CacheInvalidateHeapTuple(onerel, &tuple);
|
||||
|
||||
@ -2090,7 +2098,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No XLOG record, but still need to flag that XID exists on disk */
|
||||
/*
|
||||
* No XLOG record, but still need to flag that XID exists
|
||||
* on disk
|
||||
*/
|
||||
MyXactMadeTempRelUpdate = true;
|
||||
}
|
||||
|
||||
@ -2116,8 +2127,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
} /* walk along page */
|
||||
|
||||
/*
|
||||
* If we broke out of the walk-along-page loop early (ie, still have
|
||||
* offnum <= maxoff), then we failed to move some tuple off
|
||||
* If we broke out of the walk-along-page loop early (ie, still
|
||||
* have offnum <= maxoff), then we failed to move some tuple off
|
||||
* this page. No point in shrinking any more, so clean up and
|
||||
* exit the per-page loop.
|
||||
*/
|
||||
@ -2126,7 +2137,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
OffsetNumber off;
|
||||
|
||||
/*
|
||||
* Fix vacpage state for any unvisited tuples remaining on page
|
||||
* Fix vacpage state for any unvisited tuples remaining on
|
||||
* page
|
||||
*/
|
||||
for (off = OffsetNumberNext(offnum);
|
||||
off <= maxoff;
|
||||
@ -2389,7 +2401,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No XLOG record, but still need to flag that XID exists on disk */
|
||||
/*
|
||||
* No XLOG record, but still need to flag that XID exists
|
||||
* on disk
|
||||
*/
|
||||
MyXactMadeTempRelUpdate = true;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.18 2002/08/06 02:36:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.19 2002/09/04 20:31:17 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -93,7 +93,7 @@ typedef struct LVRelStats
|
||||
} LVRelStats;
|
||||
|
||||
|
||||
static int elevel = -1;
|
||||
static int elevel = -1;
|
||||
|
||||
static TransactionId OldestXmin;
|
||||
static TransactionId FreezeLimit;
|
||||
@ -756,7 +756,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
|
||||
*/
|
||||
|
||||
elog(elevel, "Truncated %u --> %u pages.\n\t%s", old_rel_pages,
|
||||
new_rel_pages, vac_show_rusage(&ru0));
|
||||
new_rel_pages, vac_show_rusage(&ru0));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.70 2002/07/18 02:02:29 ishii Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.71 2002/09/04 20:31:17 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -111,8 +111,8 @@ assign_datestyle(const char *value, bool doit, bool interactive)
|
||||
* Easiest way to get the current DEFAULT state is to fetch
|
||||
* the DEFAULT string from guc.c and recursively parse it.
|
||||
*
|
||||
* We can't simply "return assign_datestyle(...)" because we
|
||||
* need to handle constructs like "DEFAULT, ISO".
|
||||
* We can't simply "return assign_datestyle(...)" because we need
|
||||
* to handle constructs like "DEFAULT, ISO".
|
||||
*/
|
||||
int saveDateStyle = DateStyle;
|
||||
bool saveEuroDates = EuroDates;
|
||||
@ -164,7 +164,7 @@ assign_datestyle(const char *value, bool doit, bool interactive)
|
||||
return value;
|
||||
|
||||
/*
|
||||
* Prepare the canonical string to return. GUC wants it malloc'd.
|
||||
* Prepare the canonical string to return. GUC wants it malloc'd.
|
||||
*/
|
||||
result = (char *) malloc(32);
|
||||
if (!result)
|
||||
@ -188,8 +188,8 @@ assign_datestyle(const char *value, bool doit, bool interactive)
|
||||
strcat(result, newEuroDates ? ", EURO" : ", US");
|
||||
|
||||
/*
|
||||
* Finally, it's safe to assign to the global variables;
|
||||
* the assignment cannot fail now.
|
||||
* Finally, it's safe to assign to the global variables; the
|
||||
* assignment cannot fail now.
|
||||
*/
|
||||
DateStyle = newDateStyle;
|
||||
EuroDates = newEuroDates;
|
||||
@ -203,7 +203,7 @@ assign_datestyle(const char *value, bool doit, bool interactive)
|
||||
const char *
|
||||
show_datestyle(void)
|
||||
{
|
||||
static char buf[64];
|
||||
static char buf[64];
|
||||
|
||||
switch (DateStyle)
|
||||
{
|
||||
@ -270,6 +270,7 @@ assign_timezone(const char *value, bool doit, bool interactive)
|
||||
return NULL;
|
||||
}
|
||||
*endptr = '\0';
|
||||
|
||||
/*
|
||||
* Try to parse it. XXX an invalid interval format will result in
|
||||
* elog, which is not desirable for GUC. We did what we could to
|
||||
@ -277,9 +278,9 @@ assign_timezone(const char *value, bool doit, bool interactive)
|
||||
* coming in from postgresql.conf might contain anything.
|
||||
*/
|
||||
interval = DatumGetIntervalP(DirectFunctionCall3(interval_in,
|
||||
CStringGetDatum(val),
|
||||
ObjectIdGetDatum(InvalidOid),
|
||||
Int32GetDatum(-1)));
|
||||
CStringGetDatum(val),
|
||||
ObjectIdGetDatum(InvalidOid),
|
||||
Int32GetDatum(-1)));
|
||||
pfree(val);
|
||||
if (interval->month != 0)
|
||||
{
|
||||
@ -318,8 +319,8 @@ assign_timezone(const char *value, bool doit, bool interactive)
|
||||
* available under Solaris, among others. Apparently putenv()
|
||||
* called as below clears the process-specific environment
|
||||
* variables. Other reasonable arguments to putenv() (e.g.
|
||||
* "TZ=", "TZ", "") result in a core dump (under Linux anyway).
|
||||
* - thomas 1998-01-26
|
||||
* "TZ=", "TZ", "") result in a core dump (under Linux
|
||||
* anyway). - thomas 1998-01-26
|
||||
*/
|
||||
if (doit)
|
||||
{
|
||||
@ -339,13 +340,14 @@ assign_timezone(const char *value, bool doit, bool interactive)
|
||||
* Otherwise assume it is a timezone name.
|
||||
*
|
||||
* XXX unfortunately we have no reasonable way to check whether a
|
||||
* timezone name is good, so we have to just assume that it is.
|
||||
* timezone name is good, so we have to just assume that it
|
||||
* is.
|
||||
*/
|
||||
if (doit)
|
||||
{
|
||||
strcpy(tzbuf, "TZ=");
|
||||
strncat(tzbuf, value, sizeof(tzbuf)-4);
|
||||
if (putenv(tzbuf) != 0) /* shouldn't happen? */
|
||||
strncat(tzbuf, value, sizeof(tzbuf) - 4);
|
||||
if (putenv(tzbuf) != 0) /* shouldn't happen? */
|
||||
elog(LOG, "assign_timezone: putenv failed");
|
||||
tzset();
|
||||
HasCTZSet = false;
|
||||
@ -360,7 +362,7 @@ assign_timezone(const char *value, bool doit, bool interactive)
|
||||
return value;
|
||||
|
||||
/*
|
||||
* Prepare the canonical string to return. GUC wants it malloc'd.
|
||||
* Prepare the canonical string to return. GUC wants it malloc'd.
|
||||
*/
|
||||
result = (char *) malloc(sizeof(tzbuf));
|
||||
if (!result)
|
||||
@ -372,13 +374,9 @@ assign_timezone(const char *value, bool doit, bool interactive)
|
||||
(double) CTimeZone / 3600.0);
|
||||
}
|
||||
else if (tzbuf[0] == 'T')
|
||||
{
|
||||
strcpy(result, tzbuf + 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(result, "UNKNOWN");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -399,7 +397,7 @@ show_timezone(void)
|
||||
interval.time = CTimeZone;
|
||||
|
||||
tzn = DatumGetCString(DirectFunctionCall1(interval_out,
|
||||
IntervalPGetDatum(&interval)));
|
||||
IntervalPGetDatum(&interval)));
|
||||
}
|
||||
else
|
||||
tzn = getenv("TZ");
|
||||
@ -422,11 +420,20 @@ assign_XactIsoLevel(const char *value, bool doit, bool interactive)
|
||||
elog(ERROR, "SET TRANSACTION ISOLATION LEVEL must be called before any query");
|
||||
|
||||
if (strcmp(value, "serializable") == 0)
|
||||
{ if (doit) XactIsoLevel = XACT_SERIALIZABLE; }
|
||||
{
|
||||
if (doit)
|
||||
XactIsoLevel = XACT_SERIALIZABLE;
|
||||
}
|
||||
else if (strcmp(value, "read committed") == 0)
|
||||
{ if (doit) XactIsoLevel = XACT_READ_COMMITTED; }
|
||||
{
|
||||
if (doit)
|
||||
XactIsoLevel = XACT_READ_COMMITTED;
|
||||
}
|
||||
else if (strcmp(value, "default") == 0)
|
||||
{ if (doit) XactIsoLevel = DefaultXactIsoLevel; }
|
||||
{
|
||||
if (doit)
|
||||
XactIsoLevel = DefaultXactIsoLevel;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
@ -475,11 +482,12 @@ assign_client_encoding(const char *value, bool doit, bool interactive)
|
||||
encoding = pg_valid_client_encoding(value);
|
||||
if (encoding < 0)
|
||||
return NULL;
|
||||
|
||||
/* XXX SetClientEncoding depends on namespace functions which are
|
||||
* not available at startup time. So we accept requested client
|
||||
* encoding anyway which might not be valid (e.g. no conversion
|
||||
* procs available).
|
||||
|
||||
/*
|
||||
* XXX SetClientEncoding depends on namespace functions which are not
|
||||
* available at startup time. So we accept requested client encoding
|
||||
* anyway which might not be valid (e.g. no conversion procs
|
||||
* available).
|
||||
*/
|
||||
if (SetClientEncoding(encoding, doit) < 0)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.70 2002/09/02 20:04:40 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.71 2002/09/04 20:31:17 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -55,7 +55,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
|
||||
* the (non-junk) targetlist items from the view's SELECT list.
|
||||
*/
|
||||
attrList = NIL;
|
||||
foreach (t, tlist)
|
||||
foreach(t, tlist)
|
||||
{
|
||||
TargetEntry *entry = lfirst(t);
|
||||
Resdom *res = entry->resdom;
|
||||
@ -115,32 +115,32 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
|
||||
* Create a tuple descriptor to compare against the existing view,
|
||||
* and verify it matches.
|
||||
*/
|
||||
descriptor = BuildDescForRelation(attrList);
|
||||
descriptor = BuildDescForRelation(attrList);
|
||||
checkViewTupleDesc(descriptor, rel->rd_att);
|
||||
|
||||
/*
|
||||
* Seems okay, so return the OID of the pre-existing view.
|
||||
*/
|
||||
relation_close(rel, NoLock); /* keep the lock! */
|
||||
relation_close(rel, NoLock); /* keep the lock! */
|
||||
|
||||
return viewOid;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* now create the parameters for keys/inheritance etc. All of them are
|
||||
* nil...
|
||||
* now create the parameters for keys/inheritance etc. All of them
|
||||
* are nil...
|
||||
*/
|
||||
createStmt->relation = (RangeVar *) relation;
|
||||
createStmt->tableElts = attrList;
|
||||
createStmt->inhRelations = NIL;
|
||||
createStmt->constraints = NIL;
|
||||
createStmt->hasoids = false;
|
||||
|
||||
|
||||
/*
|
||||
* finally create the relation (this will error out if there's
|
||||
* an existing view, so we don't need more code to complain
|
||||
* if "replace" is false).
|
||||
* finally create the relation (this will error out if there's an
|
||||
* existing view, so we don't need more code to complain if
|
||||
* "replace" is false).
|
||||
*/
|
||||
return DefineRelation(createStmt, RELKIND_VIEW);
|
||||
}
|
||||
@ -179,6 +179,7 @@ checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
|
||||
NameStr(oldattr->attname));
|
||||
/* We can ignore the remaining attributes of an attribute... */
|
||||
}
|
||||
|
||||
/*
|
||||
* We ignore the constraint fields. The new view desc can't have any
|
||||
* constraints, and the only ones that could be on the old view are
|
||||
@ -316,8 +317,8 @@ DefineView(const RangeVar *view, Query *viewParse, bool replace)
|
||||
/*
|
||||
* Create the view relation
|
||||
*
|
||||
* NOTE: if it already exists and replace is false, the xact will
|
||||
* be aborted.
|
||||
* NOTE: if it already exists and replace is false, the xact will be
|
||||
* aborted.
|
||||
*/
|
||||
|
||||
viewOid = DefineVirtualRelation(view, viewParse->targetList, replace);
|
||||
|
Reference in New Issue
Block a user