Code

Ticket #4680: 4680-3.diff

File 4680-3.diff, 4.8 KB (added by claudep, 2 years ago)

Possible resolution of the issue

Line 
1diff --git a/django/core/management/sql.py b/django/core/management/sql.py
2index 19b7ec2..472f486 100644
3--- a/django/core/management/sql.py
4+++ b/django/core/management/sql.py
5@@ -144,6 +144,20 @@ def sql_all(app, style, connection):
6     "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
7     return sql_create(app, style, connection) + sql_custom(app, style, connection) + sql_indexes(app, style, connection)
8 
9+def _split_statements(content):
10+    comment_re = re.compile(r"^((?:'[^']*'|[^'])*?)--.*$")
11+    statements = []
12+    statement = u""
13+    for line in content.split("\n"):
14+        cleaned_line = comment_re.sub(r"\1", line).strip()
15+        if not cleaned_line:
16+            continue
17+        statement += cleaned_line
18+        if statement.endswith(";"):
19+            statements.append(statement)
20+            statement = u""
21+    return statements
22+
23 def custom_sql_for_model(model, style, connection):
24     opts = model._meta
25     app_dir = os.path.normpath(os.path.join(os.path.dirname(models.get_app(model._meta.app_label).__file__), 'sql'))
26@@ -157,10 +171,6 @@ def custom_sql_for_model(model, style, connection):
27         for f in post_sql_fields:
28             output.extend(f.post_create_sql(style, model._meta.db_table))
29 
30-    # Some backends can't execute more than one SQL statement at a time,
31-    # so split into separate statements.
32-    statements = re.compile(r";[ \t]*$", re.M)
33-
34     # Find custom SQL, if it's available.
35     backend_name = connection.settings_dict['ENGINE'].split('.')[-1]
36     sql_files = [os.path.join(app_dir, "%s.%s.sql" % (opts.object_name.lower(), backend_name)),
37@@ -168,11 +178,9 @@ def custom_sql_for_model(model, style, connection):
38     for sql_file in sql_files:
39         if os.path.exists(sql_file):
40             fp = open(sql_file, 'U')
41-            for statement in statements.split(fp.read().decode(settings.FILE_CHARSET)):
42-                # Remove any comments from the file
43-                statement = re.sub(ur"--.*([\n\Z]|$)", "", statement)
44-                if statement.strip():
45-                    output.append(statement + u";")
46+            # Some backends can't execute more than one SQL statement at a time,
47+            # so split into separate statements.
48+            output.extend(_split_statements(fp.read().decode(settings.FILE_CHARSET)))
49             fp.close()
50 
51     return output
52diff --git a/tests/regressiontests/initial_sql_regress/sql/simple.sql b/tests/regressiontests/initial_sql_regress/sql/simple.sql
53index ca9bd40..ef2be49 100644
54--- a/tests/regressiontests/initial_sql_regress/sql/simple.sql
55+++ b/tests/regressiontests/initial_sql_regress/sql/simple.sql
56@@ -1,4 +1,6 @@
57-INSERT INTO initial_sql_regress_simple (name) VALUES ('John');
58+-- a comment
59+INSERT INTO initial_sql_regress_simple (name) VALUES ('John'); -- another comment
60+INSERT INTO initial_sql_regress_simple (name) VALUES ('-- Comment Man');
61 INSERT INTO initial_sql_regress_simple (name) VALUES ('Paul');
62 INSERT INTO initial_sql_regress_simple (name) VALUES ('Ringo');
63 INSERT INTO initial_sql_regress_simple (name) VALUES ('George');
64diff --git a/tests/regressiontests/initial_sql_regress/tests.py b/tests/regressiontests/initial_sql_regress/tests.py
65index 815b75a..03a91cb 100644
66--- a/tests/regressiontests/initial_sql_regress/tests.py
67+++ b/tests/regressiontests/initial_sql_regress/tests.py
68@@ -4,12 +4,26 @@ from .models import Simple
69 
70 
71 class InitialSQLTests(TestCase):
72-    def test_initial_sql(self):
73-        # The format of the included SQL file for this test suite is important.
74-        # It must end with a trailing newline in order to test the fix for #2161.
75+    # The format of the included SQL file for this test suite is important.
76+    # It must end with a trailing newline in order to test the fix for #2161.
77 
78-        # However, as pointed out by #14661, test data loaded by custom SQL
79+    def test_initial_sql(self):
80+        # As pointed out by #14661, test data loaded by custom SQL
81         # can't be relied upon; as a result, the test framework flushes the
82         # data contents before every test. This test validates that this has
83         # occurred.
84         self.assertEqual(Simple.objects.count(), 0)
85+
86+    def test_custom_sql(self):
87+        from django.core.management.sql import custom_sql_for_model
88+        from django.core.management.color import no_style
89+        from django.db import connections, DEFAULT_DB_ALIAS
90+
91+        # Simulate the custom SQL loading by syncdb
92+        connection = connections[DEFAULT_DB_ALIAS]
93+        custom_sql = custom_sql_for_model(Simple, no_style(), connection)
94+        self.assertEqual(len(custom_sql), 8)
95+        cursor = connection.cursor()
96+        for sql in custom_sql:
97+            cursor.execute(sql)
98+        self.assertEqual(Simple.objects.count(), 8)