The column ALTER emitted RESTART SET START whenever START changed,
rewinding the identity sequence so the next generated value could
collide with existing rows; Schema Diff hit this too when only START
differed. RESTART is now emitted only when the sequence is still pending
at its old START with nothing generated since, or when its current value
would fall outside a new MINVALUE or MAXVALUE (which PostgreSQL refuses
without it). To decide, the column update reads last_value and is_called
from the sequence itself when START is set, since
pg_sequence_last_value() is NULL after any RESTART WITH.
The fix for #10357 remounts the dialog form on Reset so that SQL editor
values still waiting to come back through SchemaView are discarded. This
spec types into an SQL field, removes the edit, types again and presses
Reset before SchemaView has passed those values back, then checks that the
original value is shown. Without the remount the editor keeps the last
typed value.
When an edit and its undo (or a key, Backspace and the same key again) were
all reported before SchemaView passed the first value back, the editor's
pending values held the same text twice. Matching the newest copy dropped the
value in between, which then replaced the document when it came back. Values
come back in order, so InputSQL now matches the earliest copy; if some are
skipped, the leftover entries are cleared by later changes.
The inherited-columns CTE joins on column name, so a column merged from
more than one parent produced a row per parent, and DISTINCT ON then
kept whichever came first. Order by the inheritance sequence number so
the first parent in inheritance order is always reported.
A source column without a comment has a description of None, which the
column update template skips, so the comment was reported as a difference
but never dropped. Send an empty string in that case, as the column dialog
does when a comment is cleared, so COMMENT ON COLUMN ... IS '' is
generated.
The SQL_ASCII codec unescaped every valid \uXXXX and \UXXXXXXXX
sequence, so a value or column name containing '\u0041' was shown as
'A', and saving the row wrote 'A' back.
Decode each byte as latin-1 and only unescape escapes for code points
from U+0100 to U+10FFFF, which are the only ones pgAdmin writes when
encoding. Lower escapes and invalid sequences are kept as their literal
bytes. Encoding is unchanged.
- Decode long runs of backslashes in linear time in the SQL_ASCII codec.
The column and table templates only emitted an identity option when its
value was greater than -1, which was meant to skip unset options but
also dropped every negative one. So on a descending identity column,
changing INCREMENT to -2 in the column dialog or a MINVALUE difference
in Schema Diff produced no ALTER at all, and the table's CREATE SQL lost
its INCREMENT, START, MINVALUE and MAXVALUE. Test for an unset option
explicitly instead.
The tests patch psql.sio.emit globally, so a psql session from another
test that is still running can emit pty-output into the same mock. Only
count the emit calls sent to the test's own room.
pgAdmin uses raw_unicode_escape as the Python codec for SQL_ASCII
connections, and psycopg decodes column names and query text with it.
A name such as "C:\User\te" contains '\U' that is not a valid
\UXXXXXXXX escape, so decoding raised "truncated \UXXXXXXXX escape".
Register a pgAdmin codec that behaves like raw_unicode_escape but keeps
invalid escape sequences as their literal bytes, and use it for
SQL_ASCII. Encoding is unchanged.
- Give the SQL_ASCII codec incremental support, and keep invalid escapes in server errors.
Each poll of the debugger returns its own batch of notices without a
trailing newline, so appending them directly ran messages from separate
steps together. Start each appended batch on a new line.
- Clarify that debugger message batches only usually lack a trailing newline.
SchemaView passes a field's value back a render or two after the change,
so when two keys are pressed almost at once the SQL editor could be handed
the value from the first key whilst already holding the second. Applying
that older value replaced the whole document, which moved the cursor to
the start. InputSQL now remembers the values the editor has reported and
ignores one that is older than the editor's current content.
- Remount the dialog form on Reset so pending SQL editor values are discarded.
pg_constraint.confkey holds the attribute numbers of a foreign key's
referenced columns, which differ between databases when a column has been
dropped from the referenced table in only one of them. The referenced
columns are already compared by name, so ignore confkey as conkey already
is.
A foreign key whose referenced columns differ is now dropped and
recreated, rather than being reported as different with an empty diff.
parse_priv_to_db() now merges ACL entries that grant exactly the same
privileges, from the same grantor, into one entry listing every grantee,
so the templates for all object types produce
'GRANT ... TO role1, role2;' rather than one statement per role.
A privilege whose grantee is changed away from PUBLIC now also revokes
PUBLIC's privileges, rather than leaving them in place.
Schema Diff passes a changed column with all of its properties, but the
column update template emitted COMMENT ON COLUMN and every identity
sequence option without comparing them with the column as it stands.
So any difference in an identity column repeated its unchanged comment,
and repeated START as RESTART SET START, which rewinds the identity
sequence on the target. Only emit those that actually differ.
resetLayout() re-opened the non-default tabs without their metaData, so
the layout saved straight afterwards stored them as bare ids and loadTab()
had nothing to rebuild them from on the next load. Their group is now
carried over as well, rather than falling back to 'default'.
PostgreSQL 18 rejects UNLOGGED on a partitioned table, in both CREATE
TABLE and ALTER TABLE ... SET UNLOGGED/LOGGED, so on PG18 and later
the Unlogged switch is now disabled for partitioned tables (including
a partitioned partition) and the generated CREATE, ALTER and reverse
engineered SQL no longer include it. Leaf partitions can still be
unlogged, and older servers are unchanged.
The Partitions SQL section of a partitioned table's script also now
keeps UNLOGGED for partitions that are unlogged, which it previously
dropped.
The route has no user placeholder, so url_for() always dropped it and
the backend never read it; the now-unused user argument is removed
from the connect-server helpers too.
The latin-1 read fallback now records the encoding, and encodings are
tracked per resolved file path rather than by basename, and only after
a save succeeds.
A cached manager whose server definition no longer matches is rebuilt,
and the owner's settings are deep-copied before being overlaid for
shared-server users.
The #10330 branch added and then dropped a schema version bump; replayed
on top of #10506, which also took version 53, the squash set it back to
52 even though the server_passexec_name migration remains.
Tags are copied to a user's shared server entry, whilst passfile is
treated like passwords, SSH keys and SSL client files and is never
copied from or overlaid with the owner's value.
Connection parameters with a libpq environment variable are exported to
pg_dump, pg_restore, psql and the other utilities, PGSERVICE comes from
the per-user server manager, and boolean parameters stored as strings
are normalised consistently with the main connection path.
psql is launched directly through pywinpty, read errors end the session
cleanly, spawn failures are reported to the terminal, and the pty is
closed when the session ends.
Views with a single base table, all of its primary key columns exposed,
no INSTEAD OF triggers and no rules other than _RETURN can be edited in
View/Edit Data. Updates and deletes are checked row by row, and adding
rows is disabled because inserts through views are not supported.
Accumulate Responses API function calls by item, treating output_index
and the item id as names for the same call, and use
response.output_item.done for the final name, call_id and arguments.
Users holding ADMIN OPTION on a role, directly or through an inherited
membership as PostgreSQL itself allows, can now change its members,
whilst all other property changes still require CREATEROLE.
The inherited-columns CTE compared pg_inherits.inhrelid with a fixed
OID instead of the table being queried, so inherited columns were never
reported as such on PostgreSQL 14 and later.
In server mode, users choose a password exec command by name from
SERVER_PASSEXEC_COMMANDS rather than entering a command line. Existing
commands are converted on upgrade once the allowlist is configured; if
it is empty the conversion is postponed and a warning is logged.
The database is passed as a dbname= connection string, quoted when
needed, so service files and unusual names work, and backup and
import/export require a database for object-level jobs.
Converting a plain column to SERIAL now creates the sequence with the
source sequence's own type, moves it past existing values and restores
the nextval() default; converting away from SERIAL drops the default
before the owned sequence.
The providers keep credentials and authentication state in nested dicts
in the Flask session, which ManagedSession does not detect as modified,
and FileBackedSessionManager may also defer the disk write. Add a
write_session_through() helper that sets both session.modified and
session.force_write, and call it wherever a provider stores or clears
state that a later request depends on.
The shortcut called focus() on the rc-dock tab pane, a plain div that
cannot take focus, so focus stayed where it was. Focus the react-aspen
tree inside the panel instead, which is already focusable, and draw its
focus indicator with the theme's activeBorder colour on :focus-visible.
Electron 43 deliberately stopped remembering the last folder used by the
native open and save dialogs, so they always opened in Downloads. Track the
last visited directory in the runtime's config store and pass it as
defaultPath whenever the caller has not specified a location.
Results can now be saved as JSON or XML as well as CSV, with preferences
for the output file encoding, prepending a byte order mark to CSV/TXT
files, and the default state of the grid's copy-with-headers toggle.
execute_void() reused the cached server-side cursor, whose execute() cannot
run a transaction-control statement, and the resulting exception was
swallowed, so the statement never reached the database. Run such statements
through a throwaway plain cursor instead, and guard poll()'s error path
against a cursor with no query.
Tab switching now works when focus is inside a tool and defaults to
Ctrl+Alt+PageUp/PageDown, Ctrl/Cmd+Shift+D duplicates the current line or
selection in the SQL editor, and dialogs handle Enter and Escape
consistently.
Add --statistics-only, --no-policies, --no-data, --no-schema,
--no-statistics, --statistics and --sequence-data where the utilities
support them, gated on server version 18, and suppress combinations that
pg_dump, pg_dumpall and pg_restore would reject. The pg_dumpall --format
and pg_restore --exclude-database/--globals-only options were reverted
before PostgreSQL 18.0 and so are not included.
The expression check compared pg_get_indexdef() output, which is quoted,
with the raw attname, so such columns were treated as expressions and
dropped. Compare against quote_ident(attname) instead, and replace the
.strip('"') calls with an unquote_ident() helper that also unescapes
doubled inner quotes.
get_ctypes.sql wrapped a multi-row UNION in a scalar subquery, which failed
when a libc database's collation and ctype differed. Rewrite it as a flat
UNION, add a 15_plus variant, and read datlocale for ICU and builtin
providers on PostgreSQL 17+.
check_external_config_db() let connection failures and malformed URIs
propagate as exceptions. Create the engine inside the try block, return
False on any failure, and dispose of the engine in a finally block.
SSHTunnelForwarder defaults allow_agent to True, so pgAdmin probed the
agent even when it had a credential of its own. Disable the agent in that
case, keeping it enabled when neither is configured.
The shipped OAUTH2_CONFIG template sets OAUTH2_USERINFO_ENDPOINT to None,
but get_user_profile() only checked whether the key was present, so it
called client.get(None). Check whether the value is set instead, apply the
same check to OAUTH2_LOGOUT_URL and OAUTH2_ADDITIONAL_CLAIMS, and clear a
stored logout URL when the provider has none or the callback fails.
The PG17+ allowed_privs.json files for views and materialised views were
placed directly in the 17_plus bucket rather than under its sql/
subdirectory, so the versioned template loader fell back to the default
list, which lacks MAINTAIN. Move them under sql/ and add tests covering
the template path and granting MAINTAIN through RE-SQL.