1

Django's documentation on objects.raw() says the following about using named parameters:

Dictionary params are not supported with the SQLite backend; with this backend, you must pass parameters as a list.

I use SQLite when running unit tests in our codebase because it's ridiculously fast in comparison to our real database backend. But since it doesn't seem to support named parameters, I cannot write tests for a certain piece of functionality that relies on them.

Is there a clean generic way to work around this limitation? As in, without resorting to hacks that could expose code to SQL injection?

e4c5
  • 52,766
  • 11
  • 101
  • 134
Pieter
  • 893
  • 1
  • 8
  • 20
  • 2
    SQLite itself supports [named parameters](http://www.sqlite.org/c3ref/bind_parameter_name.html) (this would be [Python's style](https://www.python.org/dev/peps/pep-0249/#paramstyle) `named`, in addition to `qmark` and `numeric`), but Django's SQLite backend does not implement the proper translation from its own parameter format. In theory, this could be changed in the [source](https://github.com/django/django/blob/master/django/db/backends/sqlite3/base.py#L279). – CL. Feb 27 '17 at 14:49
  • For future visitors: I ended up rewriting the piece of code to be database-agnostic by eliminating the raw SQL statements. e4c5 still makes a valid point below, so I've marked their post as the answer. – Pieter Feb 28 '17 at 13:29

1 Answers1

2

I use SQLite when running unit tests in our codebase because it's ridiculously fast in comparison to our real database backend.

Unit tests should ideally be executed against the same database. sqlite is lacking in many features (just as you have discovered). If you code your tests to work with sqlite, you will probably end up coding your functions to work with it to, which means some of the features on your real database have just been made redundant.

You can make your tests against mysql or postgresql run much much faster by using the keep option to manage.py. So there really isn't any need to use sqlite for testing.

Is there a clean generic way to work around this limitation? As in, without resorting to hacks that could expose code to SQL injection?

No. I would say using sqlite instead of your real database is a hack to begin with.

Community
  • 1
  • 1
e4c5
  • 52,766
  • 11
  • 101
  • 134
  • Did you try this? – e4c5 Feb 28 '17 at 07:30
  • Reusing old database tables for unit tests seems like a good way to have state leak across isolated runs of tests, which makes the behavior of tests unpredictable. We have a codebase with over 2.000 tests and a whole lot of tables, so there's a big potential for interference when reusing an old database. Am I misunderstanding the semantics of `--keep`? – Pieter Feb 28 '17 at 08:15
  • Yes peter, you are misunderstading it. The database is restored to it's original state after the test suite is completed. – e4c5 Feb 28 '17 at 08:33
  • You mean that the scheme is preserved, while throwing out the data? – Pieter Feb 28 '17 at 09:50
  • exactly that. Please see the linked answer for more details – e4c5 Feb 28 '17 at 10:32