superwaba.ext.xplat.sql.db2e
Class Driver

java.lang.Object
  |
  +--superwaba.ext.xplat.sql.Driver
        |
        +--superwaba.ext.xplat.sql.db2e.Driver

public class Driver
extends Driver

There are currently no example apps ready to show how to use the DB2e WDBC driver. If you have experience with JDBC, then it should be fairly easy to get up to speed with DB2e on SW. Be sure to read this entire file for information regarding WDBC driver capabilities.

Here is a short code example that shows how to load the WDBC driver for DB2e:

try
{
Class.forName("superwaba.ext.xplat.sql.db2e.Driver");
}
catch(ClassNotFoundException cnfe)
{
// Code to handle if driver not found or unable to load...
}
Connect to the DB2e driver using a URL of the form:
wdbc:db2e:[regular db2e connection string]
DB2e currently connects only to the local database, so does not need any additional connection information (such as server, user, password, etc). For now, just use a dummy string for the [regular db2e connection string] portion. Here is example code that obtains a DB2e connection:
import superwaba.ext.xplat.sql.*;
import superwaba.ext.xplat.sql.db2e.*;

...

Connection connection = null;

try
{
connection = DriverManager.getConnection("wdbc:db2e:server");
}
catch(SQLException sqlError)
{
// Code to handle connection error...
}
These are just a few tips concerning Db2e WDBC driver:
1. To keep the driver as simple as possible, we had to impose a few limitations:
a. Access fields consistently in relation to the data type you use to retrieve the field's value. In other words, don't use "getString(...)" on a column and then "getInt(...)" on the same column. An exception will be thrown. This is because the driver caches the objects it uses to access the column so that it can minimize the creation of new instances while retrieving the value. This holds across rows too. If you use getString(...) on a column and then reposition the result set to a new row, you must still use getString(...) on the same column. In fact, this even goes across separate ResultSets returned from a prepared statement. If you re-execute the prepared statement, it will reuse the same column types, so you must still use the same access method you used before.
b. This is a DB2e limitation: you can have only one ResultSet per (Prepared)Statement.
c. Other DB2e limitations (as of V8.1): Max connections: 1. Max open (Prepared)Statements: 20. Max transactions: 1 (transaction is on a Connection basis).
d. To save space, we did not implement updatable ResultSets (CONCUR_UPDATABLE). You will have to manually update rows/data by using SQL: INSERT, UPDATE, DELETE, etc. DB2e does not provide any kind of "updatable" interface, so we would have had to implement it by dynamically building SQL statement anyway, which would have just added more overhead to the whole process.
e. We have not implements ResultSets that can fetch row sets. We fetch one row at a time from Db2e.
f. We have not implemented FETCH_REVERSE, to save having to check a "direction" flag everytime a "next()" is performed. If you need to go in reverse, do it manually using previous(), relative(), or absolute() (which are all implemented and fully functional).
g. To the best of our knowledge, DB2e supports only TYPE_FORWARD_ONLY and TYPE_SCROLL_SENSITIVE.
h. To the best of our knowledge, DB2e is TRANSACTION_READ_COMMITTED only.
i. We have not implemented any of the DatabaseMetaData methods that would return a "ResultSet". If you need any of this information, you currently have to query it manually using SQL tailored specifically for DB2e's system table structure.
j. The content of the data within a Blob instance returned from getBlob(...) is temporary! This means that it will not survive a call to any of the position methods (next, previous, relative, absolute). When you call a position method, it will overwrite the Blob byte buffer with new data. This is because the driver reuses the exact same Blob instance for that column throughout the life of a Statement to minimize object creation. If you want to keep the data around, you will have to manually copy it out of the Blob byte[] buffer (Vm.copyArray, anyone?).
k. We don't attempt data type conversion. We let DB2e handle that for us. So if you are trying to getX(...) on a field that isn't X, then it will work so long as DB2e will automatically convert to that type for you. Oh, and once you call getX(...) on a field that isn't X, you must always call getX(...) and cannot use any other get*(...) methods on that field.
l. There is no Long data type in this implementation. getLong(...) is currently implemented as 'return (long)getInt(...)'
m. We have not yet implemented float or double types!! I know this is important to some people, but we didn't need it and didn't spend the time to implement it... maybe someone could volunteer?
n. We have not implemented getObject yet. It will throw an exception. Would you like to volunteer?

2. Tips for optimizing your usage of the DB2e WDBC driver:
a. Believe it or not, getBlob(...) is much more effecient than getBytes(...). This is because getBytes() must allocate a new byte[] array every time it is called, while getBlob(...) can reuse the same Blob instance for a particular column. getBytes() just calls getBlob() and returns a copy of the byte array.
b. A SuperWaba only method (not found in the JDBC Blob interface) is Blob.getByteBuffer(). This was added because it can be made so much more effecient than Blob.getBytes(long pos, int length) in certain scenarios. The DB2e driver allocates a byte[] buffer large enough to hold the largest Blob when a Blob column is first accessed. This buffer is returned when you call getByteBuffer, which is more effecient because a new byte[] array instance does not need to be created, and also means that the buffer could actually be larger than the Blob data for this row, so you must be careful to read only Blob.length() bytes from the buffer.
c. Try to avoid using the getX(String columnName) methods, as they impose a relatively heavy hit to look up the column name and then call their getX(int columnIndex) brother.
d. We have tried to optimize PreparedStatement so that you take a light hit when you reexecute the statement. Basically, the ResultSet instance is reused, avoiding an object allocation and allows the query information to be cached (such as column info and types).
e. Same for ResultSetMetaData.
f. Take advantage of setMaxFieldSize() when you can. It will save memory and CPU cycles if your max size is less than the sizes of your fields.
g. Use common sense. Reuse as much as possible. We try to stick by this in our code (though we aren't perfect).
h. getLong() is currently implemented as 'return (long)getInt(...)'. But don't worry, because ints in SW are 32-bit, so getInt actually uses DB2e's notion of LONG.
i. We have not yet optimized Time/Date/Timestamp functions for reuse, so a new Time/Date/Timestamp instance will be created every time a 'get' method is called for one of these.
j. We have not implemented getRef. This may be pulled from SW anyway.
k. getInt(...) is faster than getShort() and getLong().
l. Try to call getString(...) just once per column per row, for you shall pay the penalty of a new String instance every time you call.


Constructor Summary
Driver()
           
 
Method Summary
 boolean acceptsURL(String url)
          This method tests whether or not the driver believes it can connect to the specified database.
protected  void checkEnvironment()
           
 Connection connect(String url, Hashtable info)
          This method connects to the specified database using the connection properties supplied.
 int getMajorVersion()
          This method returns the major version number of the driver.
 int getMinorVersion()
          This method returns the minor version number of the driver.
 DriverPropertyInfo[] getPropertyInfo(String url, Hashtable properties)
          This method returns an array of possible properties that could be used to connect to the specified database.
 boolean jdbcCompliant()
          This method tests whether or not the driver is JDBC compliant.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, toString, wait, wait
 

Constructor Detail

Driver

public Driver()
Method Detail

acceptsURL

public boolean acceptsURL(String url)
                   throws SQLException
This method tests whether or not the driver believes it can connect to the specified database. The driver should only test whether it understands and accepts the URL. It should not necessarily attempt to probe the database for a connection.
Overrides:
acceptsURL in class Driver
Parameters:
The - database URL string.
Returns:
true if the drivers can connect to the database, false otherwise.
Throws:
SQLException - If an error occurs.

connect

public Connection connect(String url,
                          Hashtable info)
                   throws SQLException
This method connects to the specified database using the connection properties supplied. If the driver does not understand the database URL, it should return null instead of throwing an exception since the DriverManager will probe a driver in this manner.
Overrides:
connect in class Driver
Parameters:
url - The URL string for this connection.
properties - The list of database connection properties.
Returns:
A Connection object for the newly established connection, or null if the URL is not understood.
Throws:
SQLException - If an error occurs.

checkEnvironment

protected void checkEnvironment()
                         throws SQLException

getMajorVersion

public int getMajorVersion()
This method returns the major version number of the driver.
Overrides:
getMajorVersion in class Driver
Returns:
The major version number of the driver.

getMinorVersion

public int getMinorVersion()
This method returns the minor version number of the driver.
Overrides:
getMinorVersion in class Driver
Returns:
The minor version number of the driver.

getPropertyInfo

public DriverPropertyInfo[] getPropertyInfo(String url,
                                            Hashtable properties)
                                     throws SQLException
This method returns an array of possible properties that could be used to connect to the specified database.
Overrides:
getPropertyInfo in class Driver
Parameters:
url - The URL string of the database to connect to.
properties - The list of properties the caller is planning to use to connect to the database.
Returns:
A list of possible additional properties for a connection to this database. This list may be empty.
Throws:
SQLException - If an error occurs.

jdbcCompliant

public boolean jdbcCompliant()
This method tests whether or not the driver is JDBC compliant. This method should only return true if the driver has been certified as JDBC compliant.
Overrides:
jdbcCompliant in class Driver
Returns:
true if the driver has been certified JDBC compliant, false otherwise.