blob: ea5708f7c3b8afd50115b8f9c39fbcf8684621b1 [file] [log] [blame]
/*
Derby - Class org.apache.derbyTesting.functionTests.tests.lang.RestrictedTableVTI
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.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import org.apache.derby.vti.VTITemplate;
import org.apache.derby.vti.RestrictedVTI;
import org.apache.derby.vti.Restriction;
/**
* <p>
* This class contains a table function which can be used to read data
* from a Derby table.
* </p>
*/
public class RestrictedTableVTI extends VTITemplate implements RestrictedVTI
{
////////////////////////////////////////////////////////////////////////
//
// CONSTANTS
//
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
// STATE
//
////////////////////////////////////////////////////////////////////////
private String _schemaName;
private String _tableName;
private Connection _connection;
private String[] _columnNames;
private Restriction _restriction;
// this maps table function columns (0-based) to table column numbers (1-based) in
// the actual query
private int[] _columnNumberMap;
private PreparedStatement _preparedStatement;
private ResultSet _resultSet;
private static String _lastQuery;
////////////////////////////////////////////////////////////////////////
//
// CONSTRUCTOR
//
////////////////////////////////////////////////////////////////////////
protected RestrictedTableVTI
(
String schemaName,
String tableName
)
throws Exception
{
_schemaName = schemaName;
_tableName = tableName;
_connection = getDerbyConnection();
}
////////////////////////////////////////////////////////////////////////
//
// TABLE FUNCTIONS
//
////////////////////////////////////////////////////////////////////////
/**
* <p>
* Table function to read a table in Derby.
* </p>
*/
public static RestrictedTableVTI readTable
(
String schemaName,
String tableName
)
throws Exception
{
return new RestrictedTableVTI( schemaName, tableName );
}
/**
* <p>
* Scalar function to retrieve the last query generated by this machinery.
* </p>
*/
public static String getLastQuery() { return _lastQuery; }
////////////////////////////////////////////////////////////////////////
//
// ResultSet BEHAVIOR
//
////////////////////////////////////////////////////////////////////////
public void close() throws SQLException
{
if ( !isClosed() )
{
_schemaName = null;
_tableName = null;
_connection = null;
_columnNames = null;
_restriction = null;
_columnNumberMap = null;
if ( _resultSet != null ) { _resultSet.close(); }
if ( _preparedStatement != null ) { _preparedStatement.close(); }
_resultSet = null;
_preparedStatement = null;
}
}
public boolean next() throws SQLException
{
if ( !isClosed() && (_resultSet == null) )
{
_preparedStatement = prepareStatement( _connection, makeQuery() );
_resultSet = _preparedStatement.executeQuery();
}
return _resultSet.next();
}
public boolean isClosed() { return (_connection == null); }
public boolean wasNull() throws SQLException
{ return _resultSet.wasNull(); }
public ResultSetMetaData getMetaData() throws SQLException
{ return _resultSet.getMetaData(); }
public InputStream getAsciiStream(int i) throws SQLException
{ return _resultSet.getAsciiStream( mapColumnNumber( i ) ); }
public BigDecimal getBigDecimal(int i) throws SQLException
{ return _resultSet.getBigDecimal( mapColumnNumber( i ) ); }
@Deprecated
public BigDecimal getBigDecimal(int i, int scale) throws SQLException
{ return _resultSet.getBigDecimal( mapColumnNumber( i ), scale ); }
public InputStream getBinaryStream(int i) throws SQLException
{ return _resultSet.getBinaryStream( mapColumnNumber( i ) ); }
public Blob getBlob(int i) throws SQLException
{ return _resultSet.getBlob( mapColumnNumber( i ) ); }
public boolean getBoolean(int i) throws SQLException
{ return _resultSet.getBoolean( mapColumnNumber( i ) ); }
public byte getByte(int i) throws SQLException
{ return _resultSet.getByte( mapColumnNumber( i ) ); }
public byte[] getBytes(int i) throws SQLException
{ return _resultSet.getBytes( mapColumnNumber( i ) ); }
public Reader getCharacterStream(int i) throws SQLException
{ return _resultSet.getCharacterStream( mapColumnNumber( i ) ); }
public Clob getClob(int i) throws SQLException
{ return _resultSet.getClob( mapColumnNumber( i ) ); }
public Date getDate(int i) throws SQLException
{ return _resultSet.getDate( mapColumnNumber( i ) ); }
public Date getDate(int i, Calendar cal) throws SQLException
{ return _resultSet.getDate( mapColumnNumber( i ), cal ); }
public double getDouble(int i) throws SQLException
{ return _resultSet.getDouble( mapColumnNumber( i ) ); }
public float getFloat(int i) throws SQLException
{ return _resultSet.getFloat( mapColumnNumber( i ) ); }
public int getInt(int i) throws SQLException
{ return _resultSet.getInt( mapColumnNumber( i ) ); }
public long getLong(int i) throws SQLException
{ return _resultSet.getLong( mapColumnNumber( i ) ); }
public Object getObject(int i) throws SQLException
{ return _resultSet.getObject( mapColumnNumber( i ) ); }
public short getShort(int i) throws SQLException
{ return _resultSet.getShort( mapColumnNumber( i ) ); }
public String getString(int i) throws SQLException
{ return _resultSet.getString( mapColumnNumber( i ) ); }
public Time getTime(int i) throws SQLException
{ return _resultSet.getTime( mapColumnNumber( i ) ); }
public Time getTime(int i, Calendar cal) throws SQLException
{ return _resultSet.getTime( mapColumnNumber( i ), cal ); }
public Timestamp getTimestamp(int i) throws SQLException
{ return _resultSet.getTimestamp( mapColumnNumber( i ) ); }
public Timestamp getTimestamp(int i, Calendar cal) throws SQLException
{ return _resultSet.getTimestamp( mapColumnNumber( i ), cal ); }
////////////////////////////////////////////////////////////////////////
//
// RestrictedVTI BEHAVIOR
//
////////////////////////////////////////////////////////////////////////
public void initScan
( String[] columnNames, Restriction restriction )
throws SQLException
{
_columnNames = columnNames;
_restriction = restriction;
int columnCount = _columnNames.length;
_columnNumberMap = new int[ columnCount ];
int foreignColumnID = 1;
for ( int i = 0; i < columnCount; i++ )
{
if ( columnNames[ i ] != null ) { _columnNumberMap[ i ] = foreignColumnID++; }
}
}
////////////////////////////////////////////////////////////////////////
//
// Connection MANAGEMENT
//
////////////////////////////////////////////////////////////////////////
private static Connection getDerbyConnection() throws SQLException
{
return DriverManager.getConnection( "jdbc:default:connection" );
}
////////////////////////////////////////////////////////////////////////
//
// QUERY FACTORY
//
////////////////////////////////////////////////////////////////////////
/**
* <p>
* Build the query which will be sent to the nested connection.
* </p>
*/
private String makeQuery()
{
StringBuffer buffer = new StringBuffer();
buffer.append( "select " );
int possibleCount = _columnNames.length;
int actualCount = 0;
for ( int i = 0; i < possibleCount; i++ )
{
String rawName = _columnNames[ i ];
if ( rawName == null ) { continue; }
if ( actualCount > 0 ) { buffer.append( ", " ); }
actualCount++;
buffer.append( doubleQuote( rawName ) );
}
buffer.append( "\nfrom " );
buffer.append( doubleQuote( _schemaName ) );
buffer.append( '.' );
buffer.append( doubleQuote( _tableName ) );
if ( _restriction != null )
{
String clause = _restriction.toSQL();
if (clause != null)
{
clause = clause.trim();
if ( clause.length() != 0 )
{
buffer.append( "\nwhere " + clause );
}
}
}
_lastQuery = buffer.toString();
return _lastQuery;
}
private static String doubleQuote( String text ) { return '"' + text + '"'; }
private static String singleQuote( String text ) { return '\'' + text + '\''; }
private static PreparedStatement prepareStatement
( Connection conn, String text )
throws SQLException
{
return conn.prepareStatement( text );
}
////////////////////////////////////////////////////////////////////////
//
// UTILITY METHODS
//
////////////////////////////////////////////////////////////////////////
/**
* <p>
* Map a 1-based Derby column number to a 1-based column number in the
* query.
* </p>
*/
private int mapColumnNumber( int derbyNumber )
{
return _columnNumberMap[ derbyNumber - 1 ];
}
}