Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion contrib/amcheck/t/001_verify_heapam.pl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use PostgresNode;
use TestLib;

use Test::More tests => 79;
use Test::More tests => 80;

my ($node, $result);

Expand Down Expand Up @@ -47,6 +47,9 @@
#
fresh_test_table('test');
$node->safe_psql('postgres', q(VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) test));
detects_no_corruption(
"verify_heapam('test')",
"all-frozen not corrupted table");
corrupt_first_page('test');
detects_heap_corruption("verify_heapam('test')",
"all-frozen corrupted table");
Expand Down Expand Up @@ -92,6 +95,15 @@ sub fresh_test_table
ALTER TABLE $relname ALTER b SET STORAGE external;
INSERT INTO $relname (a, b)
(SELECT gs, repeat('b',gs*10) FROM generate_series(1,1000) gs);
BEGIN;
SAVEPOINT s1;
SELECT 1 FROM $relname WHERE a = 42 FOR UPDATE;
UPDATE $relname SET b = b WHERE a = 42;
RELEASE s1;
SAVEPOINT s1;
SELECT 1 FROM $relname WHERE a = 42 FOR UPDATE;
UPDATE $relname SET b = b WHERE a = 42;
COMMIT;
));
}

Expand Down
7 changes: 0 additions & 7 deletions contrib/amcheck/verify_heapam.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,13 +608,6 @@ check_tuple_header_and_visibilty(HeapTupleHeader tuphdr, HeapCheckContext *ctx)
ctx->tuphdr->t_hoff, ctx->lp_len));
header_garbled = true;
}
if ((ctx->tuphdr->t_infomask & HEAP_XMAX_LOCK_ONLY) &&
(ctx->tuphdr->t_infomask2 & HEAP_KEYS_UPDATED))
{
report_corruption(ctx,
pstrdup("tuple is marked as only locked, but also claims key columns were updated"));
header_garbled = true;
}

if ((ctx->tuphdr->t_infomask & HEAP_XMAX_COMMITTED) &&
(ctx->tuphdr->t_infomask & HEAP_XMAX_IS_MULTI))
Expand Down
17 changes: 9 additions & 8 deletions doc/src/sgml/config.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -4503,15 +4503,16 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
view. The standby will report
the last write-ahead log location it has written, the last position it
has flushed to disk, and the last position it has applied.
This parameter's
value is the maximum amount of time between reports. Updates are
sent each time the write or flush positions change, or at least as
often as specified by this parameter. Thus, the apply position may
lag slightly behind the true position.
This parameter's value is the maximum amount of time between reports.
Updates are sent each time the write or flush positions change, or as
often as specified by this parameter if set to a non-zero value.
There are additional cases where updates are sent while ignoring this
parameter; for example, when processing of the existing WAL completes
or when <varname>synchronous_commit</varname> is set to
<literal>remote_apply</literal>.
Thus, the apply position may lag slightly behind the true position.
If this value is specified without units, it is taken as seconds.
The default value is 10 seconds.
Setting this parameter to zero disables status updates completely.
This parameter can only be set in
The default value is 10 seconds. This parameter can only be set in
the <filename>postgresql.conf</filename> file or on the server
command line.
</para>
Expand Down
7 changes: 4 additions & 3 deletions src/backend/access/heap/README.tuplock
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,10 @@ The following infomask bits are applicable:
FOR UPDATE; this is implemented by the HEAP_KEYS_UPDATED bit.

- HEAP_KEYS_UPDATED
This bit lives in t_infomask2. If set, indicates that the XMAX updated
this tuple and changed the key values, or it deleted the tuple.
It's set regardless of whether the XMAX is a TransactionId or a MultiXactId.
This bit lives in t_infomask2. If set, indicates that the operation(s) done
by the XMAX compromise the tuple key, such as a SELECT FOR UPDATE, an UPDATE
that modifies the columns of the key, or a DELETE. It's set regardless of
whether the XMAX is a TransactionId or a MultiXactId.

We currently never set the HEAP_XMAX_COMMITTED when the HEAP_XMAX_IS_MULTI bit
is set.
8 changes: 3 additions & 5 deletions src/backend/access/heap/hio.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,10 @@ RelationPutHeapTuple(Relation relation,

/*
* Do not allow tuples with invalid combinations of hint bits to be placed
* on a page. These combinations are detected as corruption by the
* contrib/amcheck logic, so if you disable one or both of these
* assertions, make corresponding changes there.
* on a page. This combination is detected as corruption by the
* contrib/amcheck logic, so if you disable this assertion, make
* corresponding changes there.
*/
Assert(!((tuple->t_data->t_infomask & HEAP_XMAX_LOCK_ONLY) &&
(tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED)));
Assert(!((tuple->t_data->t_infomask & HEAP_XMAX_COMMITTED) &&
(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI)));

Expand Down
9 changes: 5 additions & 4 deletions src/backend/optimizer/path/allpaths.c
Original file line number Diff line number Diff line change
Expand Up @@ -3019,10 +3019,11 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
join_search_one_level(root, lev);

/*
* Run generate_partitionwise_join_paths() and generate_gather_paths()
* for each just-processed joinrel. We could not do this earlier
* because both regular and partial paths can get added to a
* particular joinrel at multiple times within join_search_one_level.
* Run generate_partitionwise_join_paths() and
* generate_useful_gather_paths() for each just-processed joinrel. We
* could not do this earlier because both regular and partial paths
* can get added to a particular joinrel at multiple times within
* join_search_one_level.
*
* After that, we're done creating paths for the joinrel, so run
* set_cheapest().
Expand Down
17 changes: 9 additions & 8 deletions src/backend/optimizer/plan/planner.c
Original file line number Diff line number Diff line change
Expand Up @@ -7212,14 +7212,14 @@ create_partial_grouping_paths(PlannerInfo *root,
* Generate Gather and Gather Merge paths for a grouping relation or partial
* grouping relation.
*
* generate_gather_paths does most of the work, but we also consider a special
* case: we could try sorting the data by the group_pathkeys and then applying
* Gather Merge.
* generate_useful_gather_paths does most of the work, but we also consider a
* special case: we could try sorting the data by the group_pathkeys and then
* applying Gather Merge.
*
* NB: This function shouldn't be used for anything other than a grouped or
* partially grouped relation not only because of the fact that it explicitly
* references group_pathkeys but we pass "true" as the third argument to
* generate_gather_paths().
* generate_useful_gather_paths().
*/
static void
gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
Expand Down Expand Up @@ -7379,10 +7379,11 @@ apply_scanjoin_target_to_paths(PlannerInfo *root,
* variations. So we drop old paths and thereby force the work to be done
* below the Append, except in the case of a non-parallel-safe target.
*
* Some care is needed, because we have to allow generate_gather_paths to
* see the old partial paths in the next stanza. Hence, zap the main
* pathlist here, then allow generate_gather_paths to add path(s) to the
* main list, and finally zap the partial pathlist.
* Some care is needed, because we have to allow
* generate_useful_gather_paths to see the old partial paths in the next
* stanza. Hence, zap the main pathlist here, then allow
* generate_useful_gather_paths to add path(s) to the main list, and
* finally zap the partial pathlist.
*/
if (rel_is_partitioned)
rel->pathlist = NIL;
Expand Down
7 changes: 6 additions & 1 deletion src/backend/regex/regc_nfa.c
Original file line number Diff line number Diff line change
Expand Up @@ -3082,8 +3082,13 @@ checkmatchall_recurse(struct nfa *nfa, struct state *s,
{
/* We found an all-RAINBOW path to the post state */
result = true;
/* ... which should not be adjacent to the pre state */
if (depth < 0)
{
NERR(REG_ASSERT);
return false;
}
/* Record potential match lengths */
assert(depth >= 0);
hasmatch[depth] = true;
if (foundloop)
{
Expand Down