mirror of
https://github.com/apache/superset.git
synced 2026-05-25 01:35:39 +00:00
Simplify
This commit is contained in:
@@ -188,7 +188,9 @@ function CollectionControl({
|
||||
// Two items can collide when keyAccessor returns falsy and the index
|
||||
// fallback is used — breaking dnd-kit reordering and React reconciliation.
|
||||
// Assign a stable nanoid per item ref when no key is available.
|
||||
const generatedIdsRef = useRef<WeakMap<CollectionItem, string>>(new WeakMap());
|
||||
const generatedIdsRef = useRef<WeakMap<CollectionItem, string>>(
|
||||
new WeakMap(),
|
||||
);
|
||||
const itemIds = useMemo(
|
||||
() =>
|
||||
value.map(item => {
|
||||
|
||||
@@ -557,13 +557,11 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods
|
||||
# if True, database will be listed as option in the upload file form
|
||||
supports_file_upload = True
|
||||
|
||||
# Optional override for the RLS method used by ``get_rls_method``. When set,
|
||||
# the engine spec opts into a specific strategy regardless of the
|
||||
# ``allows_subqueries`` / ``allows_alias_in_select`` defaults. Use
|
||||
# ``RLSMethod.AS_PREDICATE_SPLICE`` for engines whose sqlglot dialect can
|
||||
# parse but not faithfully regenerate the SQL — splice mode rewrites the
|
||||
# original query string instead of round-tripping through the generator.
|
||||
rls_method: RLSMethod | None = None
|
||||
# RLS strategy for this engine spec. Override in engine-specific classes as
|
||||
# needed (for example ``RLSMethod.AS_PREDICATE`` for engines that don't
|
||||
# support subquery-based RLS, or ``RLSMethod.AS_PREDICATE_SPLICE`` for
|
||||
# engines where sqlglot generation is not faithful).
|
||||
rls_method = RLSMethod.AS_SUBQUERY
|
||||
|
||||
# Is the DB engine spec able to change the default schema? This requires implementing # noqa: E501
|
||||
# a custom `adjust_engine_params` method.
|
||||
@@ -626,29 +624,6 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods
|
||||
else cls.encrypted_extra_sensitive_fields
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_rls_method(cls) -> RLSMethod:
|
||||
"""
|
||||
Returns the RLS method to be used for this engine.
|
||||
|
||||
There are three ways to insert RLS: replacing the table with a subquery
|
||||
that has the RLS (safest, but not supported in all databases), appending
|
||||
the RLS to the ``WHERE`` clause via AST transformation, or splicing the
|
||||
RLS into the original SQL string (preserves dialect-specific syntax that
|
||||
the sqlglot generator would otherwise transpile).
|
||||
|
||||
Engine specs can opt into a specific strategy by setting the class-level
|
||||
``rls_method`` attribute; otherwise the choice falls back to subquery
|
||||
when supported, and predicate otherwise.
|
||||
"""
|
||||
if cls.rls_method is not None:
|
||||
return cls.rls_method
|
||||
return (
|
||||
RLSMethod.AS_SUBQUERY
|
||||
if cls.allows_subqueries and cls.allows_alias_in_select
|
||||
else RLSMethod.AS_PREDICATE
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def is_oauth2_enabled(cls) -> bool:
|
||||
return (
|
||||
|
||||
@@ -35,6 +35,7 @@ from superset.db_engine_specs.base import (
|
||||
DatabaseCategory,
|
||||
)
|
||||
from superset.errors import ErrorLevel, SupersetError, SupersetErrorType
|
||||
from superset.sql.parse import RLSMethod
|
||||
from superset.utils.network import is_hostname_valid, is_port_open
|
||||
|
||||
|
||||
@@ -82,6 +83,7 @@ class CouchbaseEngineSpec(BasicParametersMixin, BaseEngineSpec):
|
||||
default_driver = "couchbase"
|
||||
allows_joins = False
|
||||
allows_subqueries = False
|
||||
rls_method = RLSMethod.AS_PREDICATE
|
||||
sqlalchemy_uri_placeholder = (
|
||||
"couchbase://user:password@host[:port]?truststorepath=value?ssl=value"
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@ from sqlalchemy.types import TypeEngine
|
||||
|
||||
from superset.constants import TimeGrain
|
||||
from superset.db_engine_specs.base import BaseEngineSpec, DatabaseCategory
|
||||
from superset.sql.parse import RLSMethod
|
||||
|
||||
|
||||
class PinotEngineSpec(BaseEngineSpec):
|
||||
@@ -30,6 +31,7 @@ class PinotEngineSpec(BaseEngineSpec):
|
||||
allows_joins = False
|
||||
allows_alias_in_select = False
|
||||
allows_alias_in_orderby = False
|
||||
rls_method = RLSMethod.AS_PREDICATE
|
||||
|
||||
# pinotdb only sets cursor.description when the response contains
|
||||
# columnDataTypes, which Pinot omits for zero-row results.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# under the License.
|
||||
|
||||
from superset.db_engine_specs.base import BaseEngineSpec, DatabaseCategory
|
||||
from superset.sql.parse import RLSMethod
|
||||
|
||||
|
||||
class SolrEngineSpec(BaseEngineSpec): # pylint: disable=abstract-method
|
||||
@@ -27,6 +28,7 @@ class SolrEngineSpec(BaseEngineSpec): # pylint: disable=abstract-method
|
||||
time_groupby_inline = False
|
||||
allows_joins = False
|
||||
allows_subqueries = False
|
||||
rls_method = RLSMethod.AS_PREDICATE
|
||||
|
||||
metadata = {
|
||||
"description": "Apache Solr is an open-source enterprise search platform.",
|
||||
|
||||
@@ -46,7 +46,7 @@ def apply_rls(
|
||||
# - append the RLS to the ``WHERE`` clause via AST transformation
|
||||
# - splice the RLS into the original SQL string (preserves dialect-specific
|
||||
# syntax that the sqlglot generator would otherwise transpile)
|
||||
method = database.db_engine_spec.get_rls_method()
|
||||
method = database.db_engine_spec.rls_method
|
||||
|
||||
# In splice mode predicates stay as raw SQL strings and are inserted verbatim
|
||||
# into the source query — re-parsing them would force a generator round-trip
|
||||
|
||||
@@ -1285,42 +1285,6 @@ def test_start_oauth2_dance_falls_back_to_url_for(mocker: MockerFixture) -> None
|
||||
assert error.extra["redirect_uri"] == fallback_uri
|
||||
|
||||
|
||||
def test_get_rls_method_default_subquery() -> None:
|
||||
"""
|
||||
By default, an engine that supports subqueries and aliases-in-select
|
||||
uses the safer subquery RLS strategy.
|
||||
"""
|
||||
|
||||
class _Spec(BaseEngineSpec):
|
||||
allows_subqueries = True
|
||||
allows_alias_in_select = True
|
||||
|
||||
assert _Spec.get_rls_method() == RLSMethod.AS_SUBQUERY
|
||||
|
||||
|
||||
def test_get_rls_method_default_predicate_when_no_subqueries() -> None:
|
||||
"""
|
||||
Engines without subquery / alias-in-select support fall back to the
|
||||
AST predicate strategy.
|
||||
"""
|
||||
|
||||
class _Spec(BaseEngineSpec):
|
||||
allows_subqueries = False
|
||||
allows_alias_in_select = True
|
||||
|
||||
assert _Spec.get_rls_method() == RLSMethod.AS_PREDICATE
|
||||
|
||||
|
||||
def test_get_rls_method_class_attribute_override() -> None:
|
||||
"""
|
||||
Setting ``rls_method`` on an engine spec opts the engine into a specific
|
||||
strategy regardless of the subquery/alias defaults — used by engines whose
|
||||
sqlglot dialect can parse but not faithfully regenerate SQL.
|
||||
"""
|
||||
|
||||
class _SpliceSpec(BaseEngineSpec):
|
||||
allows_subqueries = True
|
||||
allows_alias_in_select = True
|
||||
rls_method = RLSMethod.AS_PREDICATE_SPLICE
|
||||
|
||||
assert _SpliceSpec.get_rls_method() == RLSMethod.AS_PREDICATE_SPLICE
|
||||
def test_default_rls_method_is_subquery() -> None:
|
||||
"""Base engine spec defaults to subquery-based RLS."""
|
||||
assert BaseEngineSpec.rls_method == RLSMethod.AS_SUBQUERY
|
||||
|
||||
@@ -2754,14 +2754,17 @@ def test_rls_predicate_splice_inserts_before_comments(sql: str, expected: str) -
|
||||
"sql, engine, expected",
|
||||
[
|
||||
(
|
||||
"SELECT * FROM some_table QUALIFY row_number() OVER (PARTITION BY id ORDER BY ts DESC) = 1",
|
||||
"SELECT * FROM some_table QUALIFY row_number() OVER "
|
||||
"(PARTITION BY id ORDER BY ts DESC) = 1",
|
||||
"snowflake",
|
||||
"SELECT * FROM some_table WHERE tenant_id = 42 QUALIFY row_number() OVER (PARTITION BY id ORDER BY ts DESC) = 1",
|
||||
"SELECT * FROM some_table WHERE tenant_id = 42 "
|
||||
"QUALIFY row_number() OVER (PARTITION BY id ORDER BY ts DESC) = 1",
|
||||
),
|
||||
(
|
||||
"SELECT sum(v) OVER () FROM some_table WINDOW w AS (PARTITION BY id)",
|
||||
"postgresql",
|
||||
"SELECT sum(v) OVER () FROM some_table WHERE tenant_id = 42 WINDOW w AS (PARTITION BY id)",
|
||||
"SELECT sum(v) OVER () FROM some_table WHERE tenant_id = 42 "
|
||||
"WINDOW w AS (PARTITION BY id)",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user