Skip to content

Commit

Permalink
fix view comparison
Browse files Browse the repository at this point in the history
The previous function would ignore changes in numbers and quoted
whitespace. We can use sqlparse to normalize the given SQL for easy
comparison.
  • Loading branch information
tfeldmann committed Jan 31, 2025
1 parent c515a96 commit d02c367
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
31 changes: 14 additions & 17 deletions django_db_views/autodetector.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import re
from itertools import zip_longest
from typing import Type

import django
import six
import sqlparse
from django.apps import apps
from django.conf import settings
from django.db import connection, ProgrammingError
Expand Down Expand Up @@ -178,21 +177,19 @@ def get_current_view_models():
view_models[key] = model_class
return view_models

def is_same_views(self, current: str, new: str) -> bool:
if not current:
return False
s1_words = filter(
lambda x: len(x) != 0, re.split(pattern="[^a-zA-Z]*", string=current)
)
s2_words = filter(
lambda x: len(x) != 0, re.split(pattern="[^a-zA-Z]*", string=new)
)
for w1, w2 in zip_longest(s1_words, s2_words):
if not w1 or not w2:
return False
if w1.lower() != w2.lower():
return False
return True
@staticmethod
def is_same_views(current: str, new: str) -> bool:
def sql_normalize(s: str) -> str:
return sqlparse.format(
s,
compact=True,
keyword_case="upper",
identifier_case="lower",
reindent=True,
strip_comments=True,
)

return sql_normalize(current) == sql_normalize(new)

def generate_views_operations(self, graph: MigrationGraph) -> None:
view_models = self.get_current_view_models()
Expand Down
16 changes: 16 additions & 0 deletions tests/test_autodetector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django_db_views.autodetector import ViewMigrationAutoDetector


def test_is_same_views():
is_same = ViewMigrationAutoDetector.is_same_views

assert is_same("A B C", "A B C")
assert is_same("select * from xyz", "SELECT * FROM xyz")
assert not is_same("select 1 from test", "select 2 from test")
assert is_same("select *\nfrom test\n", "select * from test")
assert is_same(
"SELECT\n\t * \n FROM something where a = ' ' and B = \" \"",
"select * from something where a = ' ' and b = \" \"",
)
assert not is_same('SELECT " "', 'SELECT ""')
assert not is_same('SELECT "TEST "', 'SELECT "TEST "')

0 comments on commit d02c367

Please sign in to comment.