Skip to content

[pull] master from postgres:master #121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 26, 2025
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
6 changes: 3 additions & 3 deletions contrib/pg_stat_statements/pg_stat_statements.c
Original file line number Diff line number Diff line change
Expand Up @@ -2844,9 +2844,9 @@ generate_normalized_query(JumbleState *jstate, const char *query,
/*
* If we have an external param at this location, but no lists are
* being squashed across the query, then we skip here; this will make
* us print print the characters found in the original query that
* represent the parameter in the next iteration (or after the loop is
* done), which is a bit odd but seems to work okay in most cases.
* us print the characters found in the original query that represent
* the parameter in the next iteration (or after the loop is done),
* which is a bit odd but seems to work okay in most cases.
*/
if (jstate->clocations[i].extern_param && !jstate->has_squashed_lists)
continue;
Expand Down
4 changes: 2 additions & 2 deletions doc/src/sgml/ref/pg_dump.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -1278,10 +1278,10 @@ PostgreSQL documentation
<para>
The data section contains actual table data, large-object
contents, sequence values, and statistics for tables,
materialized views, and foriegn tables.
materialized views, and foreign tables.
Post-data items include definitions of indexes, triggers, rules,
statistics for indexes, and constraints other than validated check
constraints.
and not-null constraints.
Pre-data items include all other data definition items.
</para>
</listitem>
Expand Down
7 changes: 3 additions & 4 deletions src/backend/access/heap/heapam_xlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,9 @@ heap_xlog_insert(XLogReaderState *record)
ItemPointerSetBlockNumber(&target_tid, blkno);
ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum);

/* No freezing in the heap_insert() code path */
Assert(!(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.
Expand Down Expand Up @@ -508,10 +511,6 @@ heap_xlog_insert(XLogReaderState *record)
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))
Expand Down
53 changes: 16 additions & 37 deletions src/backend/access/heap/vacuumlazy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1872,8 +1872,6 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno,
*/
if (!PageIsAllVisible(page))
{
uint8 old_vmbits;

START_CRIT_SECTION();

/* mark buffer dirty before writing a WAL record */
Expand All @@ -1893,24 +1891,16 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno,
log_newpage_buffer(buf, true);

PageSetAllVisible(page);
old_vmbits = visibilitymap_set(vacrel->rel, blkno, buf,
InvalidXLogRecPtr,
vmbuffer, InvalidTransactionId,
VISIBILITYMAP_ALL_VISIBLE |
VISIBILITYMAP_ALL_FROZEN);
visibilitymap_set(vacrel->rel, blkno, buf,
InvalidXLogRecPtr,
vmbuffer, InvalidTransactionId,
VISIBILITYMAP_ALL_VISIBLE |
VISIBILITYMAP_ALL_FROZEN);
END_CRIT_SECTION();

/*
* If the page wasn't already set all-visible and/or all-frozen in
* the VM, count it as newly set for logging.
*/
if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0)
{
vacrel->vm_new_visible_pages++;
vacrel->vm_new_visible_frozen_pages++;
}
else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0)
vacrel->vm_new_frozen_pages++;
/* Count the newly all-frozen pages for logging */
vacrel->vm_new_visible_pages++;
vacrel->vm_new_visible_frozen_pages++;
}

freespace = PageGetHeapFreeSpace(page);
Expand Down Expand Up @@ -2915,7 +2905,6 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer,
if (heap_page_is_all_visible(vacrel, buffer, &visibility_cutoff_xid,
&all_frozen))
{
uint8 old_vmbits;
uint8 flags = VISIBILITYMAP_ALL_VISIBLE;

if (all_frozen)
Expand All @@ -2925,25 +2914,15 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer,
}

PageSetAllVisible(page);
old_vmbits = visibilitymap_set(vacrel->rel, blkno, buffer,
InvalidXLogRecPtr,
vmbuffer, visibility_cutoff_xid,
flags);
visibilitymap_set(vacrel->rel, blkno, buffer,
InvalidXLogRecPtr,
vmbuffer, visibility_cutoff_xid,
flags);

/*
* If the page wasn't already set all-visible and/or all-frozen in the
* VM, count it as newly set for logging.
*/
if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0)
{
vacrel->vm_new_visible_pages++;
if (all_frozen)
vacrel->vm_new_visible_frozen_pages++;
}

else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0 &&
all_frozen)
vacrel->vm_new_frozen_pages++;
/* Count the newly set VM page for logging */
vacrel->vm_new_visible_pages++;
if (all_frozen)
vacrel->vm_new_visible_frozen_pages++;
}

/* Revert to the previous phase information for error traceback */
Expand Down
4 changes: 2 additions & 2 deletions src/backend/commands/indexcmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -2469,8 +2469,8 @@ GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype,
cmptype == COMPARE_EQ ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) :
cmptype == COMPARE_OVERLAP ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) :
cmptype == COMPARE_CONTAINED_BY ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0,
errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".",
cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid)));
errdetail("Could not translate compare type %d for operator family \"%s\" of access method \"%s\".",
cmptype, get_opfamily_name(opfamily, false), get_am_name(amid)));

/*
* We parameterize rhstype so foreign keys can ask for a <@ operator
Expand Down
4 changes: 2 additions & 2 deletions src/backend/commands/tablecmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -10330,8 +10330,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
for_overlaps
? errmsg("could not identify an overlaps operator for foreign key")
: errmsg("could not identify an equality operator for foreign key"),
errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".",
cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid)));
errdetail("Could not translate compare type %d for operator family \"%s\" of access method \"%s\".",
cmptype, get_opfamily_name(opfamily, false), get_am_name(amid)));

/*
* There had better be a primary equality operator for the index.
Expand Down
92 changes: 80 additions & 12 deletions src/bin/pg_dump/pg_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,9 @@ static void buildMatViewRefreshDependencies(Archive *fout);
static void getTableDataFKConstraints(void);
static void determineNotNullFlags(Archive *fout, PGresult *res, int r,
TableInfo *tbinfo, int j,
int i_notnull_name, int i_notnull_invalidoid,
int i_notnull_name,
int i_notnull_comment,
int i_notnull_invalidoid,
int i_notnull_noinherit,
int i_notnull_islocal,
PQExpBuffer *invalidnotnulloids);
Expand Down Expand Up @@ -9006,6 +9008,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
int i_attalign;
int i_attislocal;
int i_notnull_name;
int i_notnull_comment;
int i_notnull_noinherit;
int i_notnull_islocal;
int i_notnull_invalidoid;
Expand Down Expand Up @@ -9089,15 +9092,17 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)

/*
* Find out any NOT NULL markings for each column. In 18 and up we read
* pg_constraint to obtain the constraint name. notnull_noinherit is set
* pg_constraint to obtain the constraint name, and for valid constraints
* also pg_description to obtain its comment. notnull_noinherit is set
* according to the NO INHERIT property. For versions prior to 18, we
* store an empty string as the name when a constraint is marked as
* attnotnull (this cues dumpTableSchema to print the NOT NULL clause
* without a name); also, such cases are never NO INHERIT.
*
* For invalid constraints, we need to store their OIDs for processing
* elsewhere, so we bring the pg_constraint.oid value when the constraint
* is invalid, and NULL otherwise.
* is invalid, and NULL otherwise. Their comments are handled not here
* but by collectComments, because they're their own dumpable object.
*
* We track in notnull_islocal whether the constraint was defined directly
* in this table or via an ancestor, for binary upgrade. flagInhAttrs
Expand All @@ -9107,13 +9112,16 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
if (fout->remoteVersion >= 180000)
appendPQExpBufferStr(q,
"co.conname AS notnull_name,\n"
"CASE WHEN co.convalidated THEN pt.description"
" ELSE NULL END AS notnull_comment,\n"
"CASE WHEN NOT co.convalidated THEN co.oid "
"ELSE NULL END AS notnull_invalidoid,\n"
"co.connoinherit AS notnull_noinherit,\n"
"co.conislocal AS notnull_islocal,\n");
else
appendPQExpBufferStr(q,
"CASE WHEN a.attnotnull THEN '' ELSE NULL END AS notnull_name,\n"
"NULL AS notnull_comment,\n"
"NULL AS notnull_invalidoid,\n"
"false AS notnull_noinherit,\n"
"a.attislocal AS notnull_islocal,\n");
Expand Down Expand Up @@ -9157,15 +9165,16 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)

/*
* In versions 18 and up, we need pg_constraint for explicit NOT NULL
* entries. Also, we need to know if the NOT NULL for each column is
* backing a primary key.
* entries and pg_description to get their comments.
*/
if (fout->remoteVersion >= 180000)
appendPQExpBufferStr(q,
" LEFT JOIN pg_catalog.pg_constraint co ON "
"(a.attrelid = co.conrelid\n"
" AND co.contype = 'n' AND "
"co.conkey = array[a.attnum])\n");
"co.conkey = array[a.attnum])\n"
" LEFT JOIN pg_catalog.pg_description pt ON "
"(pt.classoid = co.tableoid AND pt.objoid = co.oid)\n");

appendPQExpBufferStr(q,
"WHERE a.attnum > 0::pg_catalog.int2\n"
Expand All @@ -9189,6 +9198,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
i_attalign = PQfnumber(res, "attalign");
i_attislocal = PQfnumber(res, "attislocal");
i_notnull_name = PQfnumber(res, "notnull_name");
i_notnull_comment = PQfnumber(res, "notnull_comment");
i_notnull_invalidoid = PQfnumber(res, "notnull_invalidoid");
i_notnull_noinherit = PQfnumber(res, "notnull_noinherit");
i_notnull_islocal = PQfnumber(res, "notnull_islocal");
Expand Down Expand Up @@ -9257,6 +9267,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
tbinfo->attfdwoptions = (char **) pg_malloc(numatts * sizeof(char *));
tbinfo->attmissingval = (char **) pg_malloc(numatts * sizeof(char *));
tbinfo->notnull_constrs = (char **) pg_malloc(numatts * sizeof(char *));
tbinfo->notnull_comment = (char **) pg_malloc(numatts * sizeof(char *));
tbinfo->notnull_invalid = (bool *) pg_malloc(numatts * sizeof(bool));
tbinfo->notnull_noinh = (bool *) pg_malloc(numatts * sizeof(bool));
tbinfo->notnull_islocal = (bool *) pg_malloc(numatts * sizeof(bool));
Expand Down Expand Up @@ -9288,11 +9299,14 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
determineNotNullFlags(fout, res, r,
tbinfo, j,
i_notnull_name,
i_notnull_comment,
i_notnull_invalidoid,
i_notnull_noinherit,
i_notnull_islocal,
&invalidnotnulloids);

tbinfo->notnull_comment[j] = PQgetisnull(res, r, i_notnull_comment) ?
NULL : pg_strdup(PQgetvalue(res, r, i_notnull_comment));
tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, r, i_attoptions));
tbinfo->attcollation[j] = atooid(PQgetvalue(res, r, i_attcollation));
tbinfo->attcompression[j] = *(PQgetvalue(res, r, i_attcompression));
Expand Down Expand Up @@ -9704,8 +9718,9 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
* 4) The column has a constraint with a known name; in that case
* notnull_constrs carries that name and dumpTableSchema will print
* "CONSTRAINT the_name NOT NULL". However, if the name is the default
* (table_column_not_null), there's no need to print that name in the dump,
* so notnull_constrs is set to the empty string and it behaves as case 2.
* (table_column_not_null) and there's no comment on the constraint,
* there's no need to print that name in the dump, so notnull_constrs
* is set to the empty string and it behaves as case 2.
*
* In a child table that inherits from a parent already containing NOT NULL
* constraints and the columns in the child don't have their own NOT NULL
Expand All @@ -9732,6 +9747,7 @@ static void
determineNotNullFlags(Archive *fout, PGresult *res, int r,
TableInfo *tbinfo, int j,
int i_notnull_name,
int i_notnull_comment,
int i_notnull_invalidoid,
int i_notnull_noinherit,
int i_notnull_islocal,
Expand Down Expand Up @@ -9805,11 +9821,13 @@ determineNotNullFlags(Archive *fout, PGresult *res, int r,
{
/*
* In binary upgrade of inheritance child tables, must have a
* constraint name that we can UPDATE later.
* constraint name that we can UPDATE later; same if there's a
* comment on the constraint.
*/
if (dopt->binary_upgrade &&
!tbinfo->ispartition &&
!tbinfo->notnull_islocal)
if ((dopt->binary_upgrade &&
!tbinfo->ispartition &&
!tbinfo->notnull_islocal) ||
!PQgetisnull(res, r, i_notnull_comment))
{
tbinfo->notnull_constrs[j] =
pstrdup(PQgetvalue(res, r, i_notnull_name));
Expand Down Expand Up @@ -17686,6 +17704,56 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
dumpTableSecLabel(fout, tbinfo, reltypename);

/*
* Dump comments for not-null constraints that aren't to be dumped
* separately (those are processed by collectComments/dumpComment).
*/
if (!fout->dopt->no_comments && dopt->dumpSchema &&
fout->remoteVersion >= 180000)
{
PQExpBuffer comment = NULL;
PQExpBuffer tag = NULL;

for (j = 0; j < tbinfo->numatts; j++)
{
if (tbinfo->notnull_constrs[j] != NULL &&
tbinfo->notnull_comment[j] != NULL)
{
if (comment == NULL)
{
comment = createPQExpBuffer();
tag = createPQExpBuffer();
}
else
{
resetPQExpBuffer(comment);
resetPQExpBuffer(tag);
}

appendPQExpBuffer(comment, "COMMENT ON CONSTRAINT %s ON %s IS ",
fmtId(tbinfo->notnull_constrs[j]), qualrelname);
appendStringLiteralAH(comment, tbinfo->notnull_comment[j], fout);
appendPQExpBufferStr(comment, ";\n");

appendPQExpBuffer(tag, "CONSTRAINT %s ON %s",
fmtId(tbinfo->notnull_constrs[j]), qrelname);

ArchiveEntry(fout, nilCatalogId, createDumpId(),
ARCHIVE_OPTS(.tag = tag->data,
.namespace = tbinfo->dobj.namespace->dobj.name,
.owner = tbinfo->rolname,
.description = "COMMENT",
.section = SECTION_NONE,
.createStmt = comment->data,
.deps = &(tbinfo->dobj.dumpId),
.nDeps = 1));
}
}

destroyPQExpBuffer(comment);
destroyPQExpBuffer(tag);
}

/* Dump comments on inlined table constraints */
for (j = 0; j < tbinfo->ncheck; j++)
{
Expand Down
1 change: 1 addition & 0 deletions src/bin/pg_dump/pg_dump.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ typedef struct _tableInfo
* there isn't one on this column. If
* empty string, unnamed constraint
* (pre-v17) */
char **notnull_comment; /* comment thereof */
bool *notnull_invalid; /* true for NOT NULL NOT VALID */
bool *notnull_noinh; /* NOT NULL is NO INHERIT */
bool *notnull_islocal; /* true if NOT NULL has local definition */
Expand Down
Loading