db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r555032 [2/2] - in /db/derby/code/trunk/java: engine/org/apache/derby/catalog/ engine/org/apache/derby/catalog/types/ engine/org/apache/derby/iapi/services/io/ engine/org/apache/derby/iapi/sql/dictionary/ engine/org/apache/derby/iapi/sql/ex...
Date Tue, 10 Jul 2007 18:40:41 GMT
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/StringColumnVTI.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/StringColumnVTI.java?view=auto&rev=555032
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/StringColumnVTI.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/StringColumnVTI.java
Tue Jul 10 11:40:39 2007
@@ -0,0 +1,543 @@
+/*
+
+Derby - Class org.apache.derbyTesting.functionTests.tests.lang.StringColumnVTI
+
+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.io.*;
+import java.math.BigDecimal;
+import java.sql.*;
+import java.text.DateFormat;
+import java.text.ParseException;
+
+import org.apache.derby.vti.VTITemplate;
+
+/**
+ * <p>
+ * This is an abstract VTI which assumes that all columns are strings and which
+ * coerces the strings to reasonable values for various getXXX()
+ * methods. Subclasses must implement the following ResultSet methods:
+ * </p>
+ *
+ * <ul>
+ * <li>next( )</li>
+ * <li>close()</li>
+ * <li>getMetaData()</li>
+ * </ul>
+ *
+ * <p>
+ * and the following protected methods introduced by this class:
+ * </p>
+ *
+ * <ul>
+ * <li>getRawColumn( int columnNumber )</li>
+ * </ul>
+ */
+public  abstract    class   StringColumnVTI extends VTITemplate
+{
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTANTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // INNER CLASSES
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * A crude Blob implementation for datatype testing.
+     * </p>
+     */
+    public	static	final	class	SimpleBlob	implements	Blob
+    {
+        private	byte[]	_bytes;
+        
+        public	SimpleBlob( byte[] bytes )
+        {
+            _bytes = bytes;
+        }
+        
+        public	InputStream	getBinaryStream()
+        {
+            return new ByteArrayInputStream( _bytes );
+        }
+        
+        public	byte[]	getBytes( long position, int length ) { return _bytes; }
+        
+        public	long	length()
+        {
+            if ( _bytes == null ) { return 0L; }
+            return (long) _bytes.length;
+        }
+        
+        public	long	position( Blob pattern, long start ) { return 0L; }
+        public	long	position( byte[] pattern, long start ) { return 0L; }
+        
+        public	boolean	equals( Object other )
+        {
+            if ( other == null ) { return false; }
+            if ( !( other instanceof Blob ) ) { return false; }
+            
+            Blob	that = (Blob) other;
+            
+            try {
+                if ( this.length() != that.length() ) { return false; }
+                
+                InputStream	thisStream = this.getBinaryStream();
+                InputStream	thatStream = that.getBinaryStream();
+                
+                while( true )
+                {
+                    int		nextByte = thisStream.read();
+                    
+                    if ( nextByte < 0 ) { break; }
+                    if ( nextByte != thatStream.read() ) { return false; }
+                }
+            }
+            catch (Exception e)
+            {
+                System.err.println( e.getMessage() );
+                e.printStackTrace();
+                return false;
+            }
+            
+            return true;
+        }
+        
+        public int setBytes(long arg0, byte[] arg1) throws SQLException {
+            throw new SQLException("not implemented");
+        }
+        
+        public int setBytes(long arg0, byte[] arg1, int arg2, int arg3) throws SQLException
{
+            throw new SQLException("not implemented");
+        }
+
+        public OutputStream setBinaryStream(long arg0) throws SQLException {
+            throw new SQLException("not implemented");
+        }
+
+        public void truncate(long arg0) throws SQLException {
+            throw new SQLException("not implemented");
+        }
+    }
+    
+    /**
+     * <p>
+     * A crude Clob implementation.
+     * </p>
+     */
+    public	static	final	class	SimpleClob	implements	Clob
+    {
+        private	String	_contents;
+
+        public	SimpleClob( String contents )
+        {
+            _contents = contents;
+        }
+        
+        public	InputStream	getAsciiStream()
+        {
+            try {
+                return new ByteArrayInputStream( _contents.getBytes( "UTF-8" ) );
+            }
+            catch (Exception e) { return null; }
+        }
+        
+        public	Reader	getCharacterStream()
+        {
+            return new CharArrayReader( _contents.toCharArray() );
+        }
+        
+        public	String	getSubString( long position, int length )
+        {
+            return _contents.substring( (int) position, length );
+        }
+		
+        public	long	length()
+        {
+            if ( _contents == null ) { return 0L; }
+            return (long) _contents.length();
+        }
+        
+        public	long	position( Clob searchstr, long start ) { return 0L; }
+        public	long	position( String searchstr, long start ) { return 0L; }
+        
+        public	boolean	equals( Object other )
+        {
+            if ( other == null ) { return false; }
+            if ( !( other instanceof Clob ) ) { return false; }
+            
+            Clob	that = (Clob) other;
+            
+            try {
+                if ( this.length() != that.length() ) { return false; }
+                
+                InputStream	thisStream = this.getAsciiStream();
+                InputStream	thatStream = that.getAsciiStream();
+                
+                while( true )
+                {
+                    int		nextByte = thisStream.read();
+                    
+                    if ( nextByte < 0 ) { break; }
+                    if ( nextByte != thatStream.read() ) { return false; }
+                }
+            }
+            catch (Exception e)
+            {
+                System.err.println( e.getMessage() );
+                e.printStackTrace();
+                return false;
+            }
+            
+            return true;
+        }
+        
+        public int setString(long arg0, String arg1) throws SQLException {
+            throw new SQLException("not implemented");
+        }
+        
+        public int setString(long arg0, String arg1, int arg2, int arg3) throws SQLException
{
+            throw new SQLException("not implemented");
+        }
+
+        public OutputStream setAsciiStream(long arg0) throws SQLException {
+            throw new SQLException("not implemented");
+        }
+
+        public Writer setCharacterStream(long arg0) throws SQLException {
+            throw new SQLException("not implemented");
+        }
+
+        public void truncate(long arg0) throws SQLException {
+            throw new SQLException("not implemented");    
+        }
+
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // STATE
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    private String[]      _columnNames;
+    private boolean _lastColumnWasNull;
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // StringColumnVTI BEHAVIOR TO BE IMPLEMENTED BY SUBCLASSES
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Get the string value of the column in the current row identified by the 1-based columnNumber.
+     * </p>
+     */
+    protected  abstract    String  getRawColumn( int columnNumber ) throws SQLException;
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTRUCTORS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Build a StringColumnVTI with the given column names
+     * </p>
+     */
+    public  StringColumnVTI( String[] columnNames )
+    {
+        _columnNames = columnNames;
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // ResultSet BEHAVIOR
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    public boolean wasNull() throws SQLException { return _lastColumnWasNull; }
+    
+    public int findColumn( String columnName ) throws SQLException
+    {
+        int     count = _columnNames.length;
+
+        for ( int i = 0; i < count; i++ ) { if ( _columnNames[ i ].equals( columnName
) ) { return i+1; } }
+
+        throw new SQLException( "Unknown column name." );
+    }
+    
+    public String getString(int columnIndex) throws SQLException
+    {
+        String  columnValue = getRawColumn( columnIndex );
+
+        checkNull( columnValue );
+
+        return columnValue;
+    }
+    
+    public boolean getBoolean(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return false; }
+        else { return Boolean.valueOf( columnValue ).booleanValue(); }
+    }
+
+    public byte getByte(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return (byte) 0; }
+        else
+        {
+            try {
+                return Byte.valueOf( columnValue ).byteValue();
+            } catch (NumberFormatException e) { throw wrap( e ); }
+        }
+    }
+
+    public short getShort(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return (short) 0; }
+        else
+        {
+            try {
+                return Short.valueOf( columnValue ).shortValue();
+            } catch (NumberFormatException e) { throw wrap( e ); }
+        }
+    }
+
+    public int getInt(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return 0; }
+        else
+        {
+            try {
+                return Integer.valueOf( columnValue ).intValue();
+            } catch (NumberFormatException e) { throw wrap( e ); }
+        }
+    }
+
+    public long getLong(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return (long) 0; }
+        else
+        {
+            try {
+                return Long.valueOf( columnValue ).longValue();
+            } catch (NumberFormatException e) { throw wrap( e ); }
+        }
+    }
+
+   public float getFloat(int columnIndex) throws SQLException
+   {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return (float) 0; }
+        else
+        {
+            try {
+                return Float.valueOf( columnValue ).floatValue();
+            } catch (NumberFormatException e) { throw wrap( e ); }
+        }
+    }
+
+    public double getDouble(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return (double) 0; }
+        else
+        {
+            try {
+                return Double.valueOf( columnValue ).doubleValue();
+            } catch (NumberFormatException e) { throw wrap( e ); }
+        }
+    }
+
+    public BigDecimal getBigDecimal(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        else
+        {
+            try {
+                return new BigDecimal( columnValue );
+            } catch (NumberFormatException e) { throw wrap( e ); }
+        }
+    }
+
+    public byte[] getBytes(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        else
+        {
+            return columnValue.getBytes();
+        }
+    }
+
+    public java.sql.Date getDate(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        else
+        {
+            return new Date( parseDateTime( columnValue ) );
+        }
+    }
+
+    public java.sql.Time getTime(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        else
+        {
+            return new Time( parseDateTime( columnValue ) );
+        }
+    }
+
+    public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        else
+        {
+            return new Timestamp( parseDateTime( columnValue ) );
+        }
+    }
+
+    public InputStream getAsciiStream(int columnIndex) throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        return getEncodedStream( columnValue, "US-ASCII" );
+    }
+
+    public java.io.InputStream getBinaryStream(int columnIndex)
+        throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        else { return new ByteArrayInputStream( getBytes( columnIndex ) ); }
+    }
+
+    public Blob getBlob(int columnIndex)
+        throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        else { return new SimpleBlob( getBytes( columnIndex ) ); }
+    }
+    
+    public Clob getClob(int columnIndex)
+        throws SQLException
+    {
+        String  columnValue = getString( columnIndex );
+
+        if ( columnValue == null ) { return null; }
+        { return new SimpleClob( getString( columnIndex ) ); }
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // MINIONS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Set the wasNull flag based on whether this column value turned out to be null.
+     * </p>
+     */
+    private void checkNull( String columnValue )
+    {
+        _lastColumnWasNull = ( columnValue == null );
+    }
+    
+    /**
+     * <p>
+     * Wrap an exception in a SQLException.
+     * </p>
+     */
+    private SQLException wrap( Throwable t )
+    {
+        return new SQLException( t.getMessage() );
+    }
+    
+    /**
+     * <p>
+     * Translate a date/time expression into the corresponding long number of
+     * milliseconds.
+     * </p>
+     */
+    private long parseDateTime( String columnValue  )
+        throws SQLException
+    {
+        try {
+            DateFormat      df = DateFormat.getDateTimeInstance();
+                
+            java.util.Date  rawDate = df.parse( columnValue );
+
+            return rawDate.getTime();
+        } catch (ParseException e) { throw wrap( e ); }
+    }
+    
+    /**
+     * <p>
+     * Turn a string into an appropriately encoded ByteArrayInputStream.
+     * </p>
+     */
+    private InputStream getEncodedStream( String columnValue, String encoding  )
+        throws SQLException
+    {
+        if ( columnValue == null ) { return null; }
+        else
+        {
+            try {
+                byte[]      rawBytes = columnValue.getBytes( encoding );
+            
+                return new ByteArrayInputStream( rawBytes );
+            } catch (UnsupportedEncodingException e) { throw wrap( e ); }
+        }
+    }
+
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/StringColumnVTI.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SysDiagVTIMappingTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SysDiagVTIMappingTest.java?view=diff&rev=555032&r1=555031&r2=555032
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SysDiagVTIMappingTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SysDiagVTIMappingTest.java
Tue Jul 10 11:40:39 2007
@@ -100,10 +100,10 @@
         // Should fail because SPACE_TABLE is not defined in APP 
         // schema.
         
-        assertStatementError("42Y03", st,
+        assertStatementError("42ZB4", st,
             "select * from TABLE(SPACE_TABLE('APP')) x");
         
-        assertStatementError("42Y03", st,
+        assertStatementError("42ZB4", st,
             "select * from TABLE(APP.SPACE_TABLE('APP', 'T1')) x");
         
         // Should fail due to extra "TABLE" keyword.
@@ -126,7 +126,7 @@
         // Should fail because SPACE_TABLE is not defined in APP schema.
         
         st.executeUpdate("set schema SYSCS_DIAG");
-        assertStatementError("42Y03", st,
+        assertStatementError("42ZB4", st,
             "select * from TABLE(APP.SPACE_TABLE('APP', 'T1')) x");
         
         // All remaining test cases in this method should succeed.
@@ -530,7 +530,7 @@
         // Use of TABLE constructor with regular tables should fail.
 
         assertStatementError("42X01", st, "select * from table (app.t1) x");
-        assertStatementError("42Y03", st, "select * from table (app.t1()) x");
+        assertStatementError("42ZB4", st, "select * from table (app.t1()) x");
 
         // Use of TABLE constructor with VTI tables (as opposed to VTI
         // table *functions*) should fail.

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TableFunctionTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TableFunctionTest.java?view=auto&rev=555032
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TableFunctionTest.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TableFunctionTest.java
Tue Jul 10 11:40:39 2007
@@ -0,0 +1,788 @@
+/*
+
+Derby - Class org.apache.derbyTesting.functionTests.tests.lang.TableFunctionTest
+
+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.*;
+import java.util.ArrayList;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.TestConfiguration;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test Table Functions. See DERBY-716 for a description of
+ * this feature.
+ */
+public class TableFunctionTest extends BaseJDBCTestCase
+{
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTANTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    // functions to drop at teardown time
+    private static  final   String[]    FUNCTION_NAMES =
+    {
+        "SIMPLEFUNCTIONTABLE",
+        "invert",
+        "returnsACoupleRows",
+        "returnsAllLegalDatatypes",
+    };
+    
+    private static  final   String[][]  SIMPLE_ROWS =
+    {
+        { "who", "put" },
+        { "the", "bop" },
+        { (String) null, "in" },
+        { "the", (String) null },
+    };
+    
+    private static  final   String[][]  ALL_TYPES_ROWS =
+    {
+        {
+            null,   // BIGINT
+            null,   // BLOB
+            null,   // CHAR
+            null,   // CHAR FOR BIT DATA
+            null,   // CLOB
+            null,   // DATE
+            null,   // DECIMAL
+            null,   // DOUBLE
+            null,   // DOUBLE PRECISION
+            null,   // FLOAT( 23 )
+            null,   // FLOAT( 24 )
+            null,   // INTEGER
+            null,   // LONG VARCHAR
+            null,   // LONG VARCHAR FOR BIT DATA
+            null,   // NUMERIC
+            null,   // REAL
+            null,   // SMALLINT
+            null,   // TIME
+            null,   // TIMESTAMP
+            null,   // VARCHAR
+            null,   // VARCHAR FOR BIT DATA
+        },
+    };
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // INNER CLASSES
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // STATE
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTRUCTORS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    public TableFunctionTest
+        (
+         String name
+        )
+    {
+         super( name );
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // JUnit MACHINERY
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Tests to run.
+     */
+    public static Test suite()
+    {
+        TestSuite       suite = new TestSuite( "TableFunctionTest" );
+
+        suite.addTest( new TableFunctionTest( "testTableFunctions" ) );
+
+        return suite;
+    }
+    
+    protected void    setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        dropSchema();
+    }
+
+    protected void    tearDown()
+        throws Exception
+    {
+        dropSchema();
+
+        super.tearDown();
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // JUnit TESTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Verify table functions.
+     */
+    public void testTableFunctions()
+        throws Exception
+    {
+        badDDL();
+        simpleDDL();
+
+        notTableFunction();
+        simpleVTIResults();
+        allLegalDatatypesVTIResults();
+    }
+    
+    /**
+     * Verify bad DDL.
+     */
+    private void badDDL()
+        throws Exception
+    {
+        //
+        // Only table functions can have parameter style DERBY_JDBC_RESULT_SET
+        //
+        expectError
+            (
+             "42ZB1",
+             "create function badParameterStyle()\n" +
+             "returns varchar(10)\n" +
+             "language java\n" +
+             "parameter style DERBY_JDBC_RESULT_SET\n" +
+             "no sql\n" +
+             "external name 'com.scores.proc.Functions.weighQuestion'\n"
+             );
+
+        //
+        // Procedures can not have parameter style DERBY_JDBC_RESULT_SET
+        //
+        expectError
+            (
+             "42ZB1",
+             "create procedure badParameterStyle\n" +
+             "( in takingID int )\n" +
+             "language java\n" +
+             "parameter style DERBY_JDBC_RESULT_SET\n" +
+             "modifies sql data\n" +
+             "external name 'com.scores.proc.Procedures.ScoreTestTaking'\n"
+             );
+
+        //
+        // Table functions must have parameter style DERBY_JDBC_RESULT_SET
+        //
+        expectError
+            (
+             "42ZB2",
+             "create function badParameterStyleForTableFunction()\n" +
+             "returns TABLE\n" +
+             "  (\n" +
+             "     intCol int,\n" +
+             "     varcharCol varchar( 10 )\n" +
+             "  )\n" +
+             "language java\n" +
+             "parameter style java\n" +
+             "no sql\n" +
+             "external name 'com.scores.proc.Functions.weighQuestion'\n"
+             );
+
+        //
+        // XML column types not allowed in table functions.
+        //
+        expectError
+            (
+             "42ZB3",
+             "create function xmlForbiddenInReturnedColumns()\n" +
+             "returns TABLE\n" +
+             "  (\n" +
+             "     intCol int,\n" +
+             "     xmlCol xml\n" +
+             "  )\n" +
+             "language java\n" +
+             "parameter style DERBY_JDBC_RESULT_SET\n" +
+             "no sql\n" +
+             "external name 'com.scores.proc.Functions.weighQuestion'\n"
+             );
+    }
+    
+    /**
+     * Verify simple good DDL.
+     */
+    private void simpleDDL()
+        throws Exception
+    {
+        goodDDL
+            (
+             "create function simpleFunctionTable()\n" +
+             "returns TABLE\n" +
+             "  (\n" +
+             "     intCol int,\n" +
+             "     varcharCol varchar( 10 )\n" +
+             "  )\n" +
+             "language java\n" +
+             "parameter style DERBY_JDBC_RESULT_SET\n" +
+             "no sql\n" +
+             "external name 'com.scores.proc.Functions.weighQuestion'\n"
+             );
+
+        verifyReturnType
+            (
+             "SIMPLEFUNCTIONTABLE",
+             "weighQuestion() " +
+             "RETURNS ROW ( INTCOL INTEGER, VARCHARCOL VARCHAR(10) ) MULTISET " +
+             "LANGUAGE JAVA PARAMETER STYLE DERBY_JDBC_RESULT_SET NO SQL CALLED ON NULL INPUT"
+             );
+    }
+    
+    /**
+     * Verify that you can't invoke an ordinary function as a VTI.
+     */
+    private void notTableFunction()
+        throws Exception
+    {
+        goodDDL
+            (
+             "create function invert( intValue int )\n" +
+             "returns int\n" +
+             "language java\n" +
+             "parameter style java\n" +
+             "no sql\n" +
+             "external name '" + getClass().getName() + ".invert'\n"
+             );
+
+        //
+        // Can't invoke a simple function as a table function.
+        //
+        expectError
+            (
+             "42ZB4",
+             "select s.*\n" +
+             "    from TABLE( invert( 1 ) ) s\n"
+             );
+    }
+    
+    /**
+     * Verify that a simple VTI returns the correct results.
+     */
+    private void  simpleVTIResults()
+        throws Exception
+    {
+        goodDDL
+            (
+             "create function returnsACoupleRows()\n" +
+             "returns TABLE\n" +
+             "  (\n" +
+             "     column0 varchar( 10 ),\n" +
+             "     column1 varchar( 10 )\n" +
+             "  )\n" +
+             "language java\n" +
+             "parameter style DERBY_JDBC_RESULT_SET\n" +
+             "no sql\n" +
+             "external name '" + getClass().getName() + ".returnsACoupleRows'\n"
+             );
+
+        assertResults
+            (
+             "select s.*\n" +
+             "    from TABLE( returnsACoupleRows() ) s\n",
+             SIMPLE_ROWS,
+             new int[] { Types.VARCHAR, Types.VARCHAR }
+             );
+    }
+    
+    /**
+     * Verify that Derby handles VTI columns of all known datatypes.
+     */
+    private void  allLegalDatatypesVTIResults()
+        throws Exception
+    {
+        goodDDL
+            (
+             "create function returnsAllLegalDatatypes()\n" +
+             "returns TABLE\n" +
+             "  (\n" +
+             "column0 BIGINT,\n" +
+             "column1 BLOB,\n" +
+             "column2 CHAR( 10 ),\n" +
+             "column3 CHAR( 10 ) FOR BIT DATA,\n" +
+             "column4 CLOB,\n" +
+             "column5 DATE,\n" +
+             "column6 DECIMAL,\n" +
+             "column7 DOUBLE,\n" +
+             "column8 DOUBLE PRECISION,\n" +
+             "column9 FLOAT( 23 ),\n" +
+             "column10 FLOAT( 24 ),\n" +
+             "column11 INTEGER,\n" +
+             "column12 LONG VARCHAR,\n" +
+             "column13 LONG VARCHAR FOR BIT DATA,\n" +
+             "column14 NUMERIC,\n" +
+             "column15 REAL,\n" +
+             "column16 SMALLINT,\n" +
+             "column17 TIME,\n" +
+             "column18 TIMESTAMP,\n" +
+             "column19 VARCHAR( 10 ),\n" +
+             "column20 VARCHAR( 10 ) FOR BIT DATA\n" +
+             "  )\n" +
+             "language java\n" +
+             "parameter style DERBY_JDBC_RESULT_SET\n" +
+             "no sql\n" +
+             "external name '" + getClass().getName() + ".returnsAllLegalDatatypes'\n"
+             );
+
+        assertResults
+            (
+             "select s.*\n" +
+             "    from TABLE( returnsAllLegalDatatypes() ) s\n",
+             ALL_TYPES_ROWS,
+             new int[]
+                {
+                    Types.BIGINT,
+                    Types.BLOB,
+                    Types.CHAR,
+                    Types.BINARY,
+                    Types.CLOB,
+                    Types.DATE,
+                    Types.DECIMAL,
+                    Types.DOUBLE,
+                    Types.DOUBLE,
+                    Types.REAL,
+                    Types.DOUBLE,
+                    Types.INTEGER,
+                    Types.LONGVARCHAR,
+                    Types.LONGVARBINARY,
+                    Types.NUMERIC,
+                    Types.REAL,
+                    Types.SMALLINT,
+                    Types.TIME,
+                    Types.TIMESTAMP,
+                    Types.VARCHAR,
+                    Types.VARBINARY,
+                }
+             );
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // Derby FUNCTIONS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Just a simple function which is not a VTI.
+     */
+    public  static  int invert( int value )
+    {
+        return -value;
+    }
+    
+    /**
+     * A VTI which returns a couple rows.
+     */
+    public  static  ResultSet returnsACoupleRows()
+    {
+        return makeVTI( SIMPLE_ROWS );
+    }
+
+    /**
+     * A VTI which returns rows having columns of all legal datatypes.
+     */
+    public  static  ResultSet returnsAllLegalDatatypes()
+    {
+        return makeVTI( ALL_TYPES_ROWS );
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // MINIONS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Assert that the ResultSet returns the desired rows.
+     */
+    public void assertResults( String sql, String[][] rows, int[] expectedJdbcTypes )
+        throws Exception
+    {
+        println( "\nExpecting good results from " + sql );
+
+        String[]    columnNames = makeColumnNames( rows[ 0 ].length, "COLUMN" );
+
+        try {
+            PreparedStatement    ps = prepareStatement( sql );
+            ResultSet                   rs = ps.executeQuery();
+
+            assertResults( expectedJdbcTypes, columnNames, rs, rows );
+            
+            rs.close();
+            ps.close();
+        }
+        catch (Exception e)
+        {
+            unexpectedThrowable( e );
+        }
+    }
+
+    /**
+     * Assert that the statement text, when compiled, raises an exception
+     */
+    private void    expectError( String sqlState, String query )
+    {
+        println( "\nExpecting " + sqlState + " when preparing:\n\t" + query );
+
+        assertCompileError( sqlState, query );
+    }
+
+    /**
+     * Run good DDL.
+     */
+    private void    goodDDL( String ddl )
+    {
+        println( "Running good DDL:\n\t" + ddl );
+        
+        try {
+            PreparedStatement    ps = prepareStatement( ddl );
+
+            ps.execute();
+            ps.close();
+        }
+        catch (Exception e)
+        {
+            unexpectedThrowable( e );
+        }
+    }
+    
+    /**
+     * Verify that the return type of function looks good.
+     */
+    private void    verifyReturnType( String functionName, String expectedReturnType )
+    {
+        println( functionName + " should have return type = " + expectedReturnType );
+        
+        try {
+            String                          ddl = "select aliasinfo from sys.sysaliases where
alias=?";
+            PreparedStatement    ps = prepareStatement( ddl );
+
+            ps.setString( 1, functionName );
+            
+            ResultSet                   rs = ps.executeQuery();
+
+            rs.next();
+
+            String                          actualReturnType = rs.getString( 1 );
+
+            assertTrue( expectedReturnType.equals( actualReturnType ) );
+            
+            rs.close();
+            ps.close();
+        }
+        catch (Exception e)
+        {
+            unexpectedThrowable( e );
+        }
+    }
+
+    /**
+     * Drop the schema that we are going to use so that we can recreate it.
+     */
+    private void    dropSchema()
+        throws Exception
+    {
+        int count = FUNCTION_NAMES.length;
+
+        for ( int i = 0; i < count; i++ ) { dropFunction( FUNCTION_NAMES[ i ] ); }
+    }
+    
+    /**
+     * Drop a function so that we can recreate it.
+     */
+    private void    dropFunction( String functionName )
+        throws Exception
+    {
+        // swallow the "object doesn't exist" diagnostic
+        try {
+            PreparedStatement   ps = prepareStatement( "drop function " + functionName );
+
+            ps.execute();
+            ps.close();
+        }
+        catch( SQLException se) {}
+    }
+
+    /**
+     * Assert that the ResultSet returns the desired rows.
+     */
+    private void assertResults( int[] expectedJdbcTypes, String[] columnNames, ResultSet
rs, String[][] rows )
+        throws Exception
+    {
+        int     rowCount = rows.length;
+        int[]   actualJdbcTypes = getJdbcColumnTypes( rs );
+
+        compareJdbcTypes( expectedJdbcTypes, actualJdbcTypes );
+        compareColumnNames( columnNames, rs );
+
+        for ( int i = 0; i < rowCount; i++ )
+        {
+            String[]    row = rows[ i ];
+            int             columnCount = row.length;
+
+            assertTrue( rs.next() );
+
+            for ( int j = 0; j < columnCount; j++ )
+            {
+                String  columnName = columnNames[ j ];
+                String  expectedValue =  row[ j ];
+                String  actualValue = null;
+                String  actualValueByName = null;
+                int         column = j+1;
+                int         actualJdbcType = actualJdbcTypes[ j ]; 
+
+                switch( actualJdbcType )
+                {
+                case Types.BOOLEAN:
+                    actualValue = new Boolean( rs.getBoolean( column ) ).toString();
+                    actualValueByName = new Boolean( rs.getBoolean( columnName ) ).toString();
+                    if ( rs.wasNull() ) { actualValue = actualValueByName = null; }
+                    break;
+
+                case Types.BIGINT:
+                    actualValue = new Long( rs.getLong( column ) ).toString();
+                    actualValueByName = new Long( rs.getLong( columnName ) ).toString();
+                    if ( rs.wasNull() ) { actualValue = actualValueByName = null; }
+                    break;
+                case Types.INTEGER:
+                    actualValue = new Integer( rs.getInt( column ) ).toString();
+                    actualValueByName = new Integer( rs.getInt( columnName ) ).toString();
+                    if ( rs.wasNull() ) { actualValue = actualValueByName = null; }
+                    break;
+                case Types.SMALLINT:
+                    actualValue = new Short( rs.getShort( column ) ).toString();
+                    actualValueByName = new Short( rs.getShort( columnName ) ).toString();
+                    if ( rs.wasNull() ) { actualValue = actualValueByName = null; }
+                    break;
+                case Types.TINYINT:
+                    actualValue = new Byte( rs.getByte( column ) ).toString();
+                    actualValueByName = new Byte( rs.getByte( columnName ) ).toString();
+                    if ( rs.wasNull() ) { actualValue = actualValueByName = null; }
+                    break;
+ 
+                case Types.DOUBLE:
+                    actualValue = new Double( rs.getDouble( column ) ).toString();
+                    actualValueByName = new Double( rs.getDouble( columnName ) ).toString();
+                    if ( rs.wasNull() ) { actualValue = actualValueByName = null; }
+                    break;
+                case Types.REAL:
+                case Types.FLOAT:
+                    actualValue = new Float( rs.getFloat( column ) ).toString();
+                    actualValueByName = new Float( rs.getFloat( columnName ) ).toString();
+                    if ( rs.wasNull() ) { actualValue = actualValueByName = null; }
+                    break;
+
+                case Types.DECIMAL:
+                case Types.NUMERIC:
+                    actualValue = squeezeString(  rs.getBigDecimal( column ) );
+                    actualValueByName = squeezeString(  rs.getBigDecimal( columnName ) );
+                    break;
+
+                case Types.DATE:
+                    actualValue = squeezeString(  rs.getDate( column ) );
+                    actualValueByName = squeezeString(  rs.getDate( columnName ) );
+                    break;
+                case Types.TIME:
+                    actualValue = squeezeString(  rs.getTime( column ) );
+                    actualValueByName = squeezeString(  rs.getTime( columnName ) );
+                    break;
+                case Types.TIMESTAMP:
+                    actualValue = squeezeString(  rs.getTimestamp( column ) );
+                    actualValueByName = squeezeString(  rs.getTimestamp( columnName ) );
+                    break;
+
+                case Types.BLOB:
+                    actualValue = squeezeString(  rs.getBlob( column ) );
+                    actualValueByName = squeezeString(  rs.getBlob( columnName ) );
+                    break;
+                case Types.CLOB:
+                    actualValue = squeezeString(  rs.getClob( column ) );
+                    actualValueByName = squeezeString(  rs.getClob( columnName ) );
+                    break;
+
+                case Types.BINARY:
+                case Types.VARBINARY:
+                case Types.LONGVARBINARY:
+                    actualValue = squeezeString(  rs.getBytes( column ) );
+                    actualValueByName = squeezeString(  rs.getBytes( columnName ) );
+                    break;
+
+                case Types.JAVA_OBJECT:
+                    actualValue = squeezeString(  rs.getObject( column ) );
+                    actualValueByName = squeezeString(  rs.getObject( columnName ) );
+                    break;
+                    
+                case Types.CHAR:
+                case Types.LONGVARCHAR:
+                case Types.VARCHAR:
+                    actualValue = rs.getString( column );
+                    actualValueByName = rs.getString( columnName );
+                    break;
+                    
+                default:
+                    fail( "Can't handle jdbc type " + actualJdbcType );
+                }
+
+                println( "Comparing " + expectedValue + " to " + actualValue + " and " +
actualValueByName );
+
+                if ( actualValue == null ) { assertNull( actualValueByName ); }
+                else { assertTrue( actualValue.equals( actualValueByName ) ); }
+                
+                assertEquals( (expectedValue == null), rs.wasNull() );
+                
+                if ( expectedValue == null )    { assertNull( actualValue ); }
+                else { assertTrue( expectedValue.equals( actualValue ) ); }
+            }
+        }
+
+        assertFalse( rs.next() );
+    }
+
+    /**
+     * Verify that we saw the jdbc types that we expected.
+     */
+    private void   compareJdbcTypes( int[] expected, int[] actual )
+        throws Exception
+    {
+        int     count = expected.length;
+
+        assertEquals( count, actual.length );
+
+        for ( int i = 0; i < count; i++ )
+        {
+            assertEquals( "Type at position " + i, expected[ i ], actual[ i ] );
+        }
+    }
+
+    /**
+     * Verify that we have the correct column names.
+     */
+    private void   compareColumnNames( String[] expectedNames, ResultSet rs )
+        throws Exception
+    {
+        ResultSetMetaData   rsmd = rs.getMetaData();
+        int                                 count = rsmd.getColumnCount();
+
+        println( "Expecting " + expectedNames.length + " columns." );
+        assertEquals( expectedNames.length, count );
+
+        for ( int i = 0; i < count; i++ )
+        {
+            assertEquals( expectedNames[ i ], rsmd.getColumnName( i+1 ) );
+        }
+   }
+
+    /**
+     * Get the datatypes of returned columns
+     */
+    private int[]   getJdbcColumnTypes( ResultSet rs )
+        throws Exception
+    {
+        ResultSetMetaData   rsmd = rs.getMetaData();
+        int                                 count = rsmd.getColumnCount();
+        int[]                           actualJdbcTypes = new int[ count ];
+
+        for ( int i = 0; i < count; i++ ) { actualJdbcTypes[ i ] = rsmd.getColumnType(
i + 1 ); }
+
+        return actualJdbcTypes;
+    }
+
+    /**
+     * Squeeze a string out of an object
+     */
+    private String  squeezeString( Object obj )
+        throws Exception
+    {
+        if ( obj == null ) { return null; }
+        else if ( obj instanceof Blob )
+        {
+            Blob    blob = (Blob) obj;
+
+            return new String( blob.getBytes( (long) 0, (int) blob.length() ) );
+        }
+        else if ( obj instanceof Clob )
+        {
+            Clob    clob = (Clob) obj;
+
+            return clob.getSubString( (long) 0, (int) clob.length() );
+        }
+        else if ( obj instanceof byte[] )
+        {
+            byte[]  bytes = (byte[]) obj;
+
+            return new String( bytes );
+        }
+        else { return obj.toString(); }
+    }
+
+    /**
+     * Fail the test for an unexpected exception
+     */
+    private void    unexpectedThrowable( Throwable t )
+    {
+        printStackTrace( t );
+        fail( "Unexpected exception: " + t );
+    }
+    
+    /**
+     * Make a VTI given its rows.
+     */
+    private static  StringArrayVTI    makeVTI( String[][] rows )
+    {
+        int         columnCount = rows[ 0 ].length;
+
+        return new StringArrayVTI( makeColumnNames( columnCount, "mycol" ), rows );
+    }
+    
+    /**
+     * Make column names.
+     */
+    private static  String[]    makeColumnNames( int columnCount, String stub )
+    {
+        String[]    names = new String[ columnCount ];
+
+        for ( int i = 0; i < columnCount; i++ ) { names[ i ] = stub + i; }
+
+        return names;
+    }
+    
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/TableFunctionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java?view=diff&rev=555032&r1=555031&r2=555032
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
Tue Jul 10 11:40:39 2007
@@ -111,6 +111,7 @@
         suite.addTest(CaseExpressionTest.suite());
         suite.addTest(CharUTF8Test.suite());
         suite.addTest(AggregateClassLoadingTest.suite());
+        suite.addTest(TableFunctionTest.suite());
 
         // Add the XML tests, which exist as a separate suite
         // so that users can "run all XML tests" easily.

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java?view=diff&rev=555032&r1=555031&r2=555032
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java Tue Jul
10 11:40:39 2007
@@ -148,6 +148,7 @@
     {
         while ( t!= null) {
             t.printStackTrace(out);
+            out.flush();
             
             if (t instanceof SQLException)  {
                 t = ((SQLException) t).getNextException();



Mime
View raw message