diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a89e63e1a..9a80a0890 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,12 @@ Changelog 0.20 ==== +0.20.1 +------ +Added +^^^^^ +- NVARCHAR non-ascii char support on mssql + 0.20.0 ------ Added diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index d944b8665..8dca0521b 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -53,6 +53,7 @@ Contributors * Paul Serov ``@thakryptex`` * Stanislav Zmiev ``@Ovsyanka83`` * Waket Zheng ``@waketzheng`` +* Mohammad Norouzi ``@mm74noroozi`` Special Thanks ============== diff --git a/tests/fields/test_nvarchar.py b/tests/fields/test_nvarchar.py new file mode 100644 index 000000000..f51d73f1b --- /dev/null +++ b/tests/fields/test_nvarchar.py @@ -0,0 +1,70 @@ +from tests import testmodels_mssql as testmodels +from tortoise.contrib import test +from tortoise.exceptions import IntegrityError, OperationalError +from tortoise.exceptions import ConfigurationError + +@test.requireCapability(dialect="mssql") +class TestNVARCHARFields(test.IsolatedTestCase): + tortoise_test_modules = ["tests.testmodels_mssql"] + + async def test_max_length_missing(self): + with self.assertRaisesRegex( + TypeError, "missing 1 required positional argument: 'max_length'" + ): + testmodels.NVARCHAR() # pylint: disable=E1120 + + async def test_max_length_bad(self): + with self.assertRaisesRegex(ConfigurationError, "'max_length' must be >= 1"): + testmodels.NVARCHAR(max_length=0) + + async def _setUpDB(self) -> None: + try: + await super()._setUpDB() + except OperationalError: + raise test.SkipTest("Works only with MSSQLServer") + + async def test_empty(self): + with self.assertRaises(IntegrityError): + await testmodels.NVARCHAR.create() + + async def test_filtering(self): + testmodels.NVARCHAR.create(nvarchar="سلام").sql() + + async def test_create(self): + obj0 = await testmodels.NVARCHAR.create(nvarchar="سلام") + obj = await testmodels.NVARCHAR.get(id=obj0.id) + self.assertEqual(obj.nvarchar, "سلام") + self.assertIs(obj.nvarchar_null, None) + await obj.save() + obj2 = await testmodels.NVARCHAR.get(id=obj.id) + self.assertEqual(obj, obj2) + + async def test_filterUTF8Chars(self): + await testmodels.NVARCHAR.create(nvarchar="سلام") + obj = await testmodels.NVARCHAR.get(nvarchar="سلام") + self.assertIsNotNone(obj) + self.assertEqual(obj.nvarchar, "سلام") + + async def test_update(self): + obj0 = await testmodels.NVARCHAR.create(nvarchar="سلام") + await testmodels.NVARCHAR.filter(id=obj0.id).update(nvarchar="non-utf8") + obj = await testmodels.NVARCHAR.get(id=obj0.id) + self.assertEqual(obj.nvarchar, "non-utf8") + self.assertIs(obj.nvarchar_null, None) + + async def test_cast(self): + obj0 = await testmodels.NVARCHAR.create(nvarchar=33) + obj = await testmodels.NVARCHAR.get(id=obj0.id) + self.assertEqual(obj.nvarchar, "33") + + async def test_values(self): + obj0 = await testmodels.NVARCHAR.create(nvarchar="سلام") + values = await testmodels.NVARCHAR.get(id=obj0.id).values("nvarchar") + self.assertEqual(values["nvarchar"], "سلام") + + async def test_values_list(self): + obj0 = await testmodels.NVARCHAR.create(nvarchar="سلام") + values = await testmodels.NVARCHAR.get(id=obj0.id).values_list("nvarchar", flat=True) + self.assertEqual(values, "سلام") + + \ No newline at end of file diff --git a/tests/testmodels_mssql.py b/tests/testmodels_mssql.py new file mode 100644 index 000000000..d6afdee77 --- /dev/null +++ b/tests/testmodels_mssql.py @@ -0,0 +1,7 @@ +from tortoise import Model, fields +from tortoise.contrib.mssql.fields import NVARCHAR + +class NVARCHARFields(Model): + id = fields.IntField(pk=True) + nvarchar = NVARCHAR(max_length=255) + nvarchar_null = NVARCHAR(max_length=255,null=True) \ No newline at end of file diff --git a/tortoise/contrib/mssql/field_types.py b/tortoise/contrib/mssql/field_types.py new file mode 100644 index 000000000..d32ebc8e3 --- /dev/null +++ b/tortoise/contrib/mssql/field_types.py @@ -0,0 +1,5 @@ +class NVARCHAR: + def __init__(self,value): + self._value = value + def __str__(self): + return f"N'{self._value}'" \ No newline at end of file diff --git a/tortoise/contrib/mssql/fields.py b/tortoise/contrib/mssql/fields.py new file mode 100644 index 000000000..e6f8791c0 --- /dev/null +++ b/tortoise/contrib/mssql/fields.py @@ -0,0 +1,11 @@ +from tortoise.fields.data import CharField +from tortoise.contrib.mssql.field_types import NVARCHAR + + +class NVARCHAR(CharField): + + field_type = NVARCHAR + + @property + def SQL_TYPE(self) -> str: + return f"NVARCHAR({self.field.max_length})" \ No newline at end of file