On Wed, Aug 24, 2022 at 10:47:31PM +1200, David Rowley wrote:
> On Wed, 24 Aug 2022 at 14:39, Justin Pryzby <[email protected]> wrote:
> > Attached are half of the remainder of what I've written, ready for review.
>
> Thanks for the patches.
> 4. "Repurpose" (variables have the same purpose and may as well use
> the same variable)
> Would you be able to write a patch for #4.
The first of the patches that I sent yesterday was all about "repurposed" vars
from outer scope (lc, l, isnull, save_errno), and was 70% of your list of vars
to repurpose.
Here, I've included the rest of your list.
Plus another patch for vars which I'd already written patches to repurpose, but
which aren't classified as "repurpose" on your list.
For subselect.c, you could remove some more "lc" vars and re-use the "l" var
for consistency (but I suppose you won't want that).
--
Justin
diff --git a/src/backend/access/transam/xlog.c
b/src/backend/access/transam/xlog.c
index 87b243e0d4b..a090cada400 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -3017,46 +3017,45 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID
logtli,
}
pgstat_report_wait_end();
if (save_errno)
{
/*
* If we fail to make the file, delete it to release disk space
*/
unlink(tmppath);
close(fd);
errno = save_errno;
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m",
tmppath)));
}
pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_SYNC);
if (pg_fsync(fd) != 0)
{
- int save_errno = errno;
-
+ save_errno = errno;
close(fd);
errno = save_errno;
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m",
tmppath)));
}
pgstat_report_wait_end();
if (close(fd) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not close file \"%s\": %m",
tmppath)));
/*
* Now move the segment into place with its final name. Cope with
* possibility that someone else has created the file while we were
* filling ours: if so, use ours to pre-create a future log segment.
*/
installed_segno = logsegno;
/*
* XXX: What should we use as max_segno? We used to use XLOGfileslop
when
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 9be04c8a1e7..dacc989d855 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -16777,45 +16777,44 @@ PreCommit_on_commit_actions(void)
oids_to_truncate =
lappend_oid(oids_to_truncate, oc->relid);
break;
case ONCOMMIT_DROP:
oids_to_drop = lappend_oid(oids_to_drop,
oc->relid);
break;
}
}
/*
* Truncate relations before dropping so that all dependencies between
* relations are removed after they are worked on. Doing it like this
* might be a waste as it is possible that a relation being truncated
will
* be dropped anyway due to its parent being dropped, but this makes the
* code more robust because of not having to re-check that the relation
* exists at truncation time.
*/
if (oids_to_truncate != NIL)
heap_truncate(oids_to_truncate);
if (oids_to_drop != NIL)
{
ObjectAddresses *targetObjects = new_object_addresses();
- ListCell *l;
foreach(l, oids_to_drop)
{
ObjectAddress object;
object.classId = RelationRelationId;
object.objectId = lfirst_oid(l);
object.objectSubId = 0;
Assert(!object_address_present(&object, targetObjects));
add_exact_object_address(&object, targetObjects);
}
/*
* Since this is an automatic drop, rather than one directly
initiated
* by the user, we pass the PERFORM_DELETION_INTERNAL flag.
*/
performMultipleDeletions(targetObjects, DROP_CASCADE,
PERFORM_DELETION_INTERNAL | PERFORM_DELETION_QUIETLY);
#ifdef USE_ASSERT_CHECKING
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index dbdfe8bd2d4..3670d1f1861 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -214,46 +214,44 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool
isTopLevel)
(skip_locked ? VACOPT_SKIP_LOCKED : 0) |
(analyze ? VACOPT_ANALYZE : 0) |
(freeze ? VACOPT_FREEZE : 0) |
(full ? VACOPT_FULL : 0) |
(disable_page_skipping ? VACOPT_DISABLE_PAGE_SKIPPING : 0) |
(process_toast ? VACOPT_PROCESS_TOAST : 0);
/* sanity checks on options */
Assert(params.options & (VACOPT_VACUUM | VACOPT_ANALYZE));
Assert((params.options & VACOPT_VACUUM) ||
!(params.options & (VACOPT_FULL | VACOPT_FREEZE)));
if ((params.options & VACOPT_FULL) && params.nworkers > 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("VACUUM FULL cannot be performed in
parallel")));
/*
* Make sure VACOPT_ANALYZE is specified if any column lists are
present.
*/
if (!(params.options & VACOPT_ANALYZE))
{
- ListCell *lc;
-
foreach(lc, vacstmt->rels)
{
VacuumRelation *vrel = lfirst_node(VacuumRelation, lc);
if (vrel->va_cols != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("ANALYZE option must be
specified when a column list is provided")));
}
}
/*
* All freeze ages are zero if the FREEZE option is given; otherwise
pass
* them as -1 which means to use the default values.
*/
if (params.options & VACOPT_FREEZE)
{
params.freeze_min_age = 0;
params.freeze_table_age = 0;
params.multixact_freeze_min_age = 0;
params.multixact_freeze_table_age = 0;
}
diff --git a/src/backend/executor/execPartition.c
b/src/backend/executor/execPartition.c
index ac03271882f..901dd435efd 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -749,45 +749,44 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState
*estate,
*/
if (map == NULL)
{
/*
* It's safe to reuse these from the partition
root, as we
* only process one tuple at a time (therefore
we won't
* overwrite needed data in slots), and the
results of
* projections are independent of the
underlying storage.
* Projections and where clauses themselves
don't store state
* / are independent of the underlying storage.
*/
onconfl->oc_ProjSlot =
rootResultRelInfo->ri_onConflict->oc_ProjSlot;
onconfl->oc_ProjInfo =
rootResultRelInfo->ri_onConflict->oc_ProjInfo;
onconfl->oc_WhereClause =
rootResultRelInfo->ri_onConflict->oc_WhereClause;
}
else
{
List *onconflset;
List *onconflcols;
- bool found_whole_row;
/*
* Translate expressions in onConflictSet to
account for
* different attribute numbers. For that, map
partition
* varattnos twice: first to catch the EXCLUDED
* pseudo-relation (INNER_VAR), and second to
handle the main
* target relation (firstVarno).
*/
onconflset = copyObject(node->onConflictSet);
if (part_attmap == NULL)
part_attmap =
build_attrmap_by_name(RelationGetDescr(partrel),
RelationGetDescr(firstResultRel));
onconflset = (List *)
map_variable_attnos((Node *) onconflset,
INNER_VAR, 0,
part_attmap,
RelationGetForm(partrel)->reltype,
&found_whole_row);
/* We ignore the value of found_whole_row. */
onconflset = (List *)
map_variable_attnos((Node *) onconflset,
diff --git a/src/backend/executor/nodeWindowAgg.c
b/src/backend/executor/nodeWindowAgg.c
index 4b104c4d98a..8b0858e9f5f 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2043,50 +2043,51 @@ update_grouptailpos(WindowAggState *winstate)
static TupleTableSlot *
ExecWindowAgg(PlanState *pstate)
{
WindowAggState *winstate = castNode(WindowAggState, pstate);
TupleTableSlot *slot;
ExprContext *econtext;
int i;
int numfuncs;
CHECK_FOR_INTERRUPTS();
if (winstate->status == WINDOWAGG_DONE)
return NULL;
/*
* Compute frame offset values, if any, during first call (or after a
* rescan). These are assumed to hold constant throughout the scan; if
* user gives us a volatile expression, we'll only use its initial
value.
*/
if (winstate->all_first)
{
int frameOptions = winstate->frameOptions;
- ExprContext *econtext = winstate->ss.ps.ps_ExprContext;
Datum value;
bool isnull;
int16 len;
bool byval;
+ econtext = winstate->ss.ps.ps_ExprContext;
+
if (frameOptions & FRAMEOPTION_START_OFFSET)
{
Assert(winstate->startOffset != NULL);
value = ExecEvalExprSwitchContext(winstate->startOffset,
econtext,
&isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("frame starting offset
must not be null")));
/* copy value into query-lifespan context */
get_typlenbyval(exprType((Node *)
winstate->startOffset->expr),
&len, &byval);
winstate->startOffsetValue = datumCopy(value, byval,
len);
if (frameOptions & (FRAMEOPTION_ROWS |
FRAMEOPTION_GROUPS))
{
/* value is known to be int8 */
int64 offset = DatumGetInt64(value);
if (offset < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
diff --git a/src/backend/lib/integerset.c b/src/backend/lib/integerset.c
index 5aff292c287..41d3abdb09c 100644
--- a/src/backend/lib/integerset.c
+++ b/src/backend/lib/integerset.c
@@ -546,46 +546,44 @@ intset_update_upper(IntegerSet *intset, int level,
intset_node *child,
intset_update_upper(intset, level + 1, (intset_node *) parent,
child_key);
}
}
/*
* Does the set contain the given value?
*/
bool
intset_is_member(IntegerSet *intset, uint64 x)
{
intset_node *node;
intset_leaf_node *leaf;
int level;
int itemno;
leaf_item *item;
/*
* The value might be in the buffer of newly-added values.
*/
if (intset->num_buffered_values > 0 && x >= intset->buffered_values[0])
{
- int itemno;
-
itemno = intset_binsrch_uint64(x,
intset->buffered_values,
intset->num_buffered_values,
false);
if (itemno >= intset->num_buffered_values)
return false;
else
return (intset->buffered_values[itemno] == x);
}
/*
* Start from the root, and walk down the B-tree to find the right leaf
* node.
*/
if (!intset->root)
return false;
node = intset->root;
for (level = intset->num_levels - 1; level > 0; level--)
{
intset_internal_node *n = (intset_internal_node *) node;
Assert(node->level == level);
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 2e7330f7bc6..10cd19e6cd9 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -1633,46 +1633,44 @@ interpret_ident_response(const char *ident_response,
while (pg_isblank(*cursor))
cursor++; /* skip blanks */
if (strcmp(response_type, "USERID") != 0)
return false;
else
{
/*
* It's a USERID response. Good. "cursor"
should be pointing
* to the colon that precedes the operating
system type.
*/
if (*cursor != ':')
return false;
else
{
cursor++; /* Go over colon */
/* Skip over operating system field. */
while (*cursor != ':' && *cursor !=
'\r')
cursor++;
if (*cursor != ':')
return false;
else
{
- int i;
/* Index into *ident_user */
-
cursor++; /* Go over
colon */
while (pg_isblank(*cursor))
cursor++; /* skip
blanks */
/* Rest of line is user name.
Copy it over. */
i = 0;
while (*cursor != '\r' && i <
IDENT_USERNAME_MAX)
ident_user[i++] =
*cursor++;
ident_user[i] = '\0';
return true;
}
}
}
}
}
}
/*
* Talk to the ident server on "remote_addr" and find out who
* owns the tcp connection to "local_addr"
* If the username is successfully retrieved, check the usermap.
*
diff --git a/src/backend/optimizer/plan/planner.c
b/src/backend/optimizer/plan/planner.c
index d929ce34171..df86d18a604 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -4757,45 +4757,45 @@ create_final_distinct_paths(PlannerInfo *root,
RelOptInfo *input_rel,
* First, if we have any adequately-presorted paths, just stick
a
* Unique node on those. Then consider doing an explicit sort
of the
* cheapest input path and Unique'ing that.
*
* When we have DISTINCT ON, we must sort by the more rigorous
of
* DISTINCT and ORDER BY, else it won't have the desired
behavior.
* Also, if we do have to do an explicit sort, we might as well
use
* the more rigorous ordering to avoid a second sort later.
(Note
* that the parser will have ensured that one clause is a
prefix of
* the other.)
*/
List *needed_pathkeys;
if (parse->hasDistinctOn &&
list_length(root->distinct_pathkeys) <
list_length(root->sort_pathkeys))
needed_pathkeys = root->sort_pathkeys;
else
needed_pathkeys = root->distinct_pathkeys;
foreach(lc, input_rel->pathlist)
{
- Path *path = (Path *) lfirst(lc);
+ path = (Path *) lfirst(lc);
if (pathkeys_contained_in(needed_pathkeys,
path->pathkeys))
{
add_path(distinct_rel, (Path *)
create_upper_unique_path(root,
distinct_rel,
path,
list_length(root->distinct_pathkeys),
numDistinctRows));
}
}
/* For explicit-sort case, always use the more rigorous clause
*/
if (list_length(root->distinct_pathkeys) <
list_length(root->sort_pathkeys))
{
needed_pathkeys = root->sort_pathkeys;
/* Assert checks that parser didn't mess up... */
Assert(pathkeys_contained_in(root->distinct_pathkeys,
needed_pathkeys));
}
else
needed_pathkeys = root->distinct_pathkeys;
diff --git a/src/backend/optimizer/prep/prepunion.c
b/src/backend/optimizer/prep/prepunion.c
index 043181b586b..71052c841d7 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -634,45 +634,44 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo
*root,
* For UNION ALL, we just need the Append path. For UNION, need to add
* node(s) to remove duplicates.
*/
if (!op->all)
path = make_union_unique(op, path, tlist, root);
add_path(result_rel, path);
/*
* Estimate number of groups. For now we just assume the output is
unique
* --- this is certainly true for the UNION case, and we want worst-case
* estimates anyway.
*/
result_rel->rows = path->rows;
/*
* Now consider doing the same thing using the partial paths plus Append
* plus Gather.
*/
if (partial_paths_valid)
{
Path *ppath;
- ListCell *lc;
int parallel_workers = 0;
/* Find the highest number of workers requested for any
subpath. */
foreach(lc, partial_pathlist)
{
Path *path = lfirst(lc);
parallel_workers = Max(parallel_workers,
path->parallel_workers);
}
Assert(parallel_workers > 0);
/*
* If the use of parallel append is permitted, always request
at least
* log2(# of children) paths. We assume it can be useful to
have
* extra workers in this case because they will be spread out
across
* the children. The precise formula is just a guess; see
* add_paths_to_append_rel.
*/
if (enable_parallel_append)
{
parallel_workers = Max(parallel_workers,
pg_leftmost_one_pos32(list_length(partial_pathlist)) + 1);
diff --git a/src/backend/statistics/dependencies.c
b/src/backend/statistics/dependencies.c
index c1c27e67d47..bf698c1fc3f 100644
--- a/src/backend/statistics/dependencies.c
+++ b/src/backend/statistics/dependencies.c
@@ -1246,45 +1246,44 @@ dependency_is_compatible_expression(Node *clause, Index
relid, List *statlist, N
* first argument, and pseudoconstant is the second one.
*/
if (!is_pseudo_constant_clause(lsecond(expr->args)))
return false;
clause_expr = linitial(expr->args);
/*
* If it's not an "=" operator, just ignore the clause, as it's
not
* compatible with functional dependencies. The operator is
identified
* simply by looking at which function it uses to estimate
* selectivity. That's a bit strange, but it's what other
similar
* places do.
*/
if (get_oprrest(expr->opno) != F_EQSEL)
return false;
/* OK to proceed with checking "var" */
}
else if (is_orclause(clause))
{
BoolExpr *bool_expr = (BoolExpr *) clause;
- ListCell *lc;
/* start with no expression (we'll use the first match) */
*expr = NULL;
foreach(lc, bool_expr->args)
{
Node *or_expr = NULL;
/*
* Had we found incompatible expression in the
arguments, treat
* the whole expression as incompatible.
*/
if (!dependency_is_compatible_expression((Node *)
lfirst(lc), relid,
statlist, &or_expr))
return false;
if (*expr == NULL)
*expr = or_expr;
/* ensure all the expressions are the same */
if (!equal(or_expr, *expr))
return false;
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index c0e907d4373..aad79493e86 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -3784,46 +3784,44 @@ advanceConnectionState(TState *thread, CState *st,
StatsData *agg)
st->estatus =
ESTATUS_META_COMMAND_ERROR;
}
/*
* We're now waiting for an SQL command to
complete, or
* finished processing a metacommand, or need
to sleep, or
* something bad happened.
*/
Assert(st->state == CSTATE_WAIT_RESULT ||
st->state == CSTATE_END_COMMAND ||
st->state == CSTATE_SLEEP ||
st->state == CSTATE_ABORTED);
break;
/*
* non executed conditional branch
*/
case CSTATE_SKIP_COMMAND:
Assert(!conditional_active(st->cstack));
/* quickly skip commands until something to
do... */
while (true)
{
- Command *command;
-
command =
sql_script[st->use_file].commands[st->command];
/* cannot reach end of script in that
state */
Assert(command != NULL);
/*
* if this is conditional related,
update conditional
* state
*/
if (command->type == META_COMMAND &&
(command->meta == META_IF ||
command->meta == META_ELIF ||
command->meta == META_ELSE ||
command->meta == META_ENDIF))
{
switch
(conditional_stack_peek(st->cstack))
{
case IFSTATE_FALSE:
if
(command->meta == META_IF ||
command->meta == META_ELIF)
{
/* we
must evaluate the condition */
@@ -3940,46 +3938,44 @@ advanceConnectionState(TState *thread, CState *st,
StatsData *agg)
* instead of CSTATE_START_TX.
*/
case CSTATE_SLEEP:
pg_time_now_lazy(&now);
if (now < st->sleep_until)
return; /* still sleeping,
nothing to do here */
/* Else done sleeping. */
st->state = CSTATE_END_COMMAND;
break;
/*
* End of command: record stats and proceed to
next command.
*/
case CSTATE_END_COMMAND:
/*
* command completed: accumulate per-command
execution times
* in thread-local data structure, if
per-command latencies
* are requested.
*/
if (report_per_command)
{
- Command *command;
-
pg_time_now_lazy(&now);
command =
sql_script[st->use_file].commands[st->command];
/* XXX could use a mutex here, but we
choose not to */
addToSimpleStats(&command->stats,
PG_TIME_GET_DOUBLE(now - st->stmt_begin));
}
/* Go ahead with next command, to be executed
or skipped */
st->command++;
st->state = conditional_active(st->cstack) ?
CSTATE_START_COMMAND :
CSTATE_SKIP_COMMAND;
break;
/*
* Clean up after an error.
*/
case CSTATE_ERROR:
{
TStatus tstatus;
Assert(st->estatus != ESTATUS_NO_ERROR);
diff --git a/src/backend/access/gist/gistbuildbuffers.c
b/src/backend/access/gist/gistbuildbuffers.c
index eabf7460182..77677150aff 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -615,46 +615,45 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb,
GISTSTATE *giststate,
* empty.
*/
newNodeBuffer = gistGetNodeBuffer(gfbb, giststate,
BufferGetBlockNumber(si->buf), level);
relocationBuffersInfos[i].nodeBuffer = newNodeBuffer;
relocationBuffersInfos[i].splitinfo = si;
i++;
}
/*
* Loop through all index tuples in the buffer of the page being split,
* moving them to buffers for the new pages. We try to move each tuple
to
* the page that will result in the lowest penalty for the leading
column
* or, in the case of a tie, the lowest penalty for the earliest column
* that is not tied.
*
* The page searching logic is very similar to gistchoose().
*/
while (gistPopItupFromNodeBuffer(gfbb, &oldBuf, &itup))
{
float best_penalty[INDEX_MAX_KEYS];
- int i,
- which;
+ int which;
IndexTuple newtup;
RelocationBufferInfo *targetBufferInfo;
gistDeCompressAtt(giststate, r,
itup, NULL, (OffsetNumber) 0,
entry, isnull);
/* default to using first page (shouldn't matter) */
which = 0;
/*
* best_penalty[j] is the best penalty we have seen so far for
column
* j, or -1 when we haven't yet examined column j. Array
entries to
* the right of the first -1 are undefined.
*/
best_penalty[0] = -1;
/*
* Loop over possible target pages, looking for one to move
this tuple
* to.
*/
for (i = 0; i < splitPagesCount; i++)
{
diff --git a/src/backend/access/hash/hash_xlog.c
b/src/backend/access/hash/hash_xlog.c
index 2e68303cbfd..e88213c7425 100644
--- a/src/backend/access/hash/hash_xlog.c
+++ b/src/backend/access/hash/hash_xlog.c
@@ -221,45 +221,44 @@ hash_xlog_add_ovfl_page(XLogReaderState *record)
PageSetLSN(leftpage, lsn);
MarkBufferDirty(leftbuf);
}
if (BufferIsValid(leftbuf))
UnlockReleaseBuffer(leftbuf);
UnlockReleaseBuffer(ovflbuf);
/*
* Note: in normal operation, we'd update the bitmap and meta page while
* still holding lock on the overflow pages. But during replay it's not
* necessary to hold those locks, since no other index updates can be
* happening concurrently.
*/
if (XLogRecHasBlockRef(record, 2))
{
Buffer mapbuffer;
if (XLogReadBufferForRedo(record, 2, &mapbuffer) ==
BLK_NEEDS_REDO)
{
Page mappage = (Page)
BufferGetPage(mapbuffer);
uint32 *freep = NULL;
- char *data;
uint32 *bitmap_page_bit;
freep = HashPageGetBitmap(mappage);
data = XLogRecGetBlockData(record, 2, &datalen);
bitmap_page_bit = (uint32 *) data;
SETBIT(freep, *bitmap_page_bit);
PageSetLSN(mappage, lsn);
MarkBufferDirty(mapbuffer);
}
if (BufferIsValid(mapbuffer))
UnlockReleaseBuffer(mapbuffer);
}
if (XLogRecHasBlockRef(record, 3))
{
Buffer newmapbuf;
newmapbuf = XLogInitBufferForRedo(record, 3);
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index aab8d6fa4e5..3133d1e0585 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -6256,45 +6256,45 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
return multi;
}
/*
* Do a more thorough second pass over the multi to figure out which
* member XIDs actually need to be kept. Checking the precise status of
* individual members might even show that we don't need to keep
anything.
*/
nnewmembers = 0;
newmembers = palloc(sizeof(MultiXactMember) * nmembers);
has_lockers = false;
update_xid = InvalidTransactionId;
update_committed = false;
temp_xid_out = *mxid_oldest_xid_out; /* init for FRM_RETURN_IS_MULTI
*/
for (i = 0; i < nmembers; i++)
{
/*
* Determine whether to keep this member or ignore it.
*/
if (ISUPDATE_from_mxstatus(members[i].status))
{
- TransactionId xid = members[i].xid;
+ xid = members[i].xid;
Assert(TransactionIdIsValid(xid));
if (TransactionIdPrecedes(xid, relfrozenxid))
ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg_internal("found update
xid %u from before relfrozenxid %u",
xid, relfrozenxid)));
/*
* It's an update; should we keep it? If the
transaction is known
* aborted or crashed then it's okay to ignore it,
otherwise not.
* Note that an updater older than cutoff_xid cannot
possibly be
* committed, because HeapTupleSatisfiesVacuum would
have returned
* HEAPTUPLE_DEAD and we would not be trying to freeze
the tuple.
*
* As with all tuple visibility routines, it's critical
to test
* TransactionIdIsInProgress before
TransactionIdDidCommit,
* because of race conditions explained in detail in
* heapam_visibility.c.
*/
if (TransactionIdIsCurrentTransactionId(xid) ||
TransactionIdIsInProgress(xid))
diff --git a/src/backend/access/transam/multixact.c
b/src/backend/access/transam/multixact.c
index 8f7d12950e5..ec57f56adf3 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1595,45 +1595,44 @@ mXactCachePut(MultiXactId multi, int nmembers,
MultiXactMember *members)
debug_elog2(DEBUG2, "CachePut: initializing memory context");
MXactContext = AllocSetContextCreate(TopTransactionContext,
"MultiXact cache context",
ALLOCSET_SMALL_SIZES);
}
entry = (mXactCacheEnt *)
MemoryContextAlloc(MXactContext,
offsetof(mXactCacheEnt,
members) +
nmembers *
sizeof(MultiXactMember));
entry->multi = multi;
entry->nmembers = nmembers;
memcpy(entry->members, members, nmembers * sizeof(MultiXactMember));
/* mXactCacheGetBySet assumes the entries are sorted, so sort them */
qsort(entry->members, nmembers, sizeof(MultiXactMember),
mxactMemberComparator);
dlist_push_head(&MXactCache, &entry->node);
if (MXactCacheMembers++ >= MAX_CACHE_ENTRIES)
{
dlist_node *node;
- mXactCacheEnt *entry;
node = dlist_tail_node(&MXactCache);
dlist_delete(node);
MXactCacheMembers--;
entry = dlist_container(mXactCacheEnt, node, node);
debug_elog3(DEBUG2, "CachePut: pruning cached multi %u",
entry->multi);
pfree(entry);
}
}
static char *
mxstatus_to_string(MultiXactStatus status)
{
switch (status)
{
case MultiXactStatusForKeyShare:
return "keysh";
case MultiXactStatusForShare:
return "sh";
diff --git a/src/backend/access/transam/xlog.c
b/src/backend/access/transam/xlog.c
index a090cada400..537845cada7 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4701,45 +4701,44 @@ XLogInitNewTimeline(TimeLineID endTLI, XLogRecPtr
endOfLog, TimeLineID newTLI)
/*
* Make a copy of the file on the new timeline.
*
* Writing WAL isn't allowed yet, so there are no locking
* considerations. But we should be just as tense as
XLogFileInit to
* avoid emplacing a bogus file.
*/
XLogFileCopy(newTLI, endLogSegNo, endTLI, endLogSegNo,
XLogSegmentOffset(endOfLog,
wal_segment_size));
}
else
{
/*
* The switch happened at a segment boundary, so just create
the next
* segment on the new timeline.
*/
int fd;
fd = XLogFileInit(startLogSegNo, newTLI);
if (close(fd) != 0)
{
- char xlogfname[MAXFNAMELEN];
int save_errno = errno;
XLogFileName(xlogfname, newTLI, startLogSegNo,
wal_segment_size);
errno = save_errno;
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not close file \"%s\":
%m", xlogfname)));
}
}
/*
* Let's just make real sure there are not .ready or .done flags posted
* for the new segment.
*/
XLogFileName(xlogfname, newTLI, startLogSegNo, wal_segment_size);
XLogArchiveCleanup(xlogfname);
}
/*
* Perform cleanup actions at the conclusion of archive recovery.
*/
static void
diff --git a/src/backend/commands/functioncmds.c
b/src/backend/commands/functioncmds.c
index e7e37146f69..e6fcfc23b93 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -102,45 +102,44 @@ compute_return_type(TypeName *returnType, Oid languageOid,
if (typtup)
{
if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
{
if (languageOid == SQLlanguageId)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("SQL function cannot
return shell type %s",
TypeNameToString(returnType))));
else
ereport(NOTICE,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("return type %s is only
a shell",
TypeNameToString(returnType))));
}
rettype = typeTypeId(typtup);
ReleaseSysCache(typtup);
}
else
{
char *typnam = TypeNameToString(returnType);
Oid namespaceId;
- AclResult aclresult;
char *typname;
ObjectAddress address;
/*
* Only C-coded functions can be I/O functions. We enforce this
* restriction here mainly to prevent littering the catalogs
with
* shell types due to simple typos in user-defined function
* definitions.
*/
if (languageOid != INTERNALlanguageId &&
languageOid != ClanguageId)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
typnam)));
/* Reject if there's typmod decoration, too */
if (returnType->typmods != NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("type modifier cannot be
specified for shell type \"%s\"",
typnam)));
@@ -1093,46 +1092,44 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt
*stmt)
language = "sql";
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("no language specified")));
}
/* Look up the language and validate permissions */
languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
if (!HeapTupleIsValid(languageTuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("language \"%s\" does not exist",
language),
(extension_file_exists(language) ?
errhint("Use CREATE EXTENSION to load the
language into the database.") : 0)));
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
languageOid = languageStruct->oid;
if (languageStruct->lanpltrusted)
{
/* if trusted language, need USAGE privilege */
- AclResult aclresult;
-
aclresult = pg_language_aclcheck(languageOid, GetUserId(),
ACL_USAGE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_LANGUAGE,
NameStr(languageStruct->lanname));
}
else
{
/* if untrusted language, must be superuser */
if (!superuser())
aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE,
NameStr(languageStruct->lanname));
}
languageValidator = languageStruct->lanvalidator;
ReleaseSysCache(languageTuple);
/*
* Only superuser is allowed to create leakproof functions because
* leakproof functions can see tuples which have not yet been filtered
out
* by security barrier views or row-level security policies.
*/
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 29bc26669b0..a250a33f8cb 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -2465,45 +2465,44 @@ _SPI_execute_plan(SPIPlanPtr plan, const
SPIExecuteOptions *options,
* there be only one query.
*/
if (options->must_return_tuples && plan->plancache_list == NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("empty query does not return tuples")));
foreach(lc1, plan->plancache_list)
{
CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
List *stmt_list;
ListCell *lc2;
spicallbackarg.query = plansource->query_string;
/*
* If this is a one-shot plan, we still need to do parse
analysis.
*/
if (plan->oneshot)
{
RawStmt *parsetree = plansource->raw_parse_tree;
const char *src = plansource->query_string;
- List *stmt_list;
/*
* Parameter datatypes are driven by parserSetup hook
if provided,
* otherwise we use the fixed parameter list.
*/
if (parsetree == NULL)
stmt_list = NIL;
else if (plan->parserSetup != NULL)
{
Assert(plan->nargs == 0);
stmt_list =
pg_analyze_and_rewrite_withcb(parsetree,
src,
plan->parserSetup,
plan->parserSetupArg,
_SPI_current->queryEnv);
}
else
{
stmt_list =
pg_analyze_and_rewrite_fixedparams(parsetree,
src,
plan->argtypes,
plan->nargs,
diff --git a/src/backend/optimizer/path/indxpath.c
b/src/backend/optimizer/path/indxpath.c
index 7d176e7b00a..0557e945ca7 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -2169,45 +2169,45 @@ match_clause_to_index(PlannerInfo *root,
* but what if someone builds an expression index on a constant? It's
not
* totally unreasonable to do so with a partial index, either.)
*/
if (rinfo->pseudoconstant)
return;
/*
* If clause can't be used as an indexqual because it must wait till
after
* some lower-security-level restriction clause, reject it.
*/
if (!restriction_is_securely_promotable(rinfo, index->rel))
return;
/* OK, check each index key column for a match */
for (indexcol = 0; indexcol < index->nkeycolumns; indexcol++)
{
IndexClause *iclause;
ListCell *lc;
/* Ignore duplicates */
foreach(lc, clauseset->indexclauses[indexcol])
{
- IndexClause *iclause = (IndexClause *) lfirst(lc);
+ iclause = (IndexClause *) lfirst(lc);
if (iclause->rinfo == rinfo)
return;
}
/* OK, try to match the clause to the index column */
iclause = match_clause_to_indexcol(root,
rinfo,
indexcol,
index);
if (iclause)
{
/* Success, so record it */
clauseset->indexclauses[indexcol] =
lappend(clauseset->indexclauses[indexcol],
iclause);
clauseset->nonempty = true;
return;
}
}
}
/*
diff --git a/src/backend/optimizer/plan/subselect.c
b/src/backend/optimizer/plan/subselect.c
index df4ca129191..b15ecc83971 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -2383,45 +2383,45 @@ finalize_plan(PlannerInfo *root, Plan *plan,
/* We must run finalize_plan on the subquery */
rel = find_base_rel(root,
sscan->scan.scanrelid);
subquery_params = rel->subroot->outer_params;
if (gather_param >= 0)
subquery_params =
bms_add_member(bms_copy(subquery_params),
gather_param);
finalize_plan(rel->subroot, sscan->subplan,
gather_param,
subquery_params,
NULL);
/* Now we can add its extParams to the parent's
params */
context.paramids =
bms_add_members(context.paramids,
sscan->subplan->extParam);
/* We need scan_params too, though */
context.paramids =
bms_add_members(context.paramids,
scan_params);
}
break;
case T_FunctionScan:
{
FunctionScan *fscan = (FunctionScan *) plan;
- ListCell *lc;
+ ListCell *lc; //
/*
* Call finalize_primnode independently on each
function
* expression, so that we can record which
params are
* referenced in each, in order to decide which
need
* re-evaluating during rescan.
*/
foreach(lc, fscan->functions)
{
RangeTblFunction *rtfunc =
(RangeTblFunction *) lfirst(lc);
finalize_primnode_context funccontext;
funccontext = context;
funccontext.paramids = NULL;
finalize_primnode(rtfunc->funcexpr,
&funccontext);
/* remember results for execution */
rtfunc->funcparams =
funccontext.paramids;
/* add the function's params to the
overall set */
context.paramids =
bms_add_members(context.paramids,
@@ -2491,158 +2491,148 @@ finalize_plan(PlannerInfo *root, Plan *plan,
case T_NamedTuplestoreScan:
context.paramids = bms_add_members(context.paramids,
scan_params);
break;
case T_ForeignScan:
{
ForeignScan *fscan = (ForeignScan *) plan;
finalize_primnode((Node *) fscan->fdw_exprs,
&context);
finalize_primnode((Node *)
fscan->fdw_recheck_quals,
&context);
/* We assume fdw_scan_tlist cannot contain
Params */
context.paramids =
bms_add_members(context.paramids,
scan_params);
}
break;
case T_CustomScan:
{
CustomScan *cscan = (CustomScan *) plan;
- ListCell *lc;
+ ListCell *lc; //
finalize_primnode((Node *) cscan->custom_exprs,
&context);
/* We assume custom_scan_tlist cannot contain
Params */
context.paramids =
bms_add_members(context.paramids,
scan_params);
/* child nodes if any */
foreach(lc, cscan->custom_plans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(lc),
gather_param,
valid_params,
scan_params));
}
}
break;
case T_ModifyTable:
{
ModifyTable *mtplan = (ModifyTable *) plan;
/* Force descendant scan nodes to reference
epqParam */
locally_added_param = mtplan->epqParam;
valid_params =
bms_add_member(bms_copy(valid_params),
locally_added_param);
scan_params =
bms_add_member(bms_copy(scan_params),
locally_added_param);
finalize_primnode((Node *)
mtplan->returningLists,
&context);
finalize_primnode((Node *)
mtplan->onConflictSet,
&context);
finalize_primnode((Node *)
mtplan->onConflictWhere,
&context);
/* exclRelTlist contains only Vars, doesn't
need examination */
}
break;
case T_Append:
{
- ListCell *l;
-
foreach(l, ((Append *) plan)->appendplans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
gather_param,
valid_params,
scan_params));
}
}
break;
case T_MergeAppend:
{
- ListCell *l;
-
foreach(l, ((MergeAppend *) plan)->mergeplans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
gather_param,
valid_params,
scan_params));
}
}
break;
case T_BitmapAnd:
{
- ListCell *l;
-
foreach(l, ((BitmapAnd *) plan)->bitmapplans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
gather_param,
valid_params,
scan_params));
}
}
break;
case T_BitmapOr:
{
- ListCell *l;
-
foreach(l, ((BitmapOr *) plan)->bitmapplans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
gather_param,
valid_params,
scan_params));
}
}
break;
case T_NestLoop:
{
- ListCell *l;
-
finalize_primnode((Node *) ((Join *)
plan)->joinqual,
&context);
/* collect set of params that will be passed to
right child */
foreach(l, ((NestLoop *) plan)->nestParams)
{
NestLoopParam *nlp = (NestLoopParam *)
lfirst(l);
nestloop_params =
bms_add_member(nestloop_params,
nlp->paramno);
}
}
break;
case T_MergeJoin:
finalize_primnode((Node *) ((Join *) plan)->joinqual,
&context);
finalize_primnode((Node *) ((MergeJoin *)
plan)->mergeclauses,
&context);
break;
case T_HashJoin:
finalize_primnode((Node *) ((Join *) plan)->joinqual,
diff --git a/src/backend/partitioning/partbounds.c
b/src/backend/partitioning/partbounds.c
index 091d6e886b6..2720a2508cb 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -4300,46 +4300,45 @@ get_qual_for_range(Relation parent, PartitionBoundSpec
*spec,
int i,
j;
PartitionRangeDatum *ldatum,
*udatum;
PartitionKey key = RelationGetPartitionKey(parent);
Expr *keyCol;
Const *lower_val,
*upper_val;
List *lower_or_arms,
*upper_or_arms;
int num_or_arms,
current_or_arm;
ListCell *lower_or_start_datum,
*upper_or_start_datum;
bool need_next_lower_arm,
need_next_upper_arm;
if (spec->is_default)
{
List *or_expr_args = NIL;
PartitionDesc pdesc = RelationGetPartitionDesc(parent, false);
Oid *inhoids = pdesc->oids;
- int nparts = pdesc->nparts,
- i;
+ int nparts = pdesc->nparts;
for (i = 0; i < nparts; i++)
{
Oid inhrelid = inhoids[i];
HeapTuple tuple;
Datum datum;
bool isnull;
PartitionBoundSpec *bspec;
tuple = SearchSysCache1(RELOID, inhrelid);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation
%u", inhrelid);
datum = SysCacheGetAttr(RELOID, tuple,
Anum_pg_class_relpartbound,
&isnull);
if (isnull)
elog(ERROR, "null relpartbound for relation
%u", inhrelid);
bspec = (PartitionBoundSpec *)
stringToNode(TextDatumGetCString(datum));
if (!IsA(bspec, PartitionBoundSpec))
diff --git a/src/backend/replication/logical/reorderbuffer.c
b/src/backend/replication/logical/reorderbuffer.c
index 89cf9f9389c..8ac78a6cf38 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -2301,45 +2301,44 @@ ReorderBufferProcessTXN(ReorderBuffer *rb,
ReorderBufferTXN *txn,
* previous tuple's toast
chunks.
*/
Assert(change->data.tp.clear_toast_afterwards);
ReorderBufferToastReset(rb,
txn);
/* We don't need this record
anymore. */
ReorderBufferReturnChange(rb,
specinsert, true);
specinsert = NULL;
}
break;
case REORDER_BUFFER_CHANGE_TRUNCATE:
{
int i;
int nrelids
= change->data.truncate.nrelids;
int
nrelations = 0;
Relation *relations;
relations = palloc0(nrelids *
sizeof(Relation));
for (i = 0; i < nrelids; i++)
{
Oid
relid = change->data.truncate.relids[i];
- Relation
relation;
relation =
RelationIdGetRelation(relid);
if
(!RelationIsValid(relation))
elog(ERROR,
"could not open relation with OID %u", relid);
if
(!RelationIsLogicallyLogged(relation))
continue;
relations[nrelations++]
= relation;
}
/* Apply the truncate. */
ReorderBufferApplyTruncate(rb,
txn, nrelations,
relations, change,
streaming);
for (i = 0; i < nrelations; i++)
RelationClose(relations[i]);
break;
}
diff --git a/src/backend/rewrite/rowsecurity.c
b/src/backend/rewrite/rowsecurity.c
index a233dd47585..b2a72374306 100644
--- a/src/backend/rewrite/rowsecurity.c
+++ b/src/backend/rewrite/rowsecurity.c
@@ -805,45 +805,44 @@ add_with_check_options(Relation rel,
wco->polname = NULL;
wco->cascaded = false;
if (list_length(permissive_quals) == 1)
wco->qual = (Node *) linitial(permissive_quals);
else
wco->qual = (Node *) makeBoolExpr(OR_EXPR,
permissive_quals, -1);
ChangeVarNodes(wco->qual, 1, rt_index, 0);
*withCheckOptions = list_append_unique(*withCheckOptions, wco);
/*
* Now add WithCheckOptions for each of the restrictive policy
clauses
* (which will be combined together using AND). We use a
separate
* WithCheckOption for each restrictive policy to allow the
policy
* name to be included in error reports if the policy is
violated.
*/
foreach(item, restrictive_policies)
{
RowSecurityPolicy *policy = (RowSecurityPolicy *)
lfirst(item);
Expr *qual = QUAL_FOR_WCO(policy);
- WithCheckOption *wco;
if (qual != NULL)
{
qual = copyObject(qual);
ChangeVarNodes((Node *) qual, 1, rt_index, 0);
wco = makeNode(WithCheckOption);
wco->kind = kind;
wco->relname =
pstrdup(RelationGetRelationName(rel));
wco->polname = pstrdup(policy->policy_name);
wco->qual = (Node *) qual;
wco->cascaded = false;
*withCheckOptions =
list_append_unique(*withCheckOptions, wco);
*hasSubLinks |= policy->hassublinks;
}
}
}
else
{
/*
* If there were no policy clauses to check new data, add a
single
diff --git a/src/backend/utils/adt/rangetypes_spgist.c
b/src/backend/utils/adt/rangetypes_spgist.c
index 1190b8000bc..71a6053b6a0 100644
--- a/src/backend/utils/adt/rangetypes_spgist.c
+++ b/src/backend/utils/adt/rangetypes_spgist.c
@@ -674,73 +674,71 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
if (minLower)
{
/*
* If the centroid's lower bound is less than
or equal to the
* minimum lower bound, anything in the 3rd and
4th quadrants
* will have an even smaller lower bound, and
thus can't
* match.
*/
if (range_cmp_bounds(typcache, ¢roidLower,
minLower) <= 0)
which &= (1 << 1) | (1 << 2) | (1 << 5);
}
if (maxLower)
{
/*
* If the centroid's lower bound is greater
than the maximum
* lower bound, anything in the 1st and 2nd
quadrants will
* also have a greater than or equal lower
bound, and thus
* can't match. If the centroid's lower bound
is equal to the
* maximum lower bound, we can still exclude
the 1st and 2nd
* quadrants if we're looking for a value
strictly greater
* than the maximum.
*/
- int cmp;
cmp = range_cmp_bounds(typcache,
¢roidLower, maxLower);
if (cmp > 0 || (!inclusive && cmp == 0))
which &= (1 << 3) | (1 << 4) | (1 << 5);
}
if (minUpper)
{
/*
* If the centroid's upper bound is less than
or equal to the
* minimum upper bound, anything in the 2nd and
3rd quadrants
* will have an even smaller upper bound, and
thus can't
* match.
*/
if (range_cmp_bounds(typcache, ¢roidUpper,
minUpper) <= 0)
which &= (1 << 1) | (1 << 4) | (1 << 5);
}
if (maxUpper)
{
/*
* If the centroid's upper bound is greater
than the maximum
* upper bound, anything in the 1st and 4th
quadrants will
* also have a greater than or equal upper
bound, and thus
* can't match. If the centroid's upper bound
is equal to the
* maximum upper bound, we can still exclude
the 1st and 4th
* quadrants if we're looking for a value
strictly greater
* than the maximum.
*/
- int cmp;
cmp = range_cmp_bounds(typcache,
¢roidUpper, maxUpper);
if (cmp > 0 || (!inclusive && cmp == 0))
which &= (1 << 2) | (1 << 3) | (1 << 5);
}
if (which == 0)
break; /* no need to consider
remaining conditions */
}
}
/* We must descend into the quadrant(s) identified by 'which' */
out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
if (needPrevious)
out->traversalValues = (void **) palloc(sizeof(void *) *
in->nNodes);
out->nNodes = 0;
/*
* Elements of traversalValues should be allocated in
* traversalMemoryContext
*/
oldCtx = MemoryContextSwitchTo(in->traversalMemoryContext);
diff --git a/src/backend/utils/adt/ruleutils.c
b/src/backend/utils/adt/ruleutils.c
index 8280711f7ef..9959f6910e9 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1284,45 +1284,44 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
/*
* Fetch the pg_am tuple of the index' access method
*/
ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
if (!HeapTupleIsValid(ht_am))
elog(ERROR, "cache lookup failed for access method %u",
idxrelrec->relam);
amrec = (Form_pg_am) GETSTRUCT(ht_am);
/* Fetch the index AM's API struct */
amroutine = GetIndexAmRoutine(amrec->amhandler);
/*
* Get the index expressions, if any. (NOTE: we do not use the relcache
* versions of the expressions and predicate, because we want to display
* non-const-folded expressions.)
*/
if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
{
Datum exprsDatum;
- bool isnull;
char *exprsString;
exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
Anum_pg_index_indexprs, &isnull);
Assert(!isnull);
exprsString = TextDatumGetCString(exprsDatum);
indexprs = (List *) stringToNode(exprsString);
pfree(exprsString);
}
else
indexprs = NIL;
indexpr_item = list_head(indexprs);
context = deparse_context_for(get_relation_name(indrelid), indrelid);
/*
* Start the index definition. Note that the index's name should never
be
* schema-qualified, but the indexed rel's name may be.
*/
initStringInfo(&buf);
@@ -1481,45 +1480,44 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
*/
if (showTblSpc)
{
Oid tblspc;
tblspc = get_rel_tablespace(indexrelid);
if (OidIsValid(tblspc))
{
if (isConstraint)
appendStringInfoString(&buf, " USING
INDEX");
appendStringInfo(&buf, " TABLESPACE %s",
quote_identifier(get_tablespace_name(tblspc)));
}
}
/*
* If it's a partial index, decompile and append the predicate
*/
if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
{
Node *node;
Datum predDatum;
- bool isnull;
char *predString;
/* Convert text string to node tree */
predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
Anum_pg_index_indpred, &isnull);
Assert(!isnull);
predString = TextDatumGetCString(predDatum);
node = (Node *) stringToNode(predString);
pfree(predString);
/* Deparse */
str = deparse_expression_pretty(node, context, false,
false,
prettyFlags, 0);
if (isConstraint)
appendStringInfo(&buf, " WHERE (%s)", str);
else
appendStringInfo(&buf, " WHERE %s", str);
}
}
/* Clean up */
ReleaseSysCache(ht_idx);
@@ -1926,45 +1924,44 @@ pg_get_partkeydef_worker(Oid relid, int prettyFlags,
Assert(form->partrelid == relid);
/* Must get partclass and partcollation the hard way */
datum = SysCacheGetAttr(PARTRELID, tuple,
Anum_pg_partitioned_table_partclass, &isnull);
Assert(!isnull);
partclass = (oidvector *) DatumGetPointer(datum);
datum = SysCacheGetAttr(PARTRELID, tuple,
Anum_pg_partitioned_table_partcollation, &isnull);
Assert(!isnull);
partcollation = (oidvector *) DatumGetPointer(datum);
/*
* Get the expressions, if any. (NOTE: we do not use the relcache
* versions of the expressions, because we want to display
* non-const-folded expressions.)
*/
if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL))
{
Datum exprsDatum;
- bool isnull;
char *exprsString;
exprsDatum = SysCacheGetAttr(PARTRELID, tuple,
Anum_pg_partitioned_table_partexprs, &isnull);
Assert(!isnull);
exprsString = TextDatumGetCString(exprsDatum);
partexprs = (List *) stringToNode(exprsString);
if (!IsA(partexprs, List))
elog(ERROR, "unexpected node type found in partexprs:
%d",
(int) nodeTag(partexprs));
pfree(exprsString);
}
else
partexprs = NIL;
partexpr_item = list_head(partexprs);
context = deparse_context_for(get_relation_name(relid), relid);
initStringInfo(&buf);