From 5f4993a9fbd11e9e26c0c664917f14b70e1102d7 Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Mon, 16 Oct 2023 12:06:49 -0700 Subject: [PATCH 1/9] Fix schema db default test --- mssql/introspection.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mssql/introspection.py b/mssql/introspection.py index 5f33bff9..f266e9fc 100644 --- a/mssql/introspection.py +++ b/mssql/introspection.py @@ -138,6 +138,17 @@ def get_table_description(self, cursor, table_name, identity_check=True): column[1] = SQL_AUTOFIELD if column[1] == Database.SQL_WVARCHAR and column[3] < 4000: column[1] = Database.SQL_WCHAR + # Remove surrounding parentheses for default values + if column[7]: + default_value = column[7] + start = 0 + end = -1 + for _ in range(2): + if default_value[start] == '(' and default_value[end] == ')': + start += 1 + end -= 1 + column[7] = default_value[start:end + 1] + items.append(FieldInfo(*column)) return items From 772f41b87b85c859f1eac7327d92801ef2e2df12 Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Wed, 25 Oct 2023 12:27:19 -0700 Subject: [PATCH 2/9] Skip nullable textfield constraint test --- testapp/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testapp/settings.py b/testapp/settings.py index 092267ca..d70d1741 100644 --- a/testapp/settings.py +++ b/testapp/settings.py @@ -301,6 +301,7 @@ 'queries.test_qs_combinators.QuerySetSetOperationTests.test_union_with_select_related_and_order', 'expressions_window.tests.WindowFunctionTests.test_limited_filter', 'schema.tests.SchemaTests.test_remove_ignored_unique_constraint_not_create_fk_index', + 'constraints.tests.UniqueConstraintTests.test_validate_nullable_textfield_with_isnull_true', ] REGEX_TESTS = [ From 880bccdac63ae3eb67b4652d5f4db3fbabf6640c Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Tue, 7 Nov 2023 14:36:55 -0800 Subject: [PATCH 3/9] Preliminary fix --- mssql/base.py | 2 +- mssql/compiler.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mssql/base.py b/mssql/base.py index cf11c506..eb7d3b7d 100644 --- a/mssql/base.py +++ b/mssql/base.py @@ -581,7 +581,7 @@ def format_sql(self, sql, params): sql = smart_str(sql, self.driver_charset) # pyodbc uses '?' instead of '%s' as parameter placeholder. - if params is not None: + if params is not None and params: sql = sql % tuple('?' * len(params)) return sql diff --git a/mssql/compiler.py b/mssql/compiler.py index 2dfe1b6c..95b4904e 100644 --- a/mssql/compiler.py +++ b/mssql/compiler.py @@ -589,10 +589,11 @@ def as_sql(self): params += param_rows result.append(self.connection.ops.bulk_insert_sql(fields, placeholder_rows)) else: + r_sql, self.returning_params = self.connection.ops.return_insert_columns(self.get_returned_fields()) result.insert(0, 'SET NOCOUNT ON') + result.append(r_sql) result.append((values_format + ';') % ', '.join(placeholder_rows[0])) params = [param_rows[0]] - result.append('SELECT CAST(SCOPE_IDENTITY() AS bigint)') sql = [(" ".join(result), tuple(chain.from_iterable(params)))] else: if can_bulk: From 4d76857d9fa40afdb2406e95d695067cc5769833 Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Wed, 8 Nov 2023 15:51:35 -0800 Subject: [PATCH 4/9] Skip add field database default test --- testapp/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testapp/settings.py b/testapp/settings.py index f6a19593..642b8814 100644 --- a/testapp/settings.py +++ b/testapp/settings.py @@ -307,6 +307,7 @@ 'constraints.tests.CheckConstraintTests.test_validate_custom_error', 'constraints.tests.CheckConstraintTests.test_validate_nullable_jsonfield', 'constraints.tests.CheckConstraintTests.test_validate_pk_field', + 'migrations.test_operations.OperationTests.test_add_field_database_default', ] REGEX_TESTS = [ From acc440f8c9032090f14607a8ce4175552c74357c Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Fri, 10 Nov 2023 11:45:13 -0800 Subject: [PATCH 5/9] Update returned values from insert --- mssql/compiler.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/mssql/compiler.py b/mssql/compiler.py index 95b4904e..b20fb713 100644 --- a/mssql/compiler.py +++ b/mssql/compiler.py @@ -589,11 +589,18 @@ def as_sql(self): params += param_rows result.append(self.connection.ops.bulk_insert_sql(fields, placeholder_rows)) else: - r_sql, self.returning_params = self.connection.ops.return_insert_columns(self.get_returned_fields()) + has_into = 'INTO' in result[0] result.insert(0, 'SET NOCOUNT ON') - result.append(r_sql) + # Use 'OUTPUT' if query contains 'INTO' + if has_into: + r_sql, self.returning_params = self.connection.ops.return_insert_columns(self.get_returned_fields()) + if r_sql: + result.append(r_sql) + # Append values result.append((values_format + ';') % ', '.join(placeholder_rows[0])) params = [param_rows[0]] + if not has_into: + result.append('SELECT CAST(SCOPE_IDENTITY() AS bigint)') sql = [(" ".join(result), tuple(chain.from_iterable(params)))] else: if can_bulk: From 360004f728ff7977598291d7aca2de26e904f86d Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Fri, 17 Nov 2023 10:52:03 -0800 Subject: [PATCH 6/9] Change can_return_rows_from_bulk_insert default to True --- mssql/base.py | 2 +- mssql/compiler.py | 10 +--------- mssql/features.py | 2 +- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/mssql/base.py b/mssql/base.py index eb7d3b7d..8f8c69e2 100644 --- a/mssql/base.py +++ b/mssql/base.py @@ -429,7 +429,7 @@ def init_connection_state(self): # Let user choose if driver can return rows from bulk insert since # inserting into tables with triggers causes errors. See issue #130 if (options.get('return_rows_bulk_insert', False)): - self.features_class.can_return_rows_from_bulk_insert = True + self.features_class.can_return_rows_from_bulk_insert = False val = self.get_system_datetime if isinstance(val, str): diff --git a/mssql/compiler.py b/mssql/compiler.py index b20fb713..2dfe1b6c 100644 --- a/mssql/compiler.py +++ b/mssql/compiler.py @@ -589,18 +589,10 @@ def as_sql(self): params += param_rows result.append(self.connection.ops.bulk_insert_sql(fields, placeholder_rows)) else: - has_into = 'INTO' in result[0] result.insert(0, 'SET NOCOUNT ON') - # Use 'OUTPUT' if query contains 'INTO' - if has_into: - r_sql, self.returning_params = self.connection.ops.return_insert_columns(self.get_returned_fields()) - if r_sql: - result.append(r_sql) - # Append values result.append((values_format + ';') % ', '.join(placeholder_rows[0])) params = [param_rows[0]] - if not has_into: - result.append('SELECT CAST(SCOPE_IDENTITY() AS bigint)') + result.append('SELECT CAST(SCOPE_IDENTITY() AS bigint)') sql = [(" ".join(result), tuple(chain.from_iterable(params)))] else: if can_bulk: diff --git a/mssql/features.py b/mssql/features.py index c1e90849..bb233395 100644 --- a/mssql/features.py +++ b/mssql/features.py @@ -13,7 +13,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): can_introspect_small_integer_field = True can_return_columns_from_insert = True can_return_id_from_insert = True - can_return_rows_from_bulk_insert = False + can_return_rows_from_bulk_insert = True can_rollback_ddl = True can_use_chunked_reads = False for_update_after_from = True From 06b58fc38f56a61709deaeb17ef72210487038f5 Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Fri, 17 Nov 2023 12:31:42 -0800 Subject: [PATCH 7/9] Revert format sql changes --- mssql/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mssql/base.py b/mssql/base.py index 8f8c69e2..0a04cb75 100644 --- a/mssql/base.py +++ b/mssql/base.py @@ -581,7 +581,7 @@ def format_sql(self, sql, params): sql = smart_str(sql, self.driver_charset) # pyodbc uses '?' instead of '%s' as parameter placeholder. - if params is not None and params: + if params is not None: sql = sql % tuple('?' * len(params)) return sql From 8b1e9e0d9adf67e51a5fb3d81072e2e2440e46c2 Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Mon, 20 Nov 2023 09:15:47 -0800 Subject: [PATCH 8/9] Prevent formatting empty params query --- mssql/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mssql/base.py b/mssql/base.py index 0a04cb75..f0be8474 100644 --- a/mssql/base.py +++ b/mssql/base.py @@ -429,7 +429,7 @@ def init_connection_state(self): # Let user choose if driver can return rows from bulk insert since # inserting into tables with triggers causes errors. See issue #130 if (options.get('return_rows_bulk_insert', False)): - self.features_class.can_return_rows_from_bulk_insert = False + self.features_class.can_return_rows_from_bulk_insert = True val = self.get_system_datetime if isinstance(val, str): @@ -581,7 +581,7 @@ def format_sql(self, sql, params): sql = smart_str(sql, self.driver_charset) # pyodbc uses '?' instead of '%s' as parameter placeholder. - if params is not None: + if params is not None and params != []: sql = sql % tuple('?' * len(params)) return sql From becbdd01b8eb075ed4348038f3c48c72bdb28726 Mon Sep 17 00:00:00 2001 From: "Daniel Au (SIMBA TECHNOLOGIES INC)" Date: Mon, 20 Nov 2023 14:18:54 -0800 Subject: [PATCH 9/9] unskip add_field_database_default --- testapp/settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testapp/settings.py b/testapp/settings.py index 642b8814..f6a19593 100644 --- a/testapp/settings.py +++ b/testapp/settings.py @@ -307,7 +307,6 @@ 'constraints.tests.CheckConstraintTests.test_validate_custom_error', 'constraints.tests.CheckConstraintTests.test_validate_nullable_jsonfield', 'constraints.tests.CheckConstraintTests.test_validate_pk_field', - 'migrations.test_operations.OperationTests.test_add_field_database_default', ] REGEX_TESTS = [