Skip to content

Commit

Permalink
Support LocalDateTime in CallableStatement
Browse files Browse the repository at this point in the history
This PR adds support for the requested functionality in #1392, but does not address the mentioned code duplication.
The added library code was copied verbatim from SQLServerResultSet.
  • Loading branch information
CasualSuperman committed Jul 28, 2020
1 parent 9877ac5 commit 03dcfee
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 6 deletions.
Expand Up @@ -24,6 +24,7 @@
import java.sql.Time;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.HashMap;
import java.util.TreeMap;
Expand Down Expand Up @@ -740,6 +741,20 @@ public <T> T getObject(int index, Class<T> type) throws SQLException {
returnValue = getTime(index);
} else if (type == java.sql.Timestamp.class) {
returnValue = getTimestamp(index);
} else if (type == java.time.LocalDateTime.class || type == java.time.LocalDate.class
|| type == java.time.LocalTime.class) {
java.time.LocalDateTime ldt = getLocalDateTime(index);
if (null == ldt) {
returnValue = null;
} else {
if (type == java.time.LocalDateTime.class) {
returnValue = ldt;
} else if (type == java.time.LocalDate.class) {
returnValue = ldt.toLocalDate();
} else {
returnValue = ldt.toLocalTime();
}
}
} else if (type == microsoft.sql.DateTimeOffset.class) {
returnValue = getDateTimeOffset(index);
} else if (type == UUID.class) {
Expand Down Expand Up @@ -893,6 +908,14 @@ public Timestamp getTimestamp(String name, Calendar cal) throws SQLServerExcepti
return value;
}

LocalDateTime getLocalDateTime(int columnIndex) throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "getLocalDateTime", columnIndex);
checkClosed();
LocalDateTime value = (LocalDateTime) getValue(columnIndex, JDBCType.LOCALDATETIME);
loggerExternal.exiting(getClassNameLogging(), "getLocalDateTime", value);
return value;
}

@Override
public Timestamp getDateTime(int index) throws SQLServerException {
if (loggerExternal.isLoggable(java.util.logging.Level.FINER))
Expand Down
Expand Up @@ -3,13 +3,12 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.sql.*;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.TimeZone;
import java.util.UUID;

import org.junit.jupiter.api.AfterAll;
Expand Down Expand Up @@ -39,6 +38,7 @@ public class CallableStatementTest extends AbstractTest {
private static String outputProcedureNameGUID = RandomUtil.getIdentifier("uniqueidentifier_SP");
private static String setNullProcedureName = RandomUtil.getIdentifier("CallableStatementTest_setNull_SP");
private static String inputParamsProcedureName = RandomUtil.getIdentifier("CallableStatementTest_inputParams_SP");
private static String getObjectLocalDateTimeProcedureName = RandomUtil.getIdentifier("CallableStatementTest_getObjectLocalDateTime_SP");

/**
* Setup before test
Expand All @@ -53,11 +53,13 @@ public static void setupTest() throws SQLException {
TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedureNameGUID), stmt);
TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(setNullProcedureName), stmt);
TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(inputParamsProcedureName), stmt);
TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(getObjectLocalDateTimeProcedureName), stmt);

createGUIDTable(stmt);
createGUIDStoredProcedure(stmt);
createSetNullProcedure(stmt);
createInputParamsProcedure(stmt);
createGetObjectLocalDateTimeProcedure(stmt);
}
}

Expand Down Expand Up @@ -123,6 +125,45 @@ public void getSetNullWithTypeVarchar() throws SQLException {
}
}


/**
* Tests getObject(n, java.time.LocalDateTime.class).
*
* @throws SQLException
*/
@Test
public void getObjectAsLocalDateTime() throws SQLException {
String sql = "{CALL " + AbstractSQLGenerator.escapeIdentifier(getObjectLocalDateTimeProcedureName) + " (?)}";
try (Connection con = DriverManager.getConnection(connectionString); CallableStatement cs = con.prepareCall(sql)) {
cs.registerOutParameter(1, Types.TIMESTAMP);
TimeZone prevTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));

// a local date/time that does not actually exist because of Daylight Saving Time
final String testValueDate = "2018-03-11";
final String testValueTime = "02:00:00.1234567";
final String testValueDateTime = testValueDate + "T" + testValueTime;

try {
cs.execute();

LocalDateTime expectedLocalDateTime = LocalDateTime.parse(testValueDateTime);
LocalDateTime actualLocalDateTime = cs.getObject(1, LocalDateTime.class);
assertEquals(expectedLocalDateTime, actualLocalDateTime);

LocalDate expectedLocalDate = LocalDate.parse(testValueDate);
LocalDate actualLocalDate = cs.getObject(1, LocalDate.class);
assertEquals(expectedLocalDate, actualLocalDate);

LocalTime expectedLocalTime = LocalTime.parse(testValueTime);
LocalTime actualLocalTime = cs.getObject(1, LocalTime.class);
assertEquals(expectedLocalTime, actualLocalTime);
} finally {
TimeZone.setDefault(prevTimeZone);
}
}
}

/**
* recognize parameter names with and without leading '@'
*
Expand Down Expand Up @@ -207,4 +248,11 @@ private static void createInputParamsProcedure(Statement stmt) throws SQLExcepti

stmt.execute(sql);
}

private static void createGetObjectLocalDateTimeProcedure(Statement stmt) throws SQLException {
String sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(getObjectLocalDateTimeProcedureName)
+ "(@p1 datetime2(7) OUTPUT) AS "
+ "SELECT '2018-03-11T02:00:00.1234567' = GETDATE()";
stmt.execute(sql);
}
}

0 comments on commit 03dcfee

Please sign in to comment.