Opened 5 months ago
Closed 5 months ago
#36347 closed Bug (duplicate)
bulk_create and postgis geometry field error
Reported by: | David Binetti | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 5.2 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I am trying to use bulk_create
to create/update records on an existing model. One of the fields of this model is a nullable geometry field (PointField.). When I run the operation, I get an error that the geometry field is not properly formatted, although it is not one of the fields I'm updating. Sample model and query here:
class Person(models.Model): id = HashidAutoField( primary_key=True, ) name = models.CharField( max_length=100, blank=False, validators=[ MinLengthValidator(1), ] ) external_id = models.IntegerField( blank=False, null=False, ) geometry = models.PointField( null=True, blank=True, ) def load_persons(rows): person = Person( [Person(**row) for row in rows], update_conflicts=True, update_fields=[ 'name', ], unique_fields=[ 'external_id', ] ) return persons
I then get the following error:
InternalError: parse error - invalid geometry LINE 1: ...LL,NULL,NULL,NULL,NULL,NULL,NULL}')::tsvector[], ('{NULL,NUL... ^ HINT: "NU" <-- parse error at position 2 within geometry
full stacktrace:
--------------------------------------------------------------------------- InternalError_ Traceback (most recent call last) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:105, in CursorWrapper._execute(self, sql, params, *ignored_wrapper_args) 104 else: --> 105 return self.cursor.execute(sql, params) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/psycopg/cursor.py:97, in Cursor.execute(self, query, params, prepare, binary) 96 except e._NO_TRACEBACK as ex: ---> 97 raise ex.with_traceback(None) 98 return self InternalError_: parse error - invalid geometry LINE 1: ...LL,NULL,NULL,NULL,NULL,NULL,NULL}')::tsvector[], ('{NULL,NUL... ^ HINT: "NU" <-- parse error at position 2 within geometry The above exception was the direct cause of the following exception: InternalError Traceback (most recent call last) Cell In[7], line 1 ----> 1 load_persons(rows) File ~/repos/registrar/project/app/loaders.py:18, in load_persons(rows) 17 def load_persons(rows): ---> 18 persons = Person.objects.bulk_create( 19 [Person(**row) for row in rows], 20 update_conflicts=True, 21 update_fields=[ 22 'last_name', 23 'first_name', 24 'middle_name', 25 'age', 26 'gender', 27 'registered', 28 'party', 29 'status', 30 'imported', 31 ], 32 unique_fields=[ 33 'external_id', 34 ] 35 ) 36 return persons File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/manager.py:87, in BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method(self, *args, **kwargs) 85 @wraps(method) 86 def manager_method(self, *args, **kwargs): ---> 87 return getattr(self.get_queryset(), name)(*args, **kwargs) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/query.py:823, in QuerySet.bulk_create(self, objs, batch_size, ignore_conflicts, update_conflicts, update_fields, unique_fields) 821 if objs_without_pk: 822 fields = [f for f in fields if not isinstance(f, AutoField)] --> 823 returned_columns = self._batched_insert( 824 objs_without_pk, 825 fields, 826 batch_size, 827 on_conflict=on_conflict, 828 update_fields=update_fields, 829 unique_fields=unique_fields, 830 ) 831 connection = connections[self.db] 832 if ( 833 connection.features.can_return_rows_from_bulk_insert 834 and on_conflict is None 835 ): File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/query.py:1882, in QuerySet._batched_insert(self, objs, fields, batch_size, on_conflict, update_fields, unique_fields) 1877 for item in [objs[i : i + batch_size] for i in range(0, len(objs), batch_size)]: 1878 if bulk_return and ( 1879 on_conflict is None or on_conflict == OnConflict.UPDATE 1880 ): 1881 inserted_rows.extend( -> 1882 self._insert( 1883 item, 1884 fields=fields, 1885 using=self.db, 1886 on_conflict=on_conflict, 1887 update_fields=update_fields, 1888 unique_fields=unique_fields, 1889 returning_fields=self.model._meta.db_returning_fields, 1890 ) 1891 ) 1892 else: 1893 self._insert( 1894 item, 1895 fields=fields, (...) 1899 unique_fields=unique_fields, 1900 ) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/query.py:1854, in QuerySet._insert(self, objs, fields, returning_fields, raw, using, on_conflict, update_fields, unique_fields) 1847 query = sql.InsertQuery( 1848 self.model, 1849 on_conflict=on_conflict, 1850 update_fields=update_fields, 1851 unique_fields=unique_fields, 1852 ) 1853 query.insert_values(fields, objs, raw=raw) -> 1854 return query.get_compiler(using=using).execute_sql(returning_fields) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/models/sql/compiler.py:1881, in SQLInsertCompiler.execute_sql(self, returning_fields) 1879 with self.connection.cursor() as cursor: 1880 for sql, params in self.as_sql(): -> 1881 cursor.execute(sql, params) 1882 if not self.returning_fields: 1883 return [] File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:122, in CursorDebugWrapper.execute(self, sql, params) 120 def execute(self, sql, params=None): 121 with self.debug_sql(sql, params, use_last_executed_query=True): --> 122 return super().execute(sql, params) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/sentry_sdk/utils.py:1811, in ensure_integration_enabled.<locals>.patcher.<locals>.runner(*args, **kwargs) 1808 if sentry_sdk.get_client().get_integration(integration) is None: 1809 return original_function(*args, **kwargs) -> 1811 return sentry_patched_function(*args, **kwargs) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/sentry_sdk/integrations/django/__init__.py:651, in install_sql_hook.<locals>.execute(self, sql, params) 642 with record_sql_queries( 643 cursor=self.cursor, 644 query=sql, (...) 648 span_origin=DjangoIntegration.origin_db, 649 ) as span: 650 _set_db_data(span, self) --> 651 result = real_execute(self, sql, params) 653 with capture_internal_exceptions(): 654 add_query_source(span) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:79, in CursorWrapper.execute(self, sql, params) 78 def execute(self, sql, params=None): ---> 79 return self._execute_with_wrappers( 80 sql, params, many=False, executor=self._execute 81 ) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:92, in CursorWrapper._execute_with_wrappers(self, sql, params, many, executor) 90 for wrapper in reversed(self.db.execute_wrappers): 91 executor = functools.partial(wrapper, executor) ---> 92 return executor(sql, params, many, context) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:100, in CursorWrapper._execute(self, sql, params, *ignored_wrapper_args) 98 warnings.warn(self.APPS_NOT_READY_WARNING_MSG, category=RuntimeWarning) 99 self.db.validate_no_broken_transaction() --> 100 with self.db.wrap_database_errors: 101 if params is None: 102 # params default might be backend specific. 103 return self.cursor.execute(sql) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/utils.py:91, in DatabaseErrorWrapper.__exit__(self, exc_type, exc_value, traceback) 89 if dj_exc_type not in (DataError, IntegrityError): 90 self.wrapper.errors_occurred = True ---> 91 raise dj_exc_value.with_traceback(traceback) from exc_value File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/django/db/backends/utils.py:105, in CursorWrapper._execute(self, sql, params, *ignored_wrapper_args) 103 return self.cursor.execute(sql) 104 else: --> 105 return self.cursor.execute(sql, params) File ~/.local/share/virtualenvs/registrar-D123KGkv/lib/python3.13/site-packages/psycopg/cursor.py:97, in Cursor.execute(self, query, params, prepare, binary) 93 self._conn.wait( 94 self._execute_gen(query, params, prepare=prepare, binary=binary) 95 ) 96 except e._NO_TRACEBACK as ex: ---> 97 raise ex.with_traceback(None) 98 return self InternalError: parse error - invalid geometry LINE 1: ...LL,NULL,NULL,NULL,NULL,NULL,NULL}')::tsvector[], ('{NULL,NUL... ^ HINT: "NU" <-- parse error at position 2 within geometry
Note:
See TracTickets
for help on using tickets.
Duplicate of #36289 (Postgres bulk_create error when geometry is null or a different SRID) fixed by d9bf0d07cc13c0351b65b025d7e8063864086975 in Django 5.2.1 meant to be
released on May 7th.