| /* 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.PreparedStatement; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.util.Random; |
| |
| import junit.framework.Test; |
| |
| import org.apache.derbyTesting.functionTests.util.SQLStateConstants; |
| import org.apache.derbyTesting.junit.BaseJDBCTestCase; |
| import org.apache.derbyTesting.junit.JDBC; |
| import org.apache.derbyTesting.junit.TestConfiguration; |
| |
| public class MathTrigFunctionsTest extends BaseJDBCTestCase { |
| |
| private static final double |
| PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE = -1.79769E+308; |
| |
| private static final double |
| SMALL_NEG_DOUBLE = -1.79768E+308; |
| |
| private static final double |
| PRE_DERBY_3398_SMALLEST_POS_DERBY_DOUBLE = 2.225E-307; |
| |
| private static final double |
| PRE_DERBY_3398_LARGEST_POS_DERBY_DOUBLE = 1.79769E+308; |
| |
| private static final double |
| PRE_DERBY_3398_LARGEST_NEG_DERBY_DOUBLE = -2.225E-307; |
| |
| private static final double[] testRadians = { -0.000000001, -0.25, |
| 0.000000001, 0.25, 0.5, 0.0, 1.0, 2.0, java.lang.StrictMath.PI, |
| java.lang.StrictMath.PI }; |
| |
| private static final double[] testArcValues = { 0.000000001, -0.000000001, |
| 0.25, -0.25, 0.5, 0.0, -0.0, 1.0, -1.0 }; |
| |
| private static final double[] logValues = { 0.000000001, 0.25, 0.5, 1.0, |
| 45.0, 90.0, 135.0, 180.0, 270, PRE_DERBY_3398_SMALLEST_POS_DERBY_DOUBLE, |
| PRE_DERBY_3398_LARGEST_POS_DERBY_DOUBLE, 10, 100, 1000, 10000, |
| 100000, 1000000, 10000000, 100000000, 1000000000}; |
| |
| private static final double[] testValues = { |
| PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE, |
| SMALL_NEG_DOUBLE, |
| PRE_DERBY_3398_SMALLEST_POS_DERBY_DOUBLE, |
| PRE_DERBY_3398_LARGEST_POS_DERBY_DOUBLE, |
| PRE_DERBY_3398_LARGEST_NEG_DERBY_DOUBLE, |
| 0.000000001, |
| -0.000000001, 0.25, -0.25, 0.5, 0.0, -0.0, 1.0, -1.0, 2.0, 3.0, |
| java.lang.StrictMath.PI, 2 * java.lang.StrictMath.PI, 4.0, 45.0, |
| 90.0, 135.0, 180.0, 270 }; |
| |
| private static final double[] testValuesTwo = { |
| PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE, |
| SMALL_NEG_DOUBLE, |
| PRE_DERBY_3398_SMALLEST_POS_DERBY_DOUBLE, |
| PRE_DERBY_3398_LARGEST_NEG_DERBY_DOUBLE, |
| 0.000000001, -0.000000001, 0.25, -0.25, |
| 0.5, 0.0, -0.0, 1.0, -1.0, 2.0, 3.0, java.lang.StrictMath.PI, |
| 2 * java.lang.StrictMath.PI, 4.0, 45.0, 90.0, 135.0, 180.0, 270 }; |
| |
| /** |
| * Tests the ACOS function which returns the arc cosine of a specified |
| * number. |
| * <p> |
| * Acceptable input values to the ACOS function are DOUBLE PRECISION values |
| * from -1 to 1. NULL returns NULL and if the absolute value of the input is |
| * greater than 1 an SQL state of 22003 is returned. |
| * <p> |
| * The return value from the ACOS function is a DOUBLE PRECISION number in |
| * radians with a range of zero to PI. |
| * |
| */ |
| public void testAcos() throws SQLException { |
| // test the case where the input value is null |
| executeNullValues("ACOS"); |
| executeNullFn("ACOS"); |
| debug(); |
| |
| PreparedStatement ps = |
| prepareStatement("VALUES ACOS(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn ACOS(?)}"); |
| |
| for (int i = 0; i < testArcValues.length; i++) { |
| double expected = java.lang.StrictMath.acos(testArcValues[i]); |
| double rValue = getValue(ps, testArcValues[i]); |
| debug("ACOS: input value: " + testArcValues[i] |
| + " expected value: " + expected + " return value: " |
| + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testArcValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| |
| } |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.acos(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| /* test the case where the input value is out of range */ |
| try { |
| getValue(ps, 2.0); |
| fail("ACOS: Out of range test failed, input value is: " + 2.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| /* test the case where the input value is out of range */ |
| try { |
| getValue(psFN, 2.0); |
| fail("ACOS: Out of range test failed, input value is: " + 2.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the ASIN function which returns the arc sine of a specified number. |
| * <p> |
| * Acceptable input values to the ASIN function are DOUBLE PRECISION values |
| * from -1 to 1. |
| * <p> |
| * If the specified number is zero (0), the result of this function is zero. |
| * Note: Derby does not support negative zero. |
| * <p> |
| * An input value of NULL returns NULL. |
| * <p> |
| * If the absolute value of the input is greater than 1 an SQL state of |
| * 22003 is returned. |
| * <p> |
| * The return value from the ASIN function is a DOUBLE PRECISION number in |
| * radians with a range of -PI/2 to PI/2. |
| * |
| */ |
| public void testAsin() throws SQLException { |
| executeNullValues("ASIN"); |
| executeNullFn("ASIN"); |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES ASIN(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn ASIN(?)}"); |
| |
| for (int i = 0; i < testArcValues.length; i++) { |
| double expected = java.lang.StrictMath.asin(testArcValues[i]); |
| double rValue = getValue(ps, testArcValues[i]); |
| debug("ASIN: input value: " + testArcValues[i] |
| + " expected value: " + expected + " return value: " |
| + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testArcValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.asin(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| try { |
| getValue(ps, 2.0); |
| fail("ASIN: Out of range test failed, input value is: " + 2.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| try { |
| getValue(psFN, 2.0); |
| fail("ASIN: Out of range test failed, input value is: " + 2.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the ATAN function which returns the arc tangent of a specified |
| * number. Acceptable input values to the ATAN function are DOUBLE PRECISION |
| * values. |
| * <p> |
| * If the specified number is zero (0), the result of this function is zero. |
| * An input value of NULL returns NULL. |
| * <p> |
| * The return value from the ATAN function is a DOUBLE PRECISION number in |
| * radians with a range of -PI/2 to PI/2. |
| * |
| */ |
| public void testAtan() throws SQLException { |
| executeNullValues("ATAN"); |
| executeNullFn("ATAN"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES ATAN(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn ATAN(?)}"); |
| |
| for (int i = 0; i < testValues.length; i++) { |
| double expected = java.lang.StrictMath.atan(testValues[i]); |
| double rValue = getValue(ps, testValues[i]); |
| debug("ATAN: input value: " + testValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.atan(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| ps.close(); |
| psFN.close(); |
| |
| } |
| |
| /** |
| * Tests the COS function which returns the cosine of a specified number. |
| * <p> |
| * Acceptable input values to the COS function are DOUBLE PRECISION values. |
| * <p> |
| * An input value of NULL returns NULL. |
| */ |
| public void testCos() throws SQLException { |
| executeNullValues("COS"); |
| executeNullFn("COS"); |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES COS(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn COS(?)}"); |
| |
| for (int i = 0; i < testValues.length; i++) { |
| double expected = java.lang.StrictMath.cos(testValues[i]); |
| double rValue = getValue(ps, testValues[i]); |
| debug("COS: input value: " + testValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.cos(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the SIN function which returns the sine of a specified number. |
| * <p> |
| * Acceptable input values to the SIN function are DOUBLE PRECISION values. |
| * <p> |
| * An input value of NULL returns NULL. |
| * <p> |
| * If the argument is zero, then the result is zero. |
| * <p> |
| * The data type of the returned value is a DOUBLE PRECISION number. |
| */ |
| public void testSin() throws SQLException { |
| executeNullValues("SIN"); |
| executeNullFn("SIN"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES SIN(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn SIN(?)}"); |
| for (int i = 0; i < testValues.length; i++) { |
| double expected = java.lang.StrictMath.sin(testValues[i]); |
| double rValue = getValue(ps, testValues[i]); |
| debug("SIN: input value: " + testValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.sin(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the TAN function which returns the tangent of a specified number. |
| * <p> |
| * Acceptable input values to the TAN function are DOUBLE PRECISION values. |
| * <p> |
| * An input value of NULL returns NULL. |
| * <p> |
| * If the argument is zero, then the result is zero. |
| * <p> |
| * The data type of the returned value is a DOUBLE PRECISION number. |
| */ |
| public void testTan() throws SQLException { |
| executeNullValues("TAN"); |
| |
| executeNullFn("TAN"); |
| |
| debug(); |
| |
| PreparedStatement ps = |
| prepareStatement("VALUES TAN(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn TAN(?)}"); |
| |
| for (int i = 0; i < testValues.length; i++) { |
| double expected = java.lang.StrictMath.tan(testValues[i]); |
| double rValue = getValue(ps, testValues[i]); |
| debug("TAN: input value: " + testValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.tan(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| public void testCot() throws SQLException { |
| executeNullValues("COT"); |
| executeNullFn("COT"); |
| debug(); |
| |
| PreparedStatement ps = prepareStatement("VALUES COT(?)"); |
| PreparedStatement psFN = prepareStatement("VALUES {fn COT(?)}"); |
| |
| for (double value : testValues) { |
| checkResult(ps, value, 1.0d / StrictMath.tan(value)); |
| } |
| |
| Random rand = new Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expected = 1.0d / StrictMath.tan(randD); |
| checkResult(ps, randD, expected); |
| checkResult(psFN, randD, expected); |
| } |
| } |
| |
| private void checkResult(PreparedStatement ps, |
| double input, double expected) |
| throws SQLException { |
| |
| // Derby doesn't distinguish between positive and negative zero. |
| if (expected == -0.0d) { |
| expected = 0.0d; |
| } |
| |
| ps.setDouble(1, input); |
| if (Double.isNaN(expected) || Double.isInfinite(expected)) { |
| debug("input value: " + input + " expected value: " + expected |
| + " : OUT OF RANGE"); |
| assertStatementError("22003", ps); |
| } else { |
| debug("input value: " + input + " expected value: " + expected); |
| JDBC.assertSingleValueResultSet( |
| ps.executeQuery(), String.valueOf(expected)); |
| } |
| } |
| |
| public void testCosh() throws SQLException { |
| executeNullValues("COSH"); |
| debug(); |
| |
| PreparedStatement ps = prepareStatement("VALUES COSH(?)"); |
| |
| // COSH is not a JDBC escape function. Expect syntax error when |
| // called as one. |
| assertCompileError("42X01", "VALUES {fn COSH(?)}"); |
| |
| for (double value : testValues) { |
| checkResult(ps, value, StrictMath.cosh(value)); |
| } |
| |
| Random rand = new Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = StrictMath.cosh(randD); |
| checkResult(ps, randD, expect); |
| } |
| } |
| |
| public void testSinh() throws SQLException { |
| executeNullValues("SINH"); |
| debug(); |
| |
| PreparedStatement ps = prepareStatement("VALUES SINH(?)"); |
| |
| // SINH is not a JDBC escape function. Expect syntax error when |
| // called as one. |
| assertCompileError("42X01", "VALUES {fn SINH(?)}"); |
| |
| for (double value : testValues) { |
| checkResult(ps, value, StrictMath.sinh(value)); |
| } |
| |
| Random rand = new Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = StrictMath.sinh(randD); |
| checkResult(ps, randD, expect); |
| } |
| } |
| |
| public void testTanh() throws SQLException { |
| executeNullValues("TANH"); |
| debug(); |
| |
| PreparedStatement ps = prepareStatement("VALUES TANH(?)"); |
| |
| // TANH is not a JDBC escape function. Expect syntax error when |
| // called as one. |
| assertCompileError("42X01", "VALUES {fn TANH(?)}"); |
| |
| for (double value : testValues) { |
| checkResult(ps, value, StrictMath.tanh(value)); |
| } |
| |
| Random rand = new Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = StrictMath.tanh(randD); |
| checkResult(ps, randD, expect); |
| } |
| } |
| |
| /** |
| * Tests the PI function which returns a value that is closer than any other |
| * value to pi. |
| * <p> |
| * The constant pi is the ratio of the circumference of a circle to the |
| * diameter of a circle. |
| * <p> |
| * No input values are allowed for the PI function. |
| */ |
| |
| public void testPI() throws SQLException { |
| double value = executeValues("PI"); |
| assertEquals(java.lang.StrictMath.PI, value, 0.0); |
| double fValue = executeFn("PI"); |
| assertEquals(java.lang.StrictMath.PI, fValue, 0.0); |
| |
| try { |
| executeValues("PI", 2.0); |
| fail("PI: Out of range test failed, input value is: " + 2.0); |
| } catch (SQLException sqlE) { |
| // '<statement>' is not recognized as a function or procedure. |
| assertSQLState("42Y03", sqlE); |
| } |
| |
| try { |
| executeFn("PI", 2.0); |
| fail("PI: Out of range test failed, input value is: " + 2.0); |
| } catch (SQLException sqlE) { |
| // '<statement>' is not recognized as a function or procedure. |
| assertSQLState("42Y03", sqlE); |
| } |
| |
| } |
| |
| /** |
| * Tests the DEGREES function which converts a DOUBLE PRECISION number from |
| * radians to degrees. |
| * <p> |
| * The input is an angle measured in radians, which is converted to an |
| * approximately equivalent angle measured in degrees. |
| * <p> |
| * The conversion from radians to degrees is not exact. You should not |
| * expect that the COS(DEGREES(PI/2)) to exactly equal 0.0. |
| * <p> |
| * The return value is a DOUBLE PRECISION number. |
| */ |
| public void testDegrees() throws SQLException { |
| executeNullValues("DEGREES"); |
| executeNullFn("DEGREES"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES DEGREES(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn DEGREES(?)}"); |
| |
| for (int i = 0; i < testRadians.length; i++) { |
| double expected = java.lang.StrictMath.toDegrees(testRadians[i]); |
| double rValue = getValue(ps, testRadians[i]); |
| // rValue = executeValues("DEGREES", SMALL_NEG_DOUBLE); |
| debug("DEGREES: input value: " + testRadians[i] |
| + " expected value: " + expected + " return value: " |
| + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testRadians[i]); |
| assertEquals(expected, fValue, 0.0); |
| |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.toDegrees(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| try { |
| // Yields -Infinity, so thould throw. |
| getValue(ps, PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE); |
| fail("DEGREES: Out of range test failed, input value is: " |
| + PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| try { |
| // Yields -Infinity, so thould throw. |
| getValue(psFN, PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE); |
| fail("DEGREES: Out of range test failed, input value is: " |
| + PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| // 2.2250738585072014E-308 remove when we move to compile with source level |
| // Java 6. Cf Double.MIN_NORMAL. |
| final static double DOUBLE_MIN_NORMAL = 2.2250738585072014E-308; |
| |
| /** |
| * Tests the RADIANS function which converts a DOUBLE PRECISION number from |
| * degrees to radians. |
| * <p> |
| * The input is an angle measured in degrees, which is converted to an |
| * approximately equivalent angle measured in radians. |
| * <p> |
| * The conversion from radians to degrees is not exact. You should not |
| * expect that the COS(RADIANS(90.0)) to exactly equal 0.0. |
| * <p> |
| * The return value is a DOUBLE PRECISION number. |
| */ |
| public void testRadians() throws SQLException { |
| executeNullValues("RADIANS"); |
| |
| executeNullFn("RADIANS"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES RADIANS(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn RADIANS(?)}"); |
| |
| for (int i = 0; i < testArcValues.length; i++) { |
| double expected = java.lang.StrictMath.toRadians(testArcValues[i]); |
| double rValue = getValue(ps, testArcValues[i]); |
| debug("RADIANS: input value: " + testArcValues[i] |
| + " expected value: " + expected + " return value: " |
| + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testArcValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.toRadians(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| // Numbers below verified by using lava.lang.StrictMath.toRadians |
| // outside Derby context. First number: argument to ps and psFN, second |
| // number: expected result. Actual results vary by JVM level. See DERBY-6755. |
| double[][] inOut = new double[][] { |
| {180.0d, java.lang.StrictMath.PI}, |
| {PRE_DERBY_3398_SMALLEST_NEG_DERBY_DOUBLE, -3.1375609430176863E306}, |
| {DOUBLE_MIN_NORMAL, 3.8834864931005E-310}, |
| {Double.MIN_VALUE, 0.0d}, |
| {Double.MAX_VALUE, 3.1375664143845866E306}, |
| {PRE_DERBY_3398_SMALLEST_POS_DERBY_DOUBLE, vmAtLeast( 1, 9 ) ? 3.883357585687384E-309 : 3.88335758568738E-309}, |
| {PRE_DERBY_3398_LARGEST_NEG_DERBY_DOUBLE, vmAtLeast( 1, 9 ) ? -3.883357585687384E-309 : -3.88335758568738E-309}, |
| }; |
| |
| for (int i=0; i < inOut.length; i++) { |
| double dv = getValue(ps, inOut[i][0]); |
| assertEquals(inOut[i][1], dv, 0.0d); |
| dv = getValue(psFN, inOut[i][0]); |
| assertEquals(inOut[i][1], dv, 0.0d); |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the EXP function which returns e raised to the power of the input |
| * DOUBLE PRECISION number. The input number is the exponent to raise e to. |
| * <p> |
| * The constant e is the base of the natural logarithms. |
| * <p> |
| * The return value is a DOUBLE PRECISION number. |
| * |
| * @throws SQLException |
| */ |
| public void testExp() throws SQLException { |
| executeNullValues("EXP"); |
| executeNullFn("EXP"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES EXP(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn EXP(?)}"); |
| |
| for (int i = 0; i < testValuesTwo.length; i++) { |
| double expected = java.lang.StrictMath.exp(testValuesTwo[i]); |
| double rValue = getValue(ps, testValuesTwo[i]); |
| debug("EXP: input value: " + testValuesTwo[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testValuesTwo[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.exp(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| try { |
| getValue(ps, PRE_DERBY_3398_LARGEST_POS_DERBY_DOUBLE); |
| fail("EXP: Out of range test failed, input value is: " |
| + PRE_DERBY_3398_LARGEST_POS_DERBY_DOUBLE); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| try { |
| getValue(psFN, PRE_DERBY_3398_LARGEST_POS_DERBY_DOUBLE); |
| fail("EXP: Out of range test failed, input value is: " |
| + PRE_DERBY_3398_LARGEST_POS_DERBY_DOUBLE); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the LOG10 function which returns the base-10 logarithm of a DOUBLE |
| * PRECISION number that is greater than zero. |
| * <p> |
| * If the input value is NULL, the result of this function is NULL. |
| * <p> |
| * If the input value is zero or a negative number, an exception is returned |
| * that indicates that the value is out of range (SQL state 22003). |
| * <p> |
| * The return type is a DOUBLE PRECISION number. |
| */ |
| |
| public void testLog10() throws SQLException { |
| executeNullValues("LOG10"); |
| executeNullFn("LOG10"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES LOG10(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn LOG10(?)}"); |
| for (int i = 0; i < logValues.length; i++) { |
| double expected = StrictMath.log10(logValues[i]); |
| double rValue = getValue(ps, logValues[i]); |
| debug("LOG10: input value: " + logValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, logValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = StrictMath.log10(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| try { |
| getValue(ps, 0.0); |
| fail("LOG10: Out of range test failed, input value is: " + 0.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| try { |
| getValue(ps, -1.0); |
| fail("LOG10: Out of range test failed, input value is: " + -1.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| try { |
| getValue(psFN, 0.0); |
| fail("LOG10: Out of range test failed, input value is: " + 0.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| try { |
| getValue(psFN, -1.0); |
| fail("LOG10: Out of range test failed, input value is: " + -1.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the LOG function which returns the natural logarithm (base e) of a |
| * DOUBLE PRECISION number that is greater than zero (0). |
| * <p> |
| * If the specified number is NULL, the result of these functions is NULL. |
| * If the specified number is zero or a negative number, an exception is |
| * returned that indicates that the value is out of range (SQL state 22003). |
| * <p> |
| * The data type of the returned value is a DOUBLE PRECISION number. |
| */ |
| public void testLog() throws SQLException { |
| executeNullValues("LOG"); |
| executeNullFn("LOG"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES LOG(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn LOG(?)}"); |
| |
| for (int i = 0; i < logValues.length; i++) { |
| double expected = java.lang.StrictMath.log(logValues[i]); |
| double rValue = getValue(ps, logValues[i]); |
| debug("LOG: input value: " + logValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, logValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.log(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| try { |
| getValue(ps, 0.0); |
| fail("LOG: Out of range test failed, input value is: " + 0.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| try { |
| getValue(psFN, 0.0); |
| fail("LOG: Out of range test failed, input value is: " + 0.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| ps.close(); |
| psFN.close(); |
| |
| } |
| |
| /** |
| * Tests the LN function which returns the natural logarithm (base e) of a |
| * DOUBLE PRECISION number that is greater than zero (0). |
| * <p> |
| * If the specified number is NULL, the result of these functions is NULL. |
| * If the specified number is zero or a negative number, an exception is |
| * returned that indicates that the value is out of range (SQL state 22003). |
| * <p> |
| * The data type of the returned value is a DOUBLE PRECISION number. |
| */ |
| public void testLn() throws SQLException { |
| executeNullValues("LN"); |
| // Note: the syntax 'values {fn ln(value)}' is not supported |
| // because it is not defined by JDBC. |
| // Object fnVal = executeNullFn("LN"); |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES LN(?)"); |
| for (int i = 0; i < logValues.length; i++) { |
| double expected = java.lang.StrictMath.log(logValues[i]); |
| double rValue = getValue(ps, logValues[i]); |
| debug("LOG: input value: " + logValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.log(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| } |
| |
| try { |
| getValue(ps, 0.0); |
| fail("LOG: Out of range test failed, input value is: " + 0.0); |
| } catch (SQLException sqlE) { |
| // "ERROR 22003: The resulting value is outside the range for the |
| // data type DOUBLE."; |
| assertSQLState( |
| SQLStateConstants.DATA_EXCEPTION_NUMERIC_VALUE_OUT_OF_RANGE, |
| sqlE); |
| } |
| |
| ps.close(); |
| } |
| |
| /** |
| * Tests the CEIL function which rounds a DOUBLE PRECISION number up, and |
| * return the smallest number that is greater than or equal to the input |
| * number. |
| * <p> |
| * If the input number is NULL, the result of these functions is NULL. If |
| * the input number is equal to a mathematical integer, the result of these |
| * functions is the same as the input number. If the input number is zero |
| * (0), the result of these functions is zero. If the input number is less |
| * than zero but greater than -1.0, then the result of these functions is |
| * zero. |
| * <p> |
| * The returned value is the smallest (closest to negative infinity) double |
| * floating point value that is greater than or equal to the specified |
| * number. The returned value is equal to a mathematical integer. |
| * <p> |
| * The data type of the returned value is a DOUBLE PRECISION number. |
| */ |
| |
| public void testCeil() throws SQLException { |
| executeNullValues("CEIL"); |
| |
| // Note: the syntax 'values {fn CEIL(value)}' is not supported |
| // because it is not specified by JDBC |
| // Object fnVal = executeNullFn("CEIL"); |
| |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES CEIL(?)"); |
| |
| for (int i = 0; i < testValues.length; i++) { |
| double expected = java.lang.StrictMath.ceil(testValues[i]); |
| double rValue = getValue(ps, testValues[i]); |
| debug("CEIL: input value: " + testValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.ceil(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| } |
| |
| ps.close(); |
| } |
| |
| /** |
| * Tests the CEILING function which rounds a DOUBLE PRECISION number up, and |
| * return the smallest number that is greater than or equal to the input |
| * number. |
| * <p> |
| * If the input number is NULL, the result of these functions is NULL. If |
| * the input number is equal to a mathematical integer, the result of these |
| * functions is the same as the input number. If the input number is zero |
| * (0), the result of these functions is zero. If the input number is less |
| * than zero but greater than -1.0, then the result of these functions is |
| * zero. |
| * <p> |
| * The returned value is the smallest (closest to negative infinity) double |
| * floating point value that is greater than or equal to the specified |
| * number. The returned value is equal to a mathematical integer. |
| * <p> |
| * The data type of the returned value is a DOUBLE PRECISION number. |
| */ |
| public void testCeiling() throws SQLException { |
| executeNullValues("CEILING"); |
| |
| executeNullFn("CEILING"); |
| |
| PreparedStatement ps = |
| prepareStatement("VALUES CEILING(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn CEILING(?)}"); |
| |
| debug(); |
| for (int i = 0; i < testValues.length; i++) { |
| double expected = java.lang.StrictMath.ceil(testValues[i]); |
| double rValue = getValue(ps, testValues[i]); |
| debug("CEILING: input value: " + testValues[i] |
| + " expected value: " + expected + " return value: " |
| + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.ceil(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| |
| ps.close(); |
| psFN.close(); |
| } |
| |
| /** |
| * Tests the FLOOR function which rounds the input value which must be a |
| * DOUBLE PRECISION number down, and returns the largest number that is less |
| * than or equal to the input value. |
| * <p> |
| * If the input value is NULL, the result of this function is NULL. If the |
| * input value is equal to a mathematical integer, the result of this |
| * function is the same as the input number. If the input value is zero (0), |
| * the result of this function is zero. |
| * <p> |
| * The returned value is the largest (closest to positive infinity) double |
| * floating point value that is less than or equal to the input value. The |
| * returned value is equal to a mathematical integer. The data type of the |
| * returned value is a DOUBLE PRECISION number. |
| * |
| * @throws SQLException |
| */ |
| |
| public void testFloor() throws SQLException { |
| executeNullValues("FLOOR"); |
| |
| executeNullFn("FLOOR"); |
| |
| debug(); |
| PreparedStatement ps = |
| prepareStatement("VALUES FLOOR(?)"); |
| PreparedStatement psFN = |
| prepareStatement("VALUES {fn FLOOR(?)}"); |
| |
| for (int i = 0; i < testValues.length; i++) { |
| double expected = java.lang.StrictMath.floor(testValues[i]); |
| double rValue = getValue(ps, testValues[i]); |
| debug("FLOOR: input value: " + testValues[i] + " expected value: " |
| + expected + " return value: " + rValue); |
| assertEquals(expected, rValue, 0.0); |
| double fValue = getValue(psFN, testValues[i]); |
| assertEquals(expected, fValue, 0.0); |
| } |
| |
| Random rand = new java.util.Random(); |
| for (int i = 0; i < 100; i++) { |
| double randD = rand.nextDouble(); |
| double expect = java.lang.StrictMath.floor(randD); |
| double rVal = getValue(ps, randD); |
| assertEquals(expect, rVal, 0.0); |
| double fVal = getValue(psFN, randD); |
| assertEquals(expect, fVal, 0.0); |
| |
| } |
| ps.close(); |
| psFN.close(); |
| } |
| |
| private double executeValues(String functionName) throws SQLException { |
| Statement stmt = createStatement(); |
| ResultSet rs = stmt.executeQuery("values " + functionName + "()"); |
| double rValue = 0.0; |
| while (rs.next()) { |
| rValue = rs.getDouble(1); |
| } |
| rs.close(); |
| stmt.close(); |
| return rValue; |
| } |
| |
| private double executeValues(String functionName, double value) |
| throws SQLException { |
| Statement stmt = createStatement(); |
| ResultSet rs = stmt.executeQuery("values " + functionName + "(" + value |
| + ")"); |
| double rValue = 0.0; |
| while (rs.next()) { |
| rValue = rs.getDouble(1); |
| } |
| rs.close(); |
| stmt.close(); |
| return rValue; |
| } |
| |
| /** |
| * Execute a prepared statement with a single double argument |
| * and return the double value from the single row returned. |
| */ |
| private double getValue(PreparedStatement ps, double value) |
| throws SQLException { |
| ps.setDouble(1, value); |
| ResultSet rs = ps.executeQuery(); |
| rs.next(); // we know a single value will be returned. |
| double rValue = rs.getDouble(1); |
| rs.close(); |
| return rValue; |
| } |
| |
| private void executeNullValues(String functionName) throws SQLException { |
| Statement stmt = createStatement(); |
| ResultSet rs = stmt.executeQuery("values " + functionName + "(null)"); |
| rs.next(); // we know a single value will be returned. |
| assertNull(rs.getObject(1)); |
| assertTrue(rs.wasNull()); |
| rs.close(); |
| stmt.close(); |
| } |
| |
| private double executeFn(String functionName) throws SQLException { |
| Statement stmt = createStatement(); |
| ResultSet rs = stmt.executeQuery("values {fn " + functionName + "()}"); |
| double rValue = 0.0; |
| while (rs.next()) { |
| rValue = rs.getDouble(1); |
| } |
| rs.close(); |
| stmt.close(); |
| return rValue; |
| } |
| |
| private double executeFn(String functionName, double value) |
| throws SQLException { |
| Statement stmt = createStatement(); |
| ResultSet rs = stmt.executeQuery("values {fn " + functionName + "(" |
| + value + ")}"); |
| double rValue = 0.0; |
| while (rs.next()) { |
| rValue = rs.getDouble(1); |
| } |
| rs.close(); |
| stmt.close(); |
| return rValue; |
| } |
| |
| private void executeNullFn(String functionName) throws SQLException { |
| Statement stmt = createStatement(); |
| ResultSet rs = stmt.executeQuery("values {fn " + functionName |
| + "(null)}"); |
| rs.next(); // we know a single value will be returned. |
| assertNull(rs.getObject(1)); |
| assertTrue(rs.wasNull()); |
| rs.close(); |
| stmt.close(); |
| } |
| |
| private void debug(String message) { |
| println(message); |
| } |
| |
| private void debug() { |
| println(""); |
| } |
| |
| public MathTrigFunctionsTest(String name) { |
| super(name); |
| } |
| |
| /** |
| * Runs the tests in the embedded and client server configuration |
| * as the JDBC escape function testing is relevant for both drivers. |
| */ |
| public static Test suite() { |
| return TestConfiguration.defaultSuite(MathTrigFunctionsTest.class); |
| } |
| |
| } |