Skip to content

Commit 647d5a7

Browse files
authored
[bug](jdbc) fix sqlserver couldn't get schema with higher version driver jar (#63626)
### What problem does this PR solve? Problem Summary: https://github.com/microsoft/mssql-jdbc/blob/v13.4.0/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java#L1887-L1934 ``` SQLServer JDBC catalog lists schemas through DatabaseMetaData.getSchemas(conn.getCatalog(), null). With mssql-jdbc 13.4.x, when catalog is non-empty and schemaPattern is null, the driver filters built-in schemas such as dbo, guest, sys, INFORMATION_SCHEMA, and db_*. As a result, SHOW DATABASES on a SQLServer JDBC catalog may miss schemas that were visible with older mssql-jdbc versions. Now SQLServer-specific override for schema discovery and passes schemaPattern % to getSchemas. % is the JDBC wildcard pattern for matching all schemas, so mssql-jdbc 13.4.x returns the expected schemas without the driver-side built-in schema filtering. Older mssql-jdbc versions are also compatible with this behavior. ```
1 parent eb46d1e commit 647d5a7

8 files changed

Lines changed: 84 additions & 2 deletions

File tree

be/src/service/internal_service.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,13 @@ void PInternalService::test_jdbc_connection(google::protobuf::RpcController* con
991991
const PJdbcTestConnectionRequest* request,
992992
PJdbcTestConnectionResult* result,
993993
google::protobuf::Closure* done) {
994+
if (!doris::config::enable_java_support) {
995+
doris::Status status = doris::Status::InternalError(
996+
"you can change be config enable_java_support to true and restart be.");
997+
status.to_protobuf(result->mutable_status());
998+
done->Run();
999+
return;
1000+
}
9941001
bool ret = _heavy_work_pool.try_offer([request, result, done]() {
9951002
VLOG_RPC << "test jdbc connection";
9961003
brpc::ClosureGuard closure_guard(done);

fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcConnectorClient.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ public List<String> getDatabaseNameList() {
352352
String current = conn.getSchema();
353353
names.add(current);
354354
} else {
355-
rs = conn.getMetaData().getSchemas(conn.getCatalog(), null);
355+
rs = conn.getMetaData().getSchemas(conn.getCatalog(), getSchemaPatternForDatabaseNameList());
356356
while (rs.next()) {
357357
names.add(rs.getString("TABLE_SCHEM"));
358358
}
@@ -365,6 +365,18 @@ public List<String> getDatabaseNameList() {
365365
return filterDatabaseNames(names);
366366
}
367367

368+
/**
369+
* Schema pattern passed to {@link java.sql.DatabaseMetaData#getSchemas(String, String)} when listing
370+
* remote database names.
371+
*
372+
* <p>The default {@code null} follows JDBC semantics of "schema name should not be used to narrow
373+
* the search", preserving the existing generic behavior. Subclasses should override this only when
374+
* a driver treats {@code null} specially and does not return the schemas Doris expects.
375+
*/
376+
protected String getSchemaPatternForDatabaseNameList() {
377+
return null;
378+
}
379+
368380
public List<String> getTablesNameList(String remoteDbName) {
369381
List<String> names = new ArrayList<>();
370382
String[] tableTypes = getTableTypes();

fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcSQLServerConnectorClient.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ public ConnectorType jdbcTypeToConnectorType(JdbcFieldInfo fieldInfo) {
110110
}
111111
}
112112

113+
@Override
114+
protected String getSchemaPatternForDatabaseNameList() {
115+
// "%" is a JDBC schemaPattern wildcard that matches all schemas. mssql-jdbc 13.4 filters
116+
// built-in schemas when catalog is non-empty and schemaPattern is null.
117+
return "%";
118+
}
119+
113120
@Override
114121
public long getRowCount(String dbName, String tableName) {
115122
String sql = "SELECT sum(rows) FROM sys.partitions "

fe/fe-connector/fe-connector-jdbc/src/test/java/org/apache/doris/connector/jdbc/client/JdbcSQLServerConnectorClientTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,11 @@ void testTimestampTypeMapping() {
127127
Assertions.assertEquals("STRING", ct.getTypeName(),
128128
"SQL Server timestamp (rowversion) should map to STRING");
129129
}
130+
131+
@Test
132+
void testUseWildcardSchemaPatternForDatabaseNameList() {
133+
JdbcSQLServerConnectorClient client = createClient();
134+
135+
Assertions.assertEquals("%", client.getSchemaPatternForDatabaseNameList());
136+
}
130137
}

fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcClient.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public List<String> getDatabaseNameList() {
318318
String currentDatabase = conn.getSchema();
319319
remoteDatabaseNames.add(currentDatabase);
320320
} else {
321-
rs = conn.getMetaData().getSchemas(conn.getCatalog(), null);
321+
rs = conn.getMetaData().getSchemas(conn.getCatalog(), getSchemaPatternForDatabaseNameList());
322322
while (rs.next()) {
323323
remoteDatabaseNames.add(rs.getString("TABLE_SCHEM"));
324324
}
@@ -331,6 +331,18 @@ public List<String> getDatabaseNameList() {
331331
return filterDatabaseNames(remoteDatabaseNames);
332332
}
333333

334+
/**
335+
* Schema pattern passed to {@link java.sql.DatabaseMetaData#getSchemas(String, String)} when listing
336+
* remote database names.
337+
*
338+
* <p>The default {@code null} follows JDBC semantics of "schema name should not be used to narrow
339+
* the search", preserving the existing generic behavior. Subclasses should override this only when
340+
* a driver treats {@code null} specially and does not return the schemas Doris expects.
341+
*/
342+
protected String getSchemaPatternForDatabaseNameList() {
343+
return null;
344+
}
345+
334346
/**
335347
* get all tables of one database
336348
*/

fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcSQLServerClient.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ protected JdbcSQLServerClient(JdbcClientConfig jdbcClientConfig) {
2727
super(jdbcClientConfig);
2828
}
2929

30+
@Override
31+
protected String getSchemaPatternForDatabaseNameList() {
32+
// "%" is a JDBC schemaPattern wildcard that matches all schemas. mssql-jdbc 13.4 filters
33+
// built-in schemas when catalog is non-empty and schemaPattern is null.
34+
return "%";
35+
}
36+
3037
@Override
3138
protected Type jdbcTypeToDoris(JdbcFieldSchema fieldSchema) {
3239
String originSqlserverType = fieldSchema.getDataTypeName().orElse("unknown");

regression-test/data/external_table_p0/jdbc/type_test/select/test_sqlserver_all_types_select.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,19 @@ IPv6_Nullable text Yes true \N
5353
-- !select_all_types_multi_block --
5454
4100
5555

56+
-- !order_show_db --
57+
db_accessadmin
58+
db_backupoperator
59+
db_datareader
60+
db_datawriter
61+
db_ddladmin
62+
db_denydatareader
63+
db_denydatawriter
64+
db_owner
65+
db_securityadmin
66+
dbo
67+
guest
68+
information_schema
69+
mysql
70+
sys
71+

regression-test/suites/external_table_p0/jdbc/type_test/select/test_sqlserver_all_types_select.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ suite("test_sqlserver_all_types_select", "p0,external") {
2121
String s3_endpoint = getS3Endpoint()
2222
String bucket = getS3BucketName()
2323
String driver_url = "https://${bucket}.${s3_endpoint}/regression/jdbc_driver/mssql-jdbc-11.2.3.jre8.jar"
24+
String driver_url13 = "https://${bucket}.${s3_endpoint}/regression/jdbc_driver/mssql-jdbc-13.4.0.jre8.jar"
2425
if (enabled != null && enabled.equalsIgnoreCase("true")) {
2526
String sqlserver_port = context.config.otherConfigs.get("sqlserver_2022_port");
2627

@@ -43,5 +44,18 @@ suite("test_sqlserver_all_types_select", "p0,external") {
4344
qt_select_all_types_multi_block """select count(*) from dbo.extreme_test_multi_block;"""
4445

4546
sql """drop catalog if exists sqlserver_all_type_test """
47+
48+
sql """drop catalog if exists sqlserver_13_test """
49+
sql """create catalog if not exists sqlserver_13_test properties(
50+
"type"="jdbc",
51+
"user"="sa",
52+
"password"="Doris123456",
53+
"jdbc_url" = "jdbc:sqlserver://${externalEnvIp}:${sqlserver_port};encrypt=false;databaseName=doris_test;",
54+
"driver_url" = "${driver_url13}",
55+
"driver_class" = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
56+
);"""
57+
sql """switch sqlserver_13_test"""
58+
qt_order_show_db """show databases"""
59+
sql """drop catalog if exists sqlserver_13_test """
4660
}
4761
}

0 commit comments

Comments
 (0)