diff --git a/src/datajoint/adapters/mysql.py b/src/datajoint/adapters/mysql.py index 1888eccf4..a82607be5 100644 --- a/src/datajoint/adapters/mysql.py +++ b/src/datajoint/adapters/mysql.py @@ -737,8 +737,10 @@ def parse_foreign_key_error(self, error_message: str) -> dict[str, str | list[st def get_indexes_sql(self, schema_name: str, table_name: str) -> str: """Query to get index definitions. - Note: For MySQL 8.0+, EXPRESSION column contains the expression for + Note: For MySQL 8.0.13+, EXPRESSION column contains the expression for functional indexes. COLUMN_NAME is NULL for such indexes. + On MySQL < 8.0.13 and MariaDB, the EXPRESSION column does not exist; + heading.py falls back to get_indexes_sql_fallback() in that case. """ return ( f"SELECT INDEX_NAME as index_name, " @@ -751,6 +753,19 @@ def get_indexes_sql(self, schema_name: str, table_name: str) -> str: f"ORDER BY index_name, seq_in_index" ) + def get_indexes_sql_fallback(self, schema_name: str, table_name: str) -> str: + """Fallback index query for MySQL < 8.0.13 and MariaDB (no EXPRESSION column).""" + return ( + f"SELECT INDEX_NAME as index_name, " + f"COLUMN_NAME as column_name, " + f"NON_UNIQUE as non_unique, SEQ_IN_INDEX as seq_in_index " + f"FROM information_schema.statistics " + f"WHERE table_schema = {self.quote_string(schema_name)} " + f"AND table_name = {self.quote_string(table_name)} " + f"AND index_name != 'PRIMARY' " + f"ORDER BY index_name, seq_in_index" + ) + def parse_column_info(self, row: dict[str, Any]) -> dict[str, Any]: """ Parse MySQL SHOW FULL COLUMNS output into standardized format. diff --git a/src/datajoint/heading.py b/src/datajoint/heading.py index 4d7f0c62a..a0a57caaa 100644 --- a/src/datajoint/heading.py +++ b/src/datajoint/heading.py @@ -551,10 +551,22 @@ def _init_from_database(self) -> None: # Read and tabulate secondary indexes keys = defaultdict(dict) - for item in conn.query( - adapter.get_indexes_sql(database, table_name), - as_dict=True, - ): + try: + index_rows = conn.query( + adapter.get_indexes_sql(database, table_name), + as_dict=True, + ) + except Exception: + # Fall back for MySQL < 8.0.13 / MariaDB (no EXPRESSION column) + index_rows = ( + conn.query( + adapter.get_indexes_sql_fallback(database, table_name), + as_dict=True, + ) + if hasattr(adapter, "get_indexes_sql_fallback") + else [] + ) + for item in index_rows: # Note: adapter.get_indexes_sql() already filters out PRIMARY key # MySQL/PostgreSQL adapters return: index_name, column_name, non_unique index_name = item.get("index_name") or item.get("Key_name")