Skip to content

Commit

Permalink
Adding replication connection option (#1566)
Browse files Browse the repository at this point in the history
* Adding replication connection property

* Adding test

* Address feedback
  • Loading branch information
David Engel authored Apr 24, 2021
1 parent e262583 commit 50b9fdb
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,8 @@ static final String getTokenName(int tdsTokenType) {
static final byte LOGIN_OPTION2_USER_NORMAL = 0x00;
static final byte LOGIN_OPTION2_USER_SERVER = 0x10;
static final byte LOGIN_OPTION2_USER_REMUSER = 0x20;
static final byte LOGIN_OPTION2_USER_SQLREPL = 0x30;
static final byte LOGIN_OPTION2_USER_SQLREPL_OFF = 0x00;
static final byte LOGIN_OPTION2_USER_SQLREPL_ON = 0x30;
static final byte LOGIN_OPTION2_INTEGRATED_SECURITY_OFF = 0x00;
static final byte LOGIN_OPTION2_INTEGRATED_SECURITY_ON = (byte) 0x80;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,21 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
*/
String getResponseBuffering();

/**
* Sets the value to enable/disable the replication connection property.
*
* @param replication
* A Boolean value. When true, tells the server that the connection is used for replication.
*/
void setReplication(boolean replication);

/**
* Returns the value of the replication connection property.
*
* @return true if the connection is to be used for replication. Otherwise false.
*/
boolean getReplication();

/**
* Sets the value to enable/disable the sendTimeAsDatetime connection property.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ public void setUseBulkCopyForBatchInsert(boolean useBulkCopyForBatchInsert) {

boolean userSetTNIR = true;

private boolean replication = SQLServerDriverBooleanProperty.REPLICATION.getDefaultValue();
private boolean sendTimeAsDatetime = SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.getDefaultValue();
private boolean useFmtOnly = SQLServerDriverBooleanProperty.USE_FMT_ONLY.getDefaultValue();

Expand Down Expand Up @@ -1803,6 +1804,15 @@ Connection connectInternal(Properties propsIn,
applicationIntent = ApplicationIntent.valueOfString(sPropValue);
activeConnectionProperties.setProperty(sPropKey, applicationIntent.toString());

sPropKey = SQLServerDriverBooleanProperty.REPLICATION.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null == sPropValue) {
sPropValue = Boolean.toString(SQLServerDriverBooleanProperty.REPLICATION.getDefaultValue());
activeConnectionProperties.setProperty(sPropKey, sPropValue);
}

replication = isBooleanPropertyOn(sPropKey, sPropValue);

sPropKey = SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null == sPropValue) {
Expand Down Expand Up @@ -5218,6 +5228,7 @@ final boolean complete(LogonCommand logonCommand, TDSReader tdsReader) throws SQ
// fails
TDS.LOGIN_OPTION2_ODBC_ON | // Use ODBC defaults (ANSI_DEFAULTS ON, IMPLICIT_TRANSACTIONS OFF, TEXTSIZE
// inf, ROWCOUNT inf)
(replication ? TDS.LOGIN_OPTION2_USER_SQLREPL_ON : TDS.LOGIN_OPTION2_USER_SQLREPL_OFF) |
(integratedSecurity ? // integrated security if integratedSecurity requested
TDS.LOGIN_OPTION2_INTEGRATED_SECURITY_ON
: TDS.LOGIN_OPTION2_INTEGRATED_SECURITY_OFF)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,18 @@ public String getApplicationIntent() {
SQLServerDriverStringProperty.APPLICATION_INTENT.getDefaultValue());
}

@Override
public void setReplication(boolean replication) {
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.REPLICATION.toString(),
replication);
}

@Override
public boolean getReplication() {
return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.REPLICATION.toString(),
SQLServerDriverBooleanProperty.REPLICATION.getDefaultValue());
}

@Override
public void setSendTimeAsDatetime(boolean sendTimeAsDatetime) {
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ enum SQLServerDriverBooleanProperty {
INTEGRATED_SECURITY("integratedSecurity", false),
LAST_UPDATE_COUNT("lastUpdateCount", true),
MULTI_SUBNET_FAILOVER("multiSubnetFailover", false),
REPLICATION("replication", false),
SERVER_NAME_AS_ACE("serverNameAsACE", false),
SEND_STRING_PARAMETERS_AS_UNICODE("sendStringParametersAsUnicode", true),
SEND_TIME_AS_DATETIME("sendTimeAsDatetime", true),
Expand Down Expand Up @@ -589,6 +590,9 @@ public final class SQLServerDriver implements java.sql.Driver {
SQLServerDriverStringProperty.TRUST_MANAGER_CLASS.getDefaultValue(), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.toString(),
SQLServerDriverStringProperty.TRUST_MANAGER_CONSTRUCTOR_ARG.getDefaultValue(), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.REPLICATION.toString(),
Boolean.toString(SQLServerDriverBooleanProperty.REPLICATION.getDefaultValue()), false,
TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.toString(),
Boolean.toString(SQLServerDriverBooleanProperty.SEND_TIME_AS_DATETIME.getDefaultValue()), false,
TRUE_FALSE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ protected Object[][] getContents() {
"The optional argument to pass to the constructor specified by trustManagerClass."},
{"R_hostNameInCertificatePropertyDescription",
"The host name to be used when validating the SQL Server Secure Sockets Layer (SSL) certificate."},
{"R_replicationPropertyDescription",
"This setting tells the server if the connection is used for replication."},
{"R_sendTimeAsDatetimePropertyDescription",
"Determines whether to use the SQL Server datetime data type to send java.sql.Time values to the database."},
{"R_TransparentNetworkIPResolutionPropertyDescription",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ public void testDataSource() {
ds.setApplicationIntent(stringPropValue);
assertEquals(stringPropValue, ds.getApplicationIntent(), TestResource.getResource("R_valuesAreDifferent"));

ds.setReplication(booleanPropValue);
assertEquals(booleanPropValue, ds.getReplication(), TestResource.getResource("R_valuesAreDifferent"));

ds.setSendTimeAsDatetime(booleanPropValue);
assertEquals(booleanPropValue, ds.getSendTimeAsDatetime(), TestResource.getResource("R_valuesAreDifferent"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ public void testEscapeColumnDelimitersCSV() throws Exception {
i++;
}
}

TestUtils.dropTableIfExists(tableName, stmt);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
* available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.jdbc.connection;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.RandomUtil;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import com.microsoft.sqlserver.jdbc.TestUtils;
import com.microsoft.sqlserver.testframework.AbstractSQLGenerator;
import com.microsoft.sqlserver.testframework.AbstractTest;
import com.microsoft.sqlserver.testframework.Constants;

/*
* This test is for testing the replication connection property
*/
@RunWith(JUnitPlatform.class)
@Tag(Constants.xAzureSQLDW)
public class ReplicationTest extends AbstractTest {

@Test
public void testReplication() throws SQLException {
String tableName = RandomUtil.getIdentifier("repl");
String triggerName = RandomUtil.getIdentifier("trig");
String escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName);
String escapedTriggerName = AbstractSQLGenerator.escapeIdentifier(triggerName);
SQLServerDataSource ds = new SQLServerDataSource();
ds.setURL(connectionString);
ds.setReplication(false);

String sqlCreateTable = "CREATE TABLE " + escapedTableName + " ([TestReplication] [varchar](50) NULL)";
String sqlCreateTrigger = "CREATE TRIGGER " + escapedTriggerName + " ON " + escapedTableName + " "
+ "INSTEAD OF INSERT NOT FOR REPLICATION AS "
+ "BEGIN "
+ " INSERT INTO " + escapedTableName + " (TestReplication) "
+ " SELECT TestReplication + ' - REPLICATION IS OFF' "
+ " FROM INSERTED "
+ "END";
String sqlInsert = "INSERT INTO " + escapedTableName + " (TestReplication) values ('Replication test')";
String sqlSelect = "SELECT TestReplication FROM " + escapedTableName;

try (Connection con = ds.getConnection(); Statement stmt = con.createStatement()) {
// drop
TestUtils.dropTableIfExists(escapedTableName, stmt);
// create
stmt.execute(sqlCreateTable);
stmt.execute(sqlCreateTrigger);
stmt.executeUpdate(sqlInsert);
try (ResultSet rs = stmt.executeQuery(sqlSelect)) {
if (rs.next()) {
assertEquals(rs.getString(1), "Replication test - REPLICATION IS OFF");
} else {
assertTrue(false, "Expected row of data was not found.");
}
}
TestUtils.clearTable(con, escapedTableName);
}

ds.setReplication(true);
try (Connection con = ds.getConnection(); Statement stmt = con.createStatement()) {
stmt.executeUpdate(sqlInsert);
try (ResultSet rs = stmt.executeQuery(sqlSelect)) {
if (rs.next()) {
assertEquals(rs.getString(1), "Replication test");
} else {
assertTrue(false, "Expected row of data was not found.");
}
}
TestUtils.dropTableIfExists(escapedTableName, stmt);
}
}
}

0 comments on commit 50b9fdb

Please sign in to comment.