Skip to content

[SPARK-57518][SQL][FOLLOWUP] List ThriftServer schemas via SupportsNamespaces instead of special-casing spark_catalog#57468

Open
yadavay-amzn wants to merge 1 commit into
apache:masterfrom
yadavay-amzn:SPARK-57518-followup
Open

[SPARK-57518][SQL][FOLLOWUP] List ThriftServer schemas via SupportsNamespaces instead of special-casing spark_catalog#57468
yadavay-amzn wants to merge 1 commit into
apache:masterfrom
yadavay-amzn:SPARK-57518-followup

Conversation

@yadavay-amzn

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Follow-up to #56627 (SPARK-57518), addressing review feedback.

SparkGetSchemasOperation special-cased the session catalog: when the current catalog was spark_catalog, it listed databases via the V1 SessionCatalog.listDatabases, and only used the DSv2 SupportsNamespaces.listNamespaces() path for other catalogs. That assumed a spark_catalog override (e.g. a custom CatalogExtension) delegates its namespace listing to the built-in session catalog, which is not guaranteed.

This change lists schemas uniformly through the current catalog's SupportsNamespaces.listNamespaces() for all catalogs, and drops the spark_catalog special-case. The built-in V2SessionCatalog also implements SupportsNamespaces, so the default session catalog keeps working, and an overridden spark_catalog now correctly reports its own namespaces. The global_temp database is retained as a special case for the session catalog only, since it is a Spark pseudo-namespace rather than a real catalog namespace.

Why are the changes needed?

The previous approach could report the wrong schemas for a spark_catalog override that does not delegate namespace listing to the built-in session catalog.

Does this PR introduce any user-facing change?

Behavior change on the DSv2 metadata path only: schema-name matching now uses JDBC pattern semantics (% and _), consistent with DatabaseMetaData.getSchemas. Hive-style glob (*) is not a JDBC wildcard and is no longer matched on this path.

Performance consideration

SupportsNamespaces.listNamespaces() has no schema-pattern argument (unlike V1 listDatabases(pattern)), so the schema pattern is applied client-side. For a catalog with many namespaces this lists all top-level namespaces and then filters, rather than pushing the pattern down. The current DSv2 API does not support pushing the pattern down; if this becomes a concern, a DSv2 API enhancement to accept a pattern would be a separate improvement. Raising it here for discussion.

How was this patch tested?

SparkMetadataOperationSuite: verifies spark_catalog lists its namespaces via SupportsNamespaces and that global_temp still appears. Existing getSchemas coverage passes. SparkGetTablesOperation/SparkGetColumnsOperation do not have this special-case and are unchanged.

Was this patch authored or co-authored using generative AI tooling?

Authored with assistance by Claude Opus 4.8.

…upportsNamespaces instead of special-casing spark_catalog
@yadavay-amzn

Copy link
Copy Markdown
Contributor Author

@pan3793 here's the follow-up we discussed. It lists schemas uniformly via the current catalog's SupportsNamespaces and keeps global_temp as a session-catalog special case. On the perf point you raised: listNamespaces() has no pattern argument, so the schema pattern is filtered client-side; I called that out under "Performance consideration" in the description. Happy to hear how you'd like to handle pushdown, or whether a separate DSv2 API change is the better place for it.

// Use SupportsNamespaces uniformly for all catalogs including the session
// catalog (V2SessionCatalog implements SupportsNamespaces). This avoids
// assuming that a spark_catalog override delegates to the built-in session
// catalog.

@pan3793 pan3793 Jul 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yadavay-amzn I think we can accept this for now, as users still have a backdoor (isCatalogMetadataEnabled) to go back to the old impl.

@cloud-fan for the long term, do we want to extend the V2 API to support predication pushdown on listing ns/table/func/col? and the approach can also be either simple - just accept a string pattern like the current ExternalCatalog, or extendable - just like SupportsPushDownFilters

val databasePattern = Pattern.compile(CLIServiceUtils.patternToRegex(schemaName))
if (schemaName == null || schemaName.isEmpty ||
databasePattern.matcher(globalTempViewDb).matches()) {
rowSet.addRow(Array[AnyRef](globalTempViewDb, catalogNameValue))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the catalog has a real database named globalTempViewDb?

@shrirangmhalgi shrirangmhalgi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Traced the pattern-matching chain: V1 catalog.listDatabases(schemaPattern)StringUtils.filterPattern ((?i) + Hive glob *) vs V2 CLIServiceUtils.patternToRegexPattern.compile (JDBC %/_ only, no (?i)).

Verification

  • V2SessionCatalog.listNamespaces() delegates to catalog.listDatabases() (no global_temp) - separate append is needed
  • listNamespaces() returns Array[Array[String]] - materialized before iteration, no partial-result risk
  • isCatalogMetadataEnabled defaults true (4.3.0+) - this is the default path, not opt-in
  • createDatabase blocks global_temp name for built-in SessionCatalog - duplicate risk is custom CatalogExtension only

Non Blocking Suggestions (2)

  • Test file - db* removal deserves a negative assertion - see inline
  • Production - case _ => silent empty - see inline

rowSet.addRow(Array[AnyRef](nsName, catalogNameValue))
}
}
case _ =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The case _ => branch returns empty with no log. If a user's catalog doesn't implement SupportsNamespaces, they get 0 schemas with no indication why. A logWarning here would help diagnose "getSchemas returns nothing" bugs - e.g., logWarning(s"Catalog ${resolvedCatalog.name()} does not implement SupportsNamespaces; returning empty schema list").

}

Seq("db%", "db*") foreach { pattern =>
Seq("db%") foreach { pattern =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(non-blocking): The removal of "db*" from this assertion documents that Hive-style glob wildcards no longer match on the V2 path. Since isCatalogMetadataEnabled defaults to true, this is a default-on behavior change for ThriftServer users — any client passing * instead of JDBC % will get 0 results. Would a negative assertion (e.g., checkResult(metaData.getSchemas(null, "db*"), Seq.empty)) make this more explicit for future readers?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants