E52E Fixed #31055 -- Handled database errors on check constraint support check. by charettes · Pull Request #12201 · django/django · GitHub
[go: up one dir, main page]

Skip to content
/ django Public

Fixed #31055 -- Handled database errors on check constraint support check.#12201

Closed
charettes wants to merge 5 commits intodjango:masterfrom
charettes:ticket-31055
Closed

Fixed #31055 -- Handled database errors on check constraint support check.#12201
charettes wants to merge 5 commits intodjango:masterfrom
charettes:ticket-31055

Conversation

@charettes
Copy link
Member

Since #28478 test databases are only created if necessary for the subset of
tests targeted.

Under such circumstances its possible for some databases defined in
settings.DATABASES not to exist which prevents the retrieval of the
supports_table_check_constraints feature flag on MySQL since it requires a
usable connection.

Skipping the check when this happens should not be harmful given it will run
under normal circumstances when the full set of tests are targeted or when
checks are run from a different management command.


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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid that we can hit this in other cases, e.g. in _check_json_fields() in #11452. What do you think about checking connection usability in mysql_server_info(), e.g.

    @cached_property
    def mysql_server_info(self):
        if not self.is_usable():
            return ''
        with self.temporary_connection() as cursor:
            cursor.execute('SELECT VERSION()')
            return cursor.fetchone()[0]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@felixxm that's what I initially tried but it was crashing with AttributeError

  File "/tests/django/django/db/backends/mysql/base.py", line 351, in mysql_server_info
    if not self.is_usable():
  File "/tests/django/django/db/backends/mysql/base.py", line 329, in is_usable
    self.connection.ping()
AttributeError: 'NoneType' object has no attribute 'ping'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So maybe we should check connection in is_usable() 🤔 like in related fix for PostgreSQL
a96b901#diff-aef216ccdc37941bfed98ea3c80f7642R251-R252

@felixxm felixxm self-assigned this Dec 11, 2019
@charettes
Copy link
Member Author
charettes commented Dec 11, 2019

@felixxm it looks like we don't run database tagged by default for this exact reason

# By default, 'database'-tagged checks are not run as they do more
# than mere static code analysis.
checks = [check for check in checks if Tags.database not in check.tags]

And we only run these tests on migrate which seems more appropriate

def _run_checks(self, **kwargs):
issues = run_checks(tags=[Tags.database])
issues.extend(super()._run_checks(**kwargs))
return issues

The solution is likely to write these two tests the other way around by iterating over models using check constraints when the feature is not available. Thoughts?

Copy link
Member Author
@charettes charettes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@felixxm I gave it a bit more thoughts and I think I came up with an acceptable solution.

The _check_json_field check should likely be moved to MySQL's

def check_field_type(self, field, field_type):

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally opened to a better name here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a suggestion. We previously added PostgresIndex.check_supported() to handle checking support for various index types/flags.

While that currently takes in schema_editor, we could change this line to pass schema_editor.connection and then we would have some consistency if you also adopted def check_supported(self, connection): here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having said that, PostgresIndex.check_supported() doesn't return a boolean, it expects NotSupportedError to be raised as it allows checking for multiple conditions. We also don't handle those exceptions intentionally.

I'm not sure that is a deal breaker to making this look similar, however.

This check function is tagged with "database" which ensures these checks are
only performed when running the migrate command since they may require access
to a database connection run appropriately.

Refs #26351, #31055.
@charettes charettes force-pushed the ticket-31055 branch 2 times, most recently from cbffa24 to 339ebc0 Compare December 18, 2019 20:23
@charettes
Copy link
Member Author

Something we could do here instead is of special casing Tags.database when no tags is specified is too make the check a noop when no databases option is specified.

That allows the test runner to only enable checks on databases that were created and the migrate command to only run checks on the specified --database. I pushed a WIP that does just that but I'll try to revisit the commit splitting in the next days.

@charettes
Copy link
Member Author

I still think it's worth exploring plugging _check_constraints and a potential _check_indices support on check_supported but #12396 is likely less invasive until then.

@charettes charettes closed this Jan 31, 2020
@charettes charettes deleted the ticket-31055 branch January 31, 2020 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

0