Skip to content

Commit f8c2ef3

Browse files
committed
Merge branch 'REL9_5_STABLE' into PGPRO9_5
2 parents 7e4dccd + 7dfb9b4 commit f8c2ef3

File tree

14 files changed

+270
-48
lines changed

14 files changed

+270
-48
lines changed

src/backend/access/heap/heapam.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3579,6 +3579,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
35793579
ReleaseBuffer(vmbuffer);
35803580
bms_free(hot_attrs);
35813581
bms_free(key_attrs);
3582+
bms_free(id_attrs);
35823583
return result;
35833584
}
35843585

@@ -4031,6 +4032,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
40314032

40324033
bms_free(hot_attrs);
40334034
bms_free(key_attrs);
4035+
bms_free(id_attrs);
40344036

40354037
return HeapTupleMayBeUpdated;
40364038
}

src/backend/access/transam/parallel.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,9 @@ void
627627
HandleParallelMessages(void)
628628
{
629629
dlist_iter iter;
630+
MemoryContext oldcontext;
631+
632+
static MemoryContext hpm_context = NULL;
630633

631634
/*
632635
* This is invoked from ProcessInterrupts(), and since some of the
@@ -637,6 +640,23 @@ HandleParallelMessages(void)
637640
*/
638641
HOLD_INTERRUPTS();
639642

643+
/*
644+
* Moreover, CurrentMemoryContext might be pointing almost anywhere. We
645+
* don't want to risk leaking data into long-lived contexts, so let's do
646+
* our work here in a private context that we can reset on each use.
647+
*/
648+
if (hpm_context == NULL) /* first time through? */
649+
hpm_context = AllocSetContextCreate(TopMemoryContext,
650+
"HandleParallelMessages context",
651+
ALLOCSET_DEFAULT_MINSIZE,
652+
ALLOCSET_DEFAULT_INITSIZE,
653+
ALLOCSET_DEFAULT_MAXSIZE);
654+
else
655+
MemoryContextReset(hpm_context);
656+
657+
oldcontext = MemoryContextSwitchTo(hpm_context);
658+
659+
/* OK to process messages. Reset the flag saying there are more to do. */
640660
ParallelMessagePending = false;
641661

642662
dlist_foreach(iter, &pcxt_list)
@@ -683,6 +703,11 @@ HandleParallelMessages(void)
683703
}
684704
}
685705

706+
MemoryContextSwitchTo(oldcontext);
707+
708+
/* Might as well clear the context on our way out */
709+
MemoryContextReset(hpm_context);
710+
686711
RESUME_INTERRUPTS();
687712
}
688713

src/backend/access/transam/xlogreader.c

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -844,46 +844,83 @@ XLogRecPtr
844844
XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
845845
{
846846
XLogReaderState saved_state = *state;
847-
XLogRecPtr targetPagePtr;
848847
XLogRecPtr tmpRecPtr;
849-
int targetRecOff;
850848
XLogRecPtr found = InvalidXLogRecPtr;
851-
uint32 pageHeaderSize;
852849
XLogPageHeader header;
853-
int readLen;
854850
char *errormsg;
855851

856852
Assert(!XLogRecPtrIsInvalid(RecPtr));
857853

858-
targetRecOff = RecPtr % XLOG_BLCKSZ;
854+
/*
855+
* skip over potential continuation data, keeping in mind that it may span
856+
* multiple pages
857+
*/
858+
tmpRecPtr = RecPtr;
859+
while (true)
860+
{
861+
XLogRecPtr targetPagePtr;
862+
int targetRecOff;
863+
uint32 pageHeaderSize;
864+
int readLen;
859865

860-
/* scroll back to page boundary */
861-
targetPagePtr = RecPtr - targetRecOff;
866+
/*
867+
* Compute targetRecOff. It should typically be equal or greater than
868+
* short page-header since a valid record can't start anywhere before
869+
* that, except when caller has explicitly specified the offset that
870+
* falls somewhere there or when we are skipping multi-page
871+
* continuation record. It doesn't matter though because
872+
* ReadPageInternal() is prepared to handle that and will read at least
873+
* short page-header worth of data
874+
*/
875+
targetRecOff = tmpRecPtr % XLOG_BLCKSZ;
862876

863-
/* Read the page containing the record */
864-
readLen = ReadPageInternal(state, targetPagePtr, targetRecOff);
865-
if (readLen < 0)
866-
goto err;
877+
/* scroll back to page boundary */
878+
targetPagePtr = tmpRecPtr - targetRecOff;
867879

868-
header = (XLogPageHeader) state->readBuf;
880+
/* Read the page containing the record */
881+
readLen = ReadPageInternal(state, targetPagePtr, targetRecOff);
882+
if (readLen < 0)
883+
goto err;
869884

870-
pageHeaderSize = XLogPageHeaderSize(header);
885+
header = (XLogPageHeader) state->readBuf;
871886

872-
/* make sure we have enough data for the page header */
873-
readLen = ReadPageInternal(state, targetPagePtr, pageHeaderSize);
874-
if (readLen < 0)
875-
goto err;
887+
pageHeaderSize = XLogPageHeaderSize(header);
876888

877-
/* skip over potential continuation data */
878-
if (header->xlp_info & XLP_FIRST_IS_CONTRECORD)
879-
{
880-
/* record headers are MAXALIGN'ed */
881-
tmpRecPtr = targetPagePtr + pageHeaderSize
882-
+ MAXALIGN(header->xlp_rem_len);
883-
}
884-
else
885-
{
886-
tmpRecPtr = targetPagePtr + pageHeaderSize;
889+
/* make sure we have enough data for the page header */
890+
readLen = ReadPageInternal(state, targetPagePtr, pageHeaderSize);
891+
if (readLen < 0)
892+
goto err;
893+
894+
/* skip over potential continuation data */
895+
if (header->xlp_info & XLP_FIRST_IS_CONTRECORD)
896+
{
897+
/*
898+
* If the length of the remaining continuation data is more than
899+
* what can fit in this page, the continuation record crosses over
900+
* this page. Read the next page and try again. xlp_rem_len in the
901+
* next page header will contain the remaining length of the
902+
* continuation data
903+
*
904+
* Note that record headers are MAXALIGN'ed
905+
*/
906+
if (MAXALIGN(header->xlp_rem_len) > (XLOG_BLCKSZ - pageHeaderSize))
907+
tmpRecPtr = targetPagePtr + XLOG_BLCKSZ;
908+
else
909+
{
910+
/*
911+
* The previous continuation record ends in this page. Set
912+
* tmpRecPtr to point to the first valid record
913+
*/
914+
tmpRecPtr = targetPagePtr + pageHeaderSize
915+
+ MAXALIGN(header->xlp_rem_len);
916+
break;
917+
}
918+
}
919+
else
920+
{
921+
tmpRecPtr = targetPagePtr + pageHeaderSize;
922+
break;
923+
}
887924
}
888925

889926
/*

src/backend/executor/nodeAgg.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,11 +2666,13 @@ ExecReScanAgg(AggState *node)
26662666
return;
26672667

26682668
/*
2669-
* If we do have the hash table and the subplan does not have any
2670-
* parameter changes, then we can just rescan the existing hash table;
2671-
* no need to build it again.
2669+
* If we do have the hash table, and the subplan does not have any
2670+
* parameter changes, and none of our own parameter changes affect
2671+
* input expressions of the aggregated functions, then we can just
2672+
* rescan the existing hash table; no need to build it again.
26722673
*/
2673-
if (outerPlan->chgParam == NULL)
2674+
if (outerPlan->chgParam == NULL &&
2675+
!bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
26742676
{
26752677
ResetTupleHashIterator(node->hashtable, &node->hashiter);
26762678
return;

src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ _copyAgg(const Agg *from)
847847
COPY_POINTER_FIELD(grpOperators, from->numCols * sizeof(Oid));
848848
}
849849
COPY_SCALAR_FIELD(numGroups);
850+
COPY_BITMAPSET_FIELD(aggParams);
850851
COPY_NODE_FIELD(groupingSets);
851852
COPY_NODE_FIELD(chain);
852853

src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ _outAgg(StringInfo str, const Agg *node)
684684
appendStringInfo(str, " %u", node->grpOperators[i]);
685685

686686
WRITE_LONG_FIELD(numGroups);
687-
687+
WRITE_BITMAPSET_FIELD(aggParams);
688688
WRITE_NODE_FIELD(groupingSets);
689689
WRITE_NODE_FIELD(chain);
690690
}

src/backend/optimizer/plan/createplan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4535,6 +4535,7 @@ make_agg(PlannerInfo *root, List *tlist, List *qual,
45354535
node->grpColIdx = grpColIdx;
45364536
node->grpOperators = grpOperators;
45374537
node->numGroups = numGroups;
4538+
node->aggParams = NULL; /* SS_finalize_plan() will fill this */
45384539

45394540
copy_plan_costsize(plan, lefttree); /* only care about copying size */
45404541
cost_agg(&agg_path, root,

src/backend/optimizer/plan/subselect.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static Bitmapset *finalize_plan(PlannerInfo *root,
8181
Bitmapset *valid_params,
8282
Bitmapset *scan_params);
8383
static bool finalize_primnode(Node *node, finalize_primnode_context *context);
84+
static bool finalize_agg_primnode(Node *node, finalize_primnode_context *context);
8485

8586

8687
/*
@@ -2558,6 +2559,29 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
25582559
locally_added_param);
25592560
break;
25602561

2562+
case T_Agg:
2563+
{
2564+
Agg *agg = (Agg *) plan;
2565+
2566+
/*
2567+
* AGG_HASHED plans need to know which Params are referenced
2568+
* in aggregate calls. Do a separate scan to identify them.
2569+
*/
2570+
if (agg->aggstrategy == AGG_HASHED)
2571+
{
2572+
finalize_primnode_context aggcontext;
2573+
2574+
aggcontext.root = root;
2575+
aggcontext.paramids = NULL;
2576+
finalize_agg_primnode((Node *) agg->plan.targetlist,
2577+
&aggcontext);
2578+
finalize_agg_primnode((Node *) agg->plan.qual,
2579+
&aggcontext);
2580+
agg->aggParams = aggcontext.paramids;
2581+
}
2582+
}
2583+
break;
2584+
25612585
case T_WindowAgg:
25622586
finalize_primnode(((WindowAgg *) plan)->startOffset,
25632587
&context);
@@ -2566,7 +2590,6 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
25662590
break;
25672591

25682592
case T_Hash:
2569-
case T_Agg:
25702593
case T_Material:
25712594
case T_Sort:
25722595
case T_Unique:
@@ -2710,6 +2733,29 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
27102733
(void *) context);
27112734
}
27122735

2736+
/*
2737+
* finalize_agg_primnode: find all Aggref nodes in the given expression tree,
2738+
* and add IDs of all PARAM_EXEC params appearing within their aggregated
2739+
* arguments to the result set.
2740+
*/
2741+
static bool
2742+
finalize_agg_primnode(Node *node, finalize_primnode_context *context)
2743+
{
2744+
if (node == NULL)
2745+
return false;
2746+
if (IsA(node, Aggref))
2747+
{
2748+
Aggref *agg = (Aggref *) node;
2749+
2750+
/* we should not consider the direct arguments, if any */
2751+
finalize_primnode((Node *) agg->args, context);
2752+
finalize_primnode((Node *) agg->aggfilter, context);
2753+
return false; /* there can't be any Aggrefs below here */
2754+
}
2755+
return expression_tree_walker(node, finalize_agg_primnode,
2756+
(void *) context);
2757+
}
2758+
27132759
/*
27142760
* SS_make_initplan_from_plan - given a plan tree, make it an InitPlan
27152761
*

src/backend/utils/error/elog.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,7 +1585,10 @@ FlushErrorState(void)
15851585
/*
15861586
* ThrowErrorData --- report an error described by an ErrorData structure
15871587
*
1588-
* This is intended to be used to re-report errors originally thrown by
1588+
* This is somewhat like ReThrowError, but it allows elevels besides ERROR,
1589+
* and the boolean flags such as output_to_server are computed via the
1590+
* default rules rather than being copied from the given ErrorData.
1591+
* This is primarily used to re-report errors originally reported by
15891592
* background worker processes and then propagated (with or without
15901593
* modification) to the backend responsible for them.
15911594
*/
@@ -1597,13 +1600,14 @@ ThrowErrorData(ErrorData *edata)
15971600

15981601
if (!errstart(edata->elevel, edata->filename, edata->lineno,
15991602
edata->funcname, NULL))
1600-
return;
1603+
return; /* error is not to be reported at all */
16011604

16021605
newedata = &errordata[errordata_stack_depth];
1603-
oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1606+
recursion_depth++;
1607+
oldcontext = MemoryContextSwitchTo(newedata->assoc_context);
16041608

1605-
/* Copy the supplied fields to the error stack. */
1606-
if (edata->sqlerrcode > 0)
1609+
/* Copy the supplied fields to the error stack entry. */
1610+
if (edata->sqlerrcode != 0)
16071611
newedata->sqlerrcode = edata->sqlerrcode;
16081612
if (edata->message)
16091613
newedata->message = pstrdup(edata->message);
@@ -1615,6 +1619,7 @@ ThrowErrorData(ErrorData *edata)
16151619
newedata->hint = pstrdup(edata->hint);
16161620
if (edata->context)
16171621
newedata->context = pstrdup(edata->context);
1622+
/* assume message_id is not available */
16181623
if (edata->schema_name)
16191624
newedata->schema_name = pstrdup(edata->schema_name);
16201625
if (edata->table_name)
@@ -1625,11 +1630,15 @@ ThrowErrorData(ErrorData *edata)
16251630
newedata->datatype_name = pstrdup(edata->datatype_name);
16261631
if (edata->constraint_name)
16271632
newedata->constraint_name = pstrdup(edata->constraint_name);
1633+
newedata->cursorpos = edata->cursorpos;
1634+
newedata->internalpos = edata->internalpos;
16281635
if (edata->internalquery)
16291636
newedata->internalquery = pstrdup(edata->internalquery);
16301637

16311638
MemoryContextSwitchTo(oldcontext);
1639+
recursion_depth--;
16321640

1641+
/* Process the error. */
16331642
errfinish(0);
16341643
}
16351644

src/include/nodes/plannodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,8 @@ typedef struct Agg
721721
AttrNumber *grpColIdx; /* their indexes in the target list */
722722
Oid *grpOperators; /* equality operators to compare with */
723723
long numGroups; /* estimated number of groups in input */
724+
Bitmapset *aggParams; /* IDs of Params used in Aggref inputs */
725+
/* Note: planner provides numGroups & aggParams only in AGG_HASHED case */
724726
List *groupingSets; /* grouping sets to use */
725727
List *chain; /* chained Agg/Sort nodes */
726728
} Agg;

0 commit comments

Comments
 (0)