You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2026/04/22 23:01:27 UTC
(superset) branch master updated: fix(db): Add MariaDB DDL fix for `NOCYCLE` syntax (#37582)
This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new e10918307cb fix(db): Add MariaDB DDL fix for `NOCYCLE` syntax (#37582)
e10918307cb is described below
commit e10918307cb6f750c26b1ac0e2052c0ab96bfb06
Author: Joao Amaral <72...@users.noreply.github.com>
AuthorDate: Thu Apr 23 06:01:20 2026 +0700
fix(db): Add MariaDB DDL fix for `NOCYCLE` syntax (#37582)
---
superset/extensions/__init__.py | 10 +++++++
superset/utils/database.py | 22 +++++++++++++-
tests/unit_tests/utils/test_database.py | 53 +++++++++++++++++++++++++++++++++
3 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/superset/extensions/__init__.py b/superset/extensions/__init__.py
index 628af40cd62..e704a2a4048 100644
--- a/superset/extensions/__init__.py
+++ b/superset/extensions/__init__.py
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
import json
+import logging
import os
from typing import Any, Callable, Optional
@@ -45,11 +46,20 @@ from superset.extensions.ssh import SSHManagerFactory
from superset.extensions.stats_logger import BaseStatsLoggerManager
from superset.security.manager import SupersetSecurityManager
from superset.utils.cache_manager import CacheManager
+from superset.utils.database import apply_mariadb_ddl_fix
from superset.utils.encrypt import EncryptedFieldFactory
from superset.utils.feature_flag_manager import FeatureFlagManager
from superset.utils.machine_auth import MachineAuthProviderFactory
from superset.utils.profiler import SupersetProfiler
+# Apply MariaDB DDL fix early in the import chain
+try:
+ apply_mariadb_ddl_fix()
+except Exception as ex:
+ logging.exception(
+ "Applying MariaDB DDL fix failed; continuing without patch: %s", ex
+ )
+
class ResultsBackendManager:
def __init__(self) -> None:
diff --git a/superset/utils/database.py b/superset/utils/database.py
index cc16eaacb01..cd23dfff5a1 100644
--- a/superset/utils/database.py
+++ b/superset/utils/database.py
@@ -17,9 +17,10 @@
from __future__ import annotations
import logging
-from typing import TYPE_CHECKING
+from typing import Any, TYPE_CHECKING
from flask import current_app as app
+from sqlalchemy.sql import compiler
from superset.constants import EXAMPLES_DB_UUID
@@ -84,3 +85,22 @@ def remove_database(database: Database) -> None:
db.session.delete(database)
db.session.flush()
+
+
+def apply_mariadb_ddl_fix() -> None:
+ """
+ Fix MariaDB "NO CYCLE" syntax issue - MariaDB uses "NOCYCLE" (no space).
+
+ This fix will be included in SQLAlchemy v2.1.0.
+ See: https://github.com/sqlalchemy/sqlalchemy/blob/rel_2_1_0b1/lib/sqlalchemy/dialects/mysql/_mariadb_shim.py
+ """
+ original_visit_create_sequence = compiler.DDLCompiler.visit_create_sequence
+
+ def patched_visit_create_sequence(self: Any, create: Any, **kw: Any) -> str:
+ text = original_visit_create_sequence(self, create, **kw)
+ dialect_name = getattr(self.dialect, "name", "") or ""
+ if "mariadb" in dialect_name.lower():
+ return text.replace("NO CYCLE", "NOCYCLE")
+ return text
+
+ compiler.DDLCompiler.visit_create_sequence = patched_visit_create_sequence
diff --git a/tests/unit_tests/utils/test_database.py b/tests/unit_tests/utils/test_database.py
new file mode 100644
index 00000000000..22bea17765e
--- /dev/null
+++ b/tests/unit_tests/utils/test_database.py
@@ -0,0 +1,53 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Tests for superset.utils.database module."""
+
+import pytest
+from sqlalchemy import Sequence
+from sqlalchemy.dialects import mysql, postgresql
+from sqlalchemy.schema import CreateSequence
+from sqlalchemy.sql.compiler import DDLCompiler
+
+from superset.utils.database import apply_mariadb_ddl_fix
+
+
+@pytest.fixture(scope="module", autouse=True)
+def setup_mariadb_ddl_fix():
+ """Apply MariaDB DDL fix once per module before tests run."""
+ apply_mariadb_ddl_fix()
+
+
+def test_mariadb_nocycle_fix_applied():
+ """Test that 'NO CYCLE' is replaced with 'NOCYCLE' for MariaDB dialect."""
+ dialect = mysql.dialect()
+ dialect.name = "mariadb"
+ ddl_compiler = DDLCompiler(dialect, None)
+ seq = Sequence("test_seq", cycle=False)
+
+ result = ddl_compiler.visit_create_sequence(CreateSequence(seq))
+ assert "NOCYCLE" in result
+ assert "NO CYCLE" not in result
+
+
+def test_nocycle_fix_not_applied_for_postgresql():
+ """Test that 'NO CYCLE' is NOT replaced for PostgreSQL dialect."""
+ dialect = postgresql.dialect()
+ compiler = DDLCompiler(dialect, None)
+ seq = Sequence("test_seq", cycle=False)
+
+ result = compiler.visit_create_sequence(CreateSequence(seq))
+ assert "NO CYCLE" in result