diff --git a/mssql/base.py b/mssql/base.py index 6896bd4..087804d 100644 --- a/mssql/base.py +++ b/mssql/base.py @@ -39,7 +39,7 @@ from .client import DatabaseClient # noqa from .creation import DatabaseCreation # noqa from .features import DatabaseFeatures # noqa -from .introspection import DatabaseIntrospection, SQL_TIMESTAMP_WITH_TIMEZONE # noqa +from .introspection import DatabaseIntrospection, SQL_TIMESTAMP_WITH_TIMEZONE, SQL_VARIANT # noqa from .operations import DatabaseOperations # noqa from .schema import DatabaseSchemaEditor # noqa @@ -83,6 +83,9 @@ def encode_value(v): return '{%s}' % (v.replace('}', '}}'),) return v +def handle_sql_variant_as_string(value): + # SQL variant of type 150 is not supported, convert it to string and return + return value.decode('utf-16le') def handle_datetimeoffset(dto_value): # Decode bytes returned from SQL Server @@ -381,6 +384,10 @@ def get_new_connection(self, conn_params): # Handling values from DATETIMEOFFSET columns # source: https://github.com/mkleehammer/pyodbc/wiki/Using-an-Output-Converter-function conn.add_output_converter(SQL_TIMESTAMP_WITH_TIMEZONE, handle_datetimeoffset) + + # add support for sql_variant fields + conn.add_output_converter(SQL_VARIANT, handle_sql_variant_as_string) + conn.timeout = query_timeout if setencoding: for entry in setencoding: diff --git a/mssql/introspection.py b/mssql/introspection.py index 9e8d873..43fd98a 100644 --- a/mssql/introspection.py +++ b/mssql/introspection.py @@ -17,6 +17,7 @@ SQL_BIGAUTOFIELD = -777444 SQL_SMALLAUTOFIELD = -777333 SQL_TIMESTAMP_WITH_TIMEZONE = -155 +SQL_VARIANT = -150 FieldInfo = namedtuple("FieldInfo", BaseFieldInfo._fields + ("comment",)) TableInfo = namedtuple("TableInfo", BaseTableInfo._fields + ("comment",)) diff --git a/testapp/tests/test_fields.py b/testapp/tests/test_fields.py index 7f708e8..84186b3 100644 --- a/testapp/tests/test_fields.py +++ b/testapp/tests/test_fields.py @@ -4,6 +4,7 @@ from django.test import TestCase from ..models import UUIDModel, Customer_name, Customer_address +from django.db import connections class TestUUIDField(TestCase): @@ -34,3 +35,15 @@ def test_random_order_by(self): names.append(list(Customer_name.objects.order_by('?'))) self.assertNotEqual(names.count(names[0]), 20) + + +class TestSQLVariant(TestCase): + def test_sql_variant(self): + connection = connections['default'] + with connection.cursor() as cursor: + cursor.execute("CREATE TABLE sqlVariantTest(targetCol sql_variant, colB INT)") + cursor.execute("INSERT INTO sqlVariantTest values (CAST(46279.1 as decimal(8,2)), 1689)") + cursor.execute("SELECT targetCol FROM sqlVariantTest") + + rows = cursor.fetchall() + self.assertEqual(len(rows), 1)