Skip to content

FIX: Schema flushing and model schemas#497

Open
benclark158 wants to merge 19 commits into
microsoft:devfrom
benclark158:schema_flushing
Open

FIX: Schema flushing and model schemas#497
benclark158 wants to merge 19 commits into
microsoft:devfrom
benclark158:schema_flushing

Conversation

@benclark158
Copy link
Copy Markdown

Changes

  1. Added support for models that use Meta.db_table = [schema].[table_name]
  2. Added support for flush command to work as expected for models with non default schemas
  3. Made schemas created as part of create table migrations.

I have added tests for tables with different defined migrations as well as flushing

Fixes: #496

@benclark158
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@benclark158
Copy link
Copy Markdown
Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Commenter does not have sufficient privileges for PR 497 in repo microsoft/mssql-django

@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copilot AI review requested due to automatic review settings May 2, 2026 15:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the mssql-django backend’s support for non-default SQL Server schemas, aiming to ensure models using schema-qualified db_table names behave correctly in migrations, flushing, and introspection.

Changes:

  • Add schema-aware FK constraint disabling/enabling during flush.
  • Add schema-qualified table handling in introspection (table listing and per-table queries).
  • Create missing schemas automatically during CREATE TABLE migrations, plus add test coverage/models/migrations for non-dbo schemas.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
mssql/schema.py Adds auto-creation of schemas during create_model() and introduces sql_create_schema.
mssql/operations.py Updates sql_flush() to include TABLE_SCHEMA so constraints are altered with schema-qualified table names.
mssql/introspection.py Updates introspection to return schema-qualified table names and to handle schema-qualified inputs for several introspection methods.
testapp/models.py Adds test models with db_table set to [events].[...] and [dbo].[...].
testapp/migrations/0026_parentschema_childschema.py Creates ParentSchema/ChildSchema tables in the [events] schema.
testapp/migrations/0027_create_dboschema.py Creates DboSchema table in the [dbo] schema.
testapp/tests/test_schema.py Adds tests intended to validate flushing and introspection with non-default schemas.

Comment thread mssql/introspection.py
Comment on lines 163 to 166
# map pyodbc's cursor.columns to db-api cursor description
_schema_name, table_name = get_table_name_with_schema(table_name=table_name)
columns = [[c[3], c[4], c[6], c[6], c[6], c[8], c[10], c[12]] for c in cursor.columns(table=table_name)]

Comment thread mssql/introspection.py
TABLE_TYPE,
CAST(ep.value AS VARCHAR) AS COMMENT
FROM INFORMATION_SCHEMA.TABLES i
LEFT JOIN sys.tables t ON t.name = i.TABLE_NAME
Comment thread mssql/schema.py
Comment on lines +67 to +71
sql_create_schema = (
"IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = '%(schema)s') BEGIN "
"EXEC('CREATE SCHEMA [%(schema)s]') "
"END"
)
Comment thread mssql/schema.py
Comment on lines +1504 to +1510

sql = self.sql_create_schema % {
'schema': schema_name.strip('[').strip(']')
}

self.execute(sql, None)

def test_inspectdb(self):
connection = connections['default']

descs = connection.introspection.get_table_description(cursor=connection.cursor(), table_name='[events].[ParentSchema]')
Comment thread mssql/schema.py
constraints.insert(0, composite_pk_sql)

# Make the table schema
if '.' in model._meta.db_table:
Copy link
Copy Markdown
Collaborator

@saurabh500 saurabh500 May 2, 2026

Choose a reason for hiding this comment

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

. detection can be very error prone and confusing. There are a lot of edge cases that need to be considered. Table names can have . in them.

Our drivers for mssql server have a multi part identifier parsing. Once instance is https://github.com/microsoft/mssql-rs/blob/e374c4a743af9a45dfee29762afaeddaee96408b/mssql-tds/src/sql_identifier.rs#L46

We need to use a statemachine based parser instead of . detection to get this right.

Comment thread mssql/schema.py
schema_name, _ = model._meta.db_table.split('.', 1)

sql = self.sql_create_schema % {
'schema': schema_name.strip('[').strip(']')
Copy link
Copy Markdown
Collaborator

@saurabh500 saurabh500 May 2, 2026

Choose a reason for hiding this comment

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

Sql schema names can have ] in them too.

CREATE SCHEMA [odd]]schema]

This code can incorrectly strip out wrong information

Comment thread mssql/introspection.py
# is supported


if '[' in table_name and ']' in table_name and '.' in table_name:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This requires a multi part parser. [ ] and . are valid characters of tablename

Comment thread mssql/introspection.py
types = {'BASE TABLE': 't', 'VIEW': 'v'}
if VERSION >= (4, 2) and self.connection.features.supports_comments:
return [TableInfo(row[0], types.get(row[1]), row[2])
return [TableInfo(f'[{row[0]}].[{row[1]}]' if row[0] != 'dbo' else row[1], types.get(row[2]), row[3])
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why this condition?

if row[0] != 'dbo'

@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@bewithgaurav
Copy link
Copy Markdown
Collaborator

@benclark158 - thanks for your contribution!
gentle reminder to please address the review comments
have run the CI checks again with the new dev branch pulled in
will re-review once done.

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.

Non-default schemas are not used/respected

4 participants