mirror of
https://github.com/postgres/postgres.git
synced 2025-10-24 01:29:19 +03:00
pgindent run for 9.0
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.34 2010/02/01 19:28:56 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.35 2010/02/26 02:00:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -126,7 +126,7 @@ ExecRenameStmt(RenameStmt *stmt)
|
||||
stmt->subname, /* old att name */
|
||||
stmt->newname, /* new att name */
|
||||
interpretInhOption(stmt->relation->inhOpt), /* recursive? */
|
||||
0); /* expected inhcount */
|
||||
0); /* expected inhcount */
|
||||
break;
|
||||
case OBJECT_TRIGGER:
|
||||
renametrig(relid,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.151 2010/02/14 18:42:13 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.152 2010/02/26 02:00:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -99,11 +99,11 @@ static double random_fract(void);
|
||||
static double init_selection_state(int n);
|
||||
static double get_next_S(double t, int n, double *stateptr);
|
||||
static int compare_rows(const void *a, const void *b);
|
||||
static int acquire_inherited_sample_rows(Relation onerel,
|
||||
static int acquire_inherited_sample_rows(Relation onerel,
|
||||
HeapTuple *rows, int targrows,
|
||||
double *totalrows, double *totaldeadrows);
|
||||
static void update_attstats(Oid relid, bool inh,
|
||||
int natts, VacAttrStats **vacattrstats);
|
||||
int natts, VacAttrStats **vacattrstats);
|
||||
static Datum std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
|
||||
static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
|
||||
|
||||
@@ -289,8 +289,8 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
|
||||
RelationGetRelationName(onerel))));
|
||||
|
||||
/*
|
||||
* Set up a working context so that we can easily free whatever junk
|
||||
* gets created.
|
||||
* Set up a working context so that we can easily free whatever junk gets
|
||||
* created.
|
||||
*/
|
||||
anl_context = AllocSetContextCreate(CurrentMemoryContext,
|
||||
"Analyze",
|
||||
@@ -364,8 +364,8 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
|
||||
* Open all indexes of the relation, and see if there are any analyzable
|
||||
* columns in the indexes. We do not analyze index columns if there was
|
||||
* an explicit column list in the ANALYZE command, however. If we are
|
||||
* doing a recursive scan, we don't want to touch the parent's indexes
|
||||
* at all.
|
||||
* doing a recursive scan, we don't want to touch the parent's indexes at
|
||||
* all.
|
||||
*/
|
||||
if (!inh)
|
||||
vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
|
||||
@@ -495,7 +495,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
|
||||
{
|
||||
VacAttrStats *stats = vacattrstats[i];
|
||||
AttributeOpts *aopt =
|
||||
get_attribute_options(onerel->rd_id, stats->attr->attnum);
|
||||
get_attribute_options(onerel->rd_id, stats->attr->attnum);
|
||||
|
||||
stats->rows = rows;
|
||||
stats->tupDesc = onerel->rd_att;
|
||||
@@ -510,8 +510,9 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
|
||||
*/
|
||||
if (aopt != NULL)
|
||||
{
|
||||
float8 n_distinct =
|
||||
inh ? aopt->n_distinct_inherited : aopt->n_distinct;
|
||||
float8 n_distinct =
|
||||
inh ? aopt->n_distinct_inherited : aopt->n_distinct;
|
||||
|
||||
if (n_distinct != 0.0)
|
||||
stats->stadistinct = n_distinct;
|
||||
}
|
||||
@@ -546,8 +547,8 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
|
||||
}
|
||||
|
||||
/*
|
||||
* Update pages/tuples stats in pg_class, but not if we're inside a
|
||||
* VACUUM that got a more precise number.
|
||||
* Update pages/tuples stats in pg_class, but not if we're inside a VACUUM
|
||||
* that got a more precise number.
|
||||
*/
|
||||
if (update_reltuples)
|
||||
vac_update_relstats(onerel,
|
||||
@@ -574,10 +575,9 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
|
||||
}
|
||||
|
||||
/*
|
||||
* Report ANALYZE to the stats collector, too; likewise, tell it to
|
||||
* adopt these numbers only if we're not inside a VACUUM that got a
|
||||
* better number. However, a call with inh = true shouldn't reset
|
||||
* the stats.
|
||||
* Report ANALYZE to the stats collector, too; likewise, tell it to adopt
|
||||
* these numbers only if we're not inside a VACUUM that got a better
|
||||
* number. However, a call with inh = true shouldn't reset the stats.
|
||||
*/
|
||||
if (!inh)
|
||||
pgstat_report_analyze(onerel, update_reltuples,
|
||||
@@ -762,8 +762,8 @@ compute_index_stats(Relation onerel, double totalrows,
|
||||
{
|
||||
VacAttrStats *stats = thisdata->vacattrstats[i];
|
||||
AttributeOpts *aopt =
|
||||
get_attribute_options(stats->attr->attrelid,
|
||||
stats->attr->attnum);
|
||||
get_attribute_options(stats->attr->attrelid,
|
||||
stats->attr->attnum);
|
||||
|
||||
stats->exprvals = exprvals + i;
|
||||
stats->exprnulls = exprnulls + i;
|
||||
@@ -1436,10 +1436,10 @@ acquire_inherited_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
||||
}
|
||||
|
||||
/*
|
||||
* Now sample rows from each relation, proportionally to its fraction
|
||||
* of the total block count. (This might be less than desirable if the
|
||||
* child rels have radically different free-space percentages, but it's
|
||||
* not clear that it's worth working harder.)
|
||||
* Now sample rows from each relation, proportionally to its fraction of
|
||||
* the total block count. (This might be less than desirable if the child
|
||||
* rels have radically different free-space percentages, but it's not
|
||||
* clear that it's worth working harder.)
|
||||
*/
|
||||
numrows = 0;
|
||||
*totalrows = 0;
|
||||
@@ -1451,7 +1451,7 @@ acquire_inherited_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
||||
|
||||
if (childblocks > 0)
|
||||
{
|
||||
int childtargrows;
|
||||
int childtargrows;
|
||||
|
||||
childtargrows = (int) rint(targrows * childblocks / totalblocks);
|
||||
/* Make sure we don't overrun due to roundoff error */
|
||||
@@ -1478,10 +1478,10 @@ acquire_inherited_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
||||
|
||||
map = convert_tuples_by_name(RelationGetDescr(childrel),
|
||||
RelationGetDescr(onerel),
|
||||
gettext_noop("could not convert row type"));
|
||||
gettext_noop("could not convert row type"));
|
||||
if (map != NULL)
|
||||
{
|
||||
int j;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < childrows; j++)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.154 2010/02/20 21:24:02 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.155 2010/02/26 02:00:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -149,7 +149,7 @@
|
||||
*
|
||||
* This struct declaration has the maximal length, but in a real queue entry
|
||||
* the data area is only big enough for the actual channel and payload strings
|
||||
* (each null-terminated). AsyncQueueEntryEmptySize is the minimum possible
|
||||
* (each null-terminated). AsyncQueueEntryEmptySize is the minimum possible
|
||||
* entry size, if both channel and payload strings are empty (but note it
|
||||
* doesn't include alignment padding).
|
||||
*
|
||||
@@ -158,11 +158,11 @@
|
||||
*/
|
||||
typedef struct AsyncQueueEntry
|
||||
{
|
||||
int length; /* total allocated length of entry */
|
||||
Oid dboid; /* sender's database OID */
|
||||
TransactionId xid; /* sender's XID */
|
||||
int32 srcPid; /* sender's PID */
|
||||
char data[NAMEDATALEN + NOTIFY_PAYLOAD_MAX_LENGTH];
|
||||
int length; /* total allocated length of entry */
|
||||
Oid dboid; /* sender's database OID */
|
||||
TransactionId xid; /* sender's XID */
|
||||
int32 srcPid; /* sender's PID */
|
||||
char data[NAMEDATALEN + NOTIFY_PAYLOAD_MAX_LENGTH];
|
||||
} AsyncQueueEntry;
|
||||
|
||||
/* Currently, no field of AsyncQueueEntry requires more than int alignment */
|
||||
@@ -175,8 +175,8 @@ typedef struct AsyncQueueEntry
|
||||
*/
|
||||
typedef struct QueuePosition
|
||||
{
|
||||
int page; /* SLRU page number */
|
||||
int offset; /* byte offset within page */
|
||||
int page; /* SLRU page number */
|
||||
int offset; /* byte offset within page */
|
||||
} QueuePosition;
|
||||
|
||||
#define QUEUE_POS_PAGE(x) ((x).page)
|
||||
@@ -202,11 +202,11 @@ typedef struct QueuePosition
|
||||
*/
|
||||
typedef struct QueueBackendStatus
|
||||
{
|
||||
int32 pid; /* either a PID or InvalidPid */
|
||||
QueuePosition pos; /* backend has read queue up to here */
|
||||
int32 pid; /* either a PID or InvalidPid */
|
||||
QueuePosition pos; /* backend has read queue up to here */
|
||||
} QueueBackendStatus;
|
||||
|
||||
#define InvalidPid (-1)
|
||||
#define InvalidPid (-1)
|
||||
|
||||
/*
|
||||
* Shared memory state for LISTEN/NOTIFY (excluding its SLRU stuff)
|
||||
@@ -230,15 +230,15 @@ typedef struct QueueBackendStatus
|
||||
*/
|
||||
typedef struct AsyncQueueControl
|
||||
{
|
||||
QueuePosition head; /* head points to the next free location */
|
||||
QueuePosition tail; /* the global tail is equivalent to the
|
||||
tail of the "slowest" backend */
|
||||
TimestampTz lastQueueFillWarn; /* time of last queue-full msg */
|
||||
QueueBackendStatus backend[1]; /* actually of length MaxBackends+1 */
|
||||
QueuePosition head; /* head points to the next free location */
|
||||
QueuePosition tail; /* the global tail is equivalent to the tail
|
||||
* of the "slowest" backend */
|
||||
TimestampTz lastQueueFillWarn; /* time of last queue-full msg */
|
||||
QueueBackendStatus backend[1]; /* actually of length MaxBackends+1 */
|
||||
/* DO NOT ADD FURTHER STRUCT MEMBERS HERE */
|
||||
} AsyncQueueControl;
|
||||
|
||||
static AsyncQueueControl *asyncQueueControl;
|
||||
static AsyncQueueControl *asyncQueueControl;
|
||||
|
||||
#define QUEUE_HEAD (asyncQueueControl->head)
|
||||
#define QUEUE_TAIL (asyncQueueControl->tail)
|
||||
@@ -248,11 +248,11 @@ static AsyncQueueControl *asyncQueueControl;
|
||||
/*
|
||||
* The SLRU buffer area through which we access the notification queue
|
||||
*/
|
||||
static SlruCtlData AsyncCtlData;
|
||||
static SlruCtlData AsyncCtlData;
|
||||
|
||||
#define AsyncCtl (&AsyncCtlData)
|
||||
#define QUEUE_PAGESIZE BLCKSZ
|
||||
#define QUEUE_FULL_WARN_INTERVAL 5000 /* warn at most once every 5s */
|
||||
#define QUEUE_FULL_WARN_INTERVAL 5000 /* warn at most once every 5s */
|
||||
|
||||
/*
|
||||
* slru.c currently assumes that all filenames are four characters of hex
|
||||
@@ -265,7 +265,7 @@ static SlruCtlData AsyncCtlData;
|
||||
*
|
||||
* The most data we can have in the queue at a time is QUEUE_MAX_PAGE/2
|
||||
* pages, because more than that would confuse slru.c into thinking there
|
||||
* was a wraparound condition. With the default BLCKSZ this means there
|
||||
* was a wraparound condition. With the default BLCKSZ this means there
|
||||
* can be up to 8GB of queued-and-not-read data.
|
||||
*
|
||||
* Note: it's possible to redefine QUEUE_MAX_PAGE with a smaller multiple of
|
||||
@@ -309,7 +309,7 @@ static List *upperPendingActions = NIL; /* list of upper-xact lists */
|
||||
|
||||
/*
|
||||
* State for outbound notifies consists of a list of all channels+payloads
|
||||
* NOTIFYed in the current transaction. We do not actually perform a NOTIFY
|
||||
* NOTIFYed in the current transaction. We do not actually perform a NOTIFY
|
||||
* until and unless the transaction commits. pendingNotifies is NIL if no
|
||||
* NOTIFYs have been done in the current transaction.
|
||||
*
|
||||
@@ -325,11 +325,11 @@ static List *upperPendingActions = NIL; /* list of upper-xact lists */
|
||||
*/
|
||||
typedef struct Notification
|
||||
{
|
||||
char *channel; /* channel name */
|
||||
char *payload; /* payload string (can be empty) */
|
||||
char *channel; /* channel name */
|
||||
char *payload; /* payload string (can be empty) */
|
||||
} Notification;
|
||||
|
||||
static List *pendingNotifies = NIL; /* list of Notifications */
|
||||
static List *pendingNotifies = NIL; /* list of Notifications */
|
||||
|
||||
static List *upperPendingNotifies = NIL; /* list of upper-xact lists */
|
||||
|
||||
@@ -348,8 +348,10 @@ static volatile sig_atomic_t notifyInterruptOccurred = 0;
|
||||
|
||||
/* True if we've registered an on_shmem_exit cleanup */
|
||||
static bool unlistenExitRegistered = false;
|
||||
|
||||
/* has this backend sent notifications in the current transaction? */
|
||||
static bool backendHasSentNotifications = false;
|
||||
|
||||
/* has this backend executed its first LISTEN in the current transaction? */
|
||||
static bool backendHasExecutedInitialListen = false;
|
||||
|
||||
@@ -380,8 +382,8 @@ static bool asyncQueueProcessPageEntries(QueuePosition *current,
|
||||
static void asyncQueueAdvanceTail(void);
|
||||
static void ProcessIncomingNotify(void);
|
||||
static void NotifyMyFrontEnd(const char *channel,
|
||||
const char *payload,
|
||||
int32 srcPid);
|
||||
const char *payload,
|
||||
int32 srcPid);
|
||||
static bool AsyncExistsPendingNotify(const char *channel, const char *payload);
|
||||
static void ClearPendingActionsAndNotifies(void);
|
||||
|
||||
@@ -408,17 +410,17 @@ asyncQueuePagePrecedesLogically(int p, int q)
|
||||
int diff;
|
||||
|
||||
/*
|
||||
* We have to compare modulo (QUEUE_MAX_PAGE+1)/2. Both inputs should
|
||||
* be in the range 0..QUEUE_MAX_PAGE.
|
||||
* We have to compare modulo (QUEUE_MAX_PAGE+1)/2. Both inputs should be
|
||||
* in the range 0..QUEUE_MAX_PAGE.
|
||||
*/
|
||||
Assert(p >= 0 && p <= QUEUE_MAX_PAGE);
|
||||
Assert(q >= 0 && q <= QUEUE_MAX_PAGE);
|
||||
|
||||
diff = p - q;
|
||||
if (diff >= ((QUEUE_MAX_PAGE+1)/2))
|
||||
diff -= QUEUE_MAX_PAGE+1;
|
||||
else if (diff < -((QUEUE_MAX_PAGE+1)/2))
|
||||
diff += QUEUE_MAX_PAGE+1;
|
||||
if (diff >= ((QUEUE_MAX_PAGE + 1) / 2))
|
||||
diff -= QUEUE_MAX_PAGE + 1;
|
||||
else if (diff < -((QUEUE_MAX_PAGE + 1) / 2))
|
||||
diff += QUEUE_MAX_PAGE + 1;
|
||||
return diff < 0;
|
||||
}
|
||||
|
||||
@@ -428,7 +430,7 @@ asyncQueuePagePrecedesLogically(int p, int q)
|
||||
Size
|
||||
AsyncShmemSize(void)
|
||||
{
|
||||
Size size;
|
||||
Size size;
|
||||
|
||||
/* This had better match AsyncShmemInit */
|
||||
size = mul_size(MaxBackends, sizeof(QueueBackendStatus));
|
||||
@@ -445,9 +447,9 @@ AsyncShmemSize(void)
|
||||
void
|
||||
AsyncShmemInit(void)
|
||||
{
|
||||
bool found;
|
||||
int slotno;
|
||||
Size size;
|
||||
bool found;
|
||||
int slotno;
|
||||
Size size;
|
||||
|
||||
/*
|
||||
* Create or attach to the AsyncQueueControl structure.
|
||||
@@ -468,7 +470,7 @@ AsyncShmemInit(void)
|
||||
if (!found)
|
||||
{
|
||||
/* First time through, so initialize it */
|
||||
int i;
|
||||
int i;
|
||||
|
||||
SET_QUEUE_POS(QUEUE_HEAD, 0, 0);
|
||||
SET_QUEUE_POS(QUEUE_TAIL, 0, 0);
|
||||
@@ -598,8 +600,8 @@ Async_Notify(const char *channel, const char *payload)
|
||||
n->payload = "";
|
||||
|
||||
/*
|
||||
* We want to preserve the order so we need to append every
|
||||
* notification. See comments at AsyncExistsPendingNotify().
|
||||
* We want to preserve the order so we need to append every notification.
|
||||
* See comments at AsyncExistsPendingNotify().
|
||||
*/
|
||||
pendingNotifies = lappend(pendingNotifies, n);
|
||||
|
||||
@@ -698,13 +700,13 @@ Async_UnlistenAll(void)
|
||||
Datum
|
||||
pg_listening_channels(PG_FUNCTION_ARGS)
|
||||
{
|
||||
FuncCallContext *funcctx;
|
||||
ListCell **lcp;
|
||||
FuncCallContext *funcctx;
|
||||
ListCell **lcp;
|
||||
|
||||
/* stuff done only on the first call of the function */
|
||||
if (SRF_IS_FIRSTCALL())
|
||||
{
|
||||
MemoryContext oldcontext;
|
||||
MemoryContext oldcontext;
|
||||
|
||||
/* create a function context for cross-call persistence */
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
@@ -726,7 +728,7 @@ pg_listening_channels(PG_FUNCTION_ARGS)
|
||||
|
||||
while (*lcp != NULL)
|
||||
{
|
||||
char *channel = (char *) lfirst(*lcp);
|
||||
char *channel = (char *) lfirst(*lcp);
|
||||
|
||||
*lcp = lnext(*lcp);
|
||||
SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(channel));
|
||||
@@ -818,9 +820,9 @@ PreCommit_Notify(void)
|
||||
|
||||
/*
|
||||
* Make sure that we have an XID assigned to the current transaction.
|
||||
* GetCurrentTransactionId is cheap if we already have an XID, but
|
||||
* not so cheap if we don't, and we'd prefer not to do that work
|
||||
* while holding AsyncQueueLock.
|
||||
* GetCurrentTransactionId is cheap if we already have an XID, but not
|
||||
* so cheap if we don't, and we'd prefer not to do that work while
|
||||
* holding AsyncQueueLock.
|
||||
*/
|
||||
(void) GetCurrentTransactionId();
|
||||
|
||||
@@ -850,7 +852,7 @@ PreCommit_Notify(void)
|
||||
while (nextNotify != NULL)
|
||||
{
|
||||
/*
|
||||
* Add the pending notifications to the queue. We acquire and
|
||||
* Add the pending notifications to the queue. We acquire and
|
||||
* release AsyncQueueLock once per page, which might be overkill
|
||||
* but it does allow readers to get in while we're doing this.
|
||||
*
|
||||
@@ -866,7 +868,7 @@ PreCommit_Notify(void)
|
||||
if (asyncQueueIsFull())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("too many notifications in the NOTIFY queue")));
|
||||
errmsg("too many notifications in the NOTIFY queue")));
|
||||
nextNotify = asyncQueueAddEntries(nextNotify);
|
||||
LWLockRelease(AsyncQueueLock);
|
||||
}
|
||||
@@ -915,8 +917,8 @@ AtCommit_Notify(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* If we did an initial LISTEN, listenChannels now has the entry, so
|
||||
* we no longer need or want the flag to be set.
|
||||
* If we did an initial LISTEN, listenChannels now has the entry, so we no
|
||||
* longer need or want the flag to be set.
|
||||
*/
|
||||
backendHasExecutedInitialListen = false;
|
||||
|
||||
@@ -943,15 +945,15 @@ Exec_ListenPreCommit(void)
|
||||
elog(DEBUG1, "Exec_ListenPreCommit(%d)", MyProcPid);
|
||||
|
||||
/*
|
||||
* We need this variable to detect an aborted initial LISTEN.
|
||||
* In that case we would set up our pointer but not listen on any channel.
|
||||
* This flag gets cleared in AtCommit_Notify or AtAbort_Notify().
|
||||
* We need this variable to detect an aborted initial LISTEN. In that case
|
||||
* we would set up our pointer but not listen on any channel. This flag
|
||||
* gets cleared in AtCommit_Notify or AtAbort_Notify().
|
||||
*/
|
||||
backendHasExecutedInitialListen = true;
|
||||
|
||||
/*
|
||||
* Before registering, make sure we will unlisten before dying.
|
||||
* (Note: this action does not get undone if we abort later.)
|
||||
* Before registering, make sure we will unlisten before dying. (Note:
|
||||
* this action does not get undone if we abort later.)
|
||||
*/
|
||||
if (!unlistenExitRegistered)
|
||||
{
|
||||
@@ -977,8 +979,8 @@ Exec_ListenPreCommit(void)
|
||||
* already-committed notifications. Still, we could get notifications that
|
||||
* have already committed before we started to LISTEN.
|
||||
*
|
||||
* Note that we are not yet listening on anything, so we won't deliver
|
||||
* any notification to the frontend.
|
||||
* Note that we are not yet listening on anything, so we won't deliver any
|
||||
* notification to the frontend.
|
||||
*
|
||||
* This will also advance the global tail pointer if possible.
|
||||
*/
|
||||
@@ -1020,8 +1022,8 @@ Exec_ListenCommit(const char *channel)
|
||||
static void
|
||||
Exec_UnlistenCommit(const char *channel)
|
||||
{
|
||||
ListCell *q;
|
||||
ListCell *prev;
|
||||
ListCell *q;
|
||||
ListCell *prev;
|
||||
|
||||
if (Trace_notify)
|
||||
elog(DEBUG1, "Exec_UnlistenCommit(%s,%d)", channel, MyProcPid);
|
||||
@@ -1029,7 +1031,7 @@ Exec_UnlistenCommit(const char *channel)
|
||||
prev = NULL;
|
||||
foreach(q, listenChannels)
|
||||
{
|
||||
char *lchan = (char *) lfirst(q);
|
||||
char *lchan = (char *) lfirst(q);
|
||||
|
||||
if (strcmp(lchan, channel) == 0)
|
||||
{
|
||||
@@ -1078,12 +1080,12 @@ Exec_UnlistenAllCommit(void)
|
||||
* The reason that this is not done in AtCommit_Notify is that there is
|
||||
* a nonzero chance of errors here (for example, encoding conversion errors
|
||||
* while trying to format messages to our frontend). An error during
|
||||
* AtCommit_Notify would be a PANIC condition. The timing is also arranged
|
||||
* AtCommit_Notify would be a PANIC condition. The timing is also arranged
|
||||
* to ensure that a transaction's self-notifies are delivered to the frontend
|
||||
* before it gets the terminating ReadyForQuery message.
|
||||
*
|
||||
* Note that we send signals and process the queue even if the transaction
|
||||
* eventually aborted. This is because we need to clean out whatever got
|
||||
* eventually aborted. This is because we need to clean out whatever got
|
||||
* added to the queue.
|
||||
*
|
||||
* NOTE: we are outside of any transaction here.
|
||||
@@ -1098,9 +1100,9 @@ ProcessCompletedNotifies(void)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We reset the flag immediately; otherwise, if any sort of error
|
||||
* occurs below, we'd be locked up in an infinite loop, because
|
||||
* control will come right back here after error cleanup.
|
||||
* We reset the flag immediately; otherwise, if any sort of error occurs
|
||||
* below, we'd be locked up in an infinite loop, because control will come
|
||||
* right back here after error cleanup.
|
||||
*/
|
||||
backendHasSentNotifications = false;
|
||||
|
||||
@@ -1108,8 +1110,8 @@ ProcessCompletedNotifies(void)
|
||||
elog(DEBUG1, "ProcessCompletedNotifies");
|
||||
|
||||
/*
|
||||
* We must run asyncQueueReadAllNotifications inside a transaction,
|
||||
* else bad things happen if it gets an error.
|
||||
* We must run asyncQueueReadAllNotifications inside a transaction, else
|
||||
* bad things happen if it gets an error.
|
||||
*/
|
||||
StartTransactionCommand();
|
||||
|
||||
@@ -1125,11 +1127,11 @@ ProcessCompletedNotifies(void)
|
||||
{
|
||||
/*
|
||||
* If we found no other listening backends, and we aren't listening
|
||||
* ourselves, then we must execute asyncQueueAdvanceTail to flush
|
||||
* the queue, because ain't nobody else gonna do it. This prevents
|
||||
* queue overflow when we're sending useless notifies to nobody.
|
||||
* (A new listener could have joined since we looked, but if so this
|
||||
* is harmless.)
|
||||
* ourselves, then we must execute asyncQueueAdvanceTail to flush the
|
||||
* queue, because ain't nobody else gonna do it. This prevents queue
|
||||
* overflow when we're sending useless notifies to nobody. (A new
|
||||
* listener could have joined since we looked, but if so this is
|
||||
* harmless.)
|
||||
*/
|
||||
asyncQueueAdvanceTail();
|
||||
}
|
||||
@@ -1164,14 +1166,14 @@ IsListeningOn(const char *channel)
|
||||
|
||||
/*
|
||||
* Remove our entry from the listeners array when we are no longer listening
|
||||
* on any channel. NB: must not fail if we're already not listening.
|
||||
* on any channel. NB: must not fail if we're already not listening.
|
||||
*/
|
||||
static void
|
||||
asyncQueueUnregister(void)
|
||||
{
|
||||
bool advanceTail;
|
||||
bool advanceTail;
|
||||
|
||||
Assert(listenChannels == NIL); /* else caller error */
|
||||
Assert(listenChannels == NIL); /* else caller error */
|
||||
|
||||
LWLockAcquire(AsyncQueueLock, LW_SHARED);
|
||||
/* check if entry is valid and oldest ... */
|
||||
@@ -1200,7 +1202,7 @@ asyncQueueIsFull(void)
|
||||
/*
|
||||
* The queue is full if creating a new head page would create a page that
|
||||
* logically precedes the current global tail pointer, ie, the head
|
||||
* pointer would wrap around compared to the tail. We cannot create such
|
||||
* pointer would wrap around compared to the tail. We cannot create such
|
||||
* a head page for fear of confusing slru.c. For safety we round the tail
|
||||
* pointer back to a segment boundary (compare the truncation logic in
|
||||
* asyncQueueAdvanceTail).
|
||||
@@ -1219,15 +1221,15 @@ asyncQueueIsFull(void)
|
||||
|
||||
/*
|
||||
* Advance the QueuePosition to the next entry, assuming that the current
|
||||
* entry is of length entryLength. If we jump to a new page the function
|
||||
* entry is of length entryLength. If we jump to a new page the function
|
||||
* returns true, else false.
|
||||
*/
|
||||
static bool
|
||||
asyncQueueAdvance(QueuePosition *position, int entryLength)
|
||||
{
|
||||
int pageno = QUEUE_POS_PAGE(*position);
|
||||
int offset = QUEUE_POS_OFFSET(*position);
|
||||
bool pageJump = false;
|
||||
int pageno = QUEUE_POS_PAGE(*position);
|
||||
int offset = QUEUE_POS_OFFSET(*position);
|
||||
bool pageJump = false;
|
||||
|
||||
/*
|
||||
* Move to the next writing position: First jump over what we have just
|
||||
@@ -1245,7 +1247,7 @@ asyncQueueAdvance(QueuePosition *position, int entryLength)
|
||||
{
|
||||
pageno++;
|
||||
if (pageno > QUEUE_MAX_PAGE)
|
||||
pageno = 0; /* wrap around */
|
||||
pageno = 0; /* wrap around */
|
||||
offset = 0;
|
||||
pageJump = true;
|
||||
}
|
||||
@@ -1260,9 +1262,9 @@ asyncQueueAdvance(QueuePosition *position, int entryLength)
|
||||
static void
|
||||
asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe)
|
||||
{
|
||||
size_t channellen = strlen(n->channel);
|
||||
size_t payloadlen = strlen(n->payload);
|
||||
int entryLength;
|
||||
size_t channellen = strlen(n->channel);
|
||||
size_t payloadlen = strlen(n->payload);
|
||||
int entryLength;
|
||||
|
||||
Assert(channellen < NAMEDATALEN);
|
||||
Assert(payloadlen < NOTIFY_PAYLOAD_MAX_LENGTH);
|
||||
@@ -1288,7 +1290,7 @@ asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe)
|
||||
* the last byte which simplifies reading the page later.
|
||||
*
|
||||
* We are passed the list cell containing the next notification to write
|
||||
* and return the first still-unwritten cell back. Eventually we will return
|
||||
* and return the first still-unwritten cell back. Eventually we will return
|
||||
* NULL indicating all is done.
|
||||
*
|
||||
* We are holding AsyncQueueLock already from the caller and grab AsyncCtlLock
|
||||
@@ -1297,10 +1299,10 @@ asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe)
|
||||
static ListCell *
|
||||
asyncQueueAddEntries(ListCell *nextNotify)
|
||||
{
|
||||
AsyncQueueEntry qe;
|
||||
int pageno;
|
||||
int offset;
|
||||
int slotno;
|
||||
AsyncQueueEntry qe;
|
||||
int pageno;
|
||||
int offset;
|
||||
int slotno;
|
||||
|
||||
/* We hold both AsyncQueueLock and AsyncCtlLock during this operation */
|
||||
LWLockAcquire(AsyncCtlLock, LW_EXCLUSIVE);
|
||||
@@ -1313,7 +1315,7 @@ asyncQueueAddEntries(ListCell *nextNotify)
|
||||
|
||||
while (nextNotify != NULL)
|
||||
{
|
||||
Notification *n = (Notification *) lfirst(nextNotify);
|
||||
Notification *n = (Notification *) lfirst(nextNotify);
|
||||
|
||||
/* Construct a valid queue entry in local variable qe */
|
||||
asyncQueueNotificationToEntry(n, &qe);
|
||||
@@ -1335,8 +1337,8 @@ asyncQueueAddEntries(ListCell *nextNotify)
|
||||
*/
|
||||
qe.length = QUEUE_PAGESIZE - offset;
|
||||
qe.dboid = InvalidOid;
|
||||
qe.data[0] = '\0'; /* empty channel */
|
||||
qe.data[1] = '\0'; /* empty payload */
|
||||
qe.data[0] = '\0'; /* empty channel */
|
||||
qe.data[1] = '\0'; /* empty payload */
|
||||
}
|
||||
|
||||
/* Now copy qe into the shared buffer page */
|
||||
@@ -1348,12 +1350,12 @@ asyncQueueAddEntries(ListCell *nextNotify)
|
||||
if (asyncQueueAdvance(&(QUEUE_HEAD), qe.length))
|
||||
{
|
||||
/*
|
||||
* Page is full, so we're done here, but first fill the next
|
||||
* page with zeroes. The reason to do this is to ensure that
|
||||
* slru.c's idea of the head page is always the same as ours,
|
||||
* which avoids boundary problems in SimpleLruTruncate. The
|
||||
* test in asyncQueueIsFull() ensured that there is room to
|
||||
* create this page without overrunning the queue.
|
||||
* Page is full, so we're done here, but first fill the next page
|
||||
* with zeroes. The reason to do this is to ensure that slru.c's
|
||||
* idea of the head page is always the same as ours, which avoids
|
||||
* boundary problems in SimpleLruTruncate. The test in
|
||||
* asyncQueueIsFull() ensured that there is room to create this
|
||||
* page without overrunning the queue.
|
||||
*/
|
||||
slotno = SimpleLruZeroPage(AsyncCtl, QUEUE_POS_PAGE(QUEUE_HEAD));
|
||||
/* And exit the loop */
|
||||
@@ -1377,24 +1379,24 @@ asyncQueueAddEntries(ListCell *nextNotify)
|
||||
static void
|
||||
asyncQueueFillWarning(void)
|
||||
{
|
||||
int headPage = QUEUE_POS_PAGE(QUEUE_HEAD);
|
||||
int tailPage = QUEUE_POS_PAGE(QUEUE_TAIL);
|
||||
int occupied;
|
||||
double fillDegree;
|
||||
TimestampTz t;
|
||||
int headPage = QUEUE_POS_PAGE(QUEUE_HEAD);
|
||||
int tailPage = QUEUE_POS_PAGE(QUEUE_TAIL);
|
||||
int occupied;
|
||||
double fillDegree;
|
||||
TimestampTz t;
|
||||
|
||||
occupied = headPage - tailPage;
|
||||
|
||||
if (occupied == 0)
|
||||
return; /* fast exit for common case */
|
||||
|
||||
|
||||
if (occupied < 0)
|
||||
{
|
||||
/* head has wrapped around, tail not yet */
|
||||
occupied += QUEUE_MAX_PAGE+1;
|
||||
occupied += QUEUE_MAX_PAGE + 1;
|
||||
}
|
||||
|
||||
fillDegree = (double) occupied / (double) ((QUEUE_MAX_PAGE+1)/2);
|
||||
fillDegree = (double) occupied / (double) ((QUEUE_MAX_PAGE + 1) / 2);
|
||||
|
||||
if (fillDegree < 0.5)
|
||||
return;
|
||||
@@ -1404,9 +1406,9 @@ asyncQueueFillWarning(void)
|
||||
if (TimestampDifferenceExceeds(asyncQueueControl->lastQueueFillWarn,
|
||||
t, QUEUE_FULL_WARN_INTERVAL))
|
||||
{
|
||||
QueuePosition min = QUEUE_HEAD;
|
||||
int32 minPid = InvalidPid;
|
||||
int i;
|
||||
QueuePosition min = QUEUE_HEAD;
|
||||
int32 minPid = InvalidPid;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= MaxBackends; i++)
|
||||
{
|
||||
@@ -1455,13 +1457,13 @@ SignalBackends(void)
|
||||
int32 pid;
|
||||
|
||||
/*
|
||||
* Identify all backends that are listening and not already up-to-date.
|
||||
* We don't want to send signals while holding the AsyncQueueLock, so
|
||||
* we just build a list of target PIDs.
|
||||
* Identify all backends that are listening and not already up-to-date. We
|
||||
* don't want to send signals while holding the AsyncQueueLock, so we just
|
||||
* build a list of target PIDs.
|
||||
*
|
||||
* XXX in principle these pallocs could fail, which would be bad.
|
||||
* Maybe preallocate the arrays? But in practice this is only run
|
||||
* in trivial transactions, so there should surely be space available.
|
||||
* XXX in principle these pallocs could fail, which would be bad. Maybe
|
||||
* preallocate the arrays? But in practice this is only run in trivial
|
||||
* transactions, so there should surely be space available.
|
||||
*/
|
||||
pids = (int32 *) palloc(MaxBackends * sizeof(int32));
|
||||
ids = (BackendId *) palloc(MaxBackends * sizeof(BackendId));
|
||||
@@ -1493,8 +1495,8 @@ SignalBackends(void)
|
||||
/*
|
||||
* Note: assuming things aren't broken, a signal failure here could
|
||||
* only occur if the target backend exited since we released
|
||||
* AsyncQueueLock; which is unlikely but certainly possible.
|
||||
* So we just log a low-level debug message if it happens.
|
||||
* AsyncQueueLock; which is unlikely but certainly possible. So we
|
||||
* just log a low-level debug message if it happens.
|
||||
*/
|
||||
if (SendProcSignal(pid, PROCSIG_NOTIFY_INTERRUPT, ids[i]) < 0)
|
||||
elog(DEBUG3, "could not signal backend with PID %d: %m", pid);
|
||||
@@ -1521,8 +1523,8 @@ AtAbort_Notify(void)
|
||||
{
|
||||
/*
|
||||
* If we LISTEN but then roll back the transaction we have set our pointer
|
||||
* but have not made any entry in listenChannels. In that case, remove
|
||||
* our pointer again.
|
||||
* but have not made any entry in listenChannels. In that case, remove our
|
||||
* pointer again.
|
||||
*/
|
||||
if (backendHasExecutedInitialListen)
|
||||
{
|
||||
@@ -1778,7 +1780,7 @@ EnableNotifyInterrupt(void)
|
||||
* is disabled until the next EnableNotifyInterrupt call.
|
||||
*
|
||||
* The PROCSIG_CATCHUP_INTERRUPT signal handler also needs to call this,
|
||||
* so as to prevent conflicts if one signal interrupts the other. So we
|
||||
* so as to prevent conflicts if one signal interrupts the other. So we
|
||||
* must return the previous state of the flag.
|
||||
*/
|
||||
bool
|
||||
@@ -1799,15 +1801,17 @@ DisableNotifyInterrupt(void)
|
||||
static void
|
||||
asyncQueueReadAllNotifications(void)
|
||||
{
|
||||
QueuePosition pos;
|
||||
QueuePosition oldpos;
|
||||
QueuePosition head;
|
||||
QueuePosition pos;
|
||||
QueuePosition oldpos;
|
||||
QueuePosition head;
|
||||
bool advanceTail;
|
||||
|
||||
/* page_buffer must be adequately aligned, so use a union */
|
||||
union {
|
||||
union
|
||||
{
|
||||
char buf[QUEUE_PAGESIZE];
|
||||
AsyncQueueEntry align;
|
||||
} page_buffer;
|
||||
} page_buffer;
|
||||
|
||||
/* Fetch current state */
|
||||
LWLockAcquire(AsyncQueueLock, LW_SHARED);
|
||||
@@ -1829,16 +1833,16 @@ asyncQueueReadAllNotifications(void)
|
||||
* Especially we do not take into account different commit times.
|
||||
* Consider the following example:
|
||||
*
|
||||
* Backend 1: Backend 2:
|
||||
* Backend 1: Backend 2:
|
||||
*
|
||||
* transaction starts
|
||||
* NOTIFY foo;
|
||||
* commit starts
|
||||
* transaction starts
|
||||
* LISTEN foo;
|
||||
* commit starts
|
||||
* transaction starts
|
||||
* LISTEN foo;
|
||||
* commit starts
|
||||
* commit to clog
|
||||
* commit to clog
|
||||
* commit to clog
|
||||
*
|
||||
* It could happen that backend 2 sees the notification from backend 1 in
|
||||
* the queue. Even though the notifying transaction committed before
|
||||
@@ -1861,7 +1865,7 @@ asyncQueueReadAllNotifications(void)
|
||||
{
|
||||
bool reachedStop;
|
||||
|
||||
do
|
||||
do
|
||||
{
|
||||
int curpage = QUEUE_POS_PAGE(pos);
|
||||
int curoffset = QUEUE_POS_OFFSET(pos);
|
||||
@@ -1871,7 +1875,7 @@ asyncQueueReadAllNotifications(void)
|
||||
/*
|
||||
* We copy the data from SLRU into a local buffer, so as to avoid
|
||||
* holding the AsyncCtlLock while we are examining the entries and
|
||||
* possibly transmitting them to our frontend. Copy only the part
|
||||
* possibly transmitting them to our frontend. Copy only the part
|
||||
* of the page we will actually inspect.
|
||||
*/
|
||||
slotno = SimpleLruReadPage_ReadOnly(AsyncCtl, curpage,
|
||||
@@ -1881,7 +1885,7 @@ asyncQueueReadAllNotifications(void)
|
||||
/* we only want to read as far as head */
|
||||
copysize = QUEUE_POS_OFFSET(head) - curoffset;
|
||||
if (copysize < 0)
|
||||
copysize = 0; /* just for safety */
|
||||
copysize = 0; /* just for safety */
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1899,9 +1903,9 @@ asyncQueueReadAllNotifications(void)
|
||||
* uncommitted message.
|
||||
*
|
||||
* Our stop position is what we found to be the head's position
|
||||
* when we entered this function. It might have changed
|
||||
* already. But if it has, we will receive (or have already
|
||||
* received and queued) another signal and come here again.
|
||||
* when we entered this function. It might have changed already.
|
||||
* But if it has, we will receive (or have already received and
|
||||
* queued) another signal and come here again.
|
||||
*
|
||||
* We are not holding AsyncQueueLock here! The queue can only
|
||||
* extend beyond the head pointer (see above) and we leave our
|
||||
@@ -1945,7 +1949,7 @@ asyncQueueReadAllNotifications(void)
|
||||
* and deliver relevant ones to my frontend.
|
||||
*
|
||||
* The current page must have been fetched into page_buffer from shared
|
||||
* memory. (We could access the page right in shared memory, but that
|
||||
* memory. (We could access the page right in shared memory, but that
|
||||
* would imply holding the AsyncCtlLock throughout this routine.)
|
||||
*
|
||||
* We stop if we reach the "stop" position, or reach a notification from an
|
||||
@@ -1963,11 +1967,11 @@ asyncQueueProcessPageEntries(QueuePosition *current,
|
||||
{
|
||||
bool reachedStop = false;
|
||||
bool reachedEndOfPage;
|
||||
AsyncQueueEntry *qe;
|
||||
AsyncQueueEntry *qe;
|
||||
|
||||
do
|
||||
{
|
||||
QueuePosition thisentry = *current;
|
||||
QueuePosition thisentry = *current;
|
||||
|
||||
if (QUEUE_POS_EQUAL(thisentry, stop))
|
||||
break;
|
||||
@@ -1975,9 +1979,9 @@ asyncQueueProcessPageEntries(QueuePosition *current,
|
||||
qe = (AsyncQueueEntry *) (page_buffer + QUEUE_POS_OFFSET(thisentry));
|
||||
|
||||
/*
|
||||
* Advance *current over this message, possibly to the next page.
|
||||
* As noted in the comments for asyncQueueReadAllNotifications, we
|
||||
* must do this before possibly failing while processing the message.
|
||||
* Advance *current over this message, possibly to the next page. As
|
||||
* noted in the comments for asyncQueueReadAllNotifications, we must
|
||||
* do this before possibly failing while processing the message.
|
||||
*/
|
||||
reachedEndOfPage = asyncQueueAdvance(current, qe->length);
|
||||
|
||||
@@ -1987,12 +1991,12 @@ asyncQueueProcessPageEntries(QueuePosition *current,
|
||||
if (TransactionIdDidCommit(qe->xid))
|
||||
{
|
||||
/* qe->data is the null-terminated channel name */
|
||||
char *channel = qe->data;
|
||||
char *channel = qe->data;
|
||||
|
||||
if (IsListeningOn(channel))
|
||||
{
|
||||
/* payload follows channel name */
|
||||
char *payload = qe->data + strlen(channel) + 1;
|
||||
char *payload = qe->data + strlen(channel) + 1;
|
||||
|
||||
NotifyMyFrontEnd(channel, payload, qe->srcPid);
|
||||
}
|
||||
@@ -2008,12 +2012,12 @@ asyncQueueProcessPageEntries(QueuePosition *current,
|
||||
{
|
||||
/*
|
||||
* The transaction has neither committed nor aborted so far,
|
||||
* so we can't process its message yet. Break out of the loop,
|
||||
* but first back up *current so we will reprocess the message
|
||||
* next time. (Note: it is unlikely but not impossible for
|
||||
* TransactionIdDidCommit to fail, so we can't really avoid
|
||||
* this advance-then-back-up behavior when dealing with an
|
||||
* uncommitted message.)
|
||||
* so we can't process its message yet. Break out of the
|
||||
* loop, but first back up *current so we will reprocess the
|
||||
* message next time. (Note: it is unlikely but not
|
||||
* impossible for TransactionIdDidCommit to fail, so we can't
|
||||
* really avoid this advance-then-back-up behavior when
|
||||
* dealing with an uncommitted message.)
|
||||
*/
|
||||
*current = thisentry;
|
||||
reachedStop = true;
|
||||
@@ -2037,11 +2041,11 @@ asyncQueueProcessPageEntries(QueuePosition *current,
|
||||
static void
|
||||
asyncQueueAdvanceTail(void)
|
||||
{
|
||||
QueuePosition min;
|
||||
int i;
|
||||
int oldtailpage;
|
||||
int newtailpage;
|
||||
int boundary;
|
||||
QueuePosition min;
|
||||
int i;
|
||||
int oldtailpage;
|
||||
int newtailpage;
|
||||
int boundary;
|
||||
|
||||
LWLockAcquire(AsyncQueueLock, LW_EXCLUSIVE);
|
||||
min = QUEUE_HEAD;
|
||||
@@ -2058,16 +2062,16 @@ asyncQueueAdvanceTail(void)
|
||||
* We can truncate something if the global tail advanced across an SLRU
|
||||
* segment boundary.
|
||||
*
|
||||
* XXX it might be better to truncate only once every several segments,
|
||||
* to reduce the number of directory scans.
|
||||
* XXX it might be better to truncate only once every several segments, to
|
||||
* reduce the number of directory scans.
|
||||
*/
|
||||
newtailpage = QUEUE_POS_PAGE(min);
|
||||
boundary = newtailpage - (newtailpage % SLRU_PAGES_PER_SEGMENT);
|
||||
if (asyncQueuePagePrecedesLogically(oldtailpage, boundary))
|
||||
{
|
||||
/*
|
||||
* SimpleLruTruncate() will ask for AsyncCtlLock but will also
|
||||
* release the lock again.
|
||||
* SimpleLruTruncate() will ask for AsyncCtlLock but will also release
|
||||
* the lock again.
|
||||
*/
|
||||
SimpleLruTruncate(AsyncCtl, newtailpage);
|
||||
}
|
||||
@@ -2104,8 +2108,8 @@ ProcessIncomingNotify(void)
|
||||
notifyInterruptOccurred = 0;
|
||||
|
||||
/*
|
||||
* We must run asyncQueueReadAllNotifications inside a transaction,
|
||||
* else bad things happen if it gets an error.
|
||||
* We must run asyncQueueReadAllNotifications inside a transaction, else
|
||||
* bad things happen if it gets an error.
|
||||
*/
|
||||
StartTransactionCommand();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* cluster.c
|
||||
* CLUSTER a table on an index. This is now also used for VACUUM FULL.
|
||||
* CLUSTER a table on an index. This is now also used for VACUUM FULL.
|
||||
*
|
||||
* There is hardly anything left of Paul Brown's original implementation...
|
||||
*
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.201 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.202 2010/02/26 02:00:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -64,7 +64,7 @@ typedef struct
|
||||
|
||||
|
||||
static void rebuild_relation(Relation OldHeap, Oid indexOid,
|
||||
int freeze_min_age, int freeze_table_age);
|
||||
int freeze_min_age, int freeze_table_age);
|
||||
static void copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
int freeze_min_age, int freeze_table_age,
|
||||
bool *pSwapToastByContent, TransactionId *pFreezeXid);
|
||||
@@ -252,7 +252,7 @@ cluster(ClusterStmt *stmt, bool isTopLevel)
|
||||
* them incrementally while we load the table.
|
||||
*
|
||||
* If indexOid is InvalidOid, the table will be rewritten in physical order
|
||||
* instead of index order. This is the new implementation of VACUUM FULL,
|
||||
* instead of index order. This is the new implementation of VACUUM FULL,
|
||||
* and error messages should refer to the operation as VACUUM not CLUSTER.
|
||||
*/
|
||||
void
|
||||
@@ -301,8 +301,8 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
|
||||
* check in the "recheck" case is appropriate (which currently means
|
||||
* somebody is executing a database-wide CLUSTER), because there is
|
||||
* another check in cluster() which will stop any attempt to cluster
|
||||
* remote temp tables by name. There is another check in
|
||||
* cluster_rel which is redundant, but we leave it for extra safety.
|
||||
* remote temp tables by name. There is another check in cluster_rel
|
||||
* which is redundant, but we leave it for extra safety.
|
||||
*/
|
||||
if (RELATION_IS_OTHER_TEMP(OldHeap))
|
||||
{
|
||||
@@ -325,7 +325,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
|
||||
* Check that the index is still the one with indisclustered set.
|
||||
*/
|
||||
tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexOid));
|
||||
if (!HeapTupleIsValid(tuple)) /* probably can't happen */
|
||||
if (!HeapTupleIsValid(tuple)) /* probably can't happen */
|
||||
{
|
||||
relation_close(OldHeap, AccessExclusiveLock);
|
||||
return;
|
||||
@@ -353,19 +353,19 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
|
||||
errmsg("cannot cluster a shared catalog")));
|
||||
|
||||
/*
|
||||
* Don't process temp tables of other backends ... their local
|
||||
* buffer manager is not going to cope.
|
||||
* Don't process temp tables of other backends ... their local buffer
|
||||
* manager is not going to cope.
|
||||
*/
|
||||
if (RELATION_IS_OTHER_TEMP(OldHeap))
|
||||
{
|
||||
if (OidIsValid(indexOid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot cluster temporary tables of other sessions")));
|
||||
errmsg("cannot cluster temporary tables of other sessions")));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot vacuum temporary tables of other sessions")));
|
||||
errmsg("cannot vacuum temporary tables of other sessions")));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -664,8 +664,8 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
|
||||
* the old, or we will have problems with the TEMP status of temp tables.
|
||||
*
|
||||
* Note: the new heap is not a shared relation, even if we are rebuilding
|
||||
* a shared rel. However, we do make the new heap mapped if the source
|
||||
* is mapped. This simplifies swap_relation_files, and is absolutely
|
||||
* a shared rel. However, we do make the new heap mapped if the source is
|
||||
* mapped. This simplifies swap_relation_files, and is absolutely
|
||||
* necessary for rebuilding pg_class, for reasons explained there.
|
||||
*/
|
||||
snprintf(NewHeapName, sizeof(NewHeapName), "pg_temp_%u", OIDOldHeap);
|
||||
@@ -701,9 +701,9 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
|
||||
* If necessary, create a TOAST table for the new relation.
|
||||
*
|
||||
* If the relation doesn't have a TOAST table already, we can't need one
|
||||
* for the new relation. The other way around is possible though: if
|
||||
* some wide columns have been dropped, AlterTableCreateToastTable
|
||||
* can decide that no TOAST table is needed for the new table.
|
||||
* for the new relation. The other way around is possible though: if some
|
||||
* wide columns have been dropped, AlterTableCreateToastTable can decide
|
||||
* that no TOAST table is needed for the new table.
|
||||
*
|
||||
* Note that AlterTableCreateToastTable ends with CommandCounterIncrement,
|
||||
* so that the TOAST table will be visible for insertion.
|
||||
@@ -782,18 +782,18 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
isnull = (bool *) palloc(natts * sizeof(bool));
|
||||
|
||||
/*
|
||||
* We need to log the copied data in WAL iff WAL archiving/streaming
|
||||
* is enabled AND it's not a temp rel.
|
||||
* We need to log the copied data in WAL iff WAL archiving/streaming is
|
||||
* enabled AND it's not a temp rel.
|
||||
*/
|
||||
use_wal = XLogIsNeeded() && !NewHeap->rd_istemp;
|
||||
|
||||
/*
|
||||
* Write an XLOG UNLOGGED record if WAL-logging was skipped because
|
||||
* WAL archiving is not enabled.
|
||||
* Write an XLOG UNLOGGED record if WAL-logging was skipped because WAL
|
||||
* archiving is not enabled.
|
||||
*/
|
||||
if (!use_wal && !NewHeap->rd_istemp)
|
||||
{
|
||||
char reason[NAMEDATALEN + 32];
|
||||
char reason[NAMEDATALEN + 32];
|
||||
|
||||
if (OldIndex != NULL)
|
||||
snprintf(reason, sizeof(reason), "CLUSTER on \"%s\"",
|
||||
@@ -810,7 +810,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
/*
|
||||
* If both tables have TOAST tables, perform toast swap by content. It is
|
||||
* possible that the old table has a toast table but the new one doesn't,
|
||||
* if toastable columns have been dropped. In that case we have to do
|
||||
* if toastable columns have been dropped. In that case we have to do
|
||||
* swap by links. This is okay because swap by content is only essential
|
||||
* for system catalogs, and we don't support schema changes for them.
|
||||
*/
|
||||
@@ -824,7 +824,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
* data will eventually be found. Set this up by setting rd_toastoid.
|
||||
* Note that we must hold NewHeap open until we are done writing data,
|
||||
* since the relcache will not guarantee to remember this setting once
|
||||
* the relation is closed. Also, this technique depends on the fact
|
||||
* the relation is closed. Also, this technique depends on the fact
|
||||
* that no one will try to read from the NewHeap until after we've
|
||||
* finished writing it and swapping the rels --- otherwise they could
|
||||
* follow the toast pointers to the wrong place.
|
||||
@@ -860,8 +860,8 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
rwstate = begin_heap_rewrite(NewHeap, OldestXmin, FreezeXid, use_wal);
|
||||
|
||||
/*
|
||||
* Scan through the OldHeap, either in OldIndex order or sequentially,
|
||||
* and copy each tuple into the NewHeap. To ensure we see recently-dead
|
||||
* Scan through the OldHeap, either in OldIndex order or sequentially, and
|
||||
* copy each tuple into the NewHeap. To ensure we see recently-dead
|
||||
* tuples that still need to be copied, we scan with SnapshotAny and use
|
||||
* HeapTupleSatisfiesVacuum for the visibility test.
|
||||
*/
|
||||
@@ -924,12 +924,12 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
case HEAPTUPLE_INSERT_IN_PROGRESS:
|
||||
|
||||
/*
|
||||
* Since we hold exclusive lock on the relation, normally
|
||||
* the only way to see this is if it was inserted earlier
|
||||
* in our own transaction. However, it can happen in system
|
||||
* Since we hold exclusive lock on the relation, normally the
|
||||
* only way to see this is if it was inserted earlier in our
|
||||
* own transaction. However, it can happen in system
|
||||
* catalogs, since we tend to release write lock before commit
|
||||
* there. Give a warning if neither case applies; but in
|
||||
* any case we had better copy it.
|
||||
* there. Give a warning if neither case applies; but in any
|
||||
* case we had better copy it.
|
||||
*/
|
||||
if (!is_system_catalog &&
|
||||
!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple->t_data)))
|
||||
@@ -1139,7 +1139,7 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
|
||||
NameStr(relform2->relname), r2);
|
||||
|
||||
/*
|
||||
* Send replacement mappings to relmapper. Note these won't actually
|
||||
* Send replacement mappings to relmapper. Note these won't actually
|
||||
* take effect until CommandCounterIncrement.
|
||||
*/
|
||||
RelationMapUpdateMap(r1, relfilenode2, relform1->relisshared, false);
|
||||
@@ -1151,10 +1151,10 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
|
||||
|
||||
/*
|
||||
* In the case of a shared catalog, these next few steps will only affect
|
||||
* our own database's pg_class row; but that's okay, because they are
|
||||
* all noncritical updates. That's also an important fact for the case
|
||||
* of a mapped catalog, because it's possible that we'll commit the map
|
||||
* change and then fail to commit the pg_class update.
|
||||
* our own database's pg_class row; but that's okay, because they are all
|
||||
* noncritical updates. That's also an important fact for the case of a
|
||||
* mapped catalog, because it's possible that we'll commit the map change
|
||||
* and then fail to commit the pg_class update.
|
||||
*/
|
||||
|
||||
/* set rel1's frozen Xid */
|
||||
@@ -1181,10 +1181,10 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
|
||||
/*
|
||||
* Update the tuples in pg_class --- unless the target relation of the
|
||||
* swap is pg_class itself. In that case, there is zero point in making
|
||||
* changes because we'd be updating the old data that we're about to
|
||||
* throw away. Because the real work being done here for a mapped relation
|
||||
* is just to change the relation map settings, it's all right to not
|
||||
* update the pg_class rows in this case.
|
||||
* changes because we'd be updating the old data that we're about to throw
|
||||
* away. Because the real work being done here for a mapped relation is
|
||||
* just to change the relation map settings, it's all right to not update
|
||||
* the pg_class rows in this case.
|
||||
*/
|
||||
if (!target_is_pg_class)
|
||||
{
|
||||
@@ -1248,8 +1248,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
|
||||
/*
|
||||
* We disallow this case for system catalogs, to avoid the
|
||||
* possibility that the catalog we're rebuilding is one of the
|
||||
* ones the dependency changes would change. It's too late
|
||||
* to be making any data changes to the target catalog.
|
||||
* ones the dependency changes would change. It's too late to be
|
||||
* making any data changes to the target catalog.
|
||||
*/
|
||||
if (IsSystemClass(relform1))
|
||||
elog(ERROR, "cannot swap toast files by links for system catalogs");
|
||||
@@ -1302,12 +1302,12 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
|
||||
*/
|
||||
if (swap_toast_by_content &&
|
||||
relform1->reltoastidxid && relform2->reltoastidxid)
|
||||
swap_relation_files(relform1->reltoastidxid,
|
||||
relform2->reltoastidxid,
|
||||
target_is_pg_class,
|
||||
swap_toast_by_content,
|
||||
InvalidTransactionId,
|
||||
mapped_tables);
|
||||
swap_relation_files(relform1->reltoastidxid,
|
||||
relform2->reltoastidxid,
|
||||
target_is_pg_class,
|
||||
swap_toast_by_content,
|
||||
InvalidTransactionId,
|
||||
mapped_tables);
|
||||
|
||||
/* Clean up. */
|
||||
heap_freetuple(reltup1);
|
||||
@@ -1327,7 +1327,7 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
|
||||
* non-transient relation.)
|
||||
*
|
||||
* Caution: the placement of this step interacts with the decision to
|
||||
* handle toast rels by recursion. When we are trying to rebuild pg_class
|
||||
* handle toast rels by recursion. When we are trying to rebuild pg_class
|
||||
* itself, the smgr close on pg_class must happen after all accesses in
|
||||
* this function.
|
||||
*/
|
||||
@@ -1369,12 +1369,12 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
|
||||
|
||||
/*
|
||||
* Rebuild each index on the relation (but not the toast table, which is
|
||||
* all-new at this point). It is important to do this before the DROP
|
||||
* all-new at this point). It is important to do this before the DROP
|
||||
* step because if we are processing a system catalog that will be used
|
||||
* during DROP, we want to have its indexes available. There is no
|
||||
* during DROP, we want to have its indexes available. There is no
|
||||
* advantage to the other order anyway because this is all transactional,
|
||||
* so no chance to reclaim disk space before commit. We do not need
|
||||
* a final CommandCounterIncrement() because reindex_relation does it.
|
||||
* so no chance to reclaim disk space before commit. We do not need a
|
||||
* final CommandCounterIncrement() because reindex_relation does it.
|
||||
*/
|
||||
reindex_relation(OIDOldHeap, false, true);
|
||||
|
||||
@@ -1393,9 +1393,9 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
|
||||
|
||||
/*
|
||||
* Now we must remove any relation mapping entries that we set up for the
|
||||
* transient table, as well as its toast table and toast index if any.
|
||||
* If we fail to do this before commit, the relmapper will complain about
|
||||
* new permanent map entries being added post-bootstrap.
|
||||
* transient table, as well as its toast table and toast index if any. If
|
||||
* we fail to do this before commit, the relmapper will complain about new
|
||||
* permanent map entries being added post-bootstrap.
|
||||
*/
|
||||
for (i = 0; OidIsValid(mapped_tables[i]); i++)
|
||||
RelationMapRemoveMapping(mapped_tables[i]);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.113 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.114 2010/02/26 02:00:38 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -498,11 +498,11 @@ GetComment(Oid oid, Oid classoid, int32 subid)
|
||||
sd = systable_beginscan(description, DescriptionObjIndexId, true,
|
||||
SnapshotNow, 3, skey);
|
||||
|
||||
comment = NULL;
|
||||
comment = NULL;
|
||||
while ((tuple = systable_getnext(sd)) != NULL)
|
||||
{
|
||||
Datum value;
|
||||
bool isnull;
|
||||
Datum value;
|
||||
bool isnull;
|
||||
|
||||
/* Found the tuple, get description field */
|
||||
value = heap_getattr(tuple, Anum_pg_description_description, tupdesc, &isnull);
|
||||
@@ -631,9 +631,8 @@ CommentAttribute(List *qualname, char *comment)
|
||||
* Allow comments only on columns of tables, views, and composite types
|
||||
* (which are the only relkinds for which pg_dump will dump per-column
|
||||
* comments). In particular we wish to disallow comments on index
|
||||
* columns, because the naming of an index's columns may change across
|
||||
* PG versions, so dumping per-column comments could create reload
|
||||
* failures.
|
||||
* columns, because the naming of an index's columns may change across PG
|
||||
* versions, so dumping per-column comments could create reload failures.
|
||||
*/
|
||||
if (relation->rd_rel->relkind != RELKIND_RELATION &&
|
||||
relation->rd_rel->relkind != RELKIND_VIEW &&
|
||||
@@ -903,7 +902,7 @@ CommentRule(List *qualname, char *comment)
|
||||
|
||||
/* Find the rule's pg_rewrite tuple, get its OID */
|
||||
tuple = SearchSysCache2(RULERELNAME,
|
||||
ObjectIdGetDatum(reloid),
|
||||
ObjectIdGetDatum(reloid),
|
||||
PointerGetDatum(rulename));
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
@@ -1358,7 +1357,7 @@ CommentOpFamily(List *qualname, List *arguments, char *comment)
|
||||
namespaceId = LookupExplicitNamespace(schemaname);
|
||||
tuple = SearchSysCache3(OPFAMILYAMNAMENSP,
|
||||
ObjectIdGetDatum(amID),
|
||||
PointerGetDatum(opfname),
|
||||
PointerGetDatum(opfname),
|
||||
ObjectIdGetDatum(namespaceId));
|
||||
}
|
||||
else
|
||||
@@ -1448,9 +1447,8 @@ CommentLargeObject(List *qualname, char *comment)
|
||||
/*
|
||||
* Call CreateComments() to create/drop the comments
|
||||
*
|
||||
* See the comment in the inv_create() which describes
|
||||
* the reason why LargeObjectRelationId is used instead
|
||||
* of LargeObjectMetadataRelationId.
|
||||
* See the comment in the inv_create() which describes the reason why
|
||||
* LargeObjectRelationId is used instead of LargeObjectMetadataRelationId.
|
||||
*/
|
||||
CreateComments(loid, LargeObjectRelationId, 0, comment);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/constraint.c,v 1.3 2010/01/02 16:57:37 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/constraint.c,v 1.4 2010/02/26 02:00:38 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -49,9 +49,9 @@ unique_key_recheck(PG_FUNCTION_ARGS)
|
||||
bool isnull[INDEX_MAX_KEYS];
|
||||
|
||||
/*
|
||||
* Make sure this is being called as an AFTER ROW trigger. Note:
|
||||
* translatable error strings are shared with ri_triggers.c, so
|
||||
* resist the temptation to fold the function name into them.
|
||||
* Make sure this is being called as an AFTER ROW trigger. Note:
|
||||
* translatable error strings are shared with ri_triggers.c, so resist the
|
||||
* temptation to fold the function name into them.
|
||||
*/
|
||||
if (!CALLED_AS_TRIGGER(fcinfo))
|
||||
ereport(ERROR,
|
||||
@@ -86,7 +86,7 @@ unique_key_recheck(PG_FUNCTION_ARGS)
|
||||
* If the new_row is now dead (ie, inserted and then deleted within our
|
||||
* transaction), we can skip the check. However, we have to be careful,
|
||||
* because this trigger gets queued only in response to index insertions;
|
||||
* which means it does not get queued for HOT updates. The row we are
|
||||
* which means it does not get queued for HOT updates. The row we are
|
||||
* called for might now be dead, but have a live HOT child, in which case
|
||||
* we still need to make the check. Therefore we have to use
|
||||
* heap_hot_search, not just HeapTupleSatisfiesVisibility as is done in
|
||||
@@ -109,9 +109,9 @@ unique_key_recheck(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the index, acquiring a RowExclusiveLock, just as if we were
|
||||
* going to update it. (This protects against possible changes of the
|
||||
* index schema, not against concurrent updates.)
|
||||
* Open the index, acquiring a RowExclusiveLock, just as if we were going
|
||||
* to update it. (This protects against possible changes of the index
|
||||
* schema, not against concurrent updates.)
|
||||
*/
|
||||
indexRel = index_open(trigdata->tg_trigger->tgconstrindid,
|
||||
RowExclusiveLock);
|
||||
@@ -125,9 +125,9 @@ unique_key_recheck(PG_FUNCTION_ARGS)
|
||||
ExecStoreTuple(new_row, slot, InvalidBuffer, false);
|
||||
|
||||
/*
|
||||
* Typically the index won't have expressions, but if it does we need
|
||||
* an EState to evaluate them. We need it for exclusion constraints
|
||||
* too, even if they are just on simple columns.
|
||||
* Typically the index won't have expressions, but if it does we need an
|
||||
* EState to evaluate them. We need it for exclusion constraints too,
|
||||
* even if they are just on simple columns.
|
||||
*/
|
||||
if (indexInfo->ii_Expressions != NIL ||
|
||||
indexInfo->ii_ExclusionOps != NULL)
|
||||
@@ -140,13 +140,13 @@ unique_key_recheck(PG_FUNCTION_ARGS)
|
||||
estate = NULL;
|
||||
|
||||
/*
|
||||
* Form the index values and isnull flags for the index entry that
|
||||
* we need to check.
|
||||
* Form the index values and isnull flags for the index entry that we need
|
||||
* to check.
|
||||
*
|
||||
* Note: if the index uses functions that are not as immutable as they
|
||||
* are supposed to be, this could produce an index tuple different from
|
||||
* the original. The index AM can catch such errors by verifying that
|
||||
* it finds a matching index entry with the tuple's TID. For exclusion
|
||||
* Note: if the index uses functions that are not as immutable as they are
|
||||
* supposed to be, this could produce an index tuple different from the
|
||||
* original. The index AM can catch such errors by verifying that it
|
||||
* finds a matching index entry with the tuple's TID. For exclusion
|
||||
* constraints we check this in check_exclusion_constraint().
|
||||
*/
|
||||
FormIndexDatum(indexInfo, slot, estate, values, isnull);
|
||||
@@ -166,8 +166,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* For exclusion constraints we just do the normal check, but now
|
||||
* it's okay to throw error.
|
||||
* For exclusion constraints we just do the normal check, but now it's
|
||||
* okay to throw error.
|
||||
*/
|
||||
check_exclusion_constraint(trigdata->tg_relation, indexRel, indexInfo,
|
||||
&(new_row->t_self), values, isnull,
|
||||
@@ -175,8 +175,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* If that worked, then this index entry is unique or non-excluded,
|
||||
* and we are done.
|
||||
* If that worked, then this index entry is unique or non-excluded, and we
|
||||
* are done.
|
||||
*/
|
||||
if (estate != NULL)
|
||||
FreeExecutorState(estate);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.325 2010/02/20 21:24:02 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.326 2010/02/26 02:00:38 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -743,7 +743,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
|
||||
|
||||
if (strcmp(defel->defname, "format") == 0)
|
||||
{
|
||||
char *fmt = defGetString(defel);
|
||||
char *fmt = defGetString(defel);
|
||||
|
||||
if (format_specified)
|
||||
ereport(ERROR,
|
||||
@@ -751,7 +751,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
|
||||
errmsg("conflicting or redundant options")));
|
||||
format_specified = true;
|
||||
if (strcmp(fmt, "text") == 0)
|
||||
/* default format */ ;
|
||||
/* default format */ ;
|
||||
else if (strcmp(fmt, "csv") == 0)
|
||||
cstate->csv_mode = true;
|
||||
else if (strcmp(fmt, "binary") == 0)
|
||||
@@ -821,9 +821,9 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
|
||||
force_quote = (List *) defel->arg;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("argument to option \"%s\" must be a list of column names",
|
||||
defel->defname)));
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("argument to option \"%s\" must be a list of column names",
|
||||
defel->defname)));
|
||||
}
|
||||
else if (strcmp(defel->defname, "force_not_null") == 0)
|
||||
{
|
||||
@@ -835,9 +835,9 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
|
||||
force_notnull = (List *) defel->arg;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("argument to option \"%s\" must be a list of column names",
|
||||
defel->defname)));
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("argument to option \"%s\" must be a list of column names",
|
||||
defel->defname)));
|
||||
}
|
||||
else
|
||||
ereport(ERROR,
|
||||
@@ -1113,7 +1113,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
|
||||
cstate->force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
|
||||
if (force_quote_all)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_phys_attrs; i++)
|
||||
cstate->force_quote_flags[i] = true;
|
||||
@@ -2150,7 +2150,7 @@ CopyFrom(CopyState cstate)
|
||||
|
||||
if (!skip_tuple)
|
||||
{
|
||||
List *recheckIndexes = NIL;
|
||||
List *recheckIndexes = NIL;
|
||||
|
||||
/* Place tuple in tuple slot */
|
||||
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
|
||||
@@ -2224,7 +2224,8 @@ CopyFrom(CopyState cstate)
|
||||
*/
|
||||
if (hi_options & HEAP_INSERT_SKIP_WAL)
|
||||
{
|
||||
char reason[NAMEDATALEN + 30];
|
||||
char reason[NAMEDATALEN + 30];
|
||||
|
||||
snprintf(reason, sizeof(reason), "COPY FROM on \"%s\"",
|
||||
RelationGetRelationName(cstate->rel));
|
||||
XLogReportUnloggedStatement(reason);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.234 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.235 2010/02/26 02:00:38 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -338,11 +338,11 @@ createdb(const CreatedbStmt *stmt)
|
||||
* fails when presented with data in an encoding it's not expecting. We
|
||||
* allow mismatch in four cases:
|
||||
*
|
||||
* 1. locale encoding = SQL_ASCII, which means that the locale is
|
||||
* C/POSIX which works with any encoding.
|
||||
* 1. locale encoding = SQL_ASCII, which means that the locale is C/POSIX
|
||||
* which works with any encoding.
|
||||
*
|
||||
* 2. locale encoding = -1, which means that we couldn't determine
|
||||
* the locale's encoding and have to trust the user to get it right.
|
||||
* 2. locale encoding = -1, which means that we couldn't determine the
|
||||
* locale's encoding and have to trust the user to get it right.
|
||||
*
|
||||
* 3. selected encoding is UTF8 and platform is win32. This is because
|
||||
* UTF8 is a pseudo codepage that is supported in all locales since it's
|
||||
@@ -551,7 +551,7 @@ createdb(const CreatedbStmt *stmt)
|
||||
|
||||
/*
|
||||
* We deliberately set datacl to default (NULL), rather than copying it
|
||||
* from the template database. Copying it would be a bad idea when the
|
||||
* from the template database. Copying it would be a bad idea when the
|
||||
* owner is not the same as the template's owner.
|
||||
*/
|
||||
new_record_nulls[Anum_pg_database_datacl - 1] = true;
|
||||
@@ -871,9 +871,9 @@ dropdb(const char *dbname, bool missing_ok)
|
||||
heap_close(pgdbrel, NoLock);
|
||||
|
||||
/*
|
||||
* Force synchronous commit, thus minimizing the window between removal
|
||||
* of the database files and commital of the transaction. If we crash
|
||||
* before committing, we'll have a DB that's gone on disk but still there
|
||||
* Force synchronous commit, thus minimizing the window between removal of
|
||||
* the database files and commital of the transaction. If we crash before
|
||||
* committing, we'll have a DB that's gone on disk but still there
|
||||
* according to pg_database, which is not good.
|
||||
*/
|
||||
ForceSyncCommit();
|
||||
@@ -1402,13 +1402,13 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
|
||||
void
|
||||
AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
||||
{
|
||||
Oid datid = get_database_oid(stmt->dbname);
|
||||
Oid datid = get_database_oid(stmt->dbname);
|
||||
|
||||
if (!OidIsValid(datid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
||||
errmsg("database \"%s\" does not exist", stmt->dbname)));
|
||||
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
||||
errmsg("database \"%s\" does not exist", stmt->dbname)));
|
||||
|
||||
/*
|
||||
* Obtain a lock on the database and make sure it didn't go away in the
|
||||
* meantime.
|
||||
@@ -1416,11 +1416,11 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
||||
shdepLockAndCheckObject(DatabaseRelationId, datid);
|
||||
|
||||
if (!pg_database_ownercheck(datid, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
|
||||
stmt->dbname);
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
|
||||
stmt->dbname);
|
||||
|
||||
AlterSetting(datid, InvalidOid, stmt->setstmt);
|
||||
|
||||
|
||||
UnlockSharedObject(DatabaseRelationId, datid, 0, AccessShareLock);
|
||||
}
|
||||
|
||||
@@ -1936,9 +1936,10 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
if (InHotStandby)
|
||||
{
|
||||
/*
|
||||
* Lock database while we resolve conflicts to ensure that InitPostgres()
|
||||
* cannot fully re-execute concurrently. This avoids backends re-connecting
|
||||
* automatically to same database, which can happen in some cases.
|
||||
* Lock database while we resolve conflicts to ensure that
|
||||
* InitPostgres() cannot fully re-execute concurrently. This
|
||||
* avoids backends re-connecting automatically to same database,
|
||||
* which can happen in some cases.
|
||||
*/
|
||||
LockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
|
||||
ResolveRecoveryConflictWithDatabase(xlrec->db_id);
|
||||
@@ -1962,10 +1963,11 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
if (InHotStandby)
|
||||
{
|
||||
/*
|
||||
* Release locks prior to commit. XXX There is a race condition here that may allow
|
||||
* backends to reconnect, but the window for this is small because the gap between
|
||||
* here and commit is mostly fairly small and it is unlikely that people will be
|
||||
* dropping databases that we are trying to connect to anyway.
|
||||
* Release locks prior to commit. XXX There is a race condition
|
||||
* here that may allow backends to reconnect, but the window for
|
||||
* this is small because the gap between here and commit is mostly
|
||||
* fairly small and it is unlikely that people will be dropping
|
||||
* databases that we are trying to connect to anyway.
|
||||
*/
|
||||
UnlockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.107 2010/01/02 16:57:37 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.108 2010/02/26 02:00:38 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -156,8 +156,8 @@ defGetBoolean(DefElem *def)
|
||||
char *sval = defGetString(def);
|
||||
|
||||
/*
|
||||
* The set of strings accepted here should match up with
|
||||
* the grammar's opt_boolean production.
|
||||
* The set of strings accepted here should match up with the
|
||||
* grammar's opt_boolean production.
|
||||
*/
|
||||
if (pg_strcasecmp(sval, "true") == 0)
|
||||
return true;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.203 2010/02/16 22:19:59 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.204 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -55,9 +55,9 @@ static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
|
||||
ExplainState *es);
|
||||
static double elapsed_time(instr_time *starttime);
|
||||
static void ExplainNode(Plan *plan, PlanState *planstate,
|
||||
Plan *outer_plan,
|
||||
const char *relationship, const char *plan_name,
|
||||
ExplainState *es);
|
||||
Plan *outer_plan,
|
||||
const char *relationship, const char *plan_name,
|
||||
ExplainState *es);
|
||||
static void show_plan_tlist(Plan *plan, ExplainState *es);
|
||||
static void show_qual(List *qual, const char *qlabel, Plan *plan,
|
||||
Plan *outer_plan, bool useprefix, ExplainState *es);
|
||||
@@ -74,25 +74,26 @@ static void ExplainScanTarget(Scan *plan, ExplainState *es);
|
||||
static void ExplainMemberNodes(List *plans, PlanState **planstate,
|
||||
Plan *outer_plan, ExplainState *es);
|
||||
static void ExplainSubPlans(List *plans, const char *relationship,
|
||||
ExplainState *es);
|
||||
ExplainState *es);
|
||||
static void ExplainPropertyList(const char *qlabel, List *data,
|
||||
ExplainState *es);
|
||||
ExplainState *es);
|
||||
static void ExplainProperty(const char *qlabel, const char *value,
|
||||
bool numeric, ExplainState *es);
|
||||
#define ExplainPropertyText(qlabel, value, es) \
|
||||
bool numeric, ExplainState *es);
|
||||
|
||||
#define ExplainPropertyText(qlabel, value, es) \
|
||||
ExplainProperty(qlabel, value, false, es)
|
||||
static void ExplainPropertyInteger(const char *qlabel, int value,
|
||||
ExplainState *es);
|
||||
ExplainState *es);
|
||||
static void ExplainPropertyLong(const char *qlabel, long value,
|
||||
ExplainState *es);
|
||||
ExplainState *es);
|
||||
static void ExplainPropertyFloat(const char *qlabel, double value, int ndigits,
|
||||
ExplainState *es);
|
||||
ExplainState *es);
|
||||
static void ExplainOpenGroup(const char *objtype, const char *labelname,
|
||||
bool labeled, ExplainState *es);
|
||||
static void ExplainCloseGroup(const char *objtype, const char *labelname,
|
||||
bool labeled, ExplainState *es);
|
||||
bool labeled, ExplainState *es);
|
||||
static void ExplainDummyGroup(const char *objtype, const char *labelname,
|
||||
ExplainState *es);
|
||||
ExplainState *es);
|
||||
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es);
|
||||
static void ExplainJSONLineEnding(ExplainState *es);
|
||||
static void ExplainYAMLLineStarting(ExplainState *es);
|
||||
@@ -120,7 +121,7 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
|
||||
/* Parse options list. */
|
||||
foreach(lc, stmt->options)
|
||||
{
|
||||
DefElem *opt = (DefElem *) lfirst(lc);
|
||||
DefElem *opt = (DefElem *) lfirst(lc);
|
||||
|
||||
if (strcmp(opt->defname, "analyze") == 0)
|
||||
es.analyze = defGetBoolean(opt);
|
||||
@@ -132,7 +133,7 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
|
||||
es.buffers = defGetBoolean(opt);
|
||||
else if (strcmp(opt->defname, "format") == 0)
|
||||
{
|
||||
char *p = defGetString(opt);
|
||||
char *p = defGetString(opt);
|
||||
|
||||
if (strcmp(p, "text") == 0)
|
||||
es.format = EXPLAIN_FORMAT_TEXT;
|
||||
@@ -144,9 +145,9 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
|
||||
es.format = EXPLAIN_FORMAT_YAML;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
|
||||
opt->defname, p)));
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
|
||||
opt->defname, p)));
|
||||
}
|
||||
else
|
||||
ereport(ERROR,
|
||||
@@ -157,14 +158,14 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
|
||||
|
||||
if (es.buffers && !es.analyze)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
|
||||
|
||||
/*
|
||||
* Parse analysis was done already, but we still have to run the rule
|
||||
* rewriter. We do not do AcquireRewriteLocks: we assume the query
|
||||
* either came straight from the parser, or suitable locks were
|
||||
* acquired by plancache.c.
|
||||
* rewriter. We do not do AcquireRewriteLocks: we assume the query either
|
||||
* came straight from the parser, or suitable locks were acquired by
|
||||
* plancache.c.
|
||||
*
|
||||
* Because the rewriter and planner tend to scribble on the input, we make
|
||||
* a preliminary copy of the source querytree. This prevents problems in
|
||||
@@ -244,11 +245,11 @@ ExplainResultDesc(ExplainStmt *stmt)
|
||||
/* Check for XML format option */
|
||||
foreach(lc, stmt->options)
|
||||
{
|
||||
DefElem *opt = (DefElem *) lfirst(lc);
|
||||
DefElem *opt = (DefElem *) lfirst(lc);
|
||||
|
||||
if (strcmp(opt->defname, "format") == 0)
|
||||
{
|
||||
char *p = defGetString(opt);
|
||||
char *p = defGetString(opt);
|
||||
|
||||
xml = (strcmp(p, "xml") == 0);
|
||||
/* don't "break", as ExplainQuery will use the last value */
|
||||
@@ -322,7 +323,7 @@ ExplainOneUtility(Node *utilityStmt, ExplainState *es,
|
||||
{
|
||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||
appendStringInfoString(es->str,
|
||||
"Utility statements have no plan structure\n");
|
||||
"Utility statements have no plan structure\n");
|
||||
else
|
||||
ExplainDummyGroup("Utility Statement", NULL, es);
|
||||
}
|
||||
@@ -472,7 +473,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
|
||||
* convert a QueryDesc's plan tree to text and append it to es->str
|
||||
*
|
||||
* The caller should have set up the options fields of *es, as well as
|
||||
* initializing the output buffer es->str. Other fields in *es are
|
||||
* initializing the output buffer es->str. Other fields in *es are
|
||||
* initialized here.
|
||||
*
|
||||
* NB: will not work on utility statements
|
||||
@@ -489,10 +490,10 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
|
||||
|
||||
/*
|
||||
* ExplainQueryText -
|
||||
* add a "Query Text" node that contains the actual text of the query
|
||||
*
|
||||
* add a "Query Text" node that contains the actual text of the query
|
||||
*
|
||||
* The caller should have set up the options fields of *es, as well as
|
||||
* initializing the output buffer es->str.
|
||||
* initializing the output buffer es->str.
|
||||
*
|
||||
*/
|
||||
void
|
||||
@@ -538,8 +539,8 @@ report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
|
||||
|
||||
/*
|
||||
* In text format, we avoid printing both the trigger name and the
|
||||
* constraint name unless VERBOSE is specified. In non-text
|
||||
* formats we just print everything.
|
||||
* constraint name unless VERBOSE is specified. In non-text formats
|
||||
* we just print everything.
|
||||
*/
|
||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||
{
|
||||
@@ -657,11 +658,11 @@ ExplainNode(Plan *plan, PlanState *planstate,
|
||||
pname = sname = "Nested Loop";
|
||||
break;
|
||||
case T_MergeJoin:
|
||||
pname = "Merge"; /* "Join" gets added by jointype switch */
|
||||
pname = "Merge"; /* "Join" gets added by jointype switch */
|
||||
sname = "Merge Join";
|
||||
break;
|
||||
case T_HashJoin:
|
||||
pname = "Hash"; /* "Join" gets added by jointype switch */
|
||||
pname = "Hash"; /* "Join" gets added by jointype switch */
|
||||
sname = "Hash Join";
|
||||
break;
|
||||
case T_SeqScan:
|
||||
@@ -801,9 +802,9 @@ ExplainNode(Plan *plan, PlanState *planstate,
|
||||
{
|
||||
case T_IndexScan:
|
||||
{
|
||||
IndexScan *indexscan = (IndexScan *) plan;
|
||||
IndexScan *indexscan = (IndexScan *) plan;
|
||||
const char *indexname =
|
||||
explain_get_index_name(indexscan->indexid);
|
||||
explain_get_index_name(indexscan->indexid);
|
||||
|
||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||
{
|
||||
@@ -849,7 +850,7 @@ ExplainNode(Plan *plan, PlanState *planstate,
|
||||
{
|
||||
BitmapIndexScan *bitmapindexscan = (BitmapIndexScan *) plan;
|
||||
const char *indexname =
|
||||
explain_get_index_name(bitmapindexscan->indexid);
|
||||
explain_get_index_name(bitmapindexscan->indexid);
|
||||
|
||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||
appendStringInfo(es->str, " on %s", indexname);
|
||||
@@ -1084,14 +1085,14 @@ ExplainNode(Plan *plan, PlanState *planstate,
|
||||
|
||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||
{
|
||||
bool has_shared = (usage->shared_blks_hit > 0 ||
|
||||
usage->shared_blks_read > 0 ||
|
||||
usage->shared_blks_written);
|
||||
bool has_local = (usage->local_blks_hit > 0 ||
|
||||
usage->local_blks_read > 0 ||
|
||||
usage->local_blks_written);
|
||||
bool has_temp = (usage->temp_blks_read > 0 ||
|
||||
usage->temp_blks_written);
|
||||
bool has_shared = (usage->shared_blks_hit > 0 ||
|
||||
usage->shared_blks_read > 0 ||
|
||||
usage->shared_blks_written);
|
||||
bool has_local = (usage->local_blks_hit > 0 ||
|
||||
usage->local_blks_read > 0 ||
|
||||
usage->local_blks_written);
|
||||
bool has_temp = (usage->temp_blks_read > 0 ||
|
||||
usage->temp_blks_written);
|
||||
|
||||
/* Show only positive counter values. */
|
||||
if (has_shared || has_local || has_temp)
|
||||
@@ -1104,13 +1105,13 @@ ExplainNode(Plan *plan, PlanState *planstate,
|
||||
appendStringInfoString(es->str, " shared");
|
||||
if (usage->shared_blks_hit > 0)
|
||||
appendStringInfo(es->str, " hit=%ld",
|
||||
usage->shared_blks_hit);
|
||||
usage->shared_blks_hit);
|
||||
if (usage->shared_blks_read > 0)
|
||||
appendStringInfo(es->str, " read=%ld",
|
||||
usage->shared_blks_read);
|
||||
usage->shared_blks_read);
|
||||
if (usage->shared_blks_written > 0)
|
||||
appendStringInfo(es->str, " written=%ld",
|
||||
usage->shared_blks_written);
|
||||
usage->shared_blks_written);
|
||||
if (has_local || has_temp)
|
||||
appendStringInfoChar(es->str, ',');
|
||||
}
|
||||
@@ -1119,13 +1120,13 @@ ExplainNode(Plan *plan, PlanState *planstate,
|
||||
appendStringInfoString(es->str, " local");
|
||||
if (usage->local_blks_hit > 0)
|
||||
appendStringInfo(es->str, " hit=%ld",
|
||||
usage->local_blks_hit);
|
||||
usage->local_blks_hit);
|
||||
if (usage->local_blks_read > 0)
|
||||
appendStringInfo(es->str, " read=%ld",
|
||||
usage->local_blks_read);
|
||||
usage->local_blks_read);
|
||||
if (usage->local_blks_written > 0)
|
||||
appendStringInfo(es->str, " written=%ld",
|
||||
usage->local_blks_written);
|
||||
usage->local_blks_written);
|
||||
if (has_temp)
|
||||
appendStringInfoChar(es->str, ',');
|
||||
}
|
||||
@@ -1134,10 +1135,10 @@ ExplainNode(Plan *plan, PlanState *planstate,
|
||||
appendStringInfoString(es->str, " temp");
|
||||
if (usage->temp_blks_read > 0)
|
||||
appendStringInfo(es->str, " read=%ld",
|
||||
usage->temp_blks_read);
|
||||
usage->temp_blks_read);
|
||||
if (usage->temp_blks_written > 0)
|
||||
appendStringInfo(es->str, " written=%ld",
|
||||
usage->temp_blks_written);
|
||||
usage->temp_blks_written);
|
||||
}
|
||||
appendStringInfoChar(es->str, '\n');
|
||||
}
|
||||
@@ -1283,7 +1284,7 @@ show_plan_tlist(Plan *plan, ExplainState *es)
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(lc);
|
||||
|
||||
result = lappend(result,
|
||||
deparse_expression((Node *) tle->expr, context,
|
||||
deparse_expression((Node *) tle->expr, context,
|
||||
useprefix, false));
|
||||
}
|
||||
|
||||
@@ -1403,7 +1404,7 @@ show_sort_info(SortState *sortstate, ExplainState *es)
|
||||
if (es->analyze && sortstate->sort_Done &&
|
||||
sortstate->tuplesortstate != NULL)
|
||||
{
|
||||
Tuplesortstate *state = (Tuplesortstate *) sortstate->tuplesortstate;
|
||||
Tuplesortstate *state = (Tuplesortstate *) sortstate->tuplesortstate;
|
||||
const char *sortMethod;
|
||||
const char *spaceType;
|
||||
long spaceUsed;
|
||||
@@ -1438,7 +1439,8 @@ show_hash_info(HashState *hashstate, ExplainState *es)
|
||||
|
||||
if (hashtable)
|
||||
{
|
||||
long spacePeakKb = (hashtable->spacePeak + 1023) / 1024;
|
||||
long spacePeakKb = (hashtable->spacePeak + 1023) / 1024;
|
||||
|
||||
if (es->format != EXPLAIN_FORMAT_TEXT)
|
||||
{
|
||||
ExplainPropertyLong("Hash Buckets", hashtable->nbuckets, es);
|
||||
@@ -1451,7 +1453,7 @@ show_hash_info(HashState *hashstate, ExplainState *es)
|
||||
{
|
||||
appendStringInfoSpaces(es->str, es->indent * 2);
|
||||
appendStringInfo(es->str,
|
||||
"Buckets: %d Batches: %d (originally %d) Memory Usage: %ldkB\n",
|
||||
"Buckets: %d Batches: %d (originally %d) Memory Usage: %ldkB\n",
|
||||
hashtable->nbuckets, hashtable->nbatch,
|
||||
hashtable->nbatch_original, spacePeakKb);
|
||||
}
|
||||
@@ -1459,7 +1461,7 @@ show_hash_info(HashState *hashstate, ExplainState *es)
|
||||
{
|
||||
appendStringInfoSpaces(es->str, es->indent * 2);
|
||||
appendStringInfo(es->str,
|
||||
"Buckets: %d Batches: %d Memory Usage: %ldkB\n",
|
||||
"Buckets: %d Batches: %d Memory Usage: %ldkB\n",
|
||||
hashtable->nbuckets, hashtable->nbatch,
|
||||
spacePeakKb);
|
||||
}
|
||||
@@ -1600,7 +1602,7 @@ ExplainScanTarget(Scan *plan, ExplainState *es)
|
||||
*/
|
||||
static void
|
||||
ExplainMemberNodes(List *plans, PlanState **planstate, Plan *outer_plan,
|
||||
ExplainState *es)
|
||||
ExplainState *es)
|
||||
{
|
||||
ListCell *lst;
|
||||
int j = 0;
|
||||
@@ -1667,7 +1669,7 @@ ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
|
||||
ExplainXMLTag(qlabel, X_OPENING, es);
|
||||
foreach(lc, data)
|
||||
{
|
||||
char *str;
|
||||
char *str;
|
||||
|
||||
appendStringInfoSpaces(es->str, es->indent * 2 + 2);
|
||||
appendStringInfoString(es->str, "<Item>");
|
||||
@@ -1731,7 +1733,7 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric,
|
||||
|
||||
case EXPLAIN_FORMAT_XML:
|
||||
{
|
||||
char *str;
|
||||
char *str;
|
||||
|
||||
appendStringInfoSpaces(es->str, es->indent * 2);
|
||||
ExplainXMLTag(qlabel, X_OPENING | X_NOWHITESPACE, es);
|
||||
@@ -1768,7 +1770,7 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric,
|
||||
static void
|
||||
ExplainPropertyInteger(const char *qlabel, int value, ExplainState *es)
|
||||
{
|
||||
char buf[32];
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", value);
|
||||
ExplainProperty(qlabel, buf, true, es);
|
||||
@@ -1780,7 +1782,7 @@ ExplainPropertyInteger(const char *qlabel, int value, ExplainState *es)
|
||||
static void
|
||||
ExplainPropertyLong(const char *qlabel, long value, ExplainState *es)
|
||||
{
|
||||
char buf[32];
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%ld", value);
|
||||
ExplainProperty(qlabel, buf, true, es);
|
||||
@@ -1794,7 +1796,7 @@ static void
|
||||
ExplainPropertyFloat(const char *qlabel, double value, int ndigits,
|
||||
ExplainState *es)
|
||||
{
|
||||
char buf[256];
|
||||
char buf[256];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%.*f", ndigits, value);
|
||||
ExplainProperty(qlabel, buf, true, es);
|
||||
@@ -1837,8 +1839,8 @@ ExplainOpenGroup(const char *objtype, const char *labelname,
|
||||
/*
|
||||
* In JSON format, the grouping_stack is an integer list. 0 means
|
||||
* we've emitted nothing at this grouping level, 1 means we've
|
||||
* emitted something (and so the next item needs a comma).
|
||||
* See ExplainJSONLineEnding().
|
||||
* emitted something (and so the next item needs a comma). See
|
||||
* ExplainJSONLineEnding().
|
||||
*/
|
||||
es->grouping_stack = lcons_int(0, es->grouping_stack);
|
||||
es->indent++;
|
||||
@@ -1966,7 +1968,7 @@ ExplainBeginOutput(ExplainState *es)
|
||||
|
||||
case EXPLAIN_FORMAT_XML:
|
||||
appendStringInfoString(es->str,
|
||||
"<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
|
||||
"<explain xmlns=\"http://www.postgresql.org/2009/explain\">\n");
|
||||
es->indent++;
|
||||
break;
|
||||
|
||||
@@ -2065,7 +2067,7 @@ ExplainXMLTag(const char *tagname, int flags, ExplainState *es)
|
||||
/*
|
||||
* Emit a JSON line ending.
|
||||
*
|
||||
* JSON requires a comma after each property but the last. To facilitate this,
|
||||
* JSON requires a comma after each property but the last. To facilitate this,
|
||||
* in JSON format, the text emitted for each property begins just prior to the
|
||||
* preceding line-break (and comma, if applicable).
|
||||
*/
|
||||
@@ -2086,7 +2088,7 @@ ExplainJSONLineEnding(ExplainState *es)
|
||||
* YAML lines are ordinarily indented by two spaces per indentation level.
|
||||
* The text emitted for each property begins just prior to the preceding
|
||||
* line-break, except for the first property in an unlabelled group, for which
|
||||
* it begins immediately after the "- " that introduces the group. The first
|
||||
* it begins immediately after the "- " that introduces the group. The first
|
||||
* property of the group appears on the same line as the opening "- ".
|
||||
*/
|
||||
static void
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.117 2010/02/17 04:19:39 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.118 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* These routines take the parse tree and pick out the
|
||||
@@ -314,8 +314,8 @@ examine_parameter_list(List *parameters, Oid languageOid,
|
||||
strcmp(prevfp->name, fp->name) == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("parameter name \"%s\" used more than once",
|
||||
fp->name)));
|
||||
errmsg("parameter name \"%s\" used more than once",
|
||||
fp->name)));
|
||||
}
|
||||
|
||||
paramNames[i] = CStringGetTextDatum(fp->name);
|
||||
@@ -2019,8 +2019,8 @@ ExecuteDoStmt(DoStmt *stmt)
|
||||
if (!OidIsValid(laninline))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("language \"%s\" does not support inline code execution",
|
||||
NameStr(languageStruct->lanname))));
|
||||
errmsg("language \"%s\" does not support inline code execution",
|
||||
NameStr(languageStruct->lanname))));
|
||||
|
||||
ReleaseSysCache(languageTuple);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.193 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.194 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -310,8 +310,8 @@ DefineIndex(RangeVar *heapRelation,
|
||||
if (exclusionOpNames != NIL && !OidIsValid(accessMethodForm->amgettuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("access method \"%s\" does not support exclusion constraints",
|
||||
accessMethodName)));
|
||||
errmsg("access method \"%s\" does not support exclusion constraints",
|
||||
accessMethodName)));
|
||||
|
||||
amcanorder = accessMethodForm->amcanorder;
|
||||
amoptions = accessMethodForm->amoptions;
|
||||
@@ -460,7 +460,7 @@ DefineIndex(RangeVar *heapRelation,
|
||||
else
|
||||
{
|
||||
elog(ERROR, "unknown constraint type");
|
||||
constraint_type = NULL; /* keep compiler quiet */
|
||||
constraint_type = NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
ereport(NOTICE,
|
||||
@@ -476,8 +476,8 @@ DefineIndex(RangeVar *heapRelation,
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
/*
|
||||
* Make the catalog entries for the index, including constraints.
|
||||
* Then, if not skip_build || concurrent, actually build the index.
|
||||
* Make the catalog entries for the index, including constraints. Then, if
|
||||
* not skip_build || concurrent, actually build the index.
|
||||
*/
|
||||
indexRelationId =
|
||||
index_create(relationId, indexRelationName, indexRelationId,
|
||||
@@ -494,10 +494,10 @@ DefineIndex(RangeVar *heapRelation,
|
||||
|
||||
/*
|
||||
* For a concurrent build, it's important to make the catalog entries
|
||||
* visible to other transactions before we start to build the index.
|
||||
* That will prevent them from making incompatible HOT updates. The new
|
||||
* index will be marked not indisready and not indisvalid, so that no one
|
||||
* else tries to either insert into it or use it for queries.
|
||||
* visible to other transactions before we start to build the index. That
|
||||
* will prevent them from making incompatible HOT updates. The new index
|
||||
* will be marked not indisready and not indisvalid, so that no one else
|
||||
* tries to either insert into it or use it for queries.
|
||||
*
|
||||
* We must commit our current transaction so that the index becomes
|
||||
* visible; then start another. Note that all the data structures we just
|
||||
@@ -835,7 +835,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
|
||||
/* Allocate space for exclusion operator info, if needed */
|
||||
if (exclusionOpNames)
|
||||
{
|
||||
int ncols = list_length(attList);
|
||||
int ncols = list_length(attList);
|
||||
|
||||
Assert(list_length(exclusionOpNames) == ncols);
|
||||
indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * ncols);
|
||||
@@ -941,10 +941,10 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
|
||||
*/
|
||||
if (nextExclOp)
|
||||
{
|
||||
List *opname = (List *) lfirst(nextExclOp);
|
||||
Oid opid;
|
||||
Oid opfamily;
|
||||
int strat;
|
||||
List *opname = (List *) lfirst(nextExclOp);
|
||||
Oid opid;
|
||||
Oid opfamily;
|
||||
int strat;
|
||||
|
||||
/*
|
||||
* Find the operator --- it must accept the column datatype
|
||||
@@ -971,7 +971,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
|
||||
strat = get_op_opfamily_strategy(opid, opfamily);
|
||||
if (strat == 0)
|
||||
{
|
||||
HeapTuple opftuple;
|
||||
HeapTuple opftuple;
|
||||
Form_pg_opfamily opfform;
|
||||
|
||||
/*
|
||||
@@ -1433,7 +1433,7 @@ ChooseIndexNameAddition(List *colnames)
|
||||
const char *name = (const char *) lfirst(lc);
|
||||
|
||||
if (buflen > 0)
|
||||
buf[buflen++] = '_'; /* insert _ between names */
|
||||
buf[buflen++] = '_'; /* insert _ between names */
|
||||
|
||||
/*
|
||||
* At this point we have buflen <= NAMEDATALEN. name should be less
|
||||
@@ -1449,7 +1449,7 @@ ChooseIndexNameAddition(List *colnames)
|
||||
|
||||
/*
|
||||
* Select the actual names to be used for the columns of an index, given the
|
||||
* list of IndexElems for the columns. This is mostly about ensuring the
|
||||
* list of IndexElems for the columns. This is mostly about ensuring the
|
||||
* names are unique so we don't get a conflicting-attribute-names error.
|
||||
*
|
||||
* Returns a List of plain strings (char *, not String nodes).
|
||||
@@ -1470,11 +1470,11 @@ ChooseIndexColumnNames(List *indexElems)
|
||||
|
||||
/* Get the preliminary name from the IndexElem */
|
||||
if (ielem->indexcolname)
|
||||
origname = ielem->indexcolname; /* caller-specified name */
|
||||
origname = ielem->indexcolname; /* caller-specified name */
|
||||
else if (ielem->name)
|
||||
origname = ielem->name; /* simple column reference */
|
||||
origname = ielem->name; /* simple column reference */
|
||||
else
|
||||
origname = "expr"; /* default name for expression */
|
||||
origname = "expr"; /* default name for expression */
|
||||
|
||||
/* If it conflicts with any previous column, tweak it */
|
||||
curname = origname;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.28 2010/02/20 21:24:02 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.29 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -48,11 +48,10 @@ LockTableCommand(LockStmt *lockstmt)
|
||||
reloid = RangeVarGetRelid(relation, false);
|
||||
|
||||
/*
|
||||
* During recovery we only accept these variations:
|
||||
* LOCK TABLE foo IN ACCESS SHARE MODE
|
||||
* LOCK TABLE foo IN ROW SHARE MODE
|
||||
* LOCK TABLE foo IN ROW EXCLUSIVE MODE
|
||||
* This test must match the restrictions defined in LockAcquire()
|
||||
* During recovery we only accept these variations: LOCK TABLE foo IN
|
||||
* ACCESS SHARE MODE LOCK TABLE foo IN ROW SHARE MODE LOCK TABLE foo
|
||||
* IN ROW EXCLUSIVE MODE This test must match the restrictions defined
|
||||
* in LockAcquire()
|
||||
*/
|
||||
if (lockstmt->mode > RowExclusiveLock)
|
||||
PreventCommandDuringRecovery("LOCK TABLE");
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.90 2010/02/23 22:51:42 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.91 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -149,8 +149,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise for the anonymous block handler, if required;
|
||||
* but we don't care about its return type.
|
||||
* Likewise for the anonymous block handler, if required; but we don't
|
||||
* care about its return type.
|
||||
*/
|
||||
if (pltemplate->tmplinline)
|
||||
{
|
||||
@@ -161,17 +161,17 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
{
|
||||
inlineOid = ProcedureCreate(pltemplate->tmplinline,
|
||||
PG_CATALOG_NAMESPACE,
|
||||
false, /* replace */
|
||||
false, /* returnsSet */
|
||||
false, /* replace */
|
||||
false, /* returnsSet */
|
||||
VOIDOID,
|
||||
ClanguageId,
|
||||
F_FMGR_C_VALIDATOR,
|
||||
pltemplate->tmplinline,
|
||||
pltemplate->tmpllibrary,
|
||||
false, /* isAgg */
|
||||
false, /* isWindowFunc */
|
||||
false, /* security_definer */
|
||||
true, /* isStrict */
|
||||
false, /* isAgg */
|
||||
false, /* isWindowFunc */
|
||||
false, /* security_definer */
|
||||
true, /* isStrict */
|
||||
PROVOLATILE_VOLATILE,
|
||||
buildoidvector(funcargtypes, 1),
|
||||
PointerGetDatum(NULL),
|
||||
@@ -209,7 +209,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
false, /* isAgg */
|
||||
false, /* isWindowFunc */
|
||||
false, /* security_definer */
|
||||
true, /* isStrict */
|
||||
true, /* isStrict */
|
||||
PROVOLATILE_VOLATILE,
|
||||
buildoidvector(funcargtypes, 1),
|
||||
PointerGetDatum(NULL),
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.56 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.57 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -92,7 +92,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
||||
*/
|
||||
if (saved_uid != owner_uid)
|
||||
SetUserIdAndSecContext(owner_uid,
|
||||
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
|
||||
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
|
||||
|
||||
/* Create the schema's namespace */
|
||||
namespaceId = NamespaceCreate(schemaName, owner_uid);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.326 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.327 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -304,9 +304,9 @@ static void ATAddCheckConstraint(List **wqueue,
|
||||
static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
|
||||
Constraint *fkconstraint);
|
||||
static void ATExecDropConstraint(Relation rel, const char *constrName,
|
||||
DropBehavior behavior,
|
||||
bool recurse, bool recursing,
|
||||
bool missing_ok);
|
||||
DropBehavior behavior,
|
||||
bool recurse, bool recursing,
|
||||
bool missing_ok);
|
||||
static void ATPrepAlterColumnType(List **wqueue,
|
||||
AlteredTableInfo *tab, Relation rel,
|
||||
bool recurse, bool recursing,
|
||||
@@ -974,12 +974,11 @@ ExecuteTruncate(TruncateStmt *stmt)
|
||||
Relation rel = (Relation) lfirst(cell);
|
||||
|
||||
/*
|
||||
* Normally, we need a transaction-safe truncation here. However,
|
||||
* if the table was either created in the current (sub)transaction
|
||||
* or has a new relfilenode in the current (sub)transaction, then
|
||||
* we can just truncate it in-place, because a rollback would
|
||||
* cause the whole table or the current physical file to be
|
||||
* thrown away anyway.
|
||||
* Normally, we need a transaction-safe truncation here. However, if
|
||||
* the table was either created in the current (sub)transaction or has
|
||||
* a new relfilenode in the current (sub)transaction, then we can just
|
||||
* truncate it in-place, because a rollback would cause the whole
|
||||
* table or the current physical file to be thrown away anyway.
|
||||
*/
|
||||
if (rel->rd_createSubid == mySubid ||
|
||||
rel->rd_newRelfilenodeSubid == mySubid)
|
||||
@@ -1112,7 +1111,7 @@ truncate_check_rel(Relation rel)
|
||||
|
||||
/*
|
||||
* storage_name
|
||||
* returns the name corresponding to a typstorage/attstorage enum value
|
||||
* returns the name corresponding to a typstorage/attstorage enum value
|
||||
*/
|
||||
static const char *
|
||||
storage_name(char c)
|
||||
@@ -1201,7 +1200,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
int parentsWithOids = 0;
|
||||
bool have_bogus_defaults = false;
|
||||
int child_attno;
|
||||
static Node bogus_marker = { 0 }; /* marks conflicting defaults */
|
||||
static Node bogus_marker = {0}; /* marks conflicting defaults */
|
||||
|
||||
/*
|
||||
* Check for and reject tables with too many columns. We perform this
|
||||
@@ -1234,10 +1233,11 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
ListCell *prev = entry;
|
||||
|
||||
if (coldef->typeName == NULL)
|
||||
|
||||
/*
|
||||
* Typed table column option that does not belong to a
|
||||
* column from the type. This works because the columns
|
||||
* from the type come first in the list.
|
||||
* Typed table column option that does not belong to a column from
|
||||
* the type. This works because the columns from the type come
|
||||
* first in the list.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
@@ -1247,14 +1247,16 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
while (rest != NULL)
|
||||
{
|
||||
ColumnDef *restdef = lfirst(rest);
|
||||
ListCell *next = lnext(rest); /* need to save it in case we delete it */
|
||||
ListCell *next = lnext(rest); /* need to save it in case we
|
||||
* delete it */
|
||||
|
||||
if (strcmp(coldef->colname, restdef->colname) == 0)
|
||||
{
|
||||
if (coldef->is_from_type)
|
||||
{
|
||||
/* merge the column options into the column from
|
||||
* the type */
|
||||
/*
|
||||
* merge the column options into the column from the type
|
||||
*/
|
||||
coldef->is_not_null = restdef->is_not_null;
|
||||
coldef->raw_default = restdef->raw_default;
|
||||
coldef->cooked_default = restdef->cooked_default;
|
||||
@@ -1391,11 +1393,11 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
else if (def->storage != attribute->attstorage)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("inherited column \"%s\" has a storage parameter conflict",
|
||||
attributeName),
|
||||
errdetail("%s versus %s",
|
||||
storage_name(def->storage),
|
||||
storage_name(attribute->attstorage))));
|
||||
errmsg("inherited column \"%s\" has a storage parameter conflict",
|
||||
attributeName),
|
||||
errdetail("%s versus %s",
|
||||
storage_name(def->storage),
|
||||
storage_name(attribute->attstorage))));
|
||||
|
||||
def->inhcount++;
|
||||
/* Merge of NOT NULL constraints = OR 'em together */
|
||||
@@ -1563,11 +1565,11 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
else if (newdef->storage != 0 && def->storage != newdef->storage)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("column \"%s\" has a storage parameter conflict",
|
||||
attributeName),
|
||||
errdetail("%s versus %s",
|
||||
storage_name(def->storage),
|
||||
storage_name(newdef->storage))));
|
||||
errmsg("column \"%s\" has a storage parameter conflict",
|
||||
attributeName),
|
||||
errdetail("%s versus %s",
|
||||
storage_name(def->storage),
|
||||
storage_name(newdef->storage))));
|
||||
|
||||
/* Mark the column as locally defined */
|
||||
def->is_local = true;
|
||||
@@ -1978,8 +1980,10 @@ renameatt(Oid myrelid,
|
||||
*/
|
||||
if (recurse)
|
||||
{
|
||||
List *child_oids, *child_numparents;
|
||||
ListCell *lo, *li;
|
||||
List *child_oids,
|
||||
*child_numparents;
|
||||
ListCell *lo,
|
||||
*li;
|
||||
|
||||
/*
|
||||
* we need the number of parents for each child so that the recursive
|
||||
@@ -2039,13 +2043,13 @@ renameatt(Oid myrelid,
|
||||
oldattname)));
|
||||
|
||||
/*
|
||||
* if the attribute is inherited, forbid the renaming. if this is a
|
||||
* if the attribute is inherited, forbid the renaming. if this is a
|
||||
* top-level call to renameatt(), then expected_parents will be 0, so the
|
||||
* effect of this code will be to prohibit the renaming if the attribute
|
||||
* is inherited at all. if this is a recursive call to renameatt(),
|
||||
* expected_parents will be the number of parents the current relation has
|
||||
* within the inheritance hierarchy being processed, so we'll prohibit
|
||||
* the renaming only if there are additional parents from elsewhere.
|
||||
* within the inheritance hierarchy being processed, so we'll prohibit the
|
||||
* renaming only if there are additional parents from elsewhere.
|
||||
*/
|
||||
if (attform->attinhcount > expected_parents)
|
||||
ereport(ERROR,
|
||||
@@ -2861,9 +2865,9 @@ ATRewriteTables(List **wqueue)
|
||||
OldHeap = heap_open(tab->relid, NoLock);
|
||||
|
||||
/*
|
||||
* We don't support rewriting of system catalogs; there are
|
||||
* too many corner cases and too little benefit. In particular
|
||||
* this is certainly not going to work for mapped catalogs.
|
||||
* We don't support rewriting of system catalogs; there are too
|
||||
* many corner cases and too little benefit. In particular this
|
||||
* is certainly not going to work for mapped catalogs.
|
||||
*/
|
||||
if (IsSystemRelation(OldHeap))
|
||||
ereport(ERROR,
|
||||
@@ -3007,11 +3011,10 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
|
||||
newrel = NULL;
|
||||
|
||||
/*
|
||||
* Prepare a BulkInsertState and options for heap_insert. Because
|
||||
* we're building a new heap, we can skip WAL-logging and fsync it
|
||||
* to disk at the end instead (unless WAL-logging is required for
|
||||
* archiving or streaming replication). The FSM is empty too,
|
||||
* so don't bother using it.
|
||||
* Prepare a BulkInsertState and options for heap_insert. Because we're
|
||||
* building a new heap, we can skip WAL-logging and fsync it to disk at
|
||||
* the end instead (unless WAL-logging is required for archiving or
|
||||
* streaming replication). The FSM is empty too, so don't bother using it.
|
||||
*/
|
||||
if (newrel)
|
||||
{
|
||||
@@ -3255,7 +3258,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
|
||||
/* If we skipped writing WAL, then we need to sync the heap. */
|
||||
if (hi_options & HEAP_INSERT_SKIP_WAL)
|
||||
{
|
||||
char reason[NAMEDATALEN + 30];
|
||||
char reason[NAMEDATALEN + 30];
|
||||
|
||||
snprintf(reason, sizeof(reason), "table rewrite on \"%s\"",
|
||||
RelationGetRelationName(newrel));
|
||||
XLogReportUnloggedStatement(reason);
|
||||
@@ -4205,7 +4209,7 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
|
||||
/* Generate new proposed attoptions (text array) */
|
||||
Assert(IsA(options, List));
|
||||
datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
|
||||
&isnull);
|
||||
&isnull);
|
||||
newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
|
||||
(List *) options, NULL, NULL, false,
|
||||
isReset);
|
||||
@@ -4338,8 +4342,10 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
|
||||
* get the number of the attribute
|
||||
*/
|
||||
tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
|
||||
if (!HeapTupleIsValid(tuple)){
|
||||
if (!missing_ok){
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
if (!missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
@@ -4574,9 +4580,10 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||
break;
|
||||
|
||||
case CONSTR_FOREIGN:
|
||||
|
||||
/*
|
||||
* Note that we currently never recurse for FK constraints, so
|
||||
* the "recurse" flag is silently ignored.
|
||||
* Note that we currently never recurse for FK constraints, so the
|
||||
* "recurse" flag is silently ignored.
|
||||
*
|
||||
* Assign or validate constraint name
|
||||
*/
|
||||
@@ -4595,7 +4602,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||
else
|
||||
newConstraint->conname =
|
||||
ChooseConstraintName(RelationGetRelationName(rel),
|
||||
strVal(linitial(newConstraint->fk_attrs)),
|
||||
strVal(linitial(newConstraint->fk_attrs)),
|
||||
"fkey",
|
||||
RelationGetNamespace(rel),
|
||||
NIL);
|
||||
@@ -5093,9 +5100,9 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
|
||||
if (indexStruct->indisprimary)
|
||||
{
|
||||
/*
|
||||
* Refuse to use a deferrable primary key. This is per SQL spec,
|
||||
* and there would be a lot of interesting semantic problems if
|
||||
* we tried to allow it.
|
||||
* Refuse to use a deferrable primary key. This is per SQL spec,
|
||||
* and there would be a lot of interesting semantic problems if we
|
||||
* tried to allow it.
|
||||
*/
|
||||
if (!indexStruct->indimmediate)
|
||||
ereport(ERROR,
|
||||
@@ -5243,15 +5250,15 @@ transformFkeyCheckAttrs(Relation pkrel,
|
||||
}
|
||||
|
||||
/*
|
||||
* Refuse to use a deferrable unique/primary key. This is per
|
||||
* SQL spec, and there would be a lot of interesting semantic
|
||||
* problems if we tried to allow it.
|
||||
* Refuse to use a deferrable unique/primary key. This is per SQL
|
||||
* spec, and there would be a lot of interesting semantic problems
|
||||
* if we tried to allow it.
|
||||
*/
|
||||
if (found && !indexStruct->indimmediate)
|
||||
{
|
||||
/*
|
||||
* Remember that we found an otherwise matching index, so
|
||||
* that we can generate a more appropriate error message.
|
||||
* Remember that we found an otherwise matching index, so that
|
||||
* we can generate a more appropriate error message.
|
||||
*/
|
||||
found_deferrable = true;
|
||||
found = false;
|
||||
@@ -5623,12 +5630,14 @@ ATExecDropConstraint(Relation rel, const char *constrName,
|
||||
|
||||
systable_endscan(scan);
|
||||
|
||||
if (!found){
|
||||
if (!missing_ok){
|
||||
if (!found)
|
||||
{
|
||||
if (!missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
|
||||
constrName, RelationGetRelationName(rel))));
|
||||
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
|
||||
constrName, RelationGetRelationName(rel))));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5639,6 +5648,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Propagate to children as appropriate. Unlike most other ALTER
|
||||
* routines, we have to do this one level of recursion at a time; we can't
|
||||
@@ -6997,12 +7007,13 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace)
|
||||
heap_close(pg_class, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Write an XLOG UNLOGGED record if WAL-logging was skipped because
|
||||
* WAL archiving is not enabled.
|
||||
* Write an XLOG UNLOGGED record if WAL-logging was skipped because WAL
|
||||
* archiving is not enabled.
|
||||
*/
|
||||
if (!XLogIsNeeded() && !rel->rd_istemp)
|
||||
{
|
||||
char reason[NAMEDATALEN + 40];
|
||||
char reason[NAMEDATALEN + 40];
|
||||
|
||||
snprintf(reason, sizeof(reason), "ALTER TABLE SET TABLESPACE on \"%s\"",
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
@@ -7039,8 +7050,8 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst,
|
||||
* enabled AND it's not a temp rel.
|
||||
*
|
||||
* Note: If you change the conditions here, update the conditions in
|
||||
* ATExecSetTableSpace() for when an XLOG UNLOGGED record is written
|
||||
* to match.
|
||||
* ATExecSetTableSpace() for when an XLOG UNLOGGED record is written to
|
||||
* match.
|
||||
*/
|
||||
use_wal = XLogIsNeeded() && !istemp;
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.73 2010/02/17 04:19:39 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.74 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -85,7 +85,7 @@ char *temp_tablespaces = NULL;
|
||||
|
||||
|
||||
static void create_tablespace_directories(const char *location,
|
||||
const Oid tablespaceoid);
|
||||
const Oid tablespaceoid);
|
||||
static bool destroy_tablespace_directories(Oid tablespaceoid, bool redo);
|
||||
|
||||
|
||||
@@ -159,8 +159,8 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
|
||||
|
||||
/*
|
||||
* Parent directories are missing during WAL replay, so
|
||||
* continue by creating simple parent directories
|
||||
* rather than a symlink.
|
||||
* continue by creating simple parent directories rather
|
||||
* than a symlink.
|
||||
*/
|
||||
|
||||
/* create two parents up if not exist */
|
||||
@@ -272,7 +272,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
|
||||
|
||||
/*
|
||||
* Check that location isn't too long. Remember that we're going to append
|
||||
* 'PG_XXX/<dboid>/<relid>.<nnn>'. FYI, we never actually reference the
|
||||
* 'PG_XXX/<dboid>/<relid>.<nnn>'. FYI, we never actually reference the
|
||||
* whole path, but mkdir() uses the first two parts.
|
||||
*/
|
||||
if (strlen(location) + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 +
|
||||
@@ -535,13 +535,13 @@ DropTableSpace(DropTableSpaceStmt *stmt)
|
||||
static void
|
||||
create_tablespace_directories(const char *location, const Oid tablespaceoid)
|
||||
{
|
||||
char *linkloc = palloc(OIDCHARS + OIDCHARS + 1);
|
||||
char *location_with_version_dir = palloc(strlen(location) + 1 +
|
||||
strlen(TABLESPACE_VERSION_DIRECTORY) + 1);
|
||||
char *linkloc = palloc(OIDCHARS + OIDCHARS + 1);
|
||||
char *location_with_version_dir = palloc(strlen(location) + 1 +
|
||||
strlen(TABLESPACE_VERSION_DIRECTORY) + 1);
|
||||
|
||||
sprintf(linkloc, "pg_tblspc/%u", tablespaceoid);
|
||||
sprintf(location_with_version_dir, "%s/%s", location,
|
||||
TABLESPACE_VERSION_DIRECTORY);
|
||||
TABLESPACE_VERSION_DIRECTORY);
|
||||
|
||||
/*
|
||||
* Attempt to coerce target directory to safe permissions. If this fails,
|
||||
@@ -556,14 +556,14 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
|
||||
location)));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not set permissions on directory \"%s\": %m",
|
||||
location)));
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not set permissions on directory \"%s\": %m",
|
||||
location)));
|
||||
}
|
||||
|
||||
/*
|
||||
* The creation of the version directory prevents more than one
|
||||
* tablespace in a single location.
|
||||
* The creation of the version directory prevents more than one tablespace
|
||||
* in a single location.
|
||||
*/
|
||||
if (mkdir(location_with_version_dir, S_IRWXU) < 0)
|
||||
{
|
||||
@@ -575,8 +575,8 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not create directory \"%s\": %m",
|
||||
location_with_version_dir)));
|
||||
errmsg("could not create directory \"%s\": %m",
|
||||
location_with_version_dir)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -613,9 +613,9 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
|
||||
struct stat st;
|
||||
|
||||
linkloc_with_version_dir = palloc(9 + 1 + OIDCHARS + 1 +
|
||||
strlen(TABLESPACE_VERSION_DIRECTORY));
|
||||
strlen(TABLESPACE_VERSION_DIRECTORY));
|
||||
sprintf(linkloc_with_version_dir, "pg_tblspc/%u/%s", tablespaceoid,
|
||||
TABLESPACE_VERSION_DIRECTORY);
|
||||
TABLESPACE_VERSION_DIRECTORY);
|
||||
|
||||
/*
|
||||
* Check if the tablespace still contains any files. We try to rmdir each
|
||||
@@ -690,12 +690,12 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not remove directory \"%s\": %m",
|
||||
linkloc_with_version_dir)));
|
||||
|
||||
|
||||
/*
|
||||
* Try to remove the symlink. We must however deal with the
|
||||
* possibility that it's a directory instead of a symlink --- this could
|
||||
* happen during WAL replay (see TablespaceCreateDbspace), and it is also
|
||||
* the case on Windows where junction points lstat() as directories.
|
||||
* Try to remove the symlink. We must however deal with the possibility
|
||||
* that it's a directory instead of a symlink --- this could happen during
|
||||
* WAL replay (see TablespaceCreateDbspace), and it is also the case on
|
||||
* Windows where junction points lstat() as directories.
|
||||
*/
|
||||
linkloc = pstrdup(linkloc_with_version_dir);
|
||||
get_parent_directory(linkloc);
|
||||
@@ -948,7 +948,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("tablespace \"%s\" does not exist",
|
||||
stmt->tablespacename)));
|
||||
stmt->tablespacename)));
|
||||
|
||||
/* Must be owner of the existing object */
|
||||
if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
@@ -1366,30 +1366,30 @@ tblspc_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) XLogRecGetData(record);
|
||||
|
||||
/*
|
||||
* If we issued a WAL record for a drop tablespace it is
|
||||
* because there were no files in it at all. That means that
|
||||
* no permanent objects can exist in it at this point.
|
||||
* If we issued a WAL record for a drop tablespace it is because there
|
||||
* were no files in it at all. That means that no permanent objects
|
||||
* can exist in it at this point.
|
||||
*
|
||||
* It is possible for standby users to be using this tablespace
|
||||
* as a location for their temporary files, so if we fail to
|
||||
* remove all files then do conflict processing and try again,
|
||||
* if currently enabled.
|
||||
* It is possible for standby users to be using this tablespace as a
|
||||
* location for their temporary files, so if we fail to remove all
|
||||
* files then do conflict processing and try again, if currently
|
||||
* enabled.
|
||||
*/
|
||||
if (!destroy_tablespace_directories(xlrec->ts_id, true))
|
||||
{
|
||||
ResolveRecoveryConflictWithTablespace(xlrec->ts_id);
|
||||
|
||||
/*
|
||||
* If we did recovery processing then hopefully the
|
||||
* backends who wrote temp files should have cleaned up and
|
||||
* exited by now. So lets recheck before we throw an error.
|
||||
* If !process_conflicts then this will just fail again.
|
||||
* If we did recovery processing then hopefully the backends who
|
||||
* wrote temp files should have cleaned up and exited by now. So
|
||||
* lets recheck before we throw an error. If !process_conflicts
|
||||
* then this will just fail again.
|
||||
*/
|
||||
if (!destroy_tablespace_directories(xlrec->ts_id, true))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("tablespace %u is not empty",
|
||||
xlrec->ts_id)));
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("tablespace %u is not empty",
|
||||
xlrec->ts_id)));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.261 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.262 2010/02/26 02:00:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -117,7 +117,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
{
|
||||
int16 tgtype;
|
||||
int ncolumns;
|
||||
int2 *columns;
|
||||
int2 *columns;
|
||||
int2vector *tgattr;
|
||||
Node *whenClause;
|
||||
List *whenRtable;
|
||||
@@ -196,10 +196,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
*/
|
||||
if (stmt->whenClause)
|
||||
{
|
||||
ParseState *pstate;
|
||||
ParseState *pstate;
|
||||
RangeTblEntry *rte;
|
||||
List *varList;
|
||||
ListCell *lc;
|
||||
List *varList;
|
||||
ListCell *lc;
|
||||
|
||||
/* Set up a pstate to parse with */
|
||||
pstate = make_parsestate(NULL);
|
||||
@@ -230,7 +230,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
if (pstate->p_hasSubLinks)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot use subquery in trigger WHEN condition")));
|
||||
errmsg("cannot use subquery in trigger WHEN condition")));
|
||||
if (pstate->p_hasAggs)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_GROUPING_ERROR),
|
||||
@@ -238,7 +238,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
if (pstate->p_hasWindowFuncs)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WINDOWING_ERROR),
|
||||
errmsg("cannot use window function in trigger WHEN condition")));
|
||||
errmsg("cannot use window function in trigger WHEN condition")));
|
||||
|
||||
/*
|
||||
* Check for disallowed references to OLD/NEW.
|
||||
@@ -364,11 +364,11 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
stmt->deferrable,
|
||||
stmt->initdeferred,
|
||||
RelationGetRelid(rel),
|
||||
NULL, /* no conkey */
|
||||
NULL, /* no conkey */
|
||||
0,
|
||||
InvalidOid, /* no domain */
|
||||
InvalidOid, /* no index */
|
||||
InvalidOid, /* no foreign key */
|
||||
InvalidOid, /* no domain */
|
||||
InvalidOid, /* no index */
|
||||
InvalidOid, /* no foreign key */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -382,7 +382,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
NULL,
|
||||
NULL,
|
||||
true, /* islocal */
|
||||
0); /* inhcount */
|
||||
0); /* inhcount */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -394,9 +394,9 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
trigoid = GetNewOid(tgrel);
|
||||
|
||||
/*
|
||||
* If trigger is internally generated, modify the provided trigger name
|
||||
* to ensure uniqueness by appending the trigger OID. (Callers will
|
||||
* usually supply a simple constant trigger name in these cases.)
|
||||
* If trigger is internally generated, modify the provided trigger name to
|
||||
* ensure uniqueness by appending the trigger OID. (Callers will usually
|
||||
* supply a simple constant trigger name in these cases.)
|
||||
*/
|
||||
if (isInternal)
|
||||
{
|
||||
@@ -413,8 +413,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
/*
|
||||
* Scan pg_trigger for existing triggers on relation. We do this only 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.)
|
||||
* We can skip this for internally generated triggers, since the name
|
||||
* name. (The unique index on tgrelid/tgname would complain anyway.) We
|
||||
* can skip this for internally generated triggers, since the name
|
||||
* modification above should be sufficient.
|
||||
*
|
||||
* NOTE that this is cool only because we have AccessExclusiveLock on the
|
||||
@@ -435,8 +435,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("trigger \"%s\" for relation \"%s\" already exists",
|
||||
trigname, stmt->relation->relname)));
|
||||
errmsg("trigger \"%s\" for relation \"%s\" already exists",
|
||||
trigname, stmt->relation->relname)));
|
||||
}
|
||||
systable_endscan(tgscan);
|
||||
}
|
||||
@@ -515,17 +515,17 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
columns = (int2 *) palloc(ncolumns * sizeof(int2));
|
||||
foreach(cell, stmt->columns)
|
||||
{
|
||||
char *name = strVal(lfirst(cell));
|
||||
int2 attnum;
|
||||
int j;
|
||||
char *name = strVal(lfirst(cell));
|
||||
int2 attnum;
|
||||
int j;
|
||||
|
||||
/* Lookup column name. System columns are not allowed */
|
||||
/* Lookup column name. System columns are not allowed */
|
||||
attnum = attnameAttNum(rel, name, false);
|
||||
if (attnum == InvalidAttrNumber)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
name, RelationGetRelationName(rel))));
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
name, RelationGetRelationName(rel))));
|
||||
|
||||
/* Check for duplicates */
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
@@ -624,7 +624,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* User CREATE TRIGGER, so place dependencies. We make trigger be
|
||||
* User CREATE TRIGGER, so place dependencies. We 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.)
|
||||
*/
|
||||
@@ -641,6 +641,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
}
|
||||
/* Not possible to have an index dependency in this case */
|
||||
Assert(!OidIsValid(indexOid));
|
||||
|
||||
/*
|
||||
* If it's a user-specified constraint trigger, make the constraint
|
||||
* internally dependent on the trigger instead of vice versa.
|
||||
@@ -657,7 +658,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
/* If column-specific trigger, add normal dependencies on columns */
|
||||
if (columns != NULL)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
referenced.classId = RelationRelationId;
|
||||
referenced.objectId = RelationGetRelid(rel);
|
||||
@@ -669,8 +670,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
|
||||
}
|
||||
|
||||
/*
|
||||
* If it has a WHEN clause, add dependencies on objects mentioned in
|
||||
* the expression (eg, functions, as well as any columns used).
|
||||
* If it has a WHEN clause, add dependencies on objects mentioned in the
|
||||
* expression (eg, functions, as well as any columns used).
|
||||
*/
|
||||
if (whenClause != NULL)
|
||||
recordDependencyOnExpr(&myself, whenClause, whenRtable,
|
||||
@@ -1714,9 +1715,9 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
|
||||
* comparison; so we just compare corresponding slots of the two sets.
|
||||
*
|
||||
* Note: comparing the stringToNode forms of the WHEN clauses means that
|
||||
* parse column locations will affect the result. This is okay as long
|
||||
* as this function is only used for detecting exact equality, as for
|
||||
* example in checking for staleness of a cache entry.
|
||||
* parse column locations will affect the result. This is okay as long as
|
||||
* this function is only used for detecting exact equality, as for example
|
||||
* in checking for staleness of a cache entry.
|
||||
*/
|
||||
if (trigdesc1 != NULL)
|
||||
{
|
||||
@@ -1763,11 +1764,11 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
|
||||
if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
|
||||
return false;
|
||||
if (trig1->tgqual == NULL && trig2->tgqual == NULL)
|
||||
/* ok */ ;
|
||||
/* ok */ ;
|
||||
else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
|
||||
return false;
|
||||
else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (trigdesc2 != NULL)
|
||||
@@ -2114,7 +2115,7 @@ ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
|
||||
int *tgindx;
|
||||
int i;
|
||||
TriggerData LocTriggerData;
|
||||
Bitmapset *modifiedCols;
|
||||
Bitmapset *modifiedCols;
|
||||
|
||||
trigdesc = relinfo->ri_TrigDesc;
|
||||
|
||||
@@ -2185,7 +2186,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
|
||||
HeapTuple intuple = newtuple;
|
||||
TupleTableSlot *newSlot;
|
||||
int i;
|
||||
Bitmapset *modifiedCols;
|
||||
Bitmapset *modifiedCols;
|
||||
|
||||
trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
|
||||
&newSlot);
|
||||
@@ -2381,9 +2382,9 @@ ltrmark:;
|
||||
|
||||
/*
|
||||
* EvalPlanQual already locked the tuple, but we
|
||||
* re-call heap_lock_tuple anyway as an easy way
|
||||
* of re-fetching the correct tuple. Speed is
|
||||
* hardly a criterion in this path anyhow.
|
||||
* re-call heap_lock_tuple anyway as an easy way of
|
||||
* re-fetching the correct tuple. Speed is hardly a
|
||||
* criterion in this path anyhow.
|
||||
*/
|
||||
goto ltrmark;
|
||||
}
|
||||
@@ -2485,8 +2486,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
|
||||
Assert(estate != NULL);
|
||||
|
||||
/*
|
||||
* trigger is an element of relinfo->ri_TrigDesc->triggers[];
|
||||
* find the matching element of relinfo->ri_TrigWhenExprs[]
|
||||
* trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
|
||||
* matching element of relinfo->ri_TrigWhenExprs[]
|
||||
*/
|
||||
i = trigger - relinfo->ri_TrigDesc->triggers;
|
||||
predicate = &relinfo->ri_TrigWhenExprs[i];
|
||||
@@ -2498,7 +2499,7 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
|
||||
*/
|
||||
if (*predicate == NIL)
|
||||
{
|
||||
Node *tgqual;
|
||||
Node *tgqual;
|
||||
|
||||
oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
|
||||
tgqual = stringToNode(trigger->tgqual);
|
||||
@@ -3895,9 +3896,9 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
|
||||
* Handle SET CONSTRAINTS constraint-name [, ...]
|
||||
*
|
||||
* First, identify all the named constraints and make a list of their
|
||||
* OIDs. Since, unlike the SQL spec, we allow multiple constraints
|
||||
* of the same name within a schema, the specifications are not
|
||||
* necessarily unique. Our strategy is to target all matching
|
||||
* OIDs. Since, unlike the SQL spec, we allow multiple constraints of
|
||||
* the same name within a schema, the specifications are not
|
||||
* necessarily unique. Our strategy is to target all matching
|
||||
* constraints within the first search-path schema that has any
|
||||
* matches, but disregard matches in schemas beyond the first match.
|
||||
* (This is a bit odd but it's the historical behavior.)
|
||||
@@ -4025,9 +4026,9 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
|
||||
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
|
||||
|
||||
/*
|
||||
* Silently skip triggers that are marked as non-deferrable
|
||||
* in pg_trigger. This is not an error condition, since
|
||||
* a deferrable RI constraint may have some non-deferrable
|
||||
* Silently skip triggers that are marked as non-deferrable in
|
||||
* pg_trigger. This is not an error condition, since a
|
||||
* deferrable RI constraint may have some non-deferrable
|
||||
* actions.
|
||||
*/
|
||||
if (pg_trigger->tgdeferrable)
|
||||
@@ -4198,7 +4199,7 @@ AfterTriggerPendingOnRel(Oid relid)
|
||||
* be fired for an event.
|
||||
*
|
||||
* NOTE: this is called whenever there are any triggers associated with
|
||||
* the event (even if they are disabled). This function decides which
|
||||
* the event (even if they are disabled). This function decides which
|
||||
* triggers actually need to be queued.
|
||||
* ----------
|
||||
*/
|
||||
@@ -4217,9 +4218,9 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
|
||||
int *tgindx;
|
||||
|
||||
/*
|
||||
* Check state. We use normal tests not Asserts because it is possible
|
||||
* to reach here in the wrong state given misconfigured RI triggers,
|
||||
* in particular deferring a cascade action trigger.
|
||||
* Check state. We use normal tests not Asserts because it is possible to
|
||||
* reach here in the wrong state given misconfigured RI triggers, in
|
||||
* particular deferring a cascade action trigger.
|
||||
*/
|
||||
if (afterTriggers == NULL)
|
||||
elog(ERROR, "AfterTriggerSaveEvent() called outside of transaction");
|
||||
@@ -4363,9 +4364,9 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
|
||||
}
|
||||
|
||||
/*
|
||||
* If the trigger is a deferred unique constraint check trigger,
|
||||
* only queue it if the unique constraint was potentially violated,
|
||||
* which we know from index insertion time.
|
||||
* If the trigger is a deferred unique constraint check trigger, only
|
||||
* queue it if the unique constraint was potentially violated, which
|
||||
* we know from index insertion time.
|
||||
*/
|
||||
if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.147 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.148 2010/02/26 02:00:40 momjian Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -74,7 +74,7 @@ typedef struct
|
||||
/* atts[] is of allocated length RelationGetNumberOfAttributes(rel) */
|
||||
} RelToCheck;
|
||||
|
||||
Oid binary_upgrade_next_pg_type_array_oid = InvalidOid;
|
||||
Oid binary_upgrade_next_pg_type_array_oid = InvalidOid;
|
||||
|
||||
static Oid findTypeInputFunction(List *procname, Oid typeOid);
|
||||
static Oid findTypeOutputFunction(List *procname, Oid typeOid);
|
||||
@@ -527,12 +527,12 @@ DefineType(List *names, List *parameters)
|
||||
* now have TypeCreate do all the real work.
|
||||
*/
|
||||
typoid =
|
||||
/*
|
||||
* The pg_type.oid is stored in user tables as array elements
|
||||
* (base types) in ArrayType and in composite types in
|
||||
* DatumTupleFields. This oid must be preserved by binary
|
||||
* upgrades.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The pg_type.oid is stored in user tables as array elements (base types)
|
||||
* in ArrayType and in composite types in DatumTupleFields. This oid must
|
||||
* be preserved by binary upgrades.
|
||||
*/
|
||||
TypeCreate(InvalidOid, /* no predetermined type OID */
|
||||
typeName, /* type name */
|
||||
typeNamespace, /* namespace */
|
||||
@@ -986,7 +986,7 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
case CONSTR_EXCLUSION:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("exclusion constraints not possible for domains")));
|
||||
errmsg("exclusion constraints not possible for domains")));
|
||||
break;
|
||||
|
||||
case CONSTR_FOREIGN:
|
||||
@@ -1466,7 +1466,7 @@ findTypeAnalyzeFunction(List *procname, Oid typeOid)
|
||||
Oid
|
||||
AssignTypeArrayOid(void)
|
||||
{
|
||||
Oid type_array_oid;
|
||||
Oid type_array_oid;
|
||||
|
||||
/* Pre-assign the type's array OID for use in pg_type.typarray */
|
||||
if (OidIsValid(binary_upgrade_next_pg_type_array_oid))
|
||||
@@ -1525,10 +1525,10 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
|
||||
createStmt->tablespacename = NULL;
|
||||
|
||||
/*
|
||||
* Check for collision with an existing type name. If there is one
|
||||
* and it's an autogenerated array, we can rename it out of the
|
||||
* way. This check is here mainly to get a better error message
|
||||
* about a "type" instead of below about a "relation".
|
||||
* Check for collision with an existing type name. If there is one and
|
||||
* it's an autogenerated array, we can rename it out of the way. This
|
||||
* check is here mainly to get a better error message about a "type"
|
||||
* instead of below about a "relation".
|
||||
*/
|
||||
typeNamespace = RangeVarGetCreationNamespace(createStmt->relation);
|
||||
old_type_oid =
|
||||
@@ -1911,7 +1911,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
|
||||
case CONSTR_EXCLUSION:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("exclusion constraints not possible for domains")));
|
||||
errmsg("exclusion constraints not possible for domains")));
|
||||
break;
|
||||
|
||||
case CONSTR_FOREIGN:
|
||||
@@ -2343,7 +2343,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
|
||||
' ',
|
||||
' ',
|
||||
' ',
|
||||
NULL, /* not an exclusion constraint */
|
||||
NULL, /* not an exclusion constraint */
|
||||
expr, /* Tree form of check constraint */
|
||||
ccbin, /* Binary form of check constraint */
|
||||
ccsrc, /* Source form of check constraint */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.192 2010/02/14 18:42:14 rhaas Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.193 2010/02/26 02:00:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -321,7 +321,7 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
if (check_password_hook && password)
|
||||
(*check_password_hook) (stmt->role,
|
||||
password,
|
||||
isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
|
||||
isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
|
||||
validUntil_datum,
|
||||
validUntil_null);
|
||||
|
||||
@@ -630,7 +630,7 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
if (check_password_hook && password)
|
||||
(*check_password_hook) (stmt->role,
|
||||
password,
|
||||
isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
|
||||
isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT,
|
||||
validUntil_datum,
|
||||
validUntil_null);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.409 2010/02/15 16:10:34 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.410 2010/02/26 02:00:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -109,7 +109,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
|
||||
/*
|
||||
* We cannot run VACUUM inside a user transaction block; if we were inside
|
||||
* a transaction, then our commit- and start-transaction-command calls
|
||||
* would not have the intended effect! There are numerous other subtle
|
||||
* would not have the intended effect! There are numerous other subtle
|
||||
* dependencies on this, too.
|
||||
*
|
||||
* ANALYZE (without VACUUM) can run either way.
|
||||
@@ -664,9 +664,9 @@ vac_update_datfrozenxid(void)
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* If we were able to advance datfrozenxid, see if we can truncate pg_clog.
|
||||
* Also do it if the shared XID-wrap-limit info is stale, since this
|
||||
* action will update that too.
|
||||
* If we were able to advance datfrozenxid, see if we can truncate
|
||||
* pg_clog. Also do it if the shared XID-wrap-limit info is stale, since
|
||||
* this action will update that too.
|
||||
*/
|
||||
if (dirty || ForceTransactionIdLimitUpdate())
|
||||
vac_truncate_clog(newFrozenXid);
|
||||
@@ -944,8 +944,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
|
||||
/*
|
||||
* Switch to the table owner's userid, so that any index functions are run
|
||||
* as that user. Also lock down security-restricted operations and
|
||||
* arrange to make GUC variable changes local to this command.
|
||||
* (This is unnecessary, but harmless, for lazy VACUUM.)
|
||||
* arrange to make GUC variable changes local to this command. (This is
|
||||
* unnecessary, but harmless, for lazy VACUUM.)
|
||||
*/
|
||||
GetUserIdAndSecContext(&save_userid, &save_sec_context);
|
||||
SetUserIdAndSecContext(onerel->rd_rel->relowner,
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.131 2010/02/09 21:43:30 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.132 2010/02/26 02:00:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -268,8 +268,8 @@ static void
|
||||
vacuum_log_cleanup_info(Relation rel, LVRelStats *vacrelstats)
|
||||
{
|
||||
/*
|
||||
* No need to log changes for temp tables, they do not contain
|
||||
* data visible on the standby server.
|
||||
* No need to log changes for temp tables, they do not contain data
|
||||
* visible on the standby server.
|
||||
*/
|
||||
if (rel->rd_istemp || !XLogIsNeeded())
|
||||
return;
|
||||
@@ -629,7 +629,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
||||
{
|
||||
lazy_record_dead_tuple(vacrelstats, &(tuple.t_self));
|
||||
HeapTupleHeaderAdvanceLatestRemovedXid(tuple.t_data,
|
||||
&vacrelstats->latestRemovedXid);
|
||||
&vacrelstats->latestRemovedXid);
|
||||
tups_vacuumed += 1;
|
||||
}
|
||||
else
|
||||
@@ -1039,7 +1039,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
|
||||
RelationTruncate(onerel, new_rel_pages);
|
||||
|
||||
/*
|
||||
* We can release the exclusive lock as soon as we have truncated. Other
|
||||
* We can release the exclusive lock as soon as we have truncated. Other
|
||||
* backends can't safely access the relation until they have processed the
|
||||
* smgr invalidation that smgrtruncate sent out ... but that should happen
|
||||
* as part of standard invalidation processing once they acquire lock on
|
||||
|
||||
Reference in New Issue
Block a user