/*
* (C) Copyright IBM Corp. 2014
*
* LICENSE: Eclipse Public License v1.0
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.ibm.gaiandb.vti;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.store.access.Qualifier;
import org.apache.derby.iapi.types.DataValueDescriptor;
import org.apache.derby.iapi.types.SQLChar;
import org.apache.derby.iapi.types.SQLInteger;
import org.apache.derby.vti.IFastPath;
import org.apache.derby.vti.VTIEnvironment;
import com.ibm.db2j.AbstractVTI;
import com.ibm.db2j.PluralizableVTI;
import com.ibm.gaiandb.Logger;
/**
* This is a dummy VTI example with the following characteristics:
* - it *does not* make use of AbstractVTI's disk caching capabilities.
* - it can expose multiple different data sources via a single GaianDB data source wrapper, because their structures are homogeneous.
* -> Using a single wrapper makes configuration simpler to manage and reduces Java heap usage.
* -> To enable this, the class must implement interface PluralizableVTI and method getEndpointIDs() and the "PLURALIZED" option must be set for the data source wrapper
* -> Optionally, the class may implement the method PluralizableVTI.getEndpointConstantColumns() to allow GaianDB to perform predicate/policy filtering early
*
* @author DavidVyvyan
*/
public class SamplePluralizedVTI extends AbstractVTI implements PluralizableVTI {
// Use PROPRIETARY notice if class contains a main() method, otherwise use COPYRIGHT notice.
public static final String COPYRIGHT_NOTICE = "(c) Copyright IBM Corp. 2014";
private static final Logger logger = new Logger( "SamplePluralizedVTI", 30 );
private int usrCPU, sysCPU = 5;
private String dsIP;
private int agentID;
private final String DS_IP1 = "1.1.1.1", DS_IP2 = "2.2.2.2";
private final int AGENT_ID1 = 1, AGENT_ID2 = 7;
private final Map<String, DataValueDescriptor[]> endpointConstants = new HashMap<String, DataValueDescriptor[]>();
// The default value below will show up if the getEndpointIDs() method is not called by GaianDB (if PLURALIZED option is not set).
private String endpointID = "UNSET_ENDPOINT_ID:0";
private int rowCount = 0;
public SamplePluralizedVTI(String vtiArgs) throws Exception {
super(vtiArgs, "SamplePluralizedVTI");
endpointConstants.put( DS_IP1+':'+AGENT_ID1, new DataValueDescriptor[] { new SQLChar(DS_IP1), new SQLInteger(AGENT_ID1) } );
endpointConstants.put( DS_IP2+':'+AGENT_ID2, new DataValueDescriptor[] { new SQLChar(DS_IP2), new SQLInteger(AGENT_ID2) } );
}
// The end-point instance ID is passed as first argument of the String[] in this method
@Override public void setArgs(String[] args) throws Exception {
logger.logInfo("Entered setArgs(), args are: " + Arrays.asList(args) );
if ( null != args && 0 < args.length ) { if ( null != args[0] ) endpointID = args[0]; } // only interested in args[0]
};
// Compute result in this method
@Override public boolean executeAsFastPath() throws StandardException, SQLException {
int indexOfColon = null == endpointID ? -1 : endpointID.indexOf(':');
dsIP = -1 == indexOfColon ? endpointID : endpointID.substring(0, indexOfColon);
agentID = -1 == indexOfColon ? -1 : Integer.parseInt( endpointID.substring(indexOfColon+1) );
usrCPU = agentID * 10;
return true;
}
// GaianDB extract rows by calling this method repeatedly
@Override public int nextRow(DataValueDescriptor[] arg0) throws StandardException, SQLException {
logger.logDetail("Entered nextRow(), rowCount = " + rowCount + (4 < rowCount ? ", returning SCAN_COMPLETED" : ", getting row") );
if ( 4 < rowCount ) return IFastPath.SCAN_COMPLETED;
arg0[0] = new SQLInteger( usrCPU++ );
arg0[1] = new SQLInteger( sysCPU );
arg0[2] = new SQLChar("Non-rectified IP"); //new SQLChar( dsIP ); <= this value is meant to be a constant endpoint value, so GaianDB should rectify it anyway
arg0[3] = new SQLInteger( null ); //new SQLInteger( agentID ); // <= this value is meant to be a constant endpoint value, so GaianDB should rectify it anyway
rowCount++;
return IFastPath.GOT_ROW;
}
// PluralizableVTI methods - used to re-factor/generalise/simplify data source wrapper configurations
// Note each endpointID will appear as a suffix in the GDB_LEAF column when querying the logical table augmented with the provenance columns.
@Override public Set<String> getEndpointIDs() { return endpointConstants.keySet(); }
@Override public DataValueDescriptor[] getEndpointConstants(String endpointID) { return endpointConstants.get( endpointID ); }
// Qualifyable interface - used to process predicates against our columns -
// Note that predicates on our *constant* columns (e.g. for each pluralizable instance) should ideally be processed above by GaianDB (if we passed
// the constant instances up with getEndpointConstantColumns()) - however it does little harm to test/filter them again here just in case.
@Override public void setQualifiers(VTIEnvironment vtie, Qualifier[][] qual) throws SQLException { }
@Override public int getRowCount() throws Exception { return rowCount; }
// Empty local heap resources for this instance and set them to null if possible
@Override public void close() throws SQLException { super.close(); endpointConstants.clear(); }
// VTICosting methods - used for JOIN optimisations
@Override public double getEstimatedCostPerInstantiation(VTIEnvironment arg0) throws SQLException { return 0; }
@Override public double getEstimatedRowCount(VTIEnvironment arg0) throws SQLException { return 0; }
@Override public boolean supportsMultipleInstantiations(VTIEnvironment arg0) throws SQLException { return false; }
@Override public boolean isBeforeFirst() throws SQLException { return 0 == rowCount; }
}