Repository navigation
Commit 6733846
authored
feat(postgres): adopt the expression/dialect split and declare the probes core now gates on (#61)
* refactor(postgres): carry catalogue objects instead of parsed names
Core's expression and dialect layers were reworked: a relation is split into the
object it names and the source that reads it, the namespace shape became a
protocol the dialect states once, and to_sql() now inspects what answers a format
lookup instead of calling whatever is callable. Qualified names are carried here as
schema objects rather than parsed strings, which is what made the object and the
statement that acts on it able to disagree about what "the same table" meant.
Six types this backend does not have were being exported. COMMENT ON now renders
from the object it annotates.
The round-trip matrix this branch added was reporting nothing, which the refactor
made visible rather than causing. Three classes it pinned as raising AttributeError
name a format_method whose formatter PostgreSQL does not have, and core now reports
a missing formatter as UnsupportedFeatureError -- the spelling every other capability
probe in the tree already used. The pins move with it, and each now names the
formatter it is missing so the entry says which gap it is.
Walking PostgresDialect.__mro__ to resolve every format_* name to the class that
defines it shows none of the 411 resolving to a Protocol: the stub format_* a
protocol declares in the MRO are each overridden by a real mixin ahead of it. That
includes CreateRoutineSupport and DropRoutineSupport, whose presence in the base
list used to answer a dispatch with a protocol body returning None; the core
CreateFunctionExpression and DropFunctionExpression now render.
* fix(postgres): declare the sequence probes core now gates on
Core commit 9dc18ab made all three sequence DDL formatters consult
supports_sequence() first and unconditionally, and added four option probes
(supports_sequence_start, _increment, _minvalue, _maxvalue). PostgreSQL's
sequence mixin never defined supports_sequence -- core had never asked for it --
so the master switch fell back to core's default False and CREATE SEQUENCE,
DROP SEQUENCE and ALTER SEQUENCE all raised UnsupportedFeatureError. A
full-support dialect had stopped rendering the statement it supports.
The mixin now answers every probe those formatters consult. supports_sequence,
supports_create_sequence, supports_drop_sequence, supports_alter_sequence,
supports_sequence_if_not_exists, supports_sequence_if_exists, and the option
probes start, increment, minvalue, maxvalue, cycle, cache and owned_by all
return True. supports_sequence_order returns False: the PostgreSQL
CREATE SEQUENCE synopsis has no ORDER / NO ORDER clause -- that spelling is
Oracle and SQL Server -- and the live server rejects it with a syntax error,
so the formatter must refuse it rather than emit a clause the engine cannot
parse.
PostgresSequenceSupport restates the same switches, so the protocol and the
mixin agree method for method. It derives from core's CreateSequenceSupport,
DropSequenceSupport and AlterSequenceSupport, which is how the non-overlap
guard in the protocol conformance test recognises the restatement as the
deliberate overlap it is. The dialect's three redundant direct protocol bases
are dropped for the same reason: a base may not precede the subclass that
restates it. The three DDL formatters remain core's; this backend only answers
the capability questions they ask.
* fix(postgres): declare the ALTER SEQUENCE START probe explicitly
Core's format_alter_sequence_statement gated AlterSequenceExpression.start on
supports_sequence_start(), the probe for the CREATE SEQUENCE ... START WITH
clause. Those are two different clauses, and True for one does not imply True
for the other. PostgreSQL accepts START on ALTER -- it records the start value
that future RESTART calls use, while RESTART WITH sets the current value -- but
Oracle, SQL Server, Firebird and Snowflake all reject it. Reusing the CREATE
probe for the ALTER formatter would therefore let those four dialects emit SQL
their server rejects.
Add supports_alter_sequence_start() to PostgresSequenceMixin, answering True
because the live server accepts the clause, and declare it on
PostgresSequenceSupport so the protocol keeps mirroring the mixin. The default
for the new probe is False, which is the safe side: a dialect that accepts the
clause must say so explicitly, as this one does.
* feat(postgres): declare the identity probes and gate identity DDL on them
Core made the identity and auto-increment nodes fail-closed: IdentityClause
consults supports_identity_column() plus one probe per option, and
AutoIncrementClause consults supports_auto_increment_column(). PostgreSQL
declared none of the new probes -- the dialect did not mix in the identity
mixin at all -- so core's formatters refused every identity clause.
Declare the measured boundary: supports_identity_column() is True from
PostgreSQL 10 on, because PostgreSQL 9 rejects the clause with `syntax error
at or near "GENERATED"` (measured) while 10 through 19 all accept it. The six
option probes -- generation ALWAYS, start, increment, minvalue, maxvalue,
cycle -- answer True: they are part of the same synopsis.
supports_auto_increment_column() answers False: PostgreSQL has no
AUTO_INCREMENT spelling, and the probe is declared explicitly rather than
inherited from the fail-closed default.
The legacy is_auto_increment constraint now routes through the gated identity
formatter, so PostgreSQL 9 refuses an identity request instead of rendering a
GENERATED clause its server rejects. There is no fallback to SERIAL: the SERIAL
type family stays available for users who ask for it explicitly, and it keeps
executing on every version.
PostgresIdentitySupport and PostgresAutoIncrementSupport mirror the two new
mixins; the protocol conformance test pairs them with the existing
forward/reverse coverage. The new execution-confirmation suite renders and
executes each clause against a live server: accepted where the probe says True,
NOT_RENDERED on PostgreSQL 9 where it says False, with a rejected sentinel and
an accepted control before each verdict. The PG9 identity example now uses the
supported IdentityAttribute path instead of a keyword ColumnDefinition never
accepted.
* feat(postgres): consume the clause-parameter pairs and close the dialect gaps
Core split every two-spelling clause into one parameter per spelling
(438b7aa): unspecified means neither parameter, both means ValueError. The
PostgreSQL formatters still read the pre-split fields, so this follows.
Formatters consuming a pair:
- format_truncate_statement: restart_identity|continue_identity (CONTINUE
IDENTITY was silently dropped) and cascade|restrict (RESTRICT was silently
dropped).
- format_create_materialized_view_statement and
format_refresh_materialized_view_pg_statement: with_data|no_data;
unspecified renders no tail (the old else-branch spelled WITH NO DATA).
- format_drop_materialized_view_statement: cascade|restrict (RESTRICT was
silently dropped).
- format_begin_transaction / format_set_transaction: deferrable|not_deferrable;
[NOT] DEFERRABLE renders whenever requested, not only alongside SERIALIZABLE,
and unspecified no longer spells NOT DEFERRABLE.
- _format_exclude_constraint: deferrable|not_deferrable and
initially_deferred|initially_immediate; INITIALLY ... renders as the
independent constraint attribute it is.
- format_copy_to_statement: force_array|force_array_false.
- format_table_constraint: the enforced gate no longer reads a tri-state, so
table constraints render again instead of refusing every state.
Dialect-specific nodes split to the pair shape:
- PostgresRefreshMaterializedViewExpression: with_data|no_data.
- PostgresCopyToExpression: force_array|force_array_false.
- PostgresCreateMaterializedViewExpression: with_data|no_data (its constructor
dropped no_data and defaulted to WITH DATA).
- PostgresDropMaterializedViewExpression: restrict pass-through.
- PostgresExcludeConstraint: deferrable|not_deferrable and
initially_deferred|initially_immediate. The audit registry did not carry this
node; it was found by the sweep and measured before/after.
New probes declared True (measured against live PostgreSQL 16 and 19):
supports_schema_restrict, supports_restrict_view,
supports_drop_function_restrict, supports_materialized_view_restrict,
supports_truncate_restrict, and supports_identity_cache. The CACHE option's
negative spelling, NO CACHE, has no PostgreSQL form (syntax error, measured),
so no_cache is refused by name for sequences and identity while cache=n
renders; ORDER/NO ORDER stay refused.
The transaction manager now drives the split setters, so set_deferrable(False)
renders NOT DEFERRABLE instead of raising.
Behaviour changes (intended, per the round):
- CREATE MATERIALIZED VIEW default no longer emits WITH NO DATA.
- SET TRANSACTION with nothing requested no longer emits NOT DEFERRABLE.
- BEGIN ... DEFERRABLE renders for any isolation level.
- RESTRICT and CONTINUE IDENTITY become reachable where they were dropped.
Guard: test_clause_pair_guard.py asserts the four states of every pair the
dialect consumes are pairwise distinguishable; run red against the unmodified
tree first (24 failing test ids), green after. Two mutations (one removed
exclusion check, one reverted restrict branch) were each caught by the
expected guard test.
* feat(postgres): declare the master probes core now gates on
Core's c4d6adc gave call sites to three probes that had been decorative:
format_cte_expression consults supports_materialized_cte(),
format_truncate_statement consults supports_truncate(), and the CTAS /
CREATE MATERIALIZED VIEW / REFRESH MATERIALIZED VIEW renderers consult the
new supports_with_data_clause() before spelling WITH [NO] DATA. It also
added supports_transaction_wait() for the wait / no_wait pair. A dialect
that leaves any of them to a core default refuses statements it used to
render: this package answered the with-data probe False through core's
default, and its transaction formatters dropped the wait pair entirely.
Declare each from measurement or the documented grammar:
- supports_materialized_cte() keeps its >= 12 gate (already declared here).
Live measurement: 9.6, 10 and 11 reject AS MATERIALIZED / AS NOT
MATERIALIZED with a syntax error; 12 through 19beta4 accept both.
- supports_truncate() answers True explicitly. TRUNCATE is in the synopsis
of every supported version and the live matrix accepts it everywhere.
- supports_with_data_clause() answers True, version-independent. The clause
is in all three synopses -- the CTAS form long predates materialized
views, and CREATE / REFRESH MATERIALIZED VIEW ... [ WITH [ NO ] DATA ]
is documented from 9.3 (the version that introduced materialized views)
-- and the live matrix accepts every form. The same probe covers the
REFRESH form; it needs no probe of its own.
- supports_transaction_wait() answers False. BEGIN NO WAIT and SET
TRANSACTION NO WAIT are syntax errors on every measured server (9.6
through 19beta4); PostgreSQL has no lock-wait clause.
The PostgreSQL overrides now consume the probes the core formatters
consume: format_create_materialized_view_statement and
format_refresh_materialized_view_pg_statement refuse WITH [NO] DATA by
name when the clause probe declines (generic REFRESH and CTAS delegate to
core's gate), format_truncate_statement consults supports_truncate(), and
format_begin_transaction / format_set_transaction refuse wait / no_wait by
name instead of silently dropping the pair.
PostgresTruncateSupport, PostgresMaterializedViewSupport and
PostgresTransactionSupport restate the declarations so the protocol and
the mixin stay mirrored; the conformance forward / reverse coverage tests
enforce the mirror.
Behaviour changes (intended, per the round):
- CTAS and generic REFRESH MATERIALIZED VIEW with WITH DATA / WITH NO DATA
render instead of being refused by the fail-closed default.
- BEGIN / SET TRANSACTION wait=True / no_wait=True raise
UnsupportedFeatureError naming the option instead of rendering a
statement that dropped it.
Guard: test_clause_pair_guard.py adds the wait pair and a declaration /
gate class; run red against the unmodified tree first (13 failing ids of
155), green after. test_master_probe_execution.py renders each clause
through the live backend and asserts acceptance against the probe, with a
sentinel and a control before every verdict; green on the 11-scenario
matrix (9.6 through 19beta4).
* ci: pin the core dependency to the merged release line
The schema-object refactor these branches depend on landed on the core's
release/v1.0.0.dev30 line as PR #125, so the workflow no longer needs to install
the core from the feature branch. CORE_PKG now points at the release branch; the
testsuite dependency stays on its own feature branch, which is not merged yet.
* chore: add changelog fragment for PR #611 parent 9a74cca commit 6733846
218 files changed
Lines changed: 7440 additions & 2291 deletions
File tree
- .claude
- .github/workflows
- changelog.d
- docs
- en_US/postgres_specific_features
- zh_CN
- ddl
- postgres_specific_features
- src/rhosocial/activerecord/backend/impl/postgres
- cli
- examples
- connection
- ddl
- delete
- extensions
- insert
- named_expressions
- named_migrations
- pgq
- query
- schema_diff
- sqlxml
- transaction
- types
- update
- expression
- ddl
- functions
- mixins
- ddl
- dml
- extensions
- types
- protocols
- ddl
- type_values
- tests
- providers
- fixtures
- rhosocial/activerecord_postgres_test/feature/backend
- dialect
- expression
- postgres
- extensions
- transaction
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
273 | 273 | | |
274 | 274 | | |
275 | 275 | | |
276 | | - | |
277 | | - | |
| 276 | + | |
| 277 | + | |
278 | 278 | | |
279 | 279 | | |
280 | 280 | | |
281 | 281 | | |
282 | 282 | | |
283 | | - | |
284 | | - | |
| 283 | + | |
| 284 | + | |
285 | 285 | | |
286 | 286 | | |
287 | | - | |
288 | | - | |
| 287 | + | |
| 288 | + | |
289 | 289 | | |
290 | 290 | | |
291 | 291 | | |
292 | 292 | | |
293 | | - | |
294 | | - | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
295 | 299 | | |
296 | | - | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
301 | 350 | | |
302 | 351 | | |
303 | 352 | | |
| |||
315 | 364 | | |
316 | 365 | | |
317 | 366 | | |
318 | | - | |
319 | | - | |
| 367 | + | |
| 368 | + | |
320 | 369 | | |
321 | 370 | | |
322 | 371 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
69 | 69 | | |
70 | 70 | | |
71 | 71 | | |
72 | | - | |
| 72 | + | |
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
| |||
280 | 280 | | |
281 | 281 | | |
282 | 282 | | |
283 | | - | |
| 283 | + | |
284 | 284 | | |
285 | 285 | | |
286 | 286 | | |
| |||
392 | 392 | | |
393 | 393 | | |
394 | 394 | | |
395 | | - | |
| 395 | + | |
396 | 396 | | |
397 | 397 | | |
398 | 398 | | |
| |||
490 | 490 | | |
491 | 491 | | |
492 | 492 | | |
493 | | - | |
| 493 | + | |
494 | 494 | | |
495 | 495 | | |
496 | 496 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
0 commit comments