Add a new SQLExecutor class for managing all SQL operations.

Review Request #11242 — Created Oct. 24, 2020 and submitted

Information

Django Evolution
master

Reviewers

SQLExecutor is a new class intended for use whenever SQL statements
need to be executed. It's responsible for transaction management, SQL
statement preparation, and execution, and replaces the old run_sql(),
write_sql(), and execute_sql() functions.

The main thing this brings to the table is improved transaction
management. Normally with Django, you either use low-level transaction
commands (such as transaction.commit()) and juggle the various error
handling and savepoint situations yourself, or you make use of
transaction.atomic() to manage all this.

The problem with transaction.atomic() is that, being a context
manager, you can't easily start one, let it sit around outside of that
context, and then later stop it without some ugly code.

SQLExecutor simplifies this by turning transaction management and SQL
executions into just separate instructions that can be executed in
sequence. A caller can start a transaction, execute SQL, start a new one
(which will commit the previous), execute more SQL, commit, execute new
SQL outside a transaction, etc.

This change lays the ground work for this. The next change will allow
generated SQL to be marked as requiring an independent transaction or
requiring being run outside of a transaction, which will be factored in
during the SQL preparation step.

Unit tests passed.

Tested creating and upgrading databases successfully.

Summary ID
Add a new SQLExecutor class for managing all SQL operations.
`SQLExecutor` is a new class intended for use whenever SQL statements need to be executed. It's responsible for transaction management, SQL statement preparation, and execution, and replaces the old `run_sql()`, `write_sql()`, and `execute_sql()` functions. The main thing this brings to the table is improved transaction management. Normally with Django, you either use low-level transaction commands (such as `transaction.commit()`) and juggle the various error handling and savepoint situations yourself, or you make use of `transaction.atomic()` to manage all this. The problem with `transaction.atomic()` is that, being a context manager, you can't easily start one, let it sit around outside of that context, and then later stop it without some ugly code. `SQLExecutor` simplifies this by turning transaction management and SQL executions into just separate instructions that can be executed in sequence. A caller can start a transaction, execute SQL, start a new one (which will commit the previous), execute more SQL, commit, execute new SQL outside a transaction, etc. This change lays the ground work for this. The next change will allow generated SQL to be marked as requiring an independent transaction or requiring being run outside of a transaction, which will be factored in during the SQL preparation step.
4db1af7ec9738d8dc935bd06b8bc636948cf81b0
Description From Last Updated

F401 'django_evolution.utils.sql.SQLExecutor' imported but unused

reviewbotreviewbot

E127 continuation line over-indented for visual indent

reviewbotreviewbot
Checks run (1 failed, 1 succeeded)
flake8 failed.
JSHint passed.

flake8

chipx86
david
  1. Ship It!
  2. 
      
chipx86
Review request changed
Status:
Completed
Change Summary:
Pushed to master (f475c01)