($INBOX_DIR/description missing)help / color / mirror / Atom feed
[PATCH 5/7] fix 71+ messages / 5 participants [nested] [flat]
* [PATCH 5/7] fix @ 2020-03-19 01:54 Tomas Vondra <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Tomas Vondra @ 2020-03-19 01:54 UTC (permalink / raw) --- .../postgres_fdw/expected/postgres_fdw.out | 4 ++-- src/backend/executor/execExpr.c | 5 +++-- src/backend/executor/nodeAgg.c | 20 +++++++++---------- src/backend/optimizer/util/pathnode.c | 4 ++-- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 62c2697920..fc0ed2f4d5 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -3448,8 +3448,8 @@ select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls la Sort Key: ft1.c2 -> MixedAggregate Output: c2, sum(c1) - Hash Key: ft1.c2 Group Key: () + Hash Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c2, c1 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3)) @@ -3473,8 +3473,8 @@ select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last Sort Key: ft1.c2 -> MixedAggregate Output: c2, sum(c1) - Hash Key: ft1.c2 Group Key: () + Hash Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c2, c1 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3)) diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index 07789501f7..669843faf5 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -2937,7 +2937,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool nullcheck) PlanState *parent = &aggstate->ss.ps; ExprEvalStep scratch = {0}; bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit); - ListCell *lc; + ListCell *lc; LastAttnumInfo deform = {0, 0, 0}; state->expr = (Expr *) aggstate; @@ -2978,6 +2978,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool nullcheck) NullableDatum *strictargs = NULL; bool *strictnulls = NULL; int argno; + int setno; ListCell *bail; /* @@ -3155,7 +3156,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool nullcheck) * grouping set). Do so for both sort and hash based computations, as * applicable. */ - for (int setno = 0; setno < phase->numsets; setno++) + for (setno = 0; setno < phase->numsets; setno++) { ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo, pertrans, transno, setno, phase, nullcheck); diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 20c5eb98b3..38d0bd5895 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -333,7 +333,7 @@ initialize_phase(AggState *aggstate, int newphase) AggStatePerPhaseSort persort; Assert(newphase == 0 || newphase == aggstate->current_phase + 1); - + /* Don't use aggstate->phase here, it might not be initialized yet*/ current_phase = aggstate->phases[aggstate->current_phase]; @@ -1516,7 +1516,7 @@ hash_agg_entry_size(int numAggs, Size tupleWidth, Size transitionSpace) * When called, CurrentMemoryContext should be the per-query context. The * already-calculated hash value for the tuple must be specified. */ -static void +static void lookup_hash_entry(AggState *aggstate, AggStatePerPhaseHash perhash, uint32 hash) { TupleTableSlot *hashslot = perhash->hashslot; @@ -1724,7 +1724,7 @@ agg_retrieve_direct(AggState *aggstate) numGroupingSets = aggstate->phase->numsets; node = aggstate->phase->aggnode; numReset = numGroupingSets; - pergroups = aggstate->phase->pergroups; + pergroups = aggstate->phase->pergroups; } else { @@ -2123,7 +2123,7 @@ agg_retrieve_hash_table(AggState *aggstate) */ select_current_set(aggstate, 0, true); initialize_phase(aggstate, aggstate->current_phase + 1); - perhash = (AggStatePerPhaseHash) aggstate->phase; + perhash = (AggStatePerPhaseHash) aggstate->phase; ResetTupleHashIterator(perhash->hashtable, &perhash->hashiter); continue; @@ -2269,7 +2269,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) aggstate->maxsets = numGroupingSets; aggstate->numphases = 1 + list_length(node->chain); - + /* * The first phase is not sorted, agg need to do its own sort. See * agg_sort_input(), this can only happen in groupingsets case. @@ -2390,7 +2390,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) numaggs = aggstate->numaggs; Assert(numaggs == list_length(aggstate->aggs)); - /* + /* * For each phase, prepare grouping set data and fmgr lookup data for * compare functions. Accumulate all_grouped_cols in passing. */ @@ -2430,7 +2430,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) all_grouped_cols = bms_add_members(all_grouped_cols, cols); - /* + /* * Initialize pergroup state. For AGG_HASHED, all groups do transition * on the fly, all pergroup states are kept in hashtable, everytime * a tuple is processed, lookup_hash_entry() choose one group and @@ -2499,7 +2499,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) phasedata->grouped_cols = NULL; } - /* + /* * Initialize pergroup states for AGG_SORTED/AGG_PLAIN/AGG_MIXED * phases, each set only have one group on the fly, all groups in * a set can reuse a pergroup state. Unlike AGG_HASHED, we @@ -3610,8 +3610,8 @@ ExecReScanAgg(AggState *node) sizeof(AggStatePerGroupData) * node->numaggs); } - /* - * the agg did its own first sort using tuplesort and the first + /* + * The agg did its own first sort using tuplesort and the first * tuplesort is kept (see initialize_phase), if the subplan does * not have any parameter changes, and none of our own parameter * changes affect input expressions of the aggregated functions, diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 2dfa3fa17e..ff8f676dfb 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -2983,7 +2983,7 @@ create_agg_path(PlannerInfo *root, * 'rollups' is a list of RollupData nodes * 'agg_costs' contains cost info about the aggregate functions to be computed * 'numGroups' is the estimated total number of groups - * 'is_sorted' is the input sorted in the group cols of first rollup + * 'is_sorted' is the input sorted in the group cols of first rollup */ GroupingSetsPath * create_groupingsets_path(PlannerInfo *root, @@ -3098,7 +3098,7 @@ create_groupingsets_path(PlannerInfo *root, AggStrategy rollup_strategy; Path sort_path; /* dummy for result of cost_sort */ Path agg_path; /* dummy for result of cost_agg */ - + sort_path.startup_cost = 0; sort_path.total_cost = 0; sort_path.rows = subpath->rows; -- 2.21.1 --4ms6w442s2ji2wqe Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: attachment; filename="0006-Parallel-grouping-sets.patch" Content-Transfer-Encoding: 8bit ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 7/7] fix @ 2020-03-19 02:02 Tomas Vondra <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Tomas Vondra @ 2020-03-19 02:02 UTC (permalink / raw) --- src/backend/executor/nodeAgg.c | 20 ++++++++++---------- src/backend/jit/llvm/llvmjit_expr.c | 2 +- src/backend/optimizer/plan/planner.c | 12 ++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index f7b98dd798..51c7f229e2 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -360,7 +360,7 @@ initialize_phase(AggState *aggstate, int newphase) if (persort->store_in) { tuplestore_end(persort->store_in); - persort->store_in = NULL; + persort->store_in = NULL; } } @@ -2017,7 +2017,7 @@ agg_preprocess_groupingsets(AggState *aggstate) /* Initialize tuples storage for each aggregate phases */ for (phaseidx = 0; phaseidx < aggstate->numphases; phaseidx++) { - phase = aggstate->phases[phaseidx]; + phase = aggstate->phases[phaseidx]; if (!phase->is_hashed) { @@ -2039,12 +2039,12 @@ agg_preprocess_groupingsets(AggState *aggstate) } else { - persort->store_in = tuplestore_begin_heap(false, false, work_mem); + persort->store_in = tuplestore_begin_heap(false, false, work_mem); } } else { - /* + /* * If it's a AGG_HASHED, we don't need a storage to store * the tuples for later process, we can do the transition * immediately. @@ -2422,7 +2422,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) aggstate->maxsets = numGroupingSets; aggstate->numphases = 1 + list_length(node->chain); - /* + /* * We are doing final stage of partial groupingsets, do preprocess * to input tuples first, redirect the tuples to according aggregate * phases. See agg_preprocess_groupingsets(). @@ -2431,7 +2431,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) { aggstate->groupingsets_preprocess = true; - /* + /* * Allocate gsetid <-> phases mapping, in final stage of * partial groupingsets, all grouping sets are extracted * to individual phases, so the number of sets is equal @@ -2449,7 +2449,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) * agg_sort_input(), this can only happen in groupingsets case. */ if (node->sortnode) - aggstate->input_sorted = false; + aggstate->input_sorted = false; aggstate->aggcontexts = (ExprContext **) palloc0(sizeof(ExprContext *) * numGroupingSets); @@ -2626,7 +2626,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) phasedata->setno_gsetids[0] = gs->setId; } - /* + /* * Initialize pergroup state. For AGG_HASHED, all groups do transition * on the fly, all pergroup states are kept in hashtable, everytime * a tuple is processed, lookup_hash_entry() choose one group and @@ -2688,7 +2688,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) phasedata->grouped_cols[i] = cols; phasedata->gset_lengths[i] = current_length; - /* + /* * In the initial stage of partial grouping sets, it provides extra * grouping sets ID in the targetlist, fill the setno <-> gsetid * map, so EEOP_GROUPING_SET_ID can evaluate correct gsetid for @@ -3871,7 +3871,7 @@ ExecReScanAgg(AggState *node) } } - /* + /* * if the agg is doing final stage of partial groupingsets, reset the * flag to do groupingsets preprocess again. */ diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index f442442269..f70eaabd0c 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -1893,7 +1893,7 @@ llvm_compile_expr(ExprState *state) v_aggstatep = LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), ""); - /* + /* * op->resvalue = * aggstate->phase->setno_gsetids * [aggstate->current_set] diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index cedd3e1c9d..a0186091a1 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -4211,7 +4211,7 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, * added to grouped_rel->pathlist. And aggsplit value is not sufficient to * make a decision. */ -static void +static void consider_groupingsets_paths(PlannerInfo *root, RelOptInfo *grouped_rel, Path *path, @@ -4601,7 +4601,7 @@ consider_groupingsets_paths(PlannerInfo *root, } } -/* +/* * If we are combining the partial groupingsets aggregation, the input is * mixed with tuples from different grouping sets, executor dispatch the * tuples to different rollups (phases) according to the grouping set id. @@ -4644,7 +4644,7 @@ extract_final_rollups(PlannerInfo *root, { new_rollup->groupClause = NIL; new_rollup->gsets_data = list_make1(gs); - new_rollup->gsets = list_make1(NIL); + new_rollup->gsets = list_make1(NIL); new_rollup->hashable = false; new_rollup->is_hashed = false; } @@ -5364,7 +5364,7 @@ make_partial_grouping_target(PlannerInfo *root, add_new_columns_to_pathtarget(partial_target, non_group_exprs); - /* + /* * We are generate partial groupingsets path, add an expression to show * the grouping set ID for a tuple, so in the final stage, executor can * know which set this tuple belongs to and combine them. @@ -6985,7 +6985,7 @@ create_partial_grouping_paths(PlannerInfo *root, path, root->group_pathkeys, -1.0); - + if (parse->hasAggs) add_partial_path(partially_grouped_rel, (Path *) create_agg_path(root, @@ -7059,7 +7059,7 @@ create_partial_grouping_paths(PlannerInfo *root, AGGSPLIT_INITIAL_SERIAL, add_partial_path); } - else + else { hashaggtablesize = estimate_hashagg_tablesize(cheapest_partial_path, -- 2.21.1 --4ms6w442s2ji2wqe-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2020-06-15 10:28 Your Name <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Your Name @ 2020-06-15 10:28 UTC (permalink / raw) --- src/bin/pg_dump/t/002_pg_dump.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 8c89488a12..d28988b870 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -154,6 +154,8 @@ my %pgdump_runs = ( test_key => 'defaults', dump_cmd => [ [ 'pg_dump', '-Fc', '-Z6', '--no-sync', 'postgres', ], + '|', + [ 'perl', '-pe', '', ], '>', "$tempdir/defaults_custom_format_no_seek_parallel_restore.dump", # stdout disables seeking ], restore_cmd => [ -- 2.24.2 --K3vkeaB0MlFjg8U+-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/2] fix @ 2020-08-01 02:24 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-08-01 02:24 UTC (permalink / raw) --- src/backend/access/heap/vacuumlazy.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 78d1db9ae2..b6015c9297 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1860,7 +1860,6 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); vacrelstats->blkno = tblk; - vacrelstats->offnum = ItemPointerGetOffsetNumber(&vacrelstats->dead_tuples->itemptrs[tupindex]); buf = ReadBufferExtended(onerel, MAIN_FORKNUM, tblk, RBM_NORMAL, vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) @@ -1937,7 +1936,6 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, if (tblk != blkno) break; /* past end of tuples for this block */ toff = ItemPointerGetOffsetNumber(&dead_tuples->itemptrs[tupindex]); - vacrelstats->offnum = toff; itemid = PageGetItemId(page, toff); ItemIdSetUnused(itemid); unused[uncnt++] = toff; @@ -2022,6 +2020,7 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) OffsetNumber offnum, maxoff; HeapTupleHeader tupleheader; + LVSavedErrInfo saved_err_info; *hastup = false; @@ -2034,6 +2033,11 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (PageIsNew(page) || PageIsEmpty(page)) return false; + /* Update error traceback information */ + update_vacuum_error_info(vacrelstats, &saved_err_info, + VACUUM_ERRCB_PHASE_SCAN_HEAP, vacrelstats->blkno, + InvalidOffsetNumber); + maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; @@ -2056,10 +2060,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelStats *vacrelstats) if (heap_tuple_needs_freeze(tupleheader, FreezeLimit, MultiXactCutoff, buf)) - return true; + break; } /* scan along page */ - return false; + /* Revert to the previous phase information for error traceback */ + restore_vacuum_error_info(vacrelstats, &saved_err_info); + + return offnum <= maxoff ? true : false; } /* @@ -2501,7 +2508,7 @@ lazy_cleanup_index(Relation indrel, *stats = index_vacuum_cleanup(&ivinfo, *stats); - /* Revert back to the old phase information for error traceback */ + /* Revert to the old phase information for error traceback */ restore_vacuum_error_info(vacrelstats, &saved_err_info); pfree(vacrelstats->indname); vacrelstats->indname = NULL; @@ -3590,8 +3597,8 @@ vacuum_error_callback(void *arg) if (BlockNumberIsValid(errinfo->blkno)) { if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while scanning block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); + errcontext("while scanning block %u of relation \"%s.%s\", item offset %u", + errinfo->blkno, errinfo->relnamespace, errinfo->relname, errinfo->offnum); else errcontext("while scanning block %u of relation \"%s.%s\"", errinfo->blkno, errinfo->relnamespace, errinfo->relname); @@ -3601,12 +3608,8 @@ vacuum_error_callback(void *arg) case VACUUM_ERRCB_PHASE_VACUUM_HEAP: if (BlockNumberIsValid(errinfo->blkno)) { - if (OffsetNumberIsValid(errinfo->offnum)) - errcontext("while vacuuming block %u and offset %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->offnum, errinfo->relnamespace, errinfo->relname); - else - errcontext("while vacuuming block %u of relation \"%s.%s\"", - errinfo->blkno, errinfo->relnamespace, errinfo->relname); + errcontext("while vacuuming block %u of relation \"%s.%s\"", + errinfo->blkno, errinfo->relnamespace, errinfo->relname); } break; -- 2.17.0 --OQhbRXNHSL5w/5po-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH v34 2/8] fix @ 2020-12-12 17:42 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2020-12-12 17:42 UTC (permalink / raw) --- src/backend/catalog/index.c | 23 ++++++----- src/backend/commands/cluster.c | 3 +- src/backend/commands/indexcmds.c | 68 ++++++++++++++++---------------- src/backend/commands/tablecmds.c | 4 +- src/backend/tcop/utility.c | 6 +-- src/include/catalog/index.h | 4 +- src/include/commands/defrem.h | 6 +-- 7 files changed, 58 insertions(+), 56 deletions(-) diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 06342fddf1..da2f45b796 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3594,7 +3594,7 @@ IndexGetRelation(Oid indexId, bool missing_ok) */ void reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, - ReindexOptions options) + ReindexOptions *options) { Relation iRel, heapRelation; @@ -3602,7 +3602,6 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, IndexInfo *indexInfo; volatile bool skipped_constraint = false; PGRUsage ru0; - bool progress = options.REINDEXOPT_REPORT_PROGRESS; pg_rusage_init(&ru0); @@ -3611,12 +3610,12 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, * we only need to be sure no schema or data changes are going on. */ heapId = IndexGetRelation(indexId, - options.REINDEXOPT_MISSING_OK); + options->REINDEXOPT_MISSING_OK); /* if relation is missing, leave */ if (!OidIsValid(heapId)) return; - if (options.REINDEXOPT_MISSING_OK) + if (options->REINDEXOPT_MISSING_OK) heapRelation = try_table_open(heapId, ShareLock); else heapRelation = table_open(heapId, ShareLock); @@ -3625,7 +3624,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, if (!heapRelation) return; - if (progress) + if (options->REINDEXOPT_REPORT_PROGRESS) { pgstat_progress_start_command(PROGRESS_COMMAND_CREATE_INDEX, heapId); @@ -3641,7 +3640,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, */ iRel = index_open(indexId, AccessExclusiveLock); - if (progress) + if (options->REINDEXOPT_REPORT_PROGRESS) pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID, iRel->rd_rel->relam); @@ -3792,14 +3791,14 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, } /* Log what we did */ - if (options.REINDEXOPT_VERBOSE) + if (options->REINDEXOPT_VERBOSE) ereport(INFO, (errmsg("index \"%s\" was reindexed", get_rel_name(indexId)), errdetail_internal("%s", pg_rusage_show(&ru0)))); - if (progress) + if (options->REINDEXOPT_REPORT_PROGRESS) pgstat_progress_end_command(); /* Close rels, but keep locks */ @@ -3846,7 +3845,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, * index rebuild. */ bool -reindex_relation(Oid relid, int flags, ReindexOptions options) +reindex_relation(Oid relid, int flags, ReindexOptions *options) { Relation rel; Oid toast_relid; @@ -3861,7 +3860,7 @@ reindex_relation(Oid relid, int flags, ReindexOptions options) * to prevent schema and data changes in it. The lock level used here * should match ReindexTable(). */ - if (options.REINDEXOPT_MISSING_OK) + if (options->REINDEXOPT_MISSING_OK) rel = try_table_open(relid, ShareLock); else rel = table_open(relid, ShareLock); @@ -3965,9 +3964,9 @@ reindex_relation(Oid relid, int flags, ReindexOptions options) * Note that this should fail if the toast relation is missing, so * reset REINDEXOPT_MISSING_OK. */ - ReindexOptions newoptions = options; + ReindexOptions newoptions = *options; newoptions.REINDEXOPT_MISSING_OK = false; - result |= reindex_relation(toast_relid, flags, newoptions); + result |= reindex_relation(toast_relid, flags, &newoptions); } return result; diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index b0aa3536d1..272723e050 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -1353,6 +1353,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, char newrelpersistence) { ObjectAddress object; + ReindexOptions reindexopts = {false}; Oid mapped_tables[4]; int reindex_flags; int i; @@ -1412,7 +1413,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, PROGRESS_CLUSTER_PHASE_REBUILD_INDEX); - reindex_relation(OIDOldHeap, reindex_flags, (ReindexOptions){}); + reindex_relation(OIDOldHeap, reindex_flags, &reindexopts); /* Report that we are now doing clean up */ pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index cd8eaa732d..d39840d493 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -89,9 +89,9 @@ static List *ChooseIndexColumnNames(List *indexElems); static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); static void reindex_error_callback(void *args); -static void ReindexPartitions(Oid relid, ReindexOptions options, bool isTopLevel); -static void ReindexMultipleInternal(List *relids, ReindexOptions options); -static bool ReindexRelationConcurrently(Oid relationOid, ReindexOptions options); +static void ReindexPartitions(Oid relid, ReindexOptions *options, bool isTopLevel); +static void ReindexMultipleInternal(List *relids, ReindexOptions *options); +static bool ReindexRelationConcurrently(Oid relationOid, ReindexOptions *options); static void update_relispartition(Oid relationId, bool newval); static inline void set_indexsafe_procflags(void); @@ -2459,7 +2459,7 @@ ReindexOptions ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt) { ListCell *lc; - ReindexOptions options = {}; + ReindexOptions options = {0}; /* Parse option list */ foreach(lc, stmt->params) @@ -2486,7 +2486,7 @@ ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt) * Recreate a specific index. */ void -ReindexIndex(RangeVar *indexRelation, ReindexOptions options, bool isTopLevel) +ReindexIndex(RangeVar *indexRelation, ReindexOptions *options, bool isTopLevel) { struct ReindexIndexCallbackState state; Oid indOid; @@ -2503,10 +2503,10 @@ ReindexIndex(RangeVar *indexRelation, ReindexOptions options, bool isTopLevel) * upgrade the lock, but that's OK, because other sessions can't hold * locks on our temporary table. */ - state.options = options; + state.options = *options; state.locked_table_oid = InvalidOid; indOid = RangeVarGetRelidExtended(indexRelation, - options.REINDEXOPT_CONCURRENTLY ? + options->REINDEXOPT_CONCURRENTLY ? ShareUpdateExclusiveLock : AccessExclusiveLock, 0, RangeVarCallbackForReindexIndex, @@ -2521,14 +2521,14 @@ ReindexIndex(RangeVar *indexRelation, ReindexOptions options, bool isTopLevel) if (relkind == RELKIND_PARTITIONED_INDEX) ReindexPartitions(indOid, options, isTopLevel); - else if (options.REINDEXOPT_CONCURRENTLY && + else if (options->REINDEXOPT_CONCURRENTLY && persistence != RELPERSISTENCE_TEMP) ReindexRelationConcurrently(indOid, options); else { - ReindexOptions newoptions = options; + ReindexOptions newoptions = *options; newoptions.REINDEXOPT_REPORT_PROGRESS = true; - reindex_index(indOid, false, persistence, newoptions); + reindex_index(indOid, false, persistence, &newoptions); } } @@ -2608,7 +2608,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, * Recreate all indexes of a table (and of its toast table, if any) */ Oid -ReindexTable(RangeVar *relation, ReindexOptions options, bool isTopLevel) +ReindexTable(RangeVar *relation, ReindexOptions *options, bool isTopLevel) { Oid heapOid; bool result; @@ -2622,14 +2622,14 @@ ReindexTable(RangeVar *relation, ReindexOptions options, bool isTopLevel) * locks on our temporary table. */ heapOid = RangeVarGetRelidExtended(relation, - options.REINDEXOPT_CONCURRENTLY ? + options->REINDEXOPT_CONCURRENTLY ? ShareUpdateExclusiveLock : ShareLock, 0, RangeVarCallbackOwnsTable, NULL); if (get_rel_relkind(heapOid) == RELKIND_PARTITIONED_TABLE) ReindexPartitions(heapOid, options, isTopLevel); - else if (options.REINDEXOPT_CONCURRENTLY && + else if (options->REINDEXOPT_CONCURRENTLY && get_rel_persistence(heapOid) != RELPERSISTENCE_TEMP) { result = ReindexRelationConcurrently(heapOid, options); @@ -2641,12 +2641,12 @@ ReindexTable(RangeVar *relation, ReindexOptions options, bool isTopLevel) } else { - ReindexOptions newoptions = options; + ReindexOptions newoptions = *options; newoptions.REINDEXOPT_REPORT_PROGRESS = true; result = reindex_relation(heapOid, REINDEX_REL_PROCESS_TOAST | REINDEX_REL_CHECK_CONSTRAINTS, - newoptions); + &newoptions); if (!result) ereport(NOTICE, (errmsg("table \"%s\" has no indexes to reindex", @@ -2666,7 +2666,7 @@ ReindexTable(RangeVar *relation, ReindexOptions options, bool isTopLevel) */ void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, - ReindexOptions options) + ReindexOptions *options) { Oid objectOid; Relation relationRelation; @@ -2685,7 +2685,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, objectKind == REINDEX_OBJECT_DATABASE); if (objectKind == REINDEX_OBJECT_SYSTEM && - options.REINDEXOPT_CONCURRENTLY) + options->REINDEXOPT_CONCURRENTLY) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot reindex system catalogs concurrently"))); @@ -2793,7 +2793,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, * Skip system tables, since index_create() would reject indexing them * concurrently (and it would likely fail if we tried). */ - if (options.REINDEXOPT_CONCURRENTLY && + if (options->REINDEXOPT_CONCURRENTLY && IsCatalogRelationOid(relid)) { if (!concurrent_warning) @@ -2859,7 +2859,7 @@ reindex_error_callback(void *arg) * by the caller. */ static void -ReindexPartitions(Oid relid, ReindexOptions options, bool isTopLevel) +ReindexPartitions(Oid relid, ReindexOptions *options, bool isTopLevel) { List *partitions = NIL; char relkind = get_rel_relkind(relid); @@ -2954,7 +2954,7 @@ ReindexPartitions(Oid relid, ReindexOptions options, bool isTopLevel) * and starts a new transaction when finished. */ static void -ReindexMultipleInternal(List *relids, ReindexOptions options) +ReindexMultipleInternal(List *relids, ReindexOptions *options) { ListCell *l; @@ -2990,36 +2990,36 @@ ReindexMultipleInternal(List *relids, ReindexOptions options) Assert(relkind != RELKIND_PARTITIONED_INDEX && relkind != RELKIND_PARTITIONED_TABLE); - if (options.REINDEXOPT_CONCURRENTLY && + if (options->REINDEXOPT_CONCURRENTLY && relpersistence != RELPERSISTENCE_TEMP) { - ReindexOptions newoptions = options; + ReindexOptions newoptions = *options; newoptions.REINDEXOPT_MISSING_OK = true; - (void) ReindexRelationConcurrently(relid, newoptions); + (void) ReindexRelationConcurrently(relid, &newoptions); /* ReindexRelationConcurrently() does the verbose output */ } else if (relkind == RELKIND_INDEX) { - ReindexOptions newoptions = options; + ReindexOptions newoptions = *options; newoptions.REINDEXOPT_REPORT_PROGRESS = true; newoptions.REINDEXOPT_MISSING_OK = true; - reindex_index(relid, false, relpersistence, newoptions); + reindex_index(relid, false, relpersistence, &newoptions); PopActiveSnapshot(); /* reindex_index() does the verbose output */ } else { bool result; - ReindexOptions newoptions = options; + ReindexOptions newoptions = *options; newoptions.REINDEXOPT_REPORT_PROGRESS = true; newoptions.REINDEXOPT_MISSING_OK = true; result = reindex_relation(relid, REINDEX_REL_PROCESS_TOAST | REINDEX_REL_CHECK_CONSTRAINTS, - newoptions); + &newoptions); - if (result && options.REINDEXOPT_VERBOSE) + if (result && options->REINDEXOPT_VERBOSE) ereport(INFO, (errmsg("table \"%s.%s\" was reindexed", get_namespace_name(get_rel_namespace(relid)), @@ -3059,7 +3059,7 @@ ReindexMultipleInternal(List *relids, ReindexOptions options) * anyway, and a non-concurrent reindex is more efficient. */ static bool -ReindexRelationConcurrently(Oid relationOid, ReindexOptions options) +ReindexRelationConcurrently(Oid relationOid, ReindexOptions *options) { List *heapRelationIds = NIL; List *indexIds = NIL; @@ -3092,7 +3092,7 @@ ReindexRelationConcurrently(Oid relationOid, ReindexOptions options) "ReindexConcurrent", ALLOCSET_SMALL_SIZES); - if (options.REINDEXOPT_VERBOSE) + if (options->REINDEXOPT_VERBOSE) { /* Save data needed by REINDEX VERBOSE in private context */ oldcontext = MemoryContextSwitchTo(private_context); @@ -3137,7 +3137,7 @@ ReindexRelationConcurrently(Oid relationOid, ReindexOptions options) errmsg("cannot reindex system catalogs concurrently"))); /* Open relation to get its indexes */ - if (options.REINDEXOPT_MISSING_OK) + if (options->REINDEXOPT_MISSING_OK) { heapRelation = try_table_open(relationOid, ShareUpdateExclusiveLock); @@ -3233,7 +3233,7 @@ ReindexRelationConcurrently(Oid relationOid, ReindexOptions options) case RELKIND_INDEX: { Oid heapId = IndexGetRelation(relationOid, - options.REINDEXOPT_MISSING_OK); + options->REINDEXOPT_MISSING_OK); Relation heapRelation; /* if relation is missing, leave */ @@ -3262,7 +3262,7 @@ ReindexRelationConcurrently(Oid relationOid, ReindexOptions options) * to rebuild is not complete yet, and REINDEXOPT_MISSING_OK * should not be used once all the session locks are taken. */ - if (options.REINDEXOPT_MISSING_OK) + if (options->REINDEXOPT_MISSING_OK) { heapRelation = try_table_open(heapId, ShareUpdateExclusiveLock); @@ -3754,7 +3754,7 @@ ReindexRelationConcurrently(Oid relationOid, ReindexOptions options) StartTransactionCommand(); /* Log what we did */ - if (options.REINDEXOPT_VERBOSE) + if (options->REINDEXOPT_VERBOSE) { if (relkind == RELKIND_INDEX) ereport(INFO, diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 9f218ac0e4..e0f62d3c77 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1854,6 +1854,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, { Oid heap_relid; Oid toast_relid; + ReindexOptions reindexopts = {false}; /* Default options are all false */ /* * This effectively deletes all rows in the table, and may be done @@ -1891,7 +1892,8 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, /* * Reconstruct the indexes to match, and we're done. */ - reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, (ReindexOptions){}); + reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, + &reindexopts); } pgstat_count_truncate(rel); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index e5a4e8f662..23612b7a90 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -929,10 +929,10 @@ standard_ProcessUtility(PlannedStmt *pstmt, switch (stmt->kind) { case REINDEX_OBJECT_INDEX: - ReindexIndex(stmt->relation, options, isTopLevel); + ReindexIndex(stmt->relation, &options, isTopLevel); break; case REINDEX_OBJECT_TABLE: - ReindexTable(stmt->relation, options, isTopLevel); + ReindexTable(stmt->relation, &options, isTopLevel); break; case REINDEX_OBJECT_SCHEMA: case REINDEX_OBJECT_SYSTEM: @@ -948,7 +948,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" : (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" : "REINDEX DATABASE"); - ReindexMultipleTables(stmt->name, stmt->kind, options); + ReindexMultipleTables(stmt->name, stmt->kind, &options); break; default: elog(ERROR, "unrecognized object type: %d", diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 81e3de4d22..3a8671f558 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -146,7 +146,7 @@ extern void index_set_state_flags(Oid indexId, IndexStateFlagsAction action); extern Oid IndexGetRelation(Oid indexId, bool missing_ok); extern void reindex_index(Oid indexId, bool skip_constraint_checks, - char relpersistence, ReindexOptions options); + char relpersistence, ReindexOptions *options); /* Flag bits for reindex_relation(): */ #define REINDEX_REL_PROCESS_TOAST 0x01 @@ -155,7 +155,7 @@ extern void reindex_index(Oid indexId, bool skip_constraint_checks, #define REINDEX_REL_FORCE_INDEXES_UNLOGGED 0x08 #define REINDEX_REL_FORCE_INDEXES_PERMANENT 0x10 -extern bool reindex_relation(Oid relid, int flags, ReindexOptions options); +extern bool reindex_relation(Oid relid, int flags, ReindexOptions *options); extern bool ReindexIsProcessingHeap(Oid heapOid); extern bool ReindexIsProcessingIndex(Oid indexOid); diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 5b1a60d5fa..33df5d5780 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -36,10 +36,10 @@ extern ObjectAddress DefineIndex(Oid relationId, bool skip_build, bool quiet); extern ReindexOptions ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt); -extern void ReindexIndex(RangeVar *indexRelation, ReindexOptions options, bool isTopLevel); -extern Oid ReindexTable(RangeVar *relation, ReindexOptions options, bool isTopLevel); +extern void ReindexIndex(RangeVar *indexRelation, ReindexOptions *options, bool isTopLevel); +extern Oid ReindexTable(RangeVar *relation, ReindexOptions *options, bool isTopLevel); extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, - ReindexOptions options); + ReindexOptions *options); extern char *makeObjectName(const char *name1, const char *name2, const char *label); extern char *ChooseRelationName(const char *name1, const char *name2, -- 2.17.0 --ucW7QTJbHsz5ya91 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v34-0003-ExecReindex-and-ReindexParams.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH] fix @ 2021-01-10 21:41 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-01-10 21:41 UTC (permalink / raw) --- src/backend/commands/tablecmds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d7b9c63e5f..144c27c303 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17131,6 +17131,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid partrelid, parentrelid; LOCKTAG tag; + LockRelId partlockrelid; char *parentrelname; char *partrelname; @@ -17162,6 +17163,10 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, table_close(rel, NoLock); tab->rel = NULL; + partlockrelid.relId = parentrelid; + partlockrelid.dbId = MyDatabaseId; + LockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); + /* Make updated catalog entry visible */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -17204,7 +17209,7 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("partition \"%s\" was removed concurrently", partrelname))); tab->rel = rel; - + UnlockRelationIdForSession(&partlockrelid, ShareUpdateExclusiveLock); } /* Do the final part of detaching */ @@ -17444,7 +17449,10 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) TupleDesc td = RelationGetDescr(partRel); Constraint *n; - constraintExpr = make_ands_explicit(RelationGetPartitionQual(partRel)); + List *l = RelationGetPartitionQual(partRel); + Assert(partRel->rd_rel->relispartition); + Assert(l != NIL); + constraintExpr = make_ands_explicit(l); /* If an identical constraint exists, we don't need to create one */ if (td->constr && td->constr->num_check > 0) -- 2.17.0 --kR3zbvD4cgoYnS/6-- ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* [PATCH 2/3] fix @ 2021-03-13 21:51 Justin Pryzby <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Justin Pryzby @ 2021-03-13 21:51 UTC (permalink / raw) --- src/backend/access/gin/ginarrayproc.c | 3 ++- src/test/regress/expected/gin.out | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index b10bd04ec8..983cc42a86 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -93,7 +93,8 @@ ginqueryarrayextract(PG_FUNCTION_ARGS) if (strategy == GinContainsElemStrategy) { /* single element is passed, set elems to its pointer */ - elems = &PG_GETARG_DATUM(0); + elems = palloc(sizeof(*elems)); + *elems = PG_GETARG_DATUM(0); nulls = &PG_ARGISNULL(0); nelems = 1; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 698d322e14..7fc7436646 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -78,13 +78,13 @@ select count(*) from gin_test_tbl where i @>> 999; select count(*) from gin_test_tbl where i @>> 1; count ------- - 3 + 2997 (1 row) select count(*) from gin_test_tbl where i @>> 999; count ------- - 0 + 3 (1 row) -- Very weak test for gin_fuzzy_search_limit -- 2.17.0 --opg8F0UgoHELSI+9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-fk_arrays_elems.patch" ^ permalink raw reply [nested|flat] 71+ messages in thread
* Separate HEAP WAL replay logic into its own file @ 2024-06-17 06:20 Li, Yong <[email protected]> 2024-06-17 15:01 ` Re: Separate HEAP WAL replay logic into its own file Melanie Plageman <[email protected]> 0 siblings, 1 reply; 71+ messages in thread From: Li, Yong @ 2024-06-17 06:20 UTC (permalink / raw) To: Debnath, Shawn <[email protected]>; Shyrabokau, Anton <[email protected]>; PostgreSQL Hackers <[email protected]> Hi PostgreSQL hackers, For most access methods in PostgreSQL, the implementation of the access method itself and the implementation of its WAL replay logic are organized in separate source files. However, the HEAP access method is an exception. Both the access method and the WAL replay logic are collocated in the same heapam.c. To follow the pattern established by other access methods and to improve maintainability, I made the enclosed patch to separate HEAP’s replay logic into its own file. The changes are straightforward. Move the replay related functions into the new heapam_xlog.c file, push the common heap_execute_freeze_tuple() helper function into the heapam.h header, and adjust the build files. I hope people find this straightforward refactoring helpful. Yong Attachments: [application/octet-stream] heapam_refactor.patch (82.5K, ../../[email protected]/2-heapam_refactor.patch) download | inline diff: src/backend/access/heap/Makefile | 1 + src/backend/access/heap/heapam.c | 1321 -------------------------------- src/backend/access/heap/heapam_xlog.c | 1326 +++++++++++++++++++++++++++++++++ src/backend/access/heap/meson.build | 1 + src/include/access/heapam.h | 25 + 5 files changed, 1353 insertions(+), 1321 deletions(-) diff --git a/src/backend/access/heap/Makefile b/src/backend/access/heap/Makefile index af0bd1888e..394534172f 100644 --- a/src/backend/access/heap/Makefile +++ b/src/backend/access/heap/Makefile @@ -16,6 +16,7 @@ OBJS = \ heapam.o \ heapam_handler.o \ heapam_visibility.o \ + heapam_xlog.o \ heaptoast.o \ hio.o \ pruneheap.o \ diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 82bb9cb33b..2b6a72043f 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -6809,30 +6809,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, return freeze_xmin || replace_xvac || replace_xmax || freeze_xmax; } -/* - * heap_execute_freeze_tuple - * Execute the prepared freezing of a tuple with caller's freeze plan. - * - * Caller is responsible for ensuring that no other backend can access the - * storage underlying this tuple, either by holding an exclusive lock on the - * buffer containing it (which is what lazy VACUUM does), or by having it be - * in private storage (which is what CLUSTER and friends do). - */ -static inline void -heap_execute_freeze_tuple(HeapTupleHeader tuple, HeapTupleFreeze *frz) -{ - HeapTupleHeaderSetXmax(tuple, frz->xmax); - - if (frz->frzflags & XLH_FREEZE_XVAC) - HeapTupleHeaderSetXvac(tuple, FrozenTransactionId); - - if (frz->frzflags & XLH_INVALID_XVAC) - HeapTupleHeaderSetXvac(tuple, InvalidTransactionId); - - tuple->t_infomask = frz->t_infomask; - tuple->t_infomask2 = frz->t_infomask2; -} - /* * Perform xmin/xmax XID status sanity checks before actually executing freeze * plans. @@ -8743,1303 +8719,6 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required, return key_tuple; } -/* - * Replay XLOG_HEAP2_PRUNE_* records. - */ -static void -heap_xlog_prune_freeze(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - char *maindataptr = XLogRecGetData(record); - xl_heap_prune xlrec; - Buffer buffer; - RelFileLocator rlocator; - BlockNumber blkno; - XLogRedoAction action; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); - memcpy(&xlrec, maindataptr, SizeOfHeapPrune); - maindataptr += SizeOfHeapPrune; - - /* - * We will take an ordinary exclusive lock or a cleanup lock depending on - * whether the XLHP_CLEANUP_LOCK flag is set. With an ordinary exclusive - * lock, we better not be doing anything that requires moving existing - * tuple data. - */ - Assert((xlrec.flags & XLHP_CLEANUP_LOCK) != 0 || - (xlrec.flags & (XLHP_HAS_REDIRECTIONS | XLHP_HAS_DEAD_ITEMS)) == 0); - - /* - * We are about to remove and/or freeze tuples. In Hot Standby mode, - * ensure that there are no queries running for which the removed tuples - * are still visible or which still consider the frozen xids as running. - * The conflict horizon XID comes after xl_heap_prune. - */ - if ((xlrec.flags & XLHP_HAS_CONFLICT_HORIZON) != 0) - { - TransactionId snapshot_conflict_horizon; - - /* memcpy() because snapshot_conflict_horizon is stored unaligned */ - memcpy(&snapshot_conflict_horizon, maindataptr, sizeof(TransactionId)); - maindataptr += sizeof(TransactionId); - - if (InHotStandby) - ResolveRecoveryConflictWithSnapshot(snapshot_conflict_horizon, - (xlrec.flags & XLHP_IS_CATALOG_REL) != 0, - rlocator); - } - - /* - * If we have a full-page image, restore it and we're done. - */ - action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, - (xlrec.flags & XLHP_CLEANUP_LOCK) != 0, - &buffer); - if (action == BLK_NEEDS_REDO) - { - Page page = (Page) BufferGetPage(buffer); - OffsetNumber *redirected; - OffsetNumber *nowdead; - OffsetNumber *nowunused; - int nredirected; - int ndead; - int nunused; - int nplans; - Size datalen; - xlhp_freeze_plan *plans; - OffsetNumber *frz_offsets; - char *dataptr = XLogRecGetBlockData(record, 0, &datalen); - - heap_xlog_deserialize_prune_and_freeze(dataptr, xlrec.flags, - &nplans, &plans, &frz_offsets, - &nredirected, &redirected, - &ndead, &nowdead, - &nunused, &nowunused); - - /* - * Update all line pointers per the record, and repair fragmentation - * if needed. - */ - if (nredirected > 0 || ndead > 0 || nunused > 0) - heap_page_prune_execute(buffer, - (xlrec.flags & XLHP_CLEANUP_LOCK) == 0, - redirected, nredirected, - nowdead, ndead, - nowunused, nunused); - - /* Freeze tuples */ - for (int p = 0; p < nplans; p++) - { - HeapTupleFreeze frz; - - /* - * Convert freeze plan representation from WAL record into - * per-tuple format used by heap_execute_freeze_tuple - */ - frz.xmax = plans[p].xmax; - frz.t_infomask2 = plans[p].t_infomask2; - frz.t_infomask = plans[p].t_infomask; - frz.frzflags = plans[p].frzflags; - frz.offset = InvalidOffsetNumber; /* unused, but be tidy */ - - for (int i = 0; i < plans[p].ntuples; i++) - { - OffsetNumber offset = *(frz_offsets++); - ItemId lp; - HeapTupleHeader tuple; - - lp = PageGetItemId(page, offset); - tuple = (HeapTupleHeader) PageGetItem(page, lp); - heap_execute_freeze_tuple(tuple, &frz); - } - } - - /* There should be no more data */ - Assert((char *) frz_offsets == dataptr + datalen); - - /* - * Note: we don't worry about updating the page's prunability hints. - * At worst this will cause an extra prune cycle to occur soon. - */ - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - - /* - * If we released any space or line pointers, update the free space map. - * - * Do this regardless of a full-page image being applied, since the FSM - * data is not in the page anyway. - */ - if (BufferIsValid(buffer)) - { - if (xlrec.flags & (XLHP_HAS_REDIRECTIONS | - XLHP_HAS_DEAD_ITEMS | - XLHP_HAS_NOW_UNUSED_ITEMS)) - { - Size freespace = PageGetHeapFreeSpace(BufferGetPage(buffer)); - - UnlockReleaseBuffer(buffer); - - XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); - } - else - UnlockReleaseBuffer(buffer); - } -} - -/* - * Replay XLOG_HEAP2_VISIBLE record. - * - * The critical integrity requirement here is that we must never end up with - * a situation where the visibility map bit is set, and the page-level - * PD_ALL_VISIBLE bit is clear. If that were to occur, then a subsequent - * page modification would fail to clear the visibility map bit. - */ -static void -heap_xlog_visible(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_visible *xlrec = (xl_heap_visible *) XLogRecGetData(record); - Buffer vmbuffer = InvalidBuffer; - Buffer buffer; - Page page; - RelFileLocator rlocator; - BlockNumber blkno; - XLogRedoAction action; - - Assert((xlrec->flags & VISIBILITYMAP_XLOG_VALID_BITS) == xlrec->flags); - - XLogRecGetBlockTag(record, 1, &rlocator, NULL, &blkno); - - /* - * If there are any Hot Standby transactions running that have an xmin - * horizon old enough that this page isn't all-visible for them, they - * might incorrectly decide that an index-only scan can skip a heap fetch. - * - * NB: It might be better to throw some kind of "soft" conflict here that - * forces any index-only scan that is in flight to perform heap fetches, - * rather than killing the transaction outright. - */ - if (InHotStandby) - ResolveRecoveryConflictWithSnapshot(xlrec->snapshotConflictHorizon, - xlrec->flags & VISIBILITYMAP_XLOG_CATALOG_REL, - rlocator); - - /* - * Read the heap page, if it still exists. If the heap file has dropped or - * truncated later in recovery, we don't need to update the page, but we'd - * better still update the visibility map. - */ - action = XLogReadBufferForRedo(record, 1, &buffer); - if (action == BLK_NEEDS_REDO) - { - /* - * We don't bump the LSN of the heap page when setting the visibility - * map bit (unless checksums or wal_hint_bits is enabled, in which - * case we must). This exposes us to torn page hazards, but since - * we're not inspecting the existing page contents in any way, we - * don't care. - */ - page = BufferGetPage(buffer); - - PageSetAllVisible(page); - - if (XLogHintBitIsNeeded()) - PageSetLSN(page, lsn); - - MarkBufferDirty(buffer); - } - else if (action == BLK_RESTORED) - { - /* - * If heap block was backed up, we already restored it and there's - * nothing more to do. (This can only happen with checksums or - * wal_log_hints enabled.) - */ - } - - if (BufferIsValid(buffer)) - { - Size space = PageGetFreeSpace(BufferGetPage(buffer)); - - UnlockReleaseBuffer(buffer); - - /* - * Since FSM is not WAL-logged and only updated heuristically, it - * easily becomes stale in standbys. If the standby is later promoted - * and runs VACUUM, it will skip updating individual free space - * figures for pages that became all-visible (or all-frozen, depending - * on the vacuum mode,) which is troublesome when FreeSpaceMapVacuum - * propagates too optimistic free space values to upper FSM layers; - * later inserters try to use such pages only to find out that they - * are unusable. This can cause long stalls when there are many such - * pages. - * - * Forestall those problems by updating FSM's idea about a page that - * is becoming all-visible or all-frozen. - * - * Do this regardless of a full-page image being applied, since the - * FSM data is not in the page anyway. - */ - if (xlrec->flags & VISIBILITYMAP_VALID_BITS) - XLogRecordPageWithFreeSpace(rlocator, blkno, space); - } - - /* - * Even if we skipped the heap page update due to the LSN interlock, it's - * still safe to update the visibility map. Any WAL record that clears - * the visibility map bit does so before checking the page LSN, so any - * bits that need to be cleared will still be cleared. - */ - if (XLogReadBufferForRedoExtended(record, 0, RBM_ZERO_ON_ERROR, false, - &vmbuffer) == BLK_NEEDS_REDO) - { - Page vmpage = BufferGetPage(vmbuffer); - Relation reln; - uint8 vmbits; - - /* initialize the page if it was read as zeros */ - if (PageIsNew(vmpage)) - PageInit(vmpage, BLCKSZ, 0); - - /* remove VISIBILITYMAP_XLOG_* */ - vmbits = xlrec->flags & VISIBILITYMAP_VALID_BITS; - - /* - * XLogReadBufferForRedoExtended locked the buffer. But - * visibilitymap_set will handle locking itself. - */ - LockBuffer(vmbuffer, BUFFER_LOCK_UNLOCK); - - reln = CreateFakeRelcacheEntry(rlocator); - visibilitymap_pin(reln, blkno, &vmbuffer); - - visibilitymap_set(reln, blkno, InvalidBuffer, lsn, vmbuffer, - xlrec->snapshotConflictHorizon, vmbits); - - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - else if (BufferIsValid(vmbuffer)) - UnlockReleaseBuffer(vmbuffer); -} - -/* - * Given an "infobits" field from an XLog record, set the correct bits in the - * given infomask and infomask2 for the tuple touched by the record. - * - * (This is the reverse of compute_infobits). - */ -static void -fix_infomask_from_infobits(uint8 infobits, uint16 *infomask, uint16 *infomask2) -{ - *infomask &= ~(HEAP_XMAX_IS_MULTI | HEAP_XMAX_LOCK_ONLY | - HEAP_XMAX_KEYSHR_LOCK | HEAP_XMAX_EXCL_LOCK); - *infomask2 &= ~HEAP_KEYS_UPDATED; - - if (infobits & XLHL_XMAX_IS_MULTI) - *infomask |= HEAP_XMAX_IS_MULTI; - if (infobits & XLHL_XMAX_LOCK_ONLY) - *infomask |= HEAP_XMAX_LOCK_ONLY; - if (infobits & XLHL_XMAX_EXCL_LOCK) - *infomask |= HEAP_XMAX_EXCL_LOCK; - /* note HEAP_XMAX_SHR_LOCK isn't considered here */ - if (infobits & XLHL_XMAX_KEYSHR_LOCK) - *infomask |= HEAP_XMAX_KEYSHR_LOCK; - - if (infobits & XLHL_KEYS_UPDATED) - *infomask2 |= HEAP_KEYS_UPDATED; -} - -static void -heap_xlog_delete(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record); - Buffer buffer; - Page page; - ItemId lp = NULL; - HeapTupleHeader htup; - BlockNumber blkno; - RelFileLocator target_locator; - ItemPointerData target_tid; - - XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); - ItemPointerSetBlockNumber(&target_tid, blkno); - ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(target_locator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = BufferGetPage(buffer); - - if (PageGetMaxOffsetNumber(page) >= xlrec->offnum) - lp = PageGetItemId(page, xlrec->offnum); - - if (PageGetMaxOffsetNumber(page) < xlrec->offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - HeapTupleHeaderClearHotUpdated(htup); - fix_infomask_from_infobits(xlrec->infobits_set, - &htup->t_infomask, &htup->t_infomask2); - if (!(xlrec->flags & XLH_DELETE_IS_SUPER)) - HeapTupleHeaderSetXmax(htup, xlrec->xmax); - else - HeapTupleHeaderSetXmin(htup, InvalidTransactionId); - HeapTupleHeaderSetCmax(htup, FirstCommandId, false); - - /* Mark the page as a candidate for pruning */ - PageSetPrunable(page, XLogRecGetXid(record)); - - if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - /* Make sure t_ctid is set correctly */ - if (xlrec->flags & XLH_DELETE_IS_PARTITION_MOVE) - HeapTupleHeaderSetMovedPartitions(htup); - else - htup->t_ctid = target_tid; - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_insert(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record); - Buffer buffer; - Page page; - union - { - HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; - } tbuf; - HeapTupleHeader htup; - xl_heap_header xlhdr; - uint32 newlen; - Size freespace = 0; - RelFileLocator target_locator; - BlockNumber blkno; - ItemPointerData target_tid; - XLogRedoAction action; - - XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); - ItemPointerSetBlockNumber(&target_tid, blkno); - ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(target_locator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - /* - * If we inserted the first and only tuple on the page, re-initialize the - * page from scratch. - */ - if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) - { - buffer = XLogInitBufferForRedo(record, 0); - page = BufferGetPage(buffer); - PageInit(page, BufferGetPageSize(buffer), 0); - action = BLK_NEEDS_REDO; - } - else - action = XLogReadBufferForRedo(record, 0, &buffer); - if (action == BLK_NEEDS_REDO) - { - Size datalen; - char *data; - - page = BufferGetPage(buffer); - - if (PageGetMaxOffsetNumber(page) + 1 < xlrec->offnum) - elog(PANIC, "invalid max offset number"); - - data = XLogRecGetBlockData(record, 0, &datalen); - - newlen = datalen - SizeOfHeapHeader; - Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSize); - memcpy((char *) &xlhdr, data, SizeOfHeapHeader); - data += SizeOfHeapHeader; - - htup = &tbuf.hdr; - MemSet((char *) htup, 0, SizeofHeapTupleHeader); - /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ - memcpy((char *) htup + SizeofHeapTupleHeader, - data, - newlen); - newlen += SizeofHeapTupleHeader; - htup->t_infomask2 = xlhdr.t_infomask2; - htup->t_infomask = xlhdr.t_infomask; - htup->t_hoff = xlhdr.t_hoff; - HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); - HeapTupleHeaderSetCmin(htup, FirstCommandId); - htup->t_ctid = target_tid; - - if (PageAddItem(page, (Item) htup, newlen, xlrec->offnum, - true, true) == InvalidOffsetNumber) - elog(PANIC, "failed to add tuple"); - - freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ - - PageSetLSN(page, lsn); - - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ - if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) - PageSetAllVisible(page); - - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); - - /* - * If the page is running low on free space, update the FSM as well. - * Arbitrarily, our definition of "low" is less than 20%. We can't do much - * better than that without knowing the fill-factor for the table. - * - * XXX: Don't do this if the page was restored from full page image. We - * don't bother to update the FSM in that case, it doesn't need to be - * totally accurate anyway. - */ - if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) - XLogRecordPageWithFreeSpace(target_locator, blkno, freespace); -} - -/* - * Handles MULTI_INSERT record type. - */ -static void -heap_xlog_multi_insert(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_multi_insert *xlrec; - RelFileLocator rlocator; - BlockNumber blkno; - Buffer buffer; - Page page; - union - { - HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; - } tbuf; - HeapTupleHeader htup; - uint32 newlen; - Size freespace = 0; - int i; - bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0; - XLogRedoAction action; - - /* - * Insertion doesn't overwrite MVCC data, so no conflict processing is - * required. - */ - xlrec = (xl_heap_multi_insert *) XLogRecGetData(record); - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); - - /* check that the mutually exclusive flags are not both set */ - Assert(!((xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) && - (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET))); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(rlocator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (isinit) - { - buffer = XLogInitBufferForRedo(record, 0); - page = BufferGetPage(buffer); - PageInit(page, BufferGetPageSize(buffer), 0); - action = BLK_NEEDS_REDO; - } - else - action = XLogReadBufferForRedo(record, 0, &buffer); - if (action == BLK_NEEDS_REDO) - { - char *tupdata; - char *endptr; - Size len; - - /* Tuples are stored as block data */ - tupdata = XLogRecGetBlockData(record, 0, &len); - endptr = tupdata + len; - - page = (Page) BufferGetPage(buffer); - - for (i = 0; i < xlrec->ntuples; i++) - { - OffsetNumber offnum; - xl_multi_insert_tuple *xlhdr; - - /* - * If we're reinitializing the page, the tuples are stored in - * order from FirstOffsetNumber. Otherwise there's an array of - * offsets in the WAL record, and the tuples come after that. - */ - if (isinit) - offnum = FirstOffsetNumber + i; - else - offnum = xlrec->offsets[i]; - if (PageGetMaxOffsetNumber(page) + 1 < offnum) - elog(PANIC, "invalid max offset number"); - - xlhdr = (xl_multi_insert_tuple *) SHORTALIGN(tupdata); - tupdata = ((char *) xlhdr) + SizeOfMultiInsertTuple; - - newlen = xlhdr->datalen; - Assert(newlen <= MaxHeapTupleSize); - htup = &tbuf.hdr; - MemSet((char *) htup, 0, SizeofHeapTupleHeader); - /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ - memcpy((char *) htup + SizeofHeapTupleHeader, - (char *) tupdata, - newlen); - tupdata += newlen; - - newlen += SizeofHeapTupleHeader; - htup->t_infomask2 = xlhdr->t_infomask2; - htup->t_infomask = xlhdr->t_infomask; - htup->t_hoff = xlhdr->t_hoff; - HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); - HeapTupleHeaderSetCmin(htup, FirstCommandId); - ItemPointerSetBlockNumber(&htup->t_ctid, blkno); - ItemPointerSetOffsetNumber(&htup->t_ctid, offnum); - - offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); - if (offnum == InvalidOffsetNumber) - elog(PANIC, "failed to add tuple"); - } - if (tupdata != endptr) - elog(PANIC, "total tuple length mismatch"); - - freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ - - PageSetLSN(page, lsn); - - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ - if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) - PageSetAllVisible(page); - - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); - - /* - * If the page is running low on free space, update the FSM as well. - * Arbitrarily, our definition of "low" is less than 20%. We can't do much - * better than that without knowing the fill-factor for the table. - * - * XXX: Don't do this if the page was restored from full page image. We - * don't bother to update the FSM in that case, it doesn't need to be - * totally accurate anyway. - */ - if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) - XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); -} - -/* - * Handles UPDATE and HOT_UPDATE - */ -static void -heap_xlog_update(XLogReaderState *record, bool hot_update) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record); - RelFileLocator rlocator; - BlockNumber oldblk; - BlockNumber newblk; - ItemPointerData newtid; - Buffer obuffer, - nbuffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleData oldtup; - HeapTupleHeader htup; - uint16 prefixlen = 0, - suffixlen = 0; - char *newp; - union - { - HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; - } tbuf; - xl_heap_header xlhdr; - uint32 newlen; - Size freespace = 0; - XLogRedoAction oldaction; - XLogRedoAction newaction; - - /* initialize to keep the compiler quiet */ - oldtup.t_data = NULL; - oldtup.t_len = 0; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &newblk); - if (XLogRecGetBlockTagExtended(record, 1, NULL, NULL, &oldblk, NULL)) - { - /* HOT updates are never done across pages */ - Assert(!hot_update); - } - else - oldblk = newblk; - - ItemPointerSet(&newtid, newblk, xlrec->new_offnum); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(rlocator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, oldblk, &vmbuffer); - visibilitymap_clear(reln, oldblk, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - /* - * In normal operation, it is important to lock the two pages in - * page-number order, to avoid possible deadlocks against other update - * operations going the other way. However, during WAL replay there can - * be no other update happening, so we don't need to worry about that. But - * we *do* need to worry that we don't expose an inconsistent state to Hot - * Standby queries --- so the original page can't be unlocked before we've - * added the new tuple to the new page. - */ - - /* Deal with old tuple version */ - oldaction = XLogReadBufferForRedo(record, (oldblk == newblk) ? 0 : 1, - &obuffer); - if (oldaction == BLK_NEEDS_REDO) - { - page = BufferGetPage(obuffer); - offnum = xlrec->old_offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - oldtup.t_data = htup; - oldtup.t_len = ItemIdGetLength(lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - if (hot_update) - HeapTupleHeaderSetHotUpdated(htup); - else - HeapTupleHeaderClearHotUpdated(htup); - fix_infomask_from_infobits(xlrec->old_infobits_set, &htup->t_infomask, - &htup->t_infomask2); - HeapTupleHeaderSetXmax(htup, xlrec->old_xmax); - HeapTupleHeaderSetCmax(htup, FirstCommandId, false); - /* Set forward chain link in t_ctid */ - htup->t_ctid = newtid; - - /* Mark the page as a candidate for pruning */ - PageSetPrunable(page, XLogRecGetXid(record)); - - if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - PageSetLSN(page, lsn); - MarkBufferDirty(obuffer); - } - - /* - * Read the page the new tuple goes into, if different from old. - */ - if (oldblk == newblk) - { - nbuffer = obuffer; - newaction = oldaction; - } - else if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) - { - nbuffer = XLogInitBufferForRedo(record, 0); - page = (Page) BufferGetPage(nbuffer); - PageInit(page, BufferGetPageSize(nbuffer), 0); - newaction = BLK_NEEDS_REDO; - } - else - newaction = XLogReadBufferForRedo(record, 0, &nbuffer); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(rlocator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, newblk, &vmbuffer); - visibilitymap_clear(reln, newblk, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - /* Deal with new tuple */ - if (newaction == BLK_NEEDS_REDO) - { - char *recdata; - char *recdata_end; - Size datalen; - Size tuplen; - - recdata = XLogRecGetBlockData(record, 0, &datalen); - recdata_end = recdata + datalen; - - page = BufferGetPage(nbuffer); - - offnum = xlrec->new_offnum; - if (PageGetMaxOffsetNumber(page) + 1 < offnum) - elog(PANIC, "invalid max offset number"); - - if (xlrec->flags & XLH_UPDATE_PREFIX_FROM_OLD) - { - Assert(newblk == oldblk); - memcpy(&prefixlen, recdata, sizeof(uint16)); - recdata += sizeof(uint16); - } - if (xlrec->flags & XLH_UPDATE_SUFFIX_FROM_OLD) - { - Assert(newblk == oldblk); - memcpy(&suffixlen, recdata, sizeof(uint16)); - recdata += sizeof(uint16); - } - - memcpy((char *) &xlhdr, recdata, SizeOfHeapHeader); - recdata += SizeOfHeapHeader; - - tuplen = recdata_end - recdata; - Assert(tuplen <= MaxHeapTupleSize); - - htup = &tbuf.hdr; - MemSet((char *) htup, 0, SizeofHeapTupleHeader); - - /* - * Reconstruct the new tuple using the prefix and/or suffix from the - * old tuple, and the data stored in the WAL record. - */ - newp = (char *) htup + SizeofHeapTupleHeader; - if (prefixlen > 0) - { - int len; - - /* copy bitmap [+ padding] [+ oid] from WAL record */ - len = xlhdr.t_hoff - SizeofHeapTupleHeader; - memcpy(newp, recdata, len); - recdata += len; - newp += len; - - /* copy prefix from old tuple */ - memcpy(newp, (char *) oldtup.t_data + oldtup.t_data->t_hoff, prefixlen); - newp += prefixlen; - - /* copy new tuple data from WAL record */ - len = tuplen - (xlhdr.t_hoff - SizeofHeapTupleHeader); - memcpy(newp, recdata, len); - recdata += len; - newp += len; - } - else - { - /* - * copy bitmap [+ padding] [+ oid] + data from record, all in one - * go - */ - memcpy(newp, recdata, tuplen); - recdata += tuplen; - newp += tuplen; - } - Assert(recdata == recdata_end); - - /* copy suffix from old tuple */ - if (suffixlen > 0) - memcpy(newp, (char *) oldtup.t_data + oldtup.t_len - suffixlen, suffixlen); - - newlen = SizeofHeapTupleHeader + tuplen + prefixlen + suffixlen; - htup->t_infomask2 = xlhdr.t_infomask2; - htup->t_infomask = xlhdr.t_infomask; - htup->t_hoff = xlhdr.t_hoff; - - HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); - HeapTupleHeaderSetCmin(htup, FirstCommandId); - HeapTupleHeaderSetXmax(htup, xlrec->new_xmax); - /* Make sure there is no forward chain link in t_ctid */ - htup->t_ctid = newtid; - - offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); - if (offnum == InvalidOffsetNumber) - elog(PANIC, "failed to add tuple"); - - if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ - - PageSetLSN(page, lsn); - MarkBufferDirty(nbuffer); - } - - if (BufferIsValid(nbuffer) && nbuffer != obuffer) - UnlockReleaseBuffer(nbuffer); - if (BufferIsValid(obuffer)) - UnlockReleaseBuffer(obuffer); - - /* - * If the new page is running low on free space, update the FSM as well. - * Arbitrarily, our definition of "low" is less than 20%. We can't do much - * better than that without knowing the fill-factor for the table. - * - * However, don't update the FSM on HOT updates, because after crash - * recovery, either the old or the new tuple will certainly be dead and - * prunable. After pruning, the page will have roughly as much free space - * as it did before the update, assuming the new tuple is about the same - * size as the old one. - * - * XXX: Don't do this if the page was restored from full page image. We - * don't bother to update the FSM in that case, it doesn't need to be - * totally accurate anyway. - */ - if (newaction == BLK_NEEDS_REDO && !hot_update && freespace < BLCKSZ / 5) - XLogRecordPageWithFreeSpace(rlocator, newblk, freespace); -} - -static void -heap_xlog_confirm(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_confirm *xlrec = (xl_heap_confirm *) XLogRecGetData(record); - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - /* - * Confirm tuple as actually inserted - */ - ItemPointerSet(&htup->t_ctid, BufferGetBlockNumber(buffer), offnum); - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_lock(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_lock *xlrec = (xl_heap_lock *) XLogRecGetData(record); - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) - { - RelFileLocator rlocator; - Buffer vmbuffer = InvalidBuffer; - BlockNumber block; - Relation reln; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); - reln = CreateFakeRelcacheEntry(rlocator); - - visibilitymap_pin(reln, block, &vmbuffer); - visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); - - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = (Page) BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, - &htup->t_infomask2); - - /* - * Clear relevant update flags, but only if the modified infomask says - * there's no update. - */ - if (HEAP_XMAX_IS_LOCKED_ONLY(htup->t_infomask)) - { - HeapTupleHeaderClearHotUpdated(htup); - /* Make sure there is no forward chain link in t_ctid */ - ItemPointerSet(&htup->t_ctid, - BufferGetBlockNumber(buffer), - offnum); - } - HeapTupleHeaderSetXmax(htup, xlrec->xmax); - HeapTupleHeaderSetCmax(htup, FirstCommandId, false); - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_lock_updated(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_lock_updated *xlrec; - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - - xlrec = (xl_heap_lock_updated *) XLogRecGetData(record); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) - { - RelFileLocator rlocator; - Buffer vmbuffer = InvalidBuffer; - BlockNumber block; - Relation reln; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); - reln = CreateFakeRelcacheEntry(rlocator); - - visibilitymap_pin(reln, block, &vmbuffer); - visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); - - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, - &htup->t_infomask2); - HeapTupleHeaderSetXmax(htup, xlrec->xmax); - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_inplace(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_inplace *xlrec = (xl_heap_inplace *) XLogRecGetData(record); - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - uint32 oldlen; - Size newlen; - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - char *newtup = XLogRecGetBlockData(record, 0, &newlen); - - page = BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - oldlen = ItemIdGetLength(lp) - htup->t_hoff; - if (oldlen != newlen) - elog(PANIC, "wrong tuple length"); - - memcpy((char *) htup + htup->t_hoff, newtup, newlen); - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -void -heap_redo(XLogReaderState *record) -{ - uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; - - /* - * These operations don't overwrite MVCC data so no conflict processing is - * required. The ones in heap2 rmgr do. - */ - - switch (info & XLOG_HEAP_OPMASK) - { - case XLOG_HEAP_INSERT: - heap_xlog_insert(record); - break; - case XLOG_HEAP_DELETE: - heap_xlog_delete(record); - break; - case XLOG_HEAP_UPDATE: - heap_xlog_update(record, false); - break; - case XLOG_HEAP_TRUNCATE: - - /* - * TRUNCATE is a no-op because the actions are already logged as - * SMGR WAL records. TRUNCATE WAL record only exists for logical - * decoding. - */ - break; - case XLOG_HEAP_HOT_UPDATE: - heap_xlog_update(record, true); - break; - case XLOG_HEAP_CONFIRM: - heap_xlog_confirm(record); - break; - case XLOG_HEAP_LOCK: - heap_xlog_lock(record); - break; - case XLOG_HEAP_INPLACE: - heap_xlog_inplace(record); - break; - default: - elog(PANIC, "heap_redo: unknown op code %u", info); - } -} - -void -heap2_redo(XLogReaderState *record) -{ - uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; - - switch (info & XLOG_HEAP_OPMASK) - { - case XLOG_HEAP2_PRUNE_ON_ACCESS: - case XLOG_HEAP2_PRUNE_VACUUM_SCAN: - case XLOG_HEAP2_PRUNE_VACUUM_CLEANUP: - heap_xlog_prune_freeze(record); - break; - case XLOG_HEAP2_VISIBLE: - heap_xlog_visible(record); - break; - case XLOG_HEAP2_MULTI_INSERT: - heap_xlog_multi_insert(record); - break; - case XLOG_HEAP2_LOCK_UPDATED: - heap_xlog_lock_updated(record); - break; - case XLOG_HEAP2_NEW_CID: - - /* - * Nothing to do on a real replay, only used during logical - * decoding. - */ - break; - case XLOG_HEAP2_REWRITE: - heap_xlog_logical_rewrite(record); - break; - default: - elog(PANIC, "heap2_redo: unknown op code %u", info); - } -} - -/* - * Mask a heap page before performing consistency checks on it. - */ -void -heap_mask(char *pagedata, BlockNumber blkno) -{ - Page page = (Page) pagedata; - OffsetNumber off; - - mask_page_lsn_and_checksum(page); - - mask_page_hint_bits(page); - mask_unused_space(page); - - for (off = 1; off <= PageGetMaxOffsetNumber(page); off++) - { - ItemId iid = PageGetItemId(page, off); - char *page_item; - - page_item = (char *) (page + ItemIdGetOffset(iid)); - - if (ItemIdIsNormal(iid)) - { - HeapTupleHeader page_htup = (HeapTupleHeader) page_item; - - /* - * If xmin of a tuple is not yet frozen, we should ignore - * differences in hint bits, since they can be set without - * emitting WAL. - */ - if (!HeapTupleHeaderXminFrozen(page_htup)) - page_htup->t_infomask &= ~HEAP_XACT_MASK; - else - { - /* Still we need to mask xmax hint bits. */ - page_htup->t_infomask &= ~HEAP_XMAX_INVALID; - page_htup->t_infomask &= ~HEAP_XMAX_COMMITTED; - } - - /* - * During replay, we set Command Id to FirstCommandId. Hence, mask - * it. See heap_xlog_insert() for details. - */ - page_htup->t_choice.t_heap.t_field3.t_cid = MASK_MARKER; - - /* - * For a speculative tuple, heap_insert() does not set ctid in the - * caller-passed heap tuple itself, leaving the ctid field to - * contain a speculative token value - a per-backend monotonically - * increasing identifier. Besides, it does not WAL-log ctid under - * any circumstances. - * - * During redo, heap_xlog_insert() sets t_ctid to current block - * number and self offset number. It doesn't care about any - * speculative insertions on the primary. Hence, we set t_ctid to - * current block number and self offset number to ignore any - * inconsistency. - */ - if (HeapTupleHeaderIsSpeculative(page_htup)) - ItemPointerSet(&page_htup->t_ctid, blkno, off); - - /* - * NB: Not ignoring ctid changes due to the tuple having moved - * (i.e. HeapTupleHeaderIndicatesMovedPartitions), because that's - * important information that needs to be in-sync between primary - * and standby, and thus is WAL logged. - */ - } - - /* - * Ignore any padding bytes after the tuple, when the length of the - * item is not MAXALIGNed. - */ - if (ItemIdHasStorage(iid)) - { - int len = ItemIdGetLength(iid); - int padlen = MAXALIGN(len) - len; - - if (padlen > 0) - memset(page_item + len, MASK_MARKER, padlen); - } - } -} - /* * HeapCheckForSerializableConflictOut * We are reading a tuple. If it's not visible, there may be a diff --git a/src/backend/access/heap/heapam_xlog.c b/src/backend/access/heap/heapam_xlog.c new file mode 100644 index 0000000000..b372f2b4af --- /dev/null +++ b/src/backend/access/heap/heapam_xlog.c @@ -0,0 +1,1326 @@ +/*------------------------------------------------------------------------- + * + * heapam_xlog.c + * WAL replay logic for heaps. + * + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/access/heap/heapam_xlog.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/bufmask.h" +#include "access/heapam.h" +#include "access/heapam_xlog.h" +#include "access/transam.h" +#include "access/visibilitymap.h" +#include "access/xlog.h" +#include "access/xlogutils.h" +#include "port/atomics.h" +#include "storage/bufmgr.h" +#include "storage/freespace.h" +#include "storage/standby.h" +#include "utils/relcache.h" + + +/* + * Replay XLOG_HEAP2_PRUNE_* records. + */ +static void +heap_xlog_prune_freeze(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + char *maindataptr = XLogRecGetData(record); + xl_heap_prune xlrec; + Buffer buffer; + RelFileLocator rlocator; + BlockNumber blkno; + XLogRedoAction action; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); + memcpy(&xlrec, maindataptr, SizeOfHeapPrune); + maindataptr += SizeOfHeapPrune; + + /* + * We will take an ordinary exclusive lock or a cleanup lock depending on + * whether the XLHP_CLEANUP_LOCK flag is set. With an ordinary exclusive + * lock, we better not be doing anything that requires moving existing + * tuple data. + */ + Assert((xlrec.flags & XLHP_CLEANUP_LOCK) != 0 || + (xlrec.flags & (XLHP_HAS_REDIRECTIONS | XLHP_HAS_DEAD_ITEMS)) == 0); + + /* + * We are about to remove and/or freeze tuples. In Hot Standby mode, + * ensure that there are no queries running for which the removed tuples + * are still visible or which still consider the frozen xids as running. + * The conflict horizon XID comes after xl_heap_prune. + */ + if ((xlrec.flags & XLHP_HAS_CONFLICT_HORIZON) != 0) + { + TransactionId snapshot_conflict_horizon; + + /* memcpy() because snapshot_conflict_horizon is stored unaligned */ + memcpy(&snapshot_conflict_horizon, maindataptr, sizeof(TransactionId)); + maindataptr += sizeof(TransactionId); + + if (InHotStandby) + ResolveRecoveryConflictWithSnapshot(snapshot_conflict_horizon, + (xlrec.flags & XLHP_IS_CATALOG_REL) != 0, + rlocator); + } + + /* + * If we have a full-page image, restore it and we're done. + */ + action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, + (xlrec.flags & XLHP_CLEANUP_LOCK) != 0, + &buffer); + if (action == BLK_NEEDS_REDO) + { + Page page = (Page) BufferGetPage(buffer); + OffsetNumber *redirected; + OffsetNumber *nowdead; + OffsetNumber *nowunused; + int nredirected; + int ndead; + int nunused; + int nplans; + Size datalen; + xlhp_freeze_plan *plans; + OffsetNumber *frz_offsets; + char *dataptr = XLogRecGetBlockData(record, 0, &datalen); + + heap_xlog_deserialize_prune_and_freeze(dataptr, xlrec.flags, + &nplans, &plans, &frz_offsets, + &nredirected, &redirected, + &ndead, &nowdead, + &nunused, &nowunused); + + /* + * Update all line pointers per the record, and repair fragmentation + * if needed. + */ + if (nredirected > 0 || ndead > 0 || nunused > 0) + heap_page_prune_execute(buffer, + (xlrec.flags & XLHP_CLEANUP_LOCK) == 0, + redirected, nredirected, + nowdead, ndead, + nowunused, nunused); + + /* Freeze tuples */ + for (int p = 0; p < nplans; p++) + { + HeapTupleFreeze frz; + + /* + * Convert freeze plan representation from WAL record into + * per-tuple format used by heap_execute_freeze_tuple + */ + frz.xmax = plans[p].xmax; + frz.t_infomask2 = plans[p].t_infomask2; + frz.t_infomask = plans[p].t_infomask; + frz.frzflags = plans[p].frzflags; + frz.offset = InvalidOffsetNumber; /* unused, but be tidy */ + + for (int i = 0; i < plans[p].ntuples; i++) + { + OffsetNumber offset = *(frz_offsets++); + ItemId lp; + HeapTupleHeader tuple; + + lp = PageGetItemId(page, offset); + tuple = (HeapTupleHeader) PageGetItem(page, lp); + heap_execute_freeze_tuple(tuple, &frz); + } + } + + /* There should be no more data */ + Assert((char *) frz_offsets == dataptr + datalen); + + /* + * Note: we don't worry about updating the page's prunability hints. + * At worst this will cause an extra prune cycle to occur soon. + */ + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + + /* + * If we released any space or line pointers, update the free space map. + * + * Do this regardless of a full-page image being applied, since the FSM + * data is not in the page anyway. + */ + if (BufferIsValid(buffer)) + { + if (xlrec.flags & (XLHP_HAS_REDIRECTIONS | + XLHP_HAS_DEAD_ITEMS | + XLHP_HAS_NOW_UNUSED_ITEMS)) + { + Size freespace = PageGetHeapFreeSpace(BufferGetPage(buffer)); + + UnlockReleaseBuffer(buffer); + + XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); + } + else + UnlockReleaseBuffer(buffer); + } +} + +/* + * Replay XLOG_HEAP2_VISIBLE record. + * + * The critical integrity requirement here is that we must never end up with + * a situation where the visibility map bit is set, and the page-level + * PD_ALL_VISIBLE bit is clear. If that were to occur, then a subsequent + * page modification would fail to clear the visibility map bit. + */ +static void +heap_xlog_visible(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_visible *xlrec = (xl_heap_visible *) XLogRecGetData(record); + Buffer vmbuffer = InvalidBuffer; + Buffer buffer; + Page page; + RelFileLocator rlocator; + BlockNumber blkno; + XLogRedoAction action; + + Assert((xlrec->flags & VISIBILITYMAP_XLOG_VALID_BITS) == xlrec->flags); + + XLogRecGetBlockTag(record, 1, &rlocator, NULL, &blkno); + + /* + * If there are any Hot Standby transactions running that have an xmin + * horizon old enough that this page isn't all-visible for them, they + * might incorrectly decide that an index-only scan can skip a heap fetch. + * + * NB: It might be better to throw some kind of "soft" conflict here that + * forces any index-only scan that is in flight to perform heap fetches, + * rather than killing the transaction outright. + */ + if (InHotStandby) + ResolveRecoveryConflictWithSnapshot(xlrec->snapshotConflictHorizon, + xlrec->flags & VISIBILITYMAP_XLOG_CATALOG_REL, + rlocator); + + /* + * Read the heap page, if it still exists. If the heap file has dropped or + * truncated later in recovery, we don't need to update the page, but we'd + * better still update the visibility map. + */ + action = XLogReadBufferForRedo(record, 1, &buffer); + if (action == BLK_NEEDS_REDO) + { + /* + * We don't bump the LSN of the heap page when setting the visibility + * map bit (unless checksums or wal_hint_bits is enabled, in which + * case we must). This exposes us to torn page hazards, but since + * we're not inspecting the existing page contents in any way, we + * don't care. + */ + page = BufferGetPage(buffer); + + PageSetAllVisible(page); + + if (XLogHintBitIsNeeded()) + PageSetLSN(page, lsn); + + MarkBufferDirty(buffer); + } + else if (action == BLK_RESTORED) + { + /* + * If heap block was backed up, we already restored it and there's + * nothing more to do. (This can only happen with checksums or + * wal_log_hints enabled.) + */ + } + + if (BufferIsValid(buffer)) + { + Size space = PageGetFreeSpace(BufferGetPage(buffer)); + + UnlockReleaseBuffer(buffer); + + /* + * Since FSM is not WAL-logged and only updated heuristically, it + * easily becomes stale in standbys. If the standby is later promoted + * and runs VACUUM, it will skip updating individual free space + * figures for pages that became all-visible (or all-frozen, depending + * on the vacuum mode,) which is troublesome when FreeSpaceMapVacuum + * propagates too optimistic free space values to upper FSM layers; + * later inserters try to use such pages only to find out that they + * are unusable. This can cause long stalls when there are many such + * pages. + * + * Forestall those problems by updating FSM's idea about a page that + * is becoming all-visible or all-frozen. + * + * Do this regardless of a full-page image being applied, since the + * FSM data is not in the page anyway. + */ + if (xlrec->flags & VISIBILITYMAP_VALID_BITS) + XLogRecordPageWithFreeSpace(rlocator, blkno, space); + } + + /* + * Even if we skipped the heap page update due to the LSN interlock, it's + * still safe to update the visibility map. Any WAL record that clears + * the visibility map bit does so before checking the page LSN, so any + * bits that need to be cleared will still be cleared. + */ + if (XLogReadBufferForRedoExtended(record, 0, RBM_ZERO_ON_ERROR, false, + &vmbuffer) == BLK_NEEDS_REDO) + { + Page vmpage = BufferGetPage(vmbuffer); + Relation reln; + uint8 vmbits; + + /* initialize the page if it was read as zeros */ + if (PageIsNew(vmpage)) + PageInit(vmpage, BLCKSZ, 0); + + /* remove VISIBILITYMAP_XLOG_* */ + vmbits = xlrec->flags & VISIBILITYMAP_VALID_BITS; + + /* + * XLogReadBufferForRedoExtended locked the buffer. But + * visibilitymap_set will handle locking itself. + */ + LockBuffer(vmbuffer, BUFFER_LOCK_UNLOCK); + + reln = CreateFakeRelcacheEntry(rlocator); + visibilitymap_pin(reln, blkno, &vmbuffer); + + visibilitymap_set(reln, blkno, InvalidBuffer, lsn, vmbuffer, + xlrec->snapshotConflictHorizon, vmbits); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + else if (BufferIsValid(vmbuffer)) + UnlockReleaseBuffer(vmbuffer); +} + +/* + * Given an "infobits" field from an XLog record, set the correct bits in the + * given infomask and infomask2 for the tuple touched by the record. + * + * (This is the reverse of compute_infobits). + */ +static void +fix_infomask_from_infobits(uint8 infobits, uint16 *infomask, uint16 *infomask2) +{ + *infomask &= ~(HEAP_XMAX_IS_MULTI | HEAP_XMAX_LOCK_ONLY | + HEAP_XMAX_KEYSHR_LOCK | HEAP_XMAX_EXCL_LOCK); + *infomask2 &= ~HEAP_KEYS_UPDATED; + + if (infobits & XLHL_XMAX_IS_MULTI) + *infomask |= HEAP_XMAX_IS_MULTI; + if (infobits & XLHL_XMAX_LOCK_ONLY) + *infomask |= HEAP_XMAX_LOCK_ONLY; + if (infobits & XLHL_XMAX_EXCL_LOCK) + *infomask |= HEAP_XMAX_EXCL_LOCK; + /* note HEAP_XMAX_SHR_LOCK isn't considered here */ + if (infobits & XLHL_XMAX_KEYSHR_LOCK) + *infomask |= HEAP_XMAX_KEYSHR_LOCK; + + if (infobits & XLHL_KEYS_UPDATED) + *infomask2 |= HEAP_KEYS_UPDATED; +} + +static void +heap_xlog_delete(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record); + Buffer buffer; + Page page; + ItemId lp = NULL; + HeapTupleHeader htup; + BlockNumber blkno; + RelFileLocator target_locator; + ItemPointerData target_tid; + + XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); + ItemPointerSetBlockNumber(&target_tid, blkno); + ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(target_locator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, blkno, &vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = BufferGetPage(buffer); + + if (PageGetMaxOffsetNumber(page) >= xlrec->offnum) + lp = PageGetItemId(page, xlrec->offnum); + + if (PageGetMaxOffsetNumber(page) < xlrec->offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + HeapTupleHeaderClearHotUpdated(htup); + fix_infomask_from_infobits(xlrec->infobits_set, + &htup->t_infomask, &htup->t_infomask2); + if (!(xlrec->flags & XLH_DELETE_IS_SUPER)) + HeapTupleHeaderSetXmax(htup, xlrec->xmax); + else + HeapTupleHeaderSetXmin(htup, InvalidTransactionId); + HeapTupleHeaderSetCmax(htup, FirstCommandId, false); + + /* Mark the page as a candidate for pruning */ + PageSetPrunable(page, XLogRecGetXid(record)); + + if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + /* Make sure t_ctid is set correctly */ + if (xlrec->flags & XLH_DELETE_IS_PARTITION_MOVE) + HeapTupleHeaderSetMovedPartitions(htup); + else + htup->t_ctid = target_tid; + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +static void +heap_xlog_insert(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record); + Buffer buffer; + Page page; + union + { + HeapTupleHeaderData hdr; + char data[MaxHeapTupleSize]; + } tbuf; + HeapTupleHeader htup; + xl_heap_header xlhdr; + uint32 newlen; + Size freespace = 0; + RelFileLocator target_locator; + BlockNumber blkno; + ItemPointerData target_tid; + XLogRedoAction action; + + XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); + ItemPointerSetBlockNumber(&target_tid, blkno); + ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(target_locator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, blkno, &vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + /* + * If we inserted the first and only tuple on the page, re-initialize the + * page from scratch. + */ + if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) + { + buffer = XLogInitBufferForRedo(record, 0); + page = BufferGetPage(buffer); + PageInit(page, BufferGetPageSize(buffer), 0); + action = BLK_NEEDS_REDO; + } + else + action = XLogReadBufferForRedo(record, 0, &buffer); + if (action == BLK_NEEDS_REDO) + { + Size datalen; + char *data; + + page = BufferGetPage(buffer); + + if (PageGetMaxOffsetNumber(page) + 1 < xlrec->offnum) + elog(PANIC, "invalid max offset number"); + + data = XLogRecGetBlockData(record, 0, &datalen); + + newlen = datalen - SizeOfHeapHeader; + Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSize); + memcpy((char *) &xlhdr, data, SizeOfHeapHeader); + data += SizeOfHeapHeader; + + htup = &tbuf.hdr; + MemSet((char *) htup, 0, SizeofHeapTupleHeader); + /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ + memcpy((char *) htup + SizeofHeapTupleHeader, + data, + newlen); + newlen += SizeofHeapTupleHeader; + htup->t_infomask2 = xlhdr.t_infomask2; + htup->t_infomask = xlhdr.t_infomask; + htup->t_hoff = xlhdr.t_hoff; + HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); + HeapTupleHeaderSetCmin(htup, FirstCommandId); + htup->t_ctid = target_tid; + + if (PageAddItem(page, (Item) htup, newlen, xlrec->offnum, + true, true) == InvalidOffsetNumber) + elog(PANIC, "failed to add tuple"); + + freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ + + PageSetLSN(page, lsn); + + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ + if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) + PageSetAllVisible(page); + + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); + + /* + * If the page is running low on free space, update the FSM as well. + * Arbitrarily, our definition of "low" is less than 20%. We can't do much + * better than that without knowing the fill-factor for the table. + * + * XXX: Don't do this if the page was restored from full page image. We + * don't bother to update the FSM in that case, it doesn't need to be + * totally accurate anyway. + */ + if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) + XLogRecordPageWithFreeSpace(target_locator, blkno, freespace); +} + +/* + * Handles MULTI_INSERT record type. + */ +static void +heap_xlog_multi_insert(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_multi_insert *xlrec; + RelFileLocator rlocator; + BlockNumber blkno; + Buffer buffer; + Page page; + union + { + HeapTupleHeaderData hdr; + char data[MaxHeapTupleSize]; + } tbuf; + HeapTupleHeader htup; + uint32 newlen; + Size freespace = 0; + int i; + bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0; + XLogRedoAction action; + + /* + * Insertion doesn't overwrite MVCC data, so no conflict processing is + * required. + */ + xlrec = (xl_heap_multi_insert *) XLogRecGetData(record); + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); + + /* check that the mutually exclusive flags are not both set */ + Assert(!((xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) && + (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET))); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(rlocator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, blkno, &vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (isinit) + { + buffer = XLogInitBufferForRedo(record, 0); + page = BufferGetPage(buffer); + PageInit(page, BufferGetPageSize(buffer), 0); + action = BLK_NEEDS_REDO; + } + else + action = XLogReadBufferForRedo(record, 0, &buffer); + if (action == BLK_NEEDS_REDO) + { + char *tupdata; + char *endptr; + Size len; + + /* Tuples are stored as block data */ + tupdata = XLogRecGetBlockData(record, 0, &len); + endptr = tupdata + len; + + page = (Page) BufferGetPage(buffer); + + for (i = 0; i < xlrec->ntuples; i++) + { + OffsetNumber offnum; + xl_multi_insert_tuple *xlhdr; + + /* + * If we're reinitializing the page, the tuples are stored in + * order from FirstOffsetNumber. Otherwise there's an array of + * offsets in the WAL record, and the tuples come after that. + */ + if (isinit) + offnum = FirstOffsetNumber + i; + else + offnum = xlrec->offsets[i]; + if (PageGetMaxOffsetNumber(page) + 1 < offnum) + elog(PANIC, "invalid max offset number"); + + xlhdr = (xl_multi_insert_tuple *) SHORTALIGN(tupdata); + tupdata = ((char *) xlhdr) + SizeOfMultiInsertTuple; + + newlen = xlhdr->datalen; + Assert(newlen <= MaxHeapTupleSize); + htup = &tbuf.hdr; + MemSet((char *) htup, 0, SizeofHeapTupleHeader); + /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ + memcpy((char *) htup + SizeofHeapTupleHeader, + (char *) tupdata, + newlen); + tupdata += newlen; + + newlen += SizeofHeapTupleHeader; + htup->t_infomask2 = xlhdr->t_infomask2; + htup->t_infomask = xlhdr->t_infomask; + htup->t_hoff = xlhdr->t_hoff; + HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); + HeapTupleHeaderSetCmin(htup, FirstCommandId); + ItemPointerSetBlockNumber(&htup->t_ctid, blkno); + ItemPointerSetOffsetNumber(&htup->t_ctid, offnum); + + offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); + if (offnum == InvalidOffsetNumber) + elog(PANIC, "failed to add tuple"); + } + if (tupdata != endptr) + elog(PANIC, "total tuple length mismatch"); + + freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ + + PageSetLSN(page, lsn); + + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ + if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) + PageSetAllVisible(page); + + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); + + /* + * If the page is running low on free space, update the FSM as well. + * Arbitrarily, our definition of "low" is less than 20%. We can't do much + * better than that without knowing the fill-factor for the table. + * + * XXX: Don't do this if the page was restored from full page image. We + * don't bother to update the FSM in that case, it doesn't need to be + * totally accurate anyway. + */ + if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) + XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); +} + +/* + * Handles UPDATE and HOT_UPDATE + */ +static void +heap_xlog_update(XLogReaderState *record, bool hot_update) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record); + RelFileLocator rlocator; + BlockNumber oldblk; + BlockNumber newblk; + ItemPointerData newtid; + Buffer obuffer, + nbuffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleData oldtup; + HeapTupleHeader htup; + uint16 prefixlen = 0, + suffixlen = 0; + char *newp; + union + { + HeapTupleHeaderData hdr; + char data[MaxHeapTupleSize]; + } tbuf; + xl_heap_header xlhdr; + uint32 newlen; + Size freespace = 0; + XLogRedoAction oldaction; + XLogRedoAction newaction; + + /* initialize to keep the compiler quiet */ + oldtup.t_data = NULL; + oldtup.t_len = 0; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &newblk); + if (XLogRecGetBlockTagExtended(record, 1, NULL, NULL, &oldblk, NULL)) + { + /* HOT updates are never done across pages */ + Assert(!hot_update); + } + else + oldblk = newblk; + + ItemPointerSet(&newtid, newblk, xlrec->new_offnum); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(rlocator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, oldblk, &vmbuffer); + visibilitymap_clear(reln, oldblk, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + /* + * In normal operation, it is important to lock the two pages in + * page-number order, to avoid possible deadlocks against other update + * operations going the other way. However, during WAL replay there can + * be no other update happening, so we don't need to worry about that. But + * we *do* need to worry that we don't expose an inconsistent state to Hot + * Standby queries --- so the original page can't be unlocked before we've + * added the new tuple to the new page. + */ + + /* Deal with old tuple version */ + oldaction = XLogReadBufferForRedo(record, (oldblk == newblk) ? 0 : 1, + &obuffer); + if (oldaction == BLK_NEEDS_REDO) + { + page = BufferGetPage(obuffer); + offnum = xlrec->old_offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + oldtup.t_data = htup; + oldtup.t_len = ItemIdGetLength(lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + if (hot_update) + HeapTupleHeaderSetHotUpdated(htup); + else + HeapTupleHeaderClearHotUpdated(htup); + fix_infomask_from_infobits(xlrec->old_infobits_set, &htup->t_infomask, + &htup->t_infomask2); + HeapTupleHeaderSetXmax(htup, xlrec->old_xmax); + HeapTupleHeaderSetCmax(htup, FirstCommandId, false); + /* Set forward chain link in t_ctid */ + htup->t_ctid = newtid; + + /* Mark the page as a candidate for pruning */ + PageSetPrunable(page, XLogRecGetXid(record)); + + if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + PageSetLSN(page, lsn); + MarkBufferDirty(obuffer); + } + + /* + * Read the page the new tuple goes into, if different from old. + */ + if (oldblk == newblk) + { + nbuffer = obuffer; + newaction = oldaction; + } + else if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) + { + nbuffer = XLogInitBufferForRedo(record, 0); + page = (Page) BufferGetPage(nbuffer); + PageInit(page, BufferGetPageSize(nbuffer), 0); + newaction = BLK_NEEDS_REDO; + } + else + newaction = XLogReadBufferForRedo(record, 0, &nbuffer); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(rlocator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, newblk, &vmbuffer); + visibilitymap_clear(reln, newblk, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + /* Deal with new tuple */ + if (newaction == BLK_NEEDS_REDO) + { + char *recdata; + char *recdata_end; + Size datalen; + Size tuplen; + + recdata = XLogRecGetBlockData(record, 0, &datalen); + recdata_end = recdata + datalen; + + page = BufferGetPage(nbuffer); + + offnum = xlrec->new_offnum; + if (PageGetMaxOffsetNumber(page) + 1 < offnum) + elog(PANIC, "invalid max offset number"); + + if (xlrec->flags & XLH_UPDATE_PREFIX_FROM_OLD) + { + Assert(newblk == oldblk); + memcpy(&prefixlen, recdata, sizeof(uint16)); + recdata += sizeof(uint16); + } + if (xlrec->flags & XLH_UPDATE_SUFFIX_FROM_OLD) + { + Assert(newblk == oldblk); + memcpy(&suffixlen, recdata, sizeof(uint16)); + recdata += sizeof(uint16); + } + + memcpy((char *) &xlhdr, recdata, SizeOfHeapHeader); + recdata += SizeOfHeapHeader; + + tuplen = recdata_end - recdata; + Assert(tuplen <= MaxHeapTupleSize); + + htup = &tbuf.hdr; + MemSet((char *) htup, 0, SizeofHeapTupleHeader); + + /* + * Reconstruct the new tuple using the prefix and/or suffix from the + * old tuple, and the data stored in the WAL record. + */ + newp = (char *) htup + SizeofHeapTupleHeader; + if (prefixlen > 0) + { + int len; + + /* copy bitmap [+ padding] [+ oid] from WAL record */ + len = xlhdr.t_hoff - SizeofHeapTupleHeader; + memcpy(newp, recdata, len); + recdata += len; + newp += len; + + /* copy prefix from old tuple */ + memcpy(newp, (char *) oldtup.t_data + oldtup.t_data->t_hoff, prefixlen); + newp += prefixlen; + + /* copy new tuple data from WAL record */ + len = tuplen - (xlhdr.t_hoff - SizeofHeapTupleHeader); + memcpy(newp, recdata, len); + recdata += len; + newp += len; + } + else + { + /* + * copy bitmap [+ padding] [+ oid] + data from record, all in one + * go + */ + memcpy(newp, recdata, tuplen); + recdata += tuplen; + newp += tuplen; + } + Assert(recdata == recdata_end); + + /* copy suffix from old tuple */ + if (suffixlen > 0) + memcpy(newp, (char *) oldtup.t_data + oldtup.t_len - suffixlen, suffixlen); + + newlen = SizeofHeapTupleHeader + tuplen + prefixlen + suffixlen; + htup->t_infomask2 = xlhdr.t_infomask2; + htup->t_infomask = xlhdr.t_infomask; + htup->t_hoff = xlhdr.t_hoff; + + HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); + HeapTupleHeaderSetCmin(htup, FirstCommandId); + HeapTupleHeaderSetXmax(htup, xlrec->new_xmax); + /* Make sure there is no forward chain link in t_ctid */ + htup->t_ctid = newtid; + + offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); + if (offnum == InvalidOffsetNumber) + elog(PANIC, "failed to add tuple"); + + if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ + + PageSetLSN(page, lsn); + MarkBufferDirty(nbuffer); + } + + if (BufferIsValid(nbuffer) && nbuffer != obuffer) + UnlockReleaseBuffer(nbuffer); + if (BufferIsValid(obuffer)) + UnlockReleaseBuffer(obuffer); + + /* + * If the new page is running low on free space, update the FSM as well. + * Arbitrarily, our definition of "low" is less than 20%. We can't do much + * better than that without knowing the fill-factor for the table. + * + * However, don't update the FSM on HOT updates, because after crash + * recovery, either the old or the new tuple will certainly be dead and + * prunable. After pruning, the page will have roughly as much free space + * as it did before the update, assuming the new tuple is about the same + * size as the old one. + * + * XXX: Don't do this if the page was restored from full page image. We + * don't bother to update the FSM in that case, it doesn't need to be + * totally accurate anyway. + */ + if (newaction == BLK_NEEDS_REDO && !hot_update && freespace < BLCKSZ / 5) + XLogRecordPageWithFreeSpace(rlocator, newblk, freespace); +} + +static void +heap_xlog_confirm(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_confirm *xlrec = (xl_heap_confirm *) XLogRecGetData(record); + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + /* + * Confirm tuple as actually inserted + */ + ItemPointerSet(&htup->t_ctid, BufferGetBlockNumber(buffer), offnum); + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +static void +heap_xlog_lock(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_lock *xlrec = (xl_heap_lock *) XLogRecGetData(record); + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) + { + RelFileLocator rlocator; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; + Relation reln; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); + reln = CreateFakeRelcacheEntry(rlocator); + + visibilitymap_pin(reln, block, &vmbuffer); + visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = (Page) BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, + &htup->t_infomask2); + + /* + * Clear relevant update flags, but only if the modified infomask says + * there's no update. + */ + if (HEAP_XMAX_IS_LOCKED_ONLY(htup->t_infomask)) + { + HeapTupleHeaderClearHotUpdated(htup); + /* Make sure there is no forward chain link in t_ctid */ + ItemPointerSet(&htup->t_ctid, + BufferGetBlockNumber(buffer), + offnum); + } + HeapTupleHeaderSetXmax(htup, xlrec->xmax); + HeapTupleHeaderSetCmax(htup, FirstCommandId, false); + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +static void +heap_xlog_lock_updated(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_lock_updated *xlrec; + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + + xlrec = (xl_heap_lock_updated *) XLogRecGetData(record); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) + { + RelFileLocator rlocator; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; + Relation reln; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); + reln = CreateFakeRelcacheEntry(rlocator); + + visibilitymap_pin(reln, block, &vmbuffer); + visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, + &htup->t_infomask2); + HeapTupleHeaderSetXmax(htup, xlrec->xmax); + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +static void +heap_xlog_inplace(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_inplace *xlrec = (xl_heap_inplace *) XLogRecGetData(record); + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + uint32 oldlen; + Size newlen; + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + char *newtup = XLogRecGetBlockData(record, 0, &newlen); + + page = BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + oldlen = ItemIdGetLength(lp) - htup->t_hoff; + if (oldlen != newlen) + elog(PANIC, "wrong tuple length"); + + memcpy((char *) htup + htup->t_hoff, newtup, newlen); + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +void +heap_redo(XLogReaderState *record) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + + /* + * These operations don't overwrite MVCC data so no conflict processing is + * required. The ones in heap2 rmgr do. + */ + + switch (info & XLOG_HEAP_OPMASK) + { + case XLOG_HEAP_INSERT: + heap_xlog_insert(record); + break; + case XLOG_HEAP_DELETE: + heap_xlog_delete(record); + break; + case XLOG_HEAP_UPDATE: + heap_xlog_update(record, false); + break; + case XLOG_HEAP_TRUNCATE: + + /* + * TRUNCATE is a no-op because the actions are already logged as + * SMGR WAL records. TRUNCATE WAL record only exists for logical + * decoding. + */ + break; + case XLOG_HEAP_HOT_UPDATE: + heap_xlog_update(record, true); + break; + case XLOG_HEAP_CONFIRM: + heap_xlog_confirm(record); + break; + case XLOG_HEAP_LOCK: + heap_xlog_lock(record); + break; + case XLOG_HEAP_INPLACE: + heap_xlog_inplace(record); + break; + default: + elog(PANIC, "heap_redo: unknown op code %u", info); + } +} + +void +heap2_redo(XLogReaderState *record) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + + switch (info & XLOG_HEAP_OPMASK) + { + case XLOG_HEAP2_PRUNE_ON_ACCESS: + case XLOG_HEAP2_PRUNE_VACUUM_SCAN: + case XLOG_HEAP2_PRUNE_VACUUM_CLEANUP: + heap_xlog_prune_freeze(record); + break; + case XLOG_HEAP2_VISIBLE: + heap_xlog_visible(record); + break; + case XLOG_HEAP2_MULTI_INSERT: + heap_xlog_multi_insert(record); + break; + case XLOG_HEAP2_LOCK_UPDATED: + heap_xlog_lock_updated(record); + break; + case XLOG_HEAP2_NEW_CID: + + /* + * Nothing to do on a real replay, only used during logical + * decoding. + */ + break; + case XLOG_HEAP2_REWRITE: + heap_xlog_logical_rewrite(record); + break; + default: + elog(PANIC, "heap2_redo: unknown op code %u", info); + } +} + +/* + * Mask a heap page before performing consistency checks on it. + */ +void +heap_mask(char *pagedata, BlockNumber blkno) +{ + Page page = (Page) pagedata; + OffsetNumber off; + + mask_page_lsn_and_checksum(page); + + mask_page_hint_bits(page); + mask_unused_space(page); + + for (off = 1; off <= PageGetMaxOffsetNumber(page); off++) + { + ItemId iid = PageGetItemId(page, off); + char *page_item; + + page_item = (char *) (page + ItemIdGetOffset(iid)); + + if (ItemIdIsNormal(iid)) + { + HeapTupleHeader page_htup = (HeapTupleHeader) page_item; + + /* + * If xmin of a tuple is not yet frozen, we should ignore + * differences in hint bits, since they can be set without + * emitting WAL. + */ + if (!HeapTupleHeaderXminFrozen(page_htup)) + page_htup->t_infomask &= ~HEAP_XACT_MASK; + else + { + /* Still we need to mask xmax hint bits. */ + page_htup->t_infomask &= ~HEAP_XMAX_INVALID; + page_htup->t_infomask &= ~HEAP_XMAX_COMMITTED; + } + + /* + * During replay, we set Command Id to FirstCommandId. Hence, mask + * it. See heap_xlog_insert() for details. + */ + page_htup->t_choice.t_heap.t_field3.t_cid = MASK_MARKER; + + /* + * For a speculative tuple, heap_insert() does not set ctid in the + * caller-passed heap tuple itself, leaving the ctid field to + * contain a speculative token value - a per-backend monotonically + * increasing identifier. Besides, it does not WAL-log ctid under + * any circumstances. + * + * During redo, heap_xlog_insert() sets t_ctid to current block + * number and self offset number. It doesn't care about any + * speculative insertions on the primary. Hence, we set t_ctid to + * current block number and self offset number to ignore any + * inconsistency. + */ + if (HeapTupleHeaderIsSpeculative(page_htup)) + ItemPointerSet(&page_htup->t_ctid, blkno, off); + + /* + * NB: Not ignoring ctid changes due to the tuple having moved + * (i.e. HeapTupleHeaderIndicatesMovedPartitions), because that's + * important information that needs to be in-sync between primary + * and standby, and thus is WAL logged. + */ + } + + /* + * Ignore any padding bytes after the tuple, when the length of the + * item is not MAXALIGNed. + */ + if (ItemIdHasStorage(iid)) + { + int len = ItemIdGetLength(iid); + int padlen = MAXALIGN(len) - len; + + if (padlen > 0) + memset(page_item + len, MASK_MARKER, padlen); + } + } +} diff --git a/src/backend/access/heap/meson.build b/src/backend/access/heap/meson.build index e00d5b4f0d..19a990208e 100644 --- a/src/backend/access/heap/meson.build +++ b/src/backend/access/heap/meson.build @@ -4,6 +4,7 @@ backend_sources += files( 'heapam.c', 'heapam_handler.c', 'heapam_visibility.c', + 'heapam_xlog.c', 'heaptoast.c', 'hio.c', 'pruneheap.c', diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 9e9aec88a6..b92eb506ec 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -14,6 +14,7 @@ #ifndef HEAPAM_H #define HEAPAM_H +#include "access/heapam_xlog.h" #include "access/relation.h" /* for backward compatibility */ #include "access/relscan.h" #include "access/sdir.h" @@ -422,4 +423,28 @@ extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data, extern void HeapCheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot); +/* + * heap_execute_freeze_tuple + * Execute the prepared freezing of a tuple with caller's freeze plan. + * + * Caller is responsible for ensuring that no other backend can access the + * storage underlying this tuple, either by holding an exclusive lock on the + * buffer containing it (which is what lazy VACUUM does), or by having it be + * in private storage (which is what CLUSTER and friends do). + */ +static inline void +heap_execute_freeze_tuple(HeapTupleHeader tuple, HeapTupleFreeze *frz) +{ + HeapTupleHeaderSetXmax(tuple, frz->xmax); + + if (frz->frzflags & XLH_FREEZE_XVAC) + HeapTupleHeaderSetXvac(tuple, FrozenTransactionId); + + if (frz->frzflags & XLH_INVALID_XVAC) + HeapTupleHeaderSetXvac(tuple, InvalidTransactionId); + + tuple->t_infomask = frz->t_infomask; + tuple->t_infomask2 = frz->t_infomask2; +} + #endif /* HEAPAM_H */ ^ permalink raw reply [nested|flat] 71+ messages in thread
* Re: Separate HEAP WAL replay logic into its own file 2024-06-17 06:20 Separate HEAP WAL replay logic into its own file Li, Yong <[email protected]> @ 2024-06-17 15:01 ` Melanie Plageman <[email protected]> 0 siblings, 0 replies; 71+ messages in thread From: Melanie Plageman @ 2024-06-17 15:01 UTC (permalink / raw) To: Li, Yong <[email protected]>; +Cc: Debnath, Shawn <[email protected]>; Shyrabokau, Anton <[email protected]>; PostgreSQL Hackers <[email protected]> On Mon, Jun 17, 2024 at 2:20 AM Li, Yong <[email protected]> wrote: > > Hi PostgreSQL hackers, > > For most access methods in PostgreSQL, the implementation of the access method itself and the implementation of its WAL replay logic are organized in separate source files. However, the HEAP access method is an exception. Both the access method and the WAL replay logic are collocated in the same heapam.c. To follow the pattern established by other access methods and to improve maintainability, I made the enclosed patch to separate HEAP’s replay logic into its own file. The changes are straightforward. Move the replay related functions into the new heapam_xlog.c file, push the common heap_execute_freeze_tuple() helper function into the heapam.h header, and adjust the build files. I'm not against this change, but I am curious at what inspired this. Were you looking at Postgres code and simply noticed that there isn't a heapam_xlog.c (like there is a nbtxlog.c etc) and thought that you wanted to change that? Or is there some specific reason this would help you as a Postgres developer, user, or ecosystem member? - Melanie ^ permalink raw reply [nested|flat] 71+ messages in thread
end of thread, other threads:[~2024-06-17 15:01 UTC | newest] Thread overview: 71+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2020-03-19 01:54 [PATCH 5/7] fix Tomas Vondra <[email protected]> 2020-03-19 02:02 [PATCH 7/7] fix Tomas Vondra <[email protected]> 2020-06-15 10:28 [PATCH 2/3] fix Your Name <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-08-01 02:24 [PATCH 2/2] fix Justin Pryzby <[email protected]> 2020-12-12 17:42 [PATCH v34 2/8] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-01-10 21:41 [PATCH] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2021-03-13 21:51 [PATCH 2/3] fix Justin Pryzby <[email protected]> 2024-06-17 06:20 Separate HEAP WAL replay logic into its own file Li, Yong <[email protected]> 2024-06-17 15:01 ` Re: Separate HEAP WAL replay logic into its own file Melanie Plageman <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox