From 53fef72b76f3a168664b2cca5e8a070ac4e13c21 Mon Sep 17 00:00:00 2001 From: Luis Ibarra Date: Mon, 16 Feb 2026 18:14:30 -0500 Subject: [PATCH] feat: add support for READ_ONLY connection mode in MSSQL plugin - Implemented connection mode configuration for READ_ONLY, appending "ApplicationIntent=ReadOnly" to the JDBC URL and setting the HikariCP configuration to read-only. - Updated form.json to include a tooltip explaining the implications of using read-only mode. - Added unit tests to verify the correct behavior of both READ_ONLY and READ_WRITE connection modes, ensuring the JDBC URL is constructed appropriately based on the selected mode. --- .../com/external/plugins/MssqlPlugin.java | 8 ++++ .../mssqlPlugin/src/main/resources/form.json | 1 + .../com/external/plugins/MssqlPluginTest.java | 48 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/app/server/appsmith-plugins/mssqlPlugin/src/main/java/com/external/plugins/MssqlPlugin.java b/app/server/appsmith-plugins/mssqlPlugin/src/main/java/com/external/plugins/MssqlPlugin.java index c546fa03c856..be1e3d7677b3 100644 --- a/app/server/appsmith-plugins/mssqlPlugin/src/main/java/com/external/plugins/MssqlPlugin.java +++ b/app/server/appsmith-plugins/mssqlPlugin/src/main/java/com/external/plugins/MssqlPlugin.java @@ -626,6 +626,14 @@ private static HikariDataSource createConnectionPool( addSslOptionsToUrlBuilder(datasourceConfiguration, urlBuilder); + // Add connection mode configuration for READ_ONLY + if (datasourceConfiguration.getConnection() != null + && datasourceConfiguration.getConnection().getMode() + == com.appsmith.external.models.Connection.Mode.READ_ONLY) { + urlBuilder.append("ApplicationIntent=ReadOnly;"); + hikariConfig.setReadOnly(true); + } + hikariConfig.setJdbcUrl(urlBuilder.toString()); try { diff --git a/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json index 7731ac9421aa..9cf247f923d8 100644 --- a/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json @@ -9,6 +9,7 @@ "configProperty": "datasourceConfiguration.connection.mode", "controlType": "SEGMENTED_CONTROL", "initialValue": "READ_WRITE", + "tooltipText": "Read-only mode uses ApplicationIntent=ReadOnly. Note: This only enforces read-only connections when using Always On Availability Groups.", "options": [ { "label": "Read / Write", diff --git a/app/server/appsmith-plugins/mssqlPlugin/src/test/java/com/external/plugins/MssqlPluginTest.java b/app/server/appsmith-plugins/mssqlPlugin/src/test/java/com/external/plugins/MssqlPluginTest.java index 7be16681867a..befcc76ff4d0 100755 --- a/app/server/appsmith-plugins/mssqlPlugin/src/test/java/com/external/plugins/MssqlPluginTest.java +++ b/app/server/appsmith-plugins/mssqlPlugin/src/test/java/com/external/plugins/MssqlPluginTest.java @@ -773,4 +773,52 @@ public void testGetEndpointIdentifierForRateLimit_HostPresentPortAbsent_ReturnsC }) .verifyComplete(); } + + @Test + public void testReadOnlyConnectionMode() { + DatasourceConfiguration dsConfig = createDatasourceConfiguration(container); + + // Set connection mode to READ_ONLY + com.appsmith.external.models.Connection connection = new com.appsmith.external.models.Connection(); + connection.setMode(com.appsmith.external.models.Connection.Mode.READ_ONLY); + dsConfig.setConnection(connection); + + // Create connection pool + HikariDataSource connectionPool = + mssqlPluginExecutor.datasourceCreate(dsConfig).block(); + + // Verify the JDBC URL contains ApplicationIntent=ReadOnly + assertNotNull(connectionPool); + String jdbcUrl = connectionPool.getJdbcUrl(); + assertTrue( + jdbcUrl.contains("ApplicationIntent=ReadOnly"), + "JDBC URL should contain ApplicationIntent=ReadOnly parameter"); + + // Cleanup + connectionPool.close(); + } + + @Test + public void testReadWriteConnectionMode() { + DatasourceConfiguration dsConfig = createDatasourceConfiguration(container); + + // Set connection mode to READ_WRITE + com.appsmith.external.models.Connection connection = new com.appsmith.external.models.Connection(); + connection.setMode(com.appsmith.external.models.Connection.Mode.READ_WRITE); + dsConfig.setConnection(connection); + + // Create connection pool + HikariDataSource connectionPool = + mssqlPluginExecutor.datasourceCreate(dsConfig).block(); + + // Verify the JDBC URL does NOT contain ApplicationIntent parameter + assertNotNull(connectionPool); + String jdbcUrl = connectionPool.getJdbcUrl(); + assertTrue( + !jdbcUrl.contains("ApplicationIntent"), + "JDBC URL should not contain ApplicationIntent parameter for READ_WRITE mode"); + + // Cleanup + connectionPool.close(); + } }