Handle creating a unique index as adding a unique constraint
This commit is contained in:
1 parent
3fbc720650
commit
3219f9cf8a
4 files changed
+42
-25
No files matched your search
@@ -5,6 +5,7 @@
|
|||||||
- Drop support for Django 1.11, 2.0, 2.1, 3.0 and 3.1
|
- Drop support for Django 1.11, 2.0, 2.1, 3.0 and 3.1
|
||||||
- Add support for Django 4.0
|
- Add support for Django 4.0
|
||||||
- Fix index creation detection when table is being created in the transaction (issue #178)
|
- Fix index creation detection when table is being created in the transaction (issue #178)
|
||||||
|
- Handle unique index creation as adding a unique constraint (issue #183)
|
||||||
|
|
||||||
## 3.0.1
|
## 3.0.1
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ def has_not_null_column(sql_statements, **kwargs):
|
|||||||
def has_add_unique(sql_statements, **kwargs):
|
def has_add_unique(sql_statements, **kwargs):
|
||||||
regex_result = None
|
regex_result = None
|
||||||
for sql in sql_statements:
|
for sql in sql_statements:
|
||||||
regex_result = re.search("ALTER TABLE (.*) ADD CONSTRAINT .* UNIQUE", sql)
|
regex_result = re.search(
|
||||||
|
"ALTER TABLE (.*) ADD CONSTRAINT .* UNIQUE", sql
|
||||||
|
) or re.search('CREATE UNIQUE INDEX .* ON (".*?")', sql)
|
||||||
if regex_result:
|
if regex_result:
|
||||||
break
|
break
|
||||||
if not regex_result:
|
if not regex_result:
|
||||||
|
|||||||
@@ -3,23 +3,6 @@ import re
|
|||||||
from .base import BaseAnalyser
|
from .base import BaseAnalyser
|
||||||
|
|
||||||
|
|
||||||
def has_add_unique(sql_statements, **kwargs):
|
|
||||||
regex_result = None
|
|
||||||
for sql in sql_statements:
|
|
||||||
regex_result = re.search('CREATE UNIQUE INDEX .* ON (".*?")', sql)
|
|
||||||
if regex_result:
|
|
||||||
break
|
|
||||||
if not regex_result:
|
|
||||||
return False
|
|
||||||
|
|
||||||
concerned_table = regex_result.group(1)
|
|
||||||
table_is_added_in_transaction = any(
|
|
||||||
sql.startswith("CREATE TABLE {}".format(concerned_table))
|
|
||||||
for sql in sql_statements
|
|
||||||
)
|
|
||||||
return not table_is_added_in_transaction
|
|
||||||
|
|
||||||
|
|
||||||
class SqliteAnalyser(BaseAnalyser):
|
class SqliteAnalyser(BaseAnalyser):
|
||||||
migration_tests = [
|
migration_tests = [
|
||||||
{
|
{
|
||||||
@@ -54,12 +37,6 @@ class SqliteAnalyser(BaseAnalyser):
|
|||||||
"mode": "transaction",
|
"mode": "transaction",
|
||||||
"type": "error",
|
"type": "error",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"code": "ADD_UNIQUE",
|
|
||||||
"fn": has_add_unique,
|
|
||||||
"mode": "transaction",
|
|
||||||
"type": "error",
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -21,9 +21,16 @@ class SqlAnalyserTestCase(unittest.TestCase):
|
|||||||
0, len(warnings), "Found warnings in sql: {}".format(errors)
|
0, len(warnings), "Found warnings in sql: {}".format(errors)
|
||||||
)
|
)
|
||||||
|
|
||||||
def assertBackwardIncompatibleSql(self, sql):
|
def assertBackwardIncompatibleSql(self, sql, code=None):
|
||||||
errors, _, _ = self.analyse_sql(sql)
|
errors, _, _ = self.analyse_sql(sql)
|
||||||
self.assertNotEqual(0, len(errors), "Found no errors in sql")
|
self.assertNotEqual(0, len(errors), "Found no errors in sql")
|
||||||
|
if code:
|
||||||
|
self.assertTrue(
|
||||||
|
any(err["code"] == code for err in errors),
|
||||||
|
"Didn't find error code {} in returned errors ({})".format(
|
||||||
|
code, [err["code"] for err in errors]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def assertWarningSql(self, sql):
|
def assertWarningSql(self, sql):
|
||||||
_, _, warnings = self.analyse_sql(sql)
|
_, _, warnings = self.analyse_sql(sql)
|
||||||
@@ -63,6 +70,16 @@ class MySqlAnalyserTestCase(SqlAnalyserTestCase):
|
|||||||
sql = "ALTER TABLE `app_unique_together_a` DROP INDEX `app_unique_together_a_int_field_char_field_979ac7d8_uniq`;"
|
sql = "ALTER TABLE `app_unique_together_a` DROP INDEX `app_unique_together_a_int_field_char_field_979ac7d8_uniq`;"
|
||||||
self.assertValidSql(sql)
|
self.assertValidSql(sql)
|
||||||
|
|
||||||
|
def test_unique_index(self):
|
||||||
|
sql = 'CREATE UNIQUE INDEX "index_name" ON "table" ("col1", "col2");'
|
||||||
|
self.assertBackwardIncompatibleSql(sql, "ADD_UNIQUE")
|
||||||
|
|
||||||
|
sql = [
|
||||||
|
'CREATE TABLE "table" ("col1" integer, "col2" integer);',
|
||||||
|
'CREATE UNIQUE INDEX "index_name" ON "table" ("col1", "col2");',
|
||||||
|
]
|
||||||
|
self.assertValidSql(sql)
|
||||||
|
|
||||||
def test_add_many_to_many_field(self):
|
def test_add_many_to_many_field(self):
|
||||||
sql = [
|
sql = [
|
||||||
"CREATE TABLE `app_add_manytomany_field_b_many_to_many`(`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `b_id` integer NOT NULL, `a_id` integer NOT NULL);",
|
"CREATE TABLE `app_add_manytomany_field_b_many_to_many`(`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `b_id` integer NOT NULL, `a_id` integer NOT NULL);",
|
||||||
@@ -146,6 +163,16 @@ class SqliteAnalyserTestCase(SqlAnalyserTestCase):
|
|||||||
sql = 'DROP INDEX "app_unique_together_a_int_field_char_field_979ac7d8_uniq";'
|
sql = 'DROP INDEX "app_unique_together_a_int_field_char_field_979ac7d8_uniq";'
|
||||||
self.assertValidSql(sql)
|
self.assertValidSql(sql)
|
||||||
|
|
||||||
|
def test_unique_index(self):
|
||||||
|
sql = 'CREATE UNIQUE INDEX "index_name" ON "table" ("col1", "col2");'
|
||||||
|
self.assertBackwardIncompatibleSql(sql, "ADD_UNIQUE")
|
||||||
|
|
||||||
|
sql = [
|
||||||
|
'CREATE TABLE "table" ("col1" integer, "col2" integer);',
|
||||||
|
'CREATE UNIQUE INDEX "index_name" ON "table" ("col1", "col2");',
|
||||||
|
]
|
||||||
|
self.assertValidSql(sql)
|
||||||
|
|
||||||
def test_add_many_to_many_field(self):
|
def test_add_many_to_many_field(self):
|
||||||
sql = [
|
sql = [
|
||||||
'CREATE TABLE "app_add_manytomany_field_b_many_to_many"("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "b_id" integer NOT NULL REFERENCES "app_add_manytomany_field_b"("id") DEFERRABLE INITIALLY DEFERRED, "a_id" integer NOT NULL REFERENCES "app_add_manytomany_field_a"("id") DEFERRABLE INITIALLY DEFERRED);',
|
'CREATE TABLE "app_add_manytomany_field_b_many_to_many"("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "b_id" integer NOT NULL REFERENCES "app_add_manytomany_field_b"("id") DEFERRABLE INITIALLY DEFERRED, "a_id" integer NOT NULL REFERENCES "app_add_manytomany_field_a"("id") DEFERRABLE INITIALLY DEFERRED);',
|
||||||
@@ -197,6 +224,16 @@ class PostgresqlAnalyserTestCase(SqlAnalyserTestCase):
|
|||||||
sql = 'ALTER TABLE "app_unique_together_a" DROP CONSTRAINT "app_unique_together_a_int_field_char_field_979ac7d8_uniq";'
|
sql = 'ALTER TABLE "app_unique_together_a" DROP CONSTRAINT "app_unique_together_a_int_field_char_field_979ac7d8_uniq";'
|
||||||
self.assertValidSql(sql)
|
self.assertValidSql(sql)
|
||||||
|
|
||||||
|
def test_unique_index(self):
|
||||||
|
sql = 'CREATE UNIQUE INDEX "index_name" ON "table" ("col1", "col2");'
|
||||||
|
self.assertBackwardIncompatibleSql(sql, "ADD_UNIQUE")
|
||||||
|
|
||||||
|
sql = [
|
||||||
|
'CREATE TABLE "table" ("col1" integer, "col2" integer);',
|
||||||
|
'CREATE UNIQUE INDEX "index_name" ON "table" ("col1", "col2");',
|
||||||
|
]
|
||||||
|
self.assertValidSql(sql)
|
||||||
|
|
||||||
def test_add_many_to_many_field(self):
|
def test_add_many_to_many_field(self):
|
||||||
sql = [
|
sql = [
|
||||||
'CREATE TABLE "app_add_manytomany_field_b_many_to_many"("id" serial NOT NULL PRIMARY KEY, "b_id" integer NOT NULL, "a_id" integer NOT NULL);',
|
'CREATE TABLE "app_add_manytomany_field_b_many_to_many"("id" serial NOT NULL PRIMARY KEY, "b_id" integer NOT NULL, "a_id" integer NOT NULL);',
|
||||||
|
|||||||
Reference in new issue
Block a user