Update of /cvsroot/jython/jython/com/ziclix/python/sql/handler In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql/handler Added Files: MySQLDataHandler.java OracleDataHandler.java UpdateCountDataHandler.java InformixDataHandler.java PostgresqlDataHandler.java Log Message: initial zxJDBC checkin --- NEW FILE: MySQLDataHandler.java --- /* * Jython Database Specification API 2.0 * * $Id: MySQLDataHandler.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.handler; import java.io.*; import java.sql.*; import org.python.core.*; import com.ziclix.python.sql.*; /** * MySQL specific data handling. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class MySQLDataHandler extends FilterDataHandler { /** Field lastInsertId */ public long lastInsertId; /** * Decorator for handling MySql specific issues. * * @param datahandler the delegate DataHandler */ public MySQLDataHandler(DataHandler datahandler) { super(datahandler); this.lastInsertId = 0; } /** * Captures the last inserted id. */ public void postExecute(Statement stmt) throws SQLException { if (stmt instanceof org.gjt.mm.mysql.Statement) { lastInsertId = ((org.gjt.mm.mysql.Statement)stmt).getLastInsertID(); } super.postExecute(stmt); } /** * Handle LONGVARCHAR. */ public void setJDBCObject(PreparedStatement stmt, int index, PyObject object, int type) throws SQLException { if (DataHandler.checkNull(stmt, index, object, type)) { return; } switch (type) { case Types.LONGVARCHAR : if (object instanceof PyFile) { object = ((PyFile)object).read(); } String varchar = (String)object.__tojava__(String.class); InputStream stream = new ByteArrayInputStream(varchar.getBytes()); stream = new BufferedInputStream(stream); stmt.setAsciiStream(index, stream, varchar.length()); break; default : super.setJDBCObject(stmt, index, object, type); break; } } } --- NEW FILE: OracleDataHandler.java --- /* * Jython Database Specification API 2.0 * * $Id: OracleDataHandler.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.handler; import java.io.*; import java.sql.*; import org.python.core.*; import oracle.sql.*; import oracle.jdbc.driver.*; import com.ziclix.python.sql.*; /** * Oracle specific data handling. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class OracleDataHandler extends FilterDataHandler { /** * Default constructor for DataHandler filtering. */ public OracleDataHandler(DataHandler datahandler) { super(datahandler); } /** * Provide functionality for Oracle specific types, such as ROWID. */ public void setJDBCObject(PreparedStatement stmt, int index, PyObject object, int type) throws SQLException { if (DataHandler.checkNull(stmt, index, object, type)) { return; } switch (type) { case OracleTypes.ROWID : stmt.setString(index, (String)object.__tojava__(String.class)); break; case Types.NUMERIC : super.setJDBCObject(stmt, index, object, Types.DOUBLE); break; case Types.BLOB : case Types.CLOB : Integer[] vals = { new Integer(index), new Integer(type) }; String msg = zxJDBC.getString("errorSettingIndex", vals); throw new SQLException(msg); default : super.setJDBCObject(stmt, index, object, type); } } /** * Provide functionality for Oracle specific types, such as ROWID. */ public PyObject getPyObject(ResultSet set, int col, int type) throws SQLException { PyObject obj = Py.None; switch (type) { case Types.BLOB : BLOB blob = ((OracleResultSet)set).getBLOB(col); if (blob == null) { return Py.None; } InputStream stream = new BufferedInputStream(blob.getBinaryStream()); obj = Py.java2py(DataHandler.read(stream)); break; case OracleTypes.ROWID : ROWID rowid = ((OracleResultSet)set).getROWID(col); if (rowid != null) { obj = Py.java2py(rowid.stringValue()); } break; default : obj = super.getPyObject(set, col, type); } return (set.wasNull() ? Py.None : obj); } } --- NEW FILE: UpdateCountDataHandler.java --- /* * Jython Database Specification API 2.0 * * $Id: UpdateCountDataHandler.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.handler; import java.sql.*; import org.python.core.*; import com.ziclix.python.sql.*; /** * A data handler that keeps track of the update count for each execution of a * Statement. * * <p><b>Note:</b> MySql does not return the correct count for a * <a href="http://www.mysql.com/doc/D/E/DELETE.html">delete</a> statement that has * no <code>where</code> clause. Therefore, to assure the correct update count is returned, * either include a <code>where</code> clause, or understand that the value will always be * <code>0</code>.</p> * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ * @see java.sql.Statement#getUpdateCount() */ public class UpdateCountDataHandler extends FilterDataHandler { /** * The update count for the last executed statement. */ public int updateCount; /** * Handle capturing the update count. The initial value of the updateCount is * <code>-1</code>. * */ public UpdateCountDataHandler(DataHandler datahandler) { super(datahandler); this.updateCount = -1; } /** * Sets the update count to <code>-1</code> prior to the statement being executed. */ public void preExecute(Statement stmt) throws SQLException { super.preExecute(stmt); this.updateCount = -1; } /** * Gets the update count from the statement after successfully executing. */ public void postExecute(Statement stmt) throws SQLException { super.postExecute(stmt); this.updateCount = stmt.getUpdateCount(); } } --- NEW FILE: InformixDataHandler.java --- /* * Jython Database Specification API 2.0 * * $Id: InformixDataHandler.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.handler; import java.io.*; import java.sql.*; import java.math.*; import org.python.core.*; import com.ziclix.python.sql.*; /** * Informix specific data handling. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class InformixDataHandler extends FilterDataHandler { /** Field serial */ public int serial; /** * Decorator for handling Informix specific issues. * * @param datahandler the delegate DataHandler */ public InformixDataHandler(DataHandler datahandler) { super(datahandler); this.serial = 0; } /** * Sets the serial attribute to the last serial id. */ public void postExecute(Statement stmt) throws SQLException { if (stmt instanceof com.informix.jdbc.IfmxStatement) { serial = ((com.informix.jdbc.IfmxStatement)stmt).getSerial(); } super.postExecute(stmt); } /** * Provide fixes for Ifx driver. * * @param stmt * @param index * @param object * @param type * @throws SQLException */ public void setJDBCObject(PreparedStatement stmt, int index, PyObject object, int type) throws SQLException { if (DataHandler.checkNull(stmt, index, object, type)) { return; } switch (type) { case Types.LONGVARCHAR : // Ifx driver can't handle the setCharacterStream() method so use setObject() instead if (object instanceof PyFile) { object = ((PyFile)object).read(); } String varchar = (String)object.__tojava__(String.class); stmt.setObject(index, varchar, type); break; case Types.OTHER : // this is most likely an Informix boolean stmt.setBoolean(index, object.__nonzero__()); break; default : super.setJDBCObject(stmt, index, object, type); } } /** * Provide fixes for Ifx driver. * * @param stmt * @param index * @param object * @throws SQLException */ public void setJDBCObject(PreparedStatement stmt, int index, PyObject object) throws SQLException { // there is a bug in the Ifx driver when using setObject() with a String for a prepared statement if (object instanceof PyString) { super.setJDBCObject(stmt, index, object, Types.VARCHAR); } else { super.setJDBCObject(stmt, index, object); } } /** * Override to handle Informix related issues. * * @param set the result set * @param col the column number * @param type the SQL type * @return the mapped Python object * @throws SQLException thrown for a sql exception */ public PyObject getPyObject(ResultSet set, int col, int type) throws SQLException { PyObject obj = Py.None; switch (type) { case Types.OTHER : try { // informix returns boolean as OTHERs, so let's give that a try obj = set.getBoolean(col) ? Py.One : Py.Zero; } catch (SQLException e) { obj = super.getPyObject(set, col, type); } break; case Types.BLOB : int major = set.getStatement().getConnection().getMetaData().getDriverMajorVersion(); int minor = set.getStatement().getConnection().getMetaData().getDriverMinorVersion(); if ((major <= 2) && (minor <= 11)) { Blob blob = set.getBlob(col); if (blob == null) { obj = Py.None; } else { InputStream is = null; try { // the available() bug means we CANNOT buffer this stream is = blob.getBinaryStream(); obj = Py.java2py(DataHandler.read(is)); } finally { try { is.close(); } catch (Exception e) {} } } break; } default : obj = super.getPyObject(set, col, type); } return (set.wasNull() || (obj == null)) ? Py.None : obj; } } --- NEW FILE: PostgresqlDataHandler.java --- /* * Jython Database Specification API 2.0 * * $Id: PostgresqlDataHandler.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.handler; import java.sql.ResultSet; import java.sql.Types; import java.sql.SQLException; import java.sql.PreparedStatement; import java.math.BigDecimal; import org.python.core.*; import com.ziclix.python.sql.*; /** * Postgresql specific data handling. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class PostgresqlDataHandler extends FilterDataHandler { /** * Decorator for handling Postgresql specific issues. * * @param datahandler the delegate DataHandler */ public PostgresqlDataHandler(DataHandler datahandler) { super(datahandler); } /** * Override to handle Postgresql related issues. * * @param set the result set * @param col the column number * @param type the SQL type * @return the mapped Python object * @throws SQLException thrown for a sql exception */ public PyObject getPyObject(ResultSet set, int col, int type) throws SQLException { PyObject obj = Py.None; switch (type) { case Types.NUMERIC : case Types.DECIMAL : // in JDBC 2.0, use of a scale is deprecated // The big fix here is a problem with numeric types. It seems the ResultSet // tries to fix a JBuilder bug (as commented in the source) by including a // scale of 0. Well this blows up BigDecimal if the number is, say, 4.22. // It appears the workaround is to call the deprecated method with a scale of // -1 which forces the return of the BD without setting the scale. BigDecimal bd = set.getBigDecimal(col, -1); obj = (bd == null) ? Py.None : Py.newFloat(bd.doubleValue()); break; case Types.OTHER : // it seems pg doesn't like to handle OTHER types as anything but strings // but we'll try first anyways just to see what happens try { obj = super.getPyObject(set, col, type); } catch (SQLException e) { obj = super.getPyObject(set, col, Types.VARCHAR); } break; default : obj = super.getPyObject(set, col, type); } return (set.wasNull() || (obj == null)) ? Py.None : obj; } /** * Provide fixes for Postgresql driver. * * @param stmt * @param index * @param object * @param type * @throws SQLException */ public void setJDBCObject(PreparedStatement stmt, int index, PyObject object, int type) throws SQLException { if (DataHandler.checkNull(stmt, index, object, type)) { return; } switch (type) { case Types.LONGVARCHAR : // Postgresql driver can't handle the setCharacterStream() method so use setObject() instead if (object instanceof PyFile) { object = ((PyFile)object).read(); } String varchar = (String)object.__tojava__(String.class); stmt.setObject(index, varchar, type); break; default : super.setJDBCObject(stmt, index, object, type); } } } |