geoalchemy / geoalchemy2

Geospatial extension to SQLAlchemy
http://geoalchemy-2.readthedocs.org
MIT License
634 stars 112 forks source link

[Bug report] Reflection fails in mariadb #521

Open tomkcook opened 1 month ago

tomkcook commented 1 month ago

Describe the bug

In MariaDB, INFORMATION_SCHEMA.COLUMNS does not have an SRS_ID field. geoalchemy2.admin.dialects.mysql.reflect_geometry_column therefore fails because it assumes this field exists.

Optional link from https://geoalchemy-2.readthedocs.io which documents the behavior that is expected

No response

To Reproduce

$ docker run --rm -e MARIADB_ROOT_PASSWORD=root -e MARIADB_PASSWORD=root -p 3306:3306 --name mariadb mariadb:latest
$ docker exec -ti mariadb mariadb -proot
MariaDB> CREATE DATABASE test;
MariaDB> USE test;
MariaDB> CREATE TABLE test_table ( id INTEGER PRIMARY KEY AUTO_INCREMENT, loc POINT );
MariaDB> exit

$ python3 -m venv venv/
$ venv/bin/pip install geoalchemy2 sqlacodegen
$ venv/bin/sqlacodegen mariadb+mariadbconnector://root:root@127.0.0.1:3306/test

### Error

```Python traceback
/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlacodegen/main.py:47: SAWarning: Did not recognize type 'point' of column 'geolocation'
  metadata.reflect(engine, args.schema, not args.noviews, tables)
Traceback (most recent call last):
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
    self.dialect.do_execute(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
    cursor.execute(statement, parameters)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/mariadb/cursors.py", line 310, in execute
    self._readresponse()
mariadb.OperationalError: Unknown column 'SRS_ID' in 'field list'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "venv/bin/sqlacodegen", line 8, in <module>
    sys.exit(main())
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlacodegen/main.py", line 47, in main
    metadata.reflect(engine, args.schema, not args.noviews, tables)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/sql/schema.py", line 4901, in reflect
    Table(name, self, **reflect_opts)
  File "<string>", line 2, in __new__
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/util/deprecations.py", line 375, in warned
    return fn(*args, **kwargs)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/sql/schema.py", line 619, in __new__
    metadata._remove_table(name, schema)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/sql/schema.py", line 614, in __new__
    table._init(name, metadata, *args, **kw)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/sql/schema.py", line 689, in _init
    self._autoload(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/sql/schema.py", line 724, in _autoload
    conn_insp.reflect_table(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/reflection.py", line 779, in reflect_table
    self._reflect_column(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/reflection.py", line 848, in _reflect_column
    table.dispatch.column_reflect(self, table, col_d)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/event/attr.py", line 247, in __call__
    fn(*args, **kw)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/geoalchemy2/admin/__init__.py", line 102, in _reflect_geometry_column
    select_dialect(inspector.bind.dialect.name).reflect_geometry_column(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/geoalchemy2/admin/dialects/mysql.py", line 42, in reflect_geometry_column
    geometry_type, srid, nullable_str = inspector.bind.execute(text(geometry_type_query)).one()
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1385, in execute
    return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection
    return connection._execute_clauseelement(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement
    ret = self._execute_context(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context
    self._handle_dbapi_exception(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception
    util.raise_(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
    self.dialect.do_execute(
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 736, in do_execute
    cursor.execute(statement, parameters)
  File "/home/tkcook/git/netreach-controller-backend/venv/lib/python3.8/site-packages/mariadb/cursors.py", line 310, in execute
    self._readresponse()
sqlalchemy.exc.OperationalError: (mariadb.OperationalError) Unknown column 'SRS_ID' in 'field list'
[SQL: SELECT DATA_TYPE, SRS_ID, IS_NULLABLE
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'Ap' and COLUMN_NAME = 'geolocation' and table_schema = 'vtba']
(Background on this error at: https://sqlalche.me/e/14/e3q8)


### Additional context

AFAICT this is a difference between MariaDB and MySQL; MariaDB doesn't support storing SRIDs on spatial types and always does its geometry calculations in Euclidean space.

### GeoAlchemy 2 Version in Use

0.15.2

### Python Version

3.8.19

### Operating system

Linux