Skip to content

Commit e2fd494

Browse files
authored
Add workaround for insert into table with trigger error (#158)
* Fixed insert into table with trigger by adding `has_trigger` flag to `OPTIONS` dictionary * Fixed unit test comment * Added examples of `has_trigger` in README
1 parent 781e9bf commit e2fd494

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,26 @@ Dictionary. Current available keys are:
204204
},
205205
```
206206

207+
- has_trigger
208+
209+
Boolean. Sets if backend can return rows from bulk insert.
210+
Default value is False which allows for the backend to
211+
return rows from bulk insert.
212+
213+
```python
214+
# Examples
215+
"OPTIONS": {
216+
# This database has triggers so set has_trigger to True
217+
# to prevent errors related to returning rows from bulk insert
218+
"has_trigger": True
219+
}
220+
221+
"OPTIONS": {
222+
# This database doesn't have any triggers so don't need to
223+
# add has_trigger since it is False by default
224+
}
225+
```
226+
207227
### Backend-specific settings
208228

209229
The following project-level settings also control the behavior of the backend:
@@ -252,7 +272,7 @@ The following features are currently not fully supported:
252272
- Bit-shift operators
253273
- Filtered index
254274
- Date extract function
255-
- Hashing functions
275+
- Bulk insert into a table with a trigger and returning the rows inserted
256276

257277
JSONField lookups have limitations, more details [here](https://github.com/microsoft/mssql-django/wiki/JSONField).
258278

mssql/base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,11 @@ def init_connection_state(self):
421421
datefirst = options.get('datefirst', 7)
422422
cursor.execute('SET DATEFORMAT ymd; SET DATEFIRST %s' % datefirst)
423423

424+
# If there are triggers set can_return_rows_from_bulk_insert to
425+
# False to prevent errors when inserting. See issue #130
426+
if (options.get('has_trigger', False)):
427+
self.features_class.can_return_rows_from_bulk_insert = False
428+
424429
val = self.get_system_datetime()
425430
if isinstance(val, str):
426431
raise ImproperlyConfigured(

testapp/tests/test_queries.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import django.db.utils
2+
from django.db import connections
3+
from django.test import TransactionTestCase
4+
5+
from ..models import Author
6+
7+
class TestTableWithTrigger(TransactionTestCase):
8+
def test_insert_into_table_with_trigger(self):
9+
connection = connections['default']
10+
# Change can_return_rows_from_bulk_insert to be the same as when
11+
# has_trigger = True
12+
connection.features_class.can_return_rows_from_bulk_insert = False
13+
14+
with connection.schema_editor() as cursor:
15+
cursor.execute("""
16+
CREATE TRIGGER TestTrigger
17+
ON [testapp_author]
18+
FOR INSERT
19+
AS
20+
INSERT INTO [testapp_editor]([name]) VALUES ('Bar')
21+
""")
22+
23+
try:
24+
Author.objects.create(name='Foo')
25+
except django.db.utils.ProgrammingError as e:
26+
self.fail('Check for regression of issue #130. Insert with trigger failed with exception: %s' % e)
27+
finally:
28+
with connection.schema_editor() as cursor:
29+
cursor.execute("DROP TRIGGER TestTrigger")

0 commit comments

Comments
 (0)