Skip to content
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

Fixed #35334 -- Removed supports_sequence_reset feature flag #18024

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

shangxiao
Copy link
Contributor

@shangxiao shangxiao commented Mar 27, 2024

https://code.djangoproject.com/ticket/35334

Draft PR

There are a few issues with sequences resetting:

  • In some cases sequences are restarted, some cases they're set to the max value
  • The MySQL backend doesn't do the max value one, even though it could (providing it's not within a tx?)
  • The Oracle backend reset doesn't restart (comment incorrectly states it does?)

Notes about how sequences currently work in Django

sequence_reset_by_name_sql()

If supported explicitly sets the sequence to 1

Called by:

  • SQLite's sql_flush()
  • Oracle's sql_flush() see note below
  • TransactionTestCase._fixture_setup() if reset_sequences = True

Note: Despite comments in oracle.operations.sql_flush():

   # Since we've just deleted all the rows, running our sequence ALTER
   # code will reset the sequence to 0.

there is no ALTER command issued, neither do the sequences get reset.

sequence_reset_sql()

If supported by the backend re-aligns the sequence with the table's contents

Called by:

  • contrib.sites' create_default_site() on post_migrate
  • loadddata mgt command if there's at least 1 object loaded
  • in turn is called by any test case to load fixtures
  • sqlsequencereset mgt command

SQLite

  • supports_sequence_reset set
  • sql_flush() defined - uses DELETE FROM <table>
    • calls sequence_reset_by_name_sql()
  • sequence_reset_by_name_sql() defined - using UPDATE sqlite_sequence …
  • sequence_reset_sql() not defined

PostgreSQL

  • supports_sequence_reset set
  • sql_flush() defined - uses TRUCATE <table1>, <table2>, … , adds RESTART IDENTITY if resetting sequences
  • sequence_reset_by_name_sql() defined - using SELECT setval(pg_get_serial_sequence(<table>, <column>), 1, false)
  • sequence_reset_sql() defined with SELECT setval(pg_get_serial_sequence(<table>, <column>), coalesce(max(<column>), 1), max(<column>) IS NOT NULL) FROM <table>;

MySQL

  • supports_sequence_reset set
  • sql_flush() defined - resets sequences by using TRUNCATE instead of DELETE
  • sequence_reset_by_name_sql() defined using ALTER TABLE <table> AUTO_INCREMENT = 1
  • sequence_reset_sql() not defined

Oracle

  • supports_sequence_reset not set
  • sql_flush() defined - iterates over tables, disables constraints then TRUNCATE, then re-enabling constraints
    • calls sequence_reset_by_name_sql()
  • sequence_reset_by_name_sql() defined using custom PL/SQL
  • sequence_reset_sql() defined using custom PL/SQL

Some notes about resetting sequences on Oracle

  • DDL statements implicitly commit transactions
  • Implicitly generated sequences cannot be restarted with ALTER SEQUENCE, one needs to specify the start by ALTER TABLE … MODIFY id GENERATED BY DEFAULT ON NULL AS IDENTITY START WITH …
  • Identity columns can use LIMIT VALUE to specify the max value
  • Regular sequences don't have a LIMIT VALUE equivalent so we need to retain the existing SELECT MAX(…) statement to retrieve the max value

Additional notes

  • The previous sequence reset code only provided the ability to "reset" to the current max value by selecting nextvalue until it reached the max
  • The ALTER TABLE … MODIFY statement should probably get the proper type info from schema?

@shangxiao shangxiao force-pushed the ticket-35334-oracle-sequence-reset branch from 0564010 to 6775022 Compare March 27, 2024 17:44
@timgraham
Copy link
Member

Please don't remove DatabaseFeatures.supports_sequence_reset as third-party database backends (at least CockroachDB and Snowflake) set it to False.

@shangxiao shangxiao force-pushed the ticket-35334-oracle-sequence-reset branch 2 times, most recently from cfee25e to a2a6219 Compare April 2, 2024 15:52
@shangxiao
Copy link
Contributor Author

buildbot, test on oracle.

@django django deleted a comment from shangxiao Apr 2, 2024
@django django deleted a comment from shangxiao Apr 2, 2024
@shangxiao shangxiao force-pushed the ticket-35334-oracle-sequence-reset branch from 5fbd4f2 to c13dd65 Compare April 3, 2024 06:54
@shangxiao
Copy link
Contributor Author

buildbot, test on oracle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants