sadpandajoe commented on code in PR #41492:
URL: https://github.com/apache/superset/pull/41492#discussion_r3679975019


##########
superset/db_engine_specs/sybase.py:
##########
@@ -30,6 +30,11 @@ class SybaseEngineSpec(MssqlEngineSpec):
     engine = "sybase"
     engine_name = "SAP Sybase"
     engine_aliases = {"sybase_sqlany"}  # Support SQL Anywhere dialect too
+
+    # Unlike MSSQL, SAP ASE/SQL Anywhere quote identifiers with double quotes,
+    # not square brackets, so override the values inherited from 
MssqlEngineSpec.
+    identifier_quote_start: str = '"'

Review Comment:
   This override makes SQL Lab insert double-quoted names for SAP ASE, but the 
supported `sqlalchemy-sybase` adapter uses brackets and default ASE sessions do 
not treat double quotes as identifiers. Please keep the inherited `[`/`]` 
delimiters and update the Sybase test.



##########
superset/sqllab/utils.py:
##########
@@ -41,6 +41,7 @@
     "disable_data_preview",
     "disable_drill_to_detail",
     "allow_multi_catalog",
+    "engine_information",

Review Comment:
   This allowlist entry is the only bridge that puts `engine_information` into 
the initial SQL Lab store, but the added tests seed that state manually or 
exercise other APIs. Please add a `/api/v1/sqllab/` regression assertion that a 
non-ANSI database returns the expected `identifier_quote` payload.



##########
superset/db_engine_specs/base.py:
##########
@@ -540,6 +540,15 @@ class BaseEngineSpec:  # pylint: 
disable=too-many-public-methods
     arraysize = 0
     max_column_name_length: int | None = None
 
+    # Characters used to quote identifiers (table/column names) that aren't 
simple.
+    # Defaults to ANSI double quotes; dialects that differ override these — 
e.g.
+    # MySQL/MariaDB use backticks and SQL Server uses square brackets. Embedded
+    # quote characters are escaped by doubling the closing character. These are
+    # surfaced to the client (see `get_public_information`) so identifier 
quoting
+    # stays owned by the engine spec rather than duplicated per client.
+    identifier_quote_start: str = '"'

Review Comment:
   Hive, Spark, and Databricks inherit this ANSI default even though their 
registered dialects quote identifiers with backticks, so autocomplete remains 
invalid for non-simple names on those engines. Please override the shared Hive 
and Databricks base specs and add representative assertions.



##########
superset/databases/schemas.py:
##########
@@ -1191,6 +1200,12 @@ class EngineInformationSchema(Schema):
             )
         }
     )
+    identifier_quote = fields.Nested(

Review Comment:
   This documents the database API field, but the value is also added to the 
SQL Lab bootstrap response while `SQLLabBootstrapSchema` still models databases 
as `ImportV1DatabaseSchema`. Please use an `EngineInformationSchema`-aware 
database shape for the bootstrap OpenAPI contract too.



##########
superset-frontend/src/SqlLab/components/EditorWrapper/useKeywords.test.ts:
##########
@@ -210,6 +211,100 @@ test('quotes table identifiers that require quoting in 
the inserted value', asyn
   );
 });
 
+test.each([
+  ['mysql', { start: '`', end: '`' }, '`COVID Vaccines`'],
+  ['mariadb', { start: '`', end: '`' }, '`COVID Vaccines`'],
+  ['mssql', { start: '[', end: ']' }, '[COVID Vaccines]'],
+  ['postgresql', { start: '"', end: '"' }, '"COVID Vaccines"'],
+])(
+  'quotes table identifiers using the engine-provided quote characters for %s',
+  async (_dialect, identifierQuote, expectedValue) => {
+    const dbFunctionNamesApiRoute = 
`glob:*/api/v1/database/${expectDbId}/function_names/`;
+    fetchMock.get(dbFunctionNamesApiRoute, fakeFunctionNamesApiResult);
+
+    const storeWithBackend = createStore(
+      {
+        ...initialState,
+        sqlLab: {
+          ...initialState.sqlLab,
+          databases: {
+            [expectDbId]: {
+              engine_information: { identifier_quote: identifierQuote },
+            },
+          },
+        },
+      },
+      reducers,
+    );
+
+    act(() => {
+      storeWithBackend.dispatch(
+        tableApiUtil.upsertQueryData(
+          'tables',
+          { dbId: expectDbId, schema: expectSchema },
+          {
+            options: [
+              {
+                value: 'COVID Vaccines',
+                label: 'COVID Vaccines',
+                type: 'table',
+              },
+            ],
+            hasMore: false,
+          },
+        ),
+      );
+    });
+
+    const { result } = renderHook(
+      () =>
+        useKeywords({
+          queryEditorId: 'testqueryid',
+          dbId: expectDbId,
+          schema: expectSchema,
+        }),
+      {
+        wrapper: createWrapper({
+          useRedux: true,
+          store: storeWithBackend,
+        }),
+      },
+    );
+
+    await waitFor(() =>
+      expect(result.current).toContainEqual(
+        expect.objectContaining({
+          name: 'COVID Vaccines',
+          value: expectedValue,
+          meta: 'table',
+        }),
+      ),
+    );
+
+    // The caption inserted into the editor on selection is quoted with the
+    // same dialect-specific characters as `value`, not a hardcoded ANSI quote.
+    const tableKeyword = result.current.find(
+      keyword => keyword.meta === 'table' && keyword.name === 'COVID Vaccines',
+    );
+    const insertMatch = tableKeyword?.completer?.insertMatch;

Review Comment:
   This directly invokes a custom completer that 
`AceEditorProvider.toAceKeyword` drops in production, and it fabricates the 
optional `caption`. Please exercise keyword conversion and selection through 
the adapter boundary so the test validates the shipped Ace path.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to