Django Concat cannot be used in AddConstraint

93 views Asked by At

I have a constraint like this

CheckConstraint(
    check=Q(full_path__endswith=Concat(Value("/"), F("identifier"), Value("/")))  #
    | Q(full_path="/"),
    name="path_endswith_identifier_if_not_root",
 ),

Makemigrations runs fine, but when I try to actually migrate the generated migration, I get IndexError: tuple index out of range

...
  File "/opt/virtual_env/mch2/lib/python3.7/site-packages/django/db/backends/utils.py", line 99, in execute
    return super().execute(sql, params)
  File "/opt/virtual_env/mch2/lib/python3.7/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/opt/virtual_env/mch2/lib/python3.7/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/opt/virtual_env/mch2/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
IndexError: tuple index out of range

When I ran sqlmigrations for the generated migration, I get the following error TypeError: not enough arguments for format string.

Here is the full error message:

 ...
  File "/opt/virtual_env/mch2/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 345, in add_constraint
    self.execute(sql)
  File "/opt/virtual_env/mch2/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 132, in execute
    self.collected_sql.append((sql % tuple(map(self.quote_value, params))) + ending)
TypeError: not enough arguments for format string

The string that django tries to format here is:

ALTER TABLE "documents_directory" ADD CONSTRAINT "path_endswith_identifier_if_not_root" CHECK (("full_path"::text LIKE '%' || REPLACE(REPLACE(REPLACE((CONCAT('/', CONCAT("documents_directory"."identifier", '/'))), E'\\', E'\\\\'), E'%', E'\\%'), E'_', E'\\_') OR "full_path" = '/'))

and the tuple is empty

I have tried the following things to rule out plain stupidity:

  • Use Concat(Value("/"), F("identifier"), Value("/")) in an annotation, this works like a charm
  • Replace Value("/") with "/", as expected this yields problems on its own
  • Replace the concat in the constraint with a simple value, this also works

So it seems like all pieces of the puzzle work separately!

If it matters, I am using django 2.2.9

0

There are 0 answers