Skip to content

Add Synonyms to SqlServerConnector #25440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/src/main/sphinx/connector/sqlserver.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ behavior of the connector and the issues queries to the database.
- Control the automatic use of snapshot isolation for transactions issued by
Trino in SQL Server. Defaults to `false`, which means that snapshot
isolation is enabled.
* - `sqlserver.synonyms.enabled=true`
- Include [synonyms](https://learn.microsoft.com/en-us/sql/relational-databases/synonyms/synonyms-database-engine?view=sql-server-ver16)
as queryable entities. Defaults to `false`, which means synonyms are not
included by default.
:::

```{include} jdbc-case-insensitive-matching.fragment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,12 @@ public class SqlServerClient

return FULL_PUSHDOWN.apply(session, domain);
};
private final boolean synonymsEnabled;

@Inject
public SqlServerClient(
BaseJdbcConfig config,
SqlServerConfig sqlServerConfig,
JdbcStatisticsConfig statisticsConfig,
ConnectionFactory connectionFactory,
QueryBuilder queryBuilder,
Expand All @@ -300,6 +302,7 @@ public SqlServerClient(
super("\"", connectionFactory, queryBuilder, config.getJdbcTypesMappedToVarchar(), identifierMapping, queryModifier, true);

this.statisticsEnabled = statisticsConfig.isEnabled();
this.synonymsEnabled = sqlServerConfig.isSynonymsEnabled();

this.connectorExpressionRewriter = JdbcConnectorExpressionRewriterBuilder.newBuilder()
.addStandardRules(this::quoted)
Expand Down Expand Up @@ -345,6 +348,15 @@ public SqlServerClient(
.build());
}

@Override
protected Optional<List<String>> getTableTypes()
{
if (synonymsEnabled) {
return Optional.of(ImmutableList.of("TABLE", "VIEW", "SYNONYM"));
}
return Optional.of(ImmutableList.of("TABLE", "VIEW"));
}

@Override
protected void dropSchema(ConnectorSession session, Connection connection, String remoteSchemaName, boolean cascade)
throws SQLException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class SqlServerConfig
private boolean bulkCopyForWrite;
private boolean bulkCopyForWriteLockDestinationTable;
private boolean storedProcedureTableFunctionEnabled;
private boolean synonymsEnabled;

public boolean isBulkCopyForWrite()
{
Expand Down Expand Up @@ -76,4 +77,17 @@ public SqlServerConfig setStoredProcedureTableFunctionEnabled(boolean storedProc
this.storedProcedureTableFunctionEnabled = storedProcedureTableFunctionEnabled;
return this;
}

@Config("sqlserver.synonyms.enabled")
@ConfigDescription("Allows SQL Server Synonym manipulation")
public SqlServerConfig setSynonymsEnabled(boolean enabled)
{
this.synonymsEnabled = enabled;
return this;
}

public boolean isSynonymsEnabled()
{
return synonymsEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ public void testReadFromView()
}
}

@Test
public void testSynonyms()
Copy link
Member

Choose a reason for hiding this comment

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

Let's add a new test class enabling sqlserver.synonyms.enabled config property and verify that the connector can access synonyms.

{
try (TestSynonym synonym = new TestSynonym(onRemoteDatabase(), "test_synonym", "FOR ORDERS")) {
assertQueryFails("SELECT orderkey FROM " + synonym.getName(), "line 1:22: Table 'sqlserver.*' does not exist");
}
}

@Override
protected void verifyAddNotNullColumnToNonEmptyTableFailurePermissible(Throwable e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public class TestSqlServerClient

private static final JdbcClient JDBC_CLIENT = new SqlServerClient(
new BaseJdbcConfig(),
new SqlServerConfig(),
new JdbcStatisticsConfig(),
session -> {
throw new UnsupportedOperationException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class TestSqlServerConfig
public void testDefaults()
{
assertRecordedDefaults(recordDefaults(SqlServerConfig.class)
.setSynonymsEnabled(false)
.setBulkCopyForWrite(false)
.setBulkCopyForWriteLockDestinationTable(false)
.setSnapshotIsolationDisabled(false)
Expand All @@ -38,13 +39,15 @@ public void testDefaults()
public void testExplicitPropertyMappings()
{
Map<String, String> properties = ImmutableMap.<String, String>builder()
.put("sqlserver.synonyms.enabled", "true")
.put("sqlserver.bulk-copy-for-write.enabled", "true")
.put("sqlserver.bulk-copy-for-write.lock-destination-table", "true")
.put("sqlserver.snapshot-isolation.disabled", "true")
.put("sqlserver.stored-procedure-table-function-enabled", "true")
.buildOrThrow();

SqlServerConfig expected = new SqlServerConfig()
.setSynonymsEnabled(true)
.setBulkCopyForWrite(true)
.setBulkCopyForWriteLockDestinationTable(true)
.setStoredProcedureTableFunctionEnabled(true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed 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.
*/
package io.trino.plugin.sqlserver;

import io.trino.testing.sql.SqlExecutor;

import java.io.Closeable;

import static io.trino.testing.TestingNames.randomNameSuffix;
import static java.lang.String.format;

public class TestSynonym
implements Closeable
{
private final SqlExecutor sqlExecutor;
private final String name;

public TestSynonym(SqlExecutor sqlExecutor, String namePrefix, String definition)
{
this.sqlExecutor = sqlExecutor;
Copy link
Member

@ebyhr ebyhr Mar 27, 2025

Choose a reason for hiding this comment

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

Please add requireNonNull:

        requireNonNull(sqlExecutor, "sqlExecutor is null");
        requireNonNull(namePrefix, "namePrefix is null");
        requireNonNull(definition, "definition is null");

this.name = namePrefix + "_" + randomNameSuffix();
sqlExecutor.execute(format("CREATE SYNONYM %s %s", name, definition));
}

public String getName()
Copy link
Member

Choose a reason for hiding this comment

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

{
return name;
}

@Override
public void close()
{
sqlExecutor.execute("DROP SYNONYM " + name);
}
}
Loading