| /** |
| * Derby - Class org.apache.derbyTesting.functionTests.tests.lang.TimestampArithTest |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.derbyTesting.functionTests.tests.lang; |
| |
| import java.sql.Connection; |
| import java.sql.PreparedStatement; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.sql.Types; |
| import junit.framework.Test; |
| import org.apache.derbyTesting.junit.BaseJDBCTestCase; |
| import org.apache.derbyTesting.junit.BaseJDBCTestSetup; |
| import org.apache.derbyTesting.junit.BaseTestSuite; |
| import org.apache.derbyTesting.junit.JDBC; |
| |
| /** |
| * Test the JDBC TIMESTAMPADD and TIMESTAMPDIFF escape functions. |
| * |
| * Things to test: |
| * + Test each interval type with timestamp, date, and time inputs. |
| * + Test diff with all 9 combinations of datetime input types (timestamp - timestamp, timestamp - date, etc). |
| * + Test PreparedStatements with parameters, '?', in each argument, and Statements. (Statements are prepared |
| * internally so we do not also have to test PrepardStatements without parameters). |
| * + Test with null inputs. |
| * + Test with input string that is convertible to timestamp. |
| * + Test with invalid interval type. |
| * + Test with invalid arguments in the date time arguments. |
| * + Test TIMESTAMPADD with an invalid type in the count argument. |
| * + Test overflow cases. |
| */ |
| public class TimestampArithTest extends BaseJDBCTestCase { |
| |
| /** Abstract class that factors out all the common code for the timestamps tests. */ |
| private static abstract class OneTest { |
| final int interval; // FRAC_SECOND_INTERVAL, SECOND_INTERVAL, ... or |
| final String expectedSQLState; // Null if no SQLException is expected |
| final String expectedMsg; // Null if no SQLException is expected |
| String sql; |
| |
| OneTest(int interval, String expectedSQLState, String expectedMsg) { |
| this.interval = interval; |
| this.expectedSQLState = expectedSQLState; |
| this.expectedMsg = expectedMsg; |
| } |
| |
| void runTest() throws SQLException { |
| ResultSet rs = null; |
| |
| sql = composeSQL(); |
| try { |
| rs = stmt.executeQuery(sql); |
| checkResultSet(rs, sql); |
| if (expectedSQLState != null) { |
| fail("Statement '" + sql + "' did not generate an exception"); |
| } |
| } catch (SQLException sqle) { |
| if (expectedSQLState == null) { |
| fail("Unexpected exception from statement '" + sql + "'", |
| sqle); |
| } |
| assertSQLState("Incorrect SQLState from statement '" + sql + "'", expectedSQLState, sqle); |
| } |
| if (rs != null) { |
| rs.close(); |
| rs = null; |
| } |
| |
| try { |
| rs = executePS(); |
| checkResultSet(rs, sql); |
| if (expectedSQLState != null) { |
| fail("Prepared Statement '" + sql + "' did not generate an exception"); |
| } |
| } catch (SQLException sqle) { |
| if (expectedSQLState == null) { |
| fail("Unexpected exception from prepared statement '" + |
| sql + "'", sqle); |
| } |
| assertSQLState("Incorrect SQLState from prepared statement '" + sql + "'", expectedSQLState, sqle); |
| } |
| if (rs != null) { |
| rs.close(); |
| rs = null; |
| } |
| } |
| |
| private void checkResultSet(ResultSet rs, String sql) throws SQLException { |
| assertTrue("'" + sql + "' did not return any rows.", rs.next()); |
| checkResultRow(rs, sql); |
| assertFalse("'" + sql + "' returned more than one row.", rs.next()); |
| } |
| |
| abstract String composeSQL(); |
| abstract void checkResultRow(ResultSet rs, String sql) throws SQLException; |
| abstract ResultSet executePS() throws SQLException; |
| } |
| |
| private static class OneDiffTest extends OneTest { |
| private final java.util.Date ts1; |
| private final java.util.Date ts2; |
| private final int expectedDiff; |
| protected boolean expectNull; |
| |
| OneDiffTest(int interval, java.util.Date ts1, java.util.Date ts2, |
| int expectedDiff, String expectedSQLState, String expectedMsg) { |
| super(interval, expectedSQLState, expectedMsg); |
| this.ts1 = ts1; |
| this.ts2 = ts2; |
| this.expectedDiff = expectedDiff; |
| expectNull = (ts1 == null) || (ts2 == null); |
| } |
| |
| void checkResultRow(ResultSet rs, String sql) throws SQLException { |
| int actualDiff = rs.getInt(1); |
| assertFalse("Unexpected null result from '" + sql + "'.", rs.wasNull() && !expectNull); |
| assertFalse("Expected null result from '" + sql + "'.", !rs.wasNull() && expectNull); |
| assertEquals("Unexpected result from '" + sql + "'.", expectedDiff, actualDiff); |
| } |
| |
| String composeSQL() { |
| return composeSqlStr("DIFF", interval, dateTimeToLiteral(ts1), |
| dateTimeToLiteral(ts2)); |
| } |
| |
| ResultSet executePS() throws SQLException { |
| setDateTime(tsDiffPS[interval], 1, ts1); |
| setDateTime(tsDiffPS[interval], 2, ts2); |
| return tsDiffPS[interval].executeQuery(); |
| } |
| } |
| |
| private static class OneStringDiffTest extends OneDiffTest { |
| private final String ts1; |
| private final String ts2; |
| |
| OneStringDiffTest(int interval, String ts1, String ts2, |
| int expectedDiff, String expectedSQLState, String expectedMsg) { |
| super(interval, (java.util.Date) null, (java.util.Date) null, |
| expectedDiff, expectedSQLState, expectedMsg); |
| this.ts1 = ts1; |
| this.ts2 = ts2; |
| expectNull = (ts1 == null) || (ts2 == null); |
| } |
| |
| String composeSQL() { |
| return composeSqlStr("DIFF", interval, dateTimeToLiteral(ts1), |
| dateTimeToLiteral(ts2)); |
| } |
| |
| ResultSet executePS() throws SQLException { |
| tsDiffPS[interval].setString(1, ts1); |
| tsDiffPS[interval].setString(2, ts2); |
| return tsDiffPS[interval].executeQuery(); |
| } |
| } |
| |
| private static class OneAddTest extends OneTest { |
| private final java.util.Date ts; |
| final int count; |
| final java.sql.Timestamp expected; |
| |
| OneAddTest(int interval, int count, java.util.Date ts, |
| java.sql.Timestamp expected, String expectedSQLState, |
| String expectedMsg) { |
| super(interval, expectedSQLState, expectedMsg); |
| this.count = count; |
| this.ts = ts; |
| this.expected = expected; |
| } |
| |
| String composeSQL() { |
| return composeSqlStr("ADD", interval, String.valueOf(count), |
| dateTimeToLiteral(ts)); |
| } |
| |
| void checkResultRow(ResultSet rs, String sql) throws SQLException { |
| java.sql.Timestamp actual = rs.getTimestamp(1); |
| assertFalse("Unexpected null result from '" + sql + "'.", (rs.wasNull() || actual == null) && expected != null); |
| assertFalse("Expected null result from '" + sql + "'.", !(rs.wasNull() || actual == null) && expected == null); |
| assertEquals("Unexpected result from '" + sql + "'.", expected, actual); |
| } |
| |
| ResultSet executePS() throws SQLException { |
| tsAddPS[interval].setInt(1, count); |
| setDateTime(tsAddPS[interval], 2, ts); |
| return tsAddPS[interval].executeQuery(); |
| } |
| } |
| |
| private static class OneStringAddTest extends OneAddTest { |
| private final String ts; |
| |
| OneStringAddTest(int interval, int count, String ts, |
| java.sql.Timestamp expected, String expectedSQLState, |
| String expectedMsg) { |
| super(interval, count, (java.util.Date) null, expected, |
| expectedSQLState, expectedMsg); |
| this.ts = ts; |
| } |
| |
| String composeSQL() { |
| return composeSqlStr("ADD", interval, String.valueOf(count), |
| dateTimeToLiteral(ts)); |
| } |
| |
| ResultSet executePS() throws SQLException { |
| tsAddPS[interval].setInt(1, count); |
| tsAddPS[interval].setString(2, ts); |
| return tsAddPS[interval].executeQuery(); |
| } |
| } |
| |
| private static final int FRAC_SECOND_INTERVAL = 0; |
| private static final int SECOND_INTERVAL = 1; |
| private static final int MINUTE_INTERVAL = 2; |
| private static final int HOUR_INTERVAL = 3; |
| private static final int DAY_INTERVAL = 4; |
| private static final int WEEK_INTERVAL = 5; |
| private static final int MONTH_INTERVAL = 6; |
| private static final int QUARTER_INTERVAL = 7; |
| private static final int YEAR_INTERVAL = 8; |
| |
| /** timestamp - timestamp */ |
| private static final OneDiffTest[] diffBetweenTsTests = { |
| new OneDiffTest(FRAC_SECOND_INTERVAL, ts("2005-05-10 08:25:00"), ts("2005-05-10 08:25:00.000001"), 1000, null, null), |
| new OneDiffTest(SECOND_INTERVAL, ts("2005-05-10 08:25:01"), ts("2005-05-10 08:25:00"), -1, null, null), |
| new OneDiffTest(SECOND_INTERVAL, ts("2005-05-10 08:25:00.1"), ts("2005-05-10 08:25:00"), 0, null, null), |
| new OneDiffTest(SECOND_INTERVAL, ts("2005-05-10 08:25:00"), ts("2005-05-10 08:26:00"), 60, null, null), |
| new OneDiffTest(MINUTE_INTERVAL, ts("2005-05-11 08:25:00"), ts("2005-05-10 08:25:00"), -24 * 60, null, null), |
| new OneDiffTest(HOUR_INTERVAL, ts("2005-05-10 08:25:00"), ts("2005-05-11 08:25:00"), 24, null, null), |
| new OneDiffTest(DAY_INTERVAL, ts("2005-05-10 08:25:00"), ts("2005-05-11 08:25:00"), 1, null, null), |
| new OneDiffTest(DAY_INTERVAL, ts("2005-05-10 08:25:01"), ts("2005-05-11 08:25:00"), 0, null, null), |
| new OneDiffTest(WEEK_INTERVAL, ts("2005-02-23 08:25:00"), ts("2005-03-01 08:25:00"), 0, null, null), |
| new OneDiffTest(MONTH_INTERVAL, ts("2005-02-23 08:25:00"), ts("2005-03-23 08:25:00"), 1, null, null), |
| new OneDiffTest(MONTH_INTERVAL, ts("2005-02-23 08:25:01"), ts("2005-03-23 08:25:00"), 0, null, null), |
| new OneDiffTest(QUARTER_INTERVAL, ts("2005-02-23 08:25:00"), ts("2005-05-23 08:25:00"), 1, null, null), |
| new OneDiffTest(QUARTER_INTERVAL, ts("2005-02-23 08:25:01"), ts("2005-05-23 08:25:00"), 0, null, null), |
| new OneDiffTest(YEAR_INTERVAL, ts("2005-02-23 08:25:00"), ts("2005-05-23 08:25:00"), 0, null, null), |
| new OneDiffTest(YEAR_INTERVAL, ts("2005-02-23 08:25:00"), ts("2006-02-23 08:25:00"), 1, null, null) |
| }; |
| |
| /** timestamp - date */ |
| private static final OneDiffTest[] diffBetweenTsAndDateTests = { |
| new OneDiffTest(FRAC_SECOND_INTERVAL, ts("2004-05-10 00:00:00.123456"), dt("2004-05-10"), -123456000, null, null), |
| new OneDiffTest(SECOND_INTERVAL, ts("2004-05-10 08:25:01"), dt("2004-05-10"), -(1 + 60 * (25 + 60 * 8)), null, null), |
| new OneDiffTest(MINUTE_INTERVAL, ts("2004-05-11 08:25:00"), dt("2004-05-10"), -(24 * 60 + 8 * 60 + 25), null, null), |
| new OneDiffTest(HOUR_INTERVAL, ts("2004-02-28 08:25:00"), dt("2004-03-01"), 39, null, null), |
| new OneDiffTest(DAY_INTERVAL, ts("2004-05-10 08:25:00"), dt("2004-05-11"), 0, null, null), |
| new OneDiffTest(WEEK_INTERVAL, ts("2004-02-23 00:00:00"), dt("2004-03-01"), 1, null, null), |
| new OneDiffTest(MONTH_INTERVAL, ts("2004-02-23 08:25:00"), dt("2004-03-24"), 1, null, null), |
| new OneDiffTest(QUARTER_INTERVAL, ts("2004-02-23 08:25:00"), dt("2004-05-24"), 1, null, null), |
| new OneDiffTest(YEAR_INTERVAL, ts("2004-02-23 08:25:00"), dt("2004-05-23"), 0, null, null) |
| }; |
| |
| /** date - timestamp */ |
| private static final OneDiffTest[] diffBetweenDateAndTsTests = { |
| new OneDiffTest(FRAC_SECOND_INTERVAL, dt("2004-05-10"), ts("2004-05-10 00:00:00.123456"), 123456000, null, null), |
| new OneDiffTest(SECOND_INTERVAL, dt("2004-05-10"), ts("2004-05-09 23:59:00"), -60, null, null), |
| new OneDiffTest(MINUTE_INTERVAL, dt("2004-05-10"), ts("2004-05-11 08:25:00"), 24 * 60 + 8 * 60 + 25, null, null), |
| new OneDiffTest(HOUR_INTERVAL, dt("2005-03-01"), ts("2005-02-28 08:25:00"), -15, null, null), |
| new OneDiffTest(DAY_INTERVAL, dt("2004-05-10"), ts("2004-05-11 08:25:00"), 1, null, null), |
| new OneDiffTest(WEEK_INTERVAL, dt("2004-03-01"), ts("2004-02-23 00:00:00"), -1, null, null), |
| new OneDiffTest(MONTH_INTERVAL, dt("2005-03-24"), ts("2004-02-23 08:25:00"), -13, null, null), |
| new OneDiffTest(QUARTER_INTERVAL, dt("2004-05-23"), ts("2004-02-23 08:25:01"), 0, null, null), |
| new OneDiffTest(YEAR_INTERVAL, dt("2004-05-23"), ts("2003-02-23 08:25:00"), -1, null, null) |
| }; |
| |
| /** timestamp + timestamp */ |
| private static final OneAddTest[] addBetweenTsTests = { |
| new OneAddTest(FRAC_SECOND_INTERVAL, 1000, ts("2005-05-11 15:55:00"), ts("2005-05-11 15:55:00.000001"), null, null), |
| new OneAddTest(SECOND_INTERVAL, 60, ts("2005-05-11 15:55:00"), ts("2005-05-11 15:56:00"), null, null), |
| new OneAddTest(MINUTE_INTERVAL, -1, ts("2005-05-11 15:55:00"), ts("2005-05-11 15:54:00"), null, null), |
| new OneAddTest(HOUR_INTERVAL, 2, ts("2005-05-11 15:55:00"), ts("2005-05-11 17:55:00"), null, null), |
| new OneAddTest(DAY_INTERVAL, 1, ts("2005-05-11 15:55:00"), ts("2005-05-12 15:55:00"), null, null), |
| new OneAddTest(WEEK_INTERVAL, 1, ts("2005-05-11 15:55:00"), ts("2005-05-18 15:55:00"), null, null), |
| new OneAddTest(MONTH_INTERVAL, 1, ts("2005-05-11 15:55:00"), ts("2005-06-11 15:55:00"), null, null), |
| new OneAddTest(QUARTER_INTERVAL, 1, ts("2005-10-11 15:55:00"), ts("2006-01-11 15:55:00"), null, null), |
| new OneAddTest(YEAR_INTERVAL, -10, ts("2005-10-11 15:55:00"), ts("1995-10-11 15:55:00"), null, null) |
| }; |
| |
| /** date + timestamp */ |
| private static final OneAddTest[] addBetweenDateAndTsTests = { |
| // following gives an error with J2ME j9_foundation 1.1 (DERBY-2225): |
| new OneAddTest(FRAC_SECOND_INTERVAL, -1000, dt("2005-05-11"), ts("2005-05-10 23:59:59.999999"), null, null), |
| new OneAddTest(SECOND_INTERVAL, 60, dt("2005-05-11"), ts("2005-05-11 00:01:00"), null, null), |
| new OneAddTest(MINUTE_INTERVAL, 1, dt("2005-05-11"), ts("2005-05-11 00:01:00"), null, null), |
| new OneAddTest(HOUR_INTERVAL, -2, dt("2005-05-11"), ts("2005-05-10 22:00:00"), null, null), |
| new OneAddTest(DAY_INTERVAL, 1, dt("2005-05-11"), ts("2005-05-12 00:00:00"), null, null), |
| new OneAddTest(WEEK_INTERVAL, 1, dt("2005-05-11"), ts("2005-05-18 00:00:00"), null, null), |
| new OneAddTest(MONTH_INTERVAL, -1, dt("2005-03-29"), ts("2005-02-28 00:00:00"), null, null), |
| new OneAddTest(QUARTER_INTERVAL, -2, dt("2005-05-05"), ts("2004-11-05 00:00:00"), null, null), |
| new OneAddTest(YEAR_INTERVAL, 2, dt("2005-05-05"), ts("2007-05-05 00:00:00"), null, null) |
| }; |
| |
| private static final OneStringDiffTest[] diffBetweenStringTests = { |
| new OneStringDiffTest(SECOND_INTERVAL, "2005-05-10 08:25:00", "2005-05-10 08:26:00", 60, null, null) |
| }; |
| |
| private static final OneStringAddTest[] addBetweenStringTests = { |
| new OneStringAddTest(DAY_INTERVAL, 1, "2005-05-11 15:55:00", ts("2005-05-12 15:55:00"), null, null) |
| }; |
| |
| /** check overflow conditions */ |
| private static final OneTest[] overflowTests = { |
| new OneDiffTest(FRAC_SECOND_INTERVAL, ts("2004-05-10 00:00:00.123456"), ts("2004-05-10 00:00:10.123456"), 0, "22003", |
| "The resulting value is outside the range for the data type INTEGER."), |
| new OneDiffTest(FRAC_SECOND_INTERVAL, ts("2004-05-10 00:00:00.123456"), ts("2005-05-10 00:00:00.123456"), 0, "22003", |
| "The resulting value is outside the range for the data type INTEGER."), |
| new OneDiffTest(SECOND_INTERVAL, ts("1904-05-10 00:00:00"), ts("2205-05-10 00:00:00"), 0, "22003", |
| "The resulting value is outside the range for the data type INTEGER."), |
| new OneAddTest(YEAR_INTERVAL, 99999, ts("2004-05-10 00:00:00.123456"), null, "22003", |
| "The resulting value is outside the range for the data type TIMESTAMP.") |
| }; |
| |
| private static final String[][] invalid = { |
| {"values( {fn TIMESTAMPDIFF( SECOND, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)})", "42X01", |
| "Syntax error: Encountered \"SECOND\" at line 1, column 28."}, |
| {"values( {fn TIMESTAMPDIFF( , CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)})", "42X01", |
| "Syntax error: Encountered \",\" at line 1, column 28."}, |
| {"values( {fn TIMESTAMPDIFF( SQL_TSI_SECOND, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 5)})", "42X01", |
| "Syntax error: Encountered \",\" at line 1, column 80."}, |
| {"values( {fn TIMESTAMPDIFF( SQL_TSI_SECOND, CURRENT_TIMESTAMP, 'x')})", "42X45", |
| "CHAR is an invalid type for argument number 3 of TIMESTAMPDIFF."}, |
| {"values( {fn TIMESTAMPDIFF( SQL_TSI_SECOND, 'x', CURRENT_TIMESTAMP)})", "42X45", |
| "CHAR is an invalid type for argument number 2 of TIMESTAMPDIFF."}, |
| {"values( {fn TIMESTAMPDIFF( SQL_TSI_SECOND, CURRENT_TIMESTAMP)})", "42X01", |
| "Syntax error: Encountered \")\" at line 1, column 61."}, |
| {"values( {fn TIMESTAMPDIFF( SQL_TSI_SECOND)})", "42X01", |
| "Syntax error: Encountered \")\" at line 1, column 42."}, |
| {"values( {fn TIMESTAMPADD( x, 1, CURRENT_TIMESTAMP)})", "42X01", |
| "Syntax error: Encountered \"x\" at line 1, column 27."}, |
| {"values( {fn TIMESTAMPADD( SQL_TSI_SECOND, CURRENT_DATE, CURRENT_TIMESTAMP)})", "42X45", |
| "DATE is an invalid type for argument number 2 of TIMESTAMPADD."}, |
| {"values( {fn TIMESTAMPADD( SQL_TSI_SECOND, 'XX', CURRENT_TIMESTAMP)})", "42X45", |
| "CHAR is an invalid type for argument number 2 of TIMESTAMPADD."}, |
| {"values( {fn TIMESTAMPADD( SQL_TSI_SECOND, 1.1, CURRENT_TIMESTAMP)})", "42X45", |
| "DECIMAL is an invalid type for argument number 2 of TIMESTAMPADD."}, |
| {"values( {fn TIMESTAMPADD( SQL_TSI_SECOND, 1, 2.1)})", "42X45", |
| "DECIMAL is an invalid type for argument number 3 of TIMESTAMPADD."}, |
| {"values( {fn TIMESTAMPADD( SQL_TSI_SECOND, 1, 'XX')})", "42X45", |
| "CHAR is an invalid type for argument number 3 of TIMESTAMPADD."}, |
| {"values( {fn TIMESTAMPADD( SQL_TSI_SECOND, 1)})", "42X01", |
| "Syntax error: Encountered \")\" at line 1, column 44."}, |
| {"values( {fn TIMESTAMPADD( SQL_TSI_SECOND)})", "42X01", |
| "Syntax error: Encountered \")\" at line 1, column 41."} |
| }; |
| |
| private static final String[] intervalJdbcNames = { "SQL_TSI_FRAC_SECOND", |
| "SQL_TSI_SECOND", "SQL_TSI_MINUTE", "SQL_TSI_HOUR", "SQL_TSI_DAY", |
| "SQL_TSI_WEEK", "SQL_TSI_MONTH", "SQL_TSI_QUARTER", "SQL_TSI_YEAR" }; |
| |
| private static Statement stmt; |
| private static PreparedStatement[] tsAddPS = new PreparedStatement[intervalJdbcNames.length]; |
| private static PreparedStatement[] tsDiffPS = new PreparedStatement[intervalJdbcNames.length]; |
| |
| /** |
| * Basic constructor. |
| */ |
| public TimestampArithTest(String name) { |
| super(name); |
| } |
| |
| protected void initializeConnection(Connection conn) throws SQLException { |
| conn.setAutoCommit(false); |
| } |
| |
| public static Test suite() { |
| return new BaseJDBCTestSetup( |
| new BaseTestSuite( |
| TimestampArithTest.class, "TimestampArithTest")) { |
| |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| for (int i = 0; i < intervalJdbcNames.length; i++) { |
| tsAddPS[i] = getConnection().prepareStatement( |
| composeSqlStr("ADD", i, "?", "?")); |
| tsDiffPS[i] = getConnection().prepareStatement( |
| composeSqlStr("DIFF", i, "?", "?")); |
| } |
| |
| stmt = getConnection().createStatement(); |
| } |
| |
| protected void tearDown() throws Exception { |
| closeAll(tsAddPS); |
| tsAddPS = null; |
| closeAll(tsDiffPS); |
| tsDiffPS = null; |
| stmt.close(); |
| stmt = null; |
| super.tearDown(); |
| } |
| }; |
| } |
| |
| /** Close all statements in an array. */ |
| private static void closeAll(Statement[] statements) throws SQLException { |
| for (int i = 0; i < statements.length; i++) { |
| statements[i].close(); |
| } |
| } |
| |
| public void testDiffBetweenTimestamp() throws SQLException { |
| getConnection(); |
| |
| for (int i = 0; i < diffBetweenTsTests.length; i++) { |
| diffBetweenTsTests[i].runTest(); |
| } |
| } |
| |
| public void testDiffBetweenTimestampAndDate() throws SQLException { |
| for (int i = 0; i < diffBetweenTsAndDateTests.length; i++) { |
| diffBetweenTsAndDateTests[i].runTest(); |
| } |
| } |
| |
| public void testDiffBetweenDateAndTimestamp() throws SQLException { |
| for (int i = 0; i < diffBetweenDateAndTsTests.length; i++) { |
| diffBetweenDateAndTsTests[i].runTest(); |
| } |
| } |
| |
| public void testAddBetweenTimestamp() throws SQLException { |
| for (int i = 0; i < addBetweenTsTests.length; i++) { |
| addBetweenTsTests[i].runTest(); |
| } |
| } |
| |
| public void testAddBetweenDateAndTimestamps() throws SQLException { |
| for (int i = 0; i < addBetweenDateAndTsTests.length; i++) { |
| addBetweenDateAndTsTests[i].runTest(); |
| } |
| } |
| |
| public void testDiffBetweenString() throws SQLException { |
| for (int i = 0; i < diffBetweenStringTests.length; i++) { |
| diffBetweenStringTests[i].runTest(); |
| } |
| } |
| |
| public void testAddBetweenString() throws SQLException { |
| for (int i = 0; i < addBetweenStringTests.length; i++) { |
| addBetweenStringTests[i].runTest(); |
| } |
| } |
| |
| public void testOverflow() throws SQLException { |
| for (int i = 0; i < overflowTests.length; i++) { |
| overflowTests[i].runTest(); |
| } |
| } |
| |
| /** |
| * Tests null inputs, each position, each type. |
| * |
| * @throws SQLException |
| */ |
| public void testNullInputs() throws SQLException { |
| tsDiffPS[HOUR_INTERVAL].setTimestamp(1, ts( "2005-05-11 15:26:00")); |
| tsDiffPS[HOUR_INTERVAL].setNull(2, Types.TIMESTAMP); |
| |
| // TIMESTAMPDIFF with null timestamp in third argument |
| expectNullResult(tsDiffPS[HOUR_INTERVAL]); |
| |
| // TIMESTAMPDIFF with null date in third argument |
| tsDiffPS[HOUR_INTERVAL].setNull(2, Types.DATE); |
| expectNullResult(tsDiffPS[HOUR_INTERVAL]); |
| |
| // TIMESTAMPDIFF with null timestamp in second argument |
| tsDiffPS[HOUR_INTERVAL].setTimestamp(2, ts( "2005-05-11 15:26:00")); |
| tsDiffPS[HOUR_INTERVAL].setNull(1, Types.TIMESTAMP); |
| expectNullResult(tsDiffPS[HOUR_INTERVAL]); |
| |
| // TIMESTAMPDIFF with null date in second argument |
| tsDiffPS[HOUR_INTERVAL].setNull(1, Types.DATE); |
| expectNullResult(tsDiffPS[HOUR_INTERVAL]); |
| |
| // TIMESTAMPADD with null integer in second argument |
| tsAddPS[MINUTE_INTERVAL].setTimestamp(2, ts( "2005-05-11 15:26:00")); |
| tsAddPS[MINUTE_INTERVAL].setNull(1, Types.INTEGER); |
| expectNullResult(tsAddPS[MINUTE_INTERVAL]); |
| |
| // TIMESTAMPADD with null timestamp in third argument |
| tsAddPS[MINUTE_INTERVAL].setInt(1, 1); |
| tsAddPS[MINUTE_INTERVAL].setNull(2, Types.TIMESTAMP); |
| expectNullResult(tsAddPS[MINUTE_INTERVAL]); |
| |
| // TIMESTAMPADD with null date in third argument |
| tsAddPS[MINUTE_INTERVAL].setNull(2, Types.DATE); |
| expectNullResult(tsAddPS[MINUTE_INTERVAL]); |
| } |
| |
| public void testInvalidLengths() throws SQLException { |
| ResultSet rs; |
| |
| for (int i = 0; i < invalid.length; i++) { |
| try { |
| rs = stmt.executeQuery(invalid[i][0]); |
| rs.next(); |
| fail(invalid[i][0] + " did not throw an exception."); |
| } catch (SQLException sqle) { |
| assertSQLState("Unexpected SQLState from " + invalid[i][0], invalid[i][1], sqle); |
| } |
| } |
| } |
| |
| public void testInvalidArgTypes() throws SQLException { |
| expectException( tsDiffPS[ HOUR_INTERVAL], ts( "2005-05-21 15:26:00"), 2.0, "XCL12", |
| "TIMESTAMPDIFF with double ts2"); |
| expectException( tsDiffPS[ HOUR_INTERVAL], 2.0, ts( "2005-05-11 15:26:00"), "XCL12", |
| "TIMESTAMPDIFF with double ts1"); |
| expectException( tsAddPS[ MINUTE_INTERVAL], 1, -1, "XCL12", |
| "TIMESTAMPADD with int ts"); |
| expectException( tsAddPS[ MINUTE_INTERVAL], ts( "2005-05-11 15:26:00"), ts( "2005-05-11 15:26:00"), "XCL12", |
| "TIMESTAMPADD with timestamp count"); |
| } |
| |
| private static void expectException(PreparedStatement ps, Object obj1, Object obj2, |
| String expectedSQLState, String label) { |
| ResultSet rs; |
| |
| try { |
| ps.setObject(1, obj1); |
| ps.setObject(2, obj2); |
| rs = ps.executeQuery(); |
| rs.next(); |
| fail(label + " did not throw an exception."); |
| } catch (SQLException sqle) { |
| assertSQLState("Unexpected SQLState from " + label, expectedSQLState, sqle); |
| } |
| } |
| |
| private static void expectNullResult(PreparedStatement ps) |
| throws SQLException { |
| JDBC.assertSingleValueResultSet(ps.executeQuery(), null); |
| } |
| |
| private static String dateTimeToLiteral(Object ts) { |
| if (ts instanceof java.sql.Timestamp) |
| return "{ts '" + ((java.sql.Timestamp) ts).toString() + "'}"; |
| else if (ts instanceof java.sql.Time) |
| return "{t '" + ((java.sql.Time) ts).toString() + "'}"; |
| else if (ts instanceof java.sql.Date) |
| return "{d '" + ((java.sql.Date) ts).toString() + "'}"; |
| else if (ts instanceof String) |
| return "TIMESTAMP( '" + ((String) ts) + "')"; |
| else |
| return ts.toString(); |
| } |
| |
| private static String composeSqlStr(String fn, int interval, String parm1, String parm2) { |
| return "values( {fn TIMESTAMP" + fn + "( " |
| + intervalJdbcNames[interval] + ", " + parm1 + "," + parm2 |
| + ")})"; |
| } |
| |
| private static void setDateTime(PreparedStatement ps, int parameterIdx, |
| java.util.Date dateTime) throws SQLException { |
| if (dateTime instanceof java.sql.Timestamp) |
| ps.setTimestamp(parameterIdx, (java.sql.Timestamp) dateTime); |
| else if (dateTime instanceof java.sql.Date) |
| ps.setDate(parameterIdx, (java.sql.Date) dateTime); |
| else if (dateTime instanceof java.sql.Time) |
| ps.setTime(parameterIdx, (java.sql.Time) dateTime); |
| else |
| ps.setTimestamp(parameterIdx, (java.sql.Timestamp) dateTime); |
| } |
| |
| private static java.sql.Timestamp ts(String s) { |
| // Timestamp format must be yyyy-mm-dd hh:mm:ss.fffffffff |
| if (s.length() < 29) { |
| // Pad out the fraction with zeros |
| StringBuffer sb = new StringBuffer(s); |
| if (s.length() == 19) |
| sb.append('.'); |
| while (sb.length() < 29) |
| sb.append('0'); |
| s = sb.toString(); |
| } |
| return java.sql.Timestamp.valueOf(s); |
| } |
| |
| private static java.sql.Date dt(String s) { |
| return java.sql.Date.valueOf(s); |
| } |
| } |