You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(107) |
Dec
(67) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(76) |
Feb
(125) |
Mar
(72) |
Apr
(13) |
May
(18) |
Jun
(12) |
Jul
(129) |
Aug
(47) |
Sep
(1) |
Oct
(36) |
Nov
(128) |
Dec
(124) |
2002 |
Jan
(59) |
Feb
|
Mar
(14) |
Apr
(14) |
May
(72) |
Jun
(9) |
Jul
(3) |
Aug
(5) |
Sep
(18) |
Oct
(65) |
Nov
(28) |
Dec
(12) |
2003 |
Jan
(10) |
Feb
(2) |
Mar
(4) |
Apr
(33) |
May
(21) |
Jun
(9) |
Jul
(29) |
Aug
(34) |
Sep
(4) |
Oct
(8) |
Nov
(15) |
Dec
(4) |
2004 |
Jan
(26) |
Feb
(12) |
Mar
(11) |
Apr
(9) |
May
(7) |
Jun
|
Jul
(5) |
Aug
|
Sep
(3) |
Oct
(7) |
Nov
(1) |
Dec
(10) |
2005 |
Jan
(2) |
Feb
(72) |
Mar
(16) |
Apr
(39) |
May
(48) |
Jun
(97) |
Jul
(57) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(100) |
Dec
(24) |
2006 |
Jan
(15) |
Feb
(34) |
Mar
(33) |
Apr
(31) |
May
(79) |
Jun
(64) |
Jul
(41) |
Aug
(64) |
Sep
(31) |
Oct
(46) |
Nov
(55) |
Dec
(37) |
2007 |
Jan
(32) |
Feb
(61) |
Mar
(11) |
Apr
(58) |
May
(46) |
Jun
(30) |
Jul
(94) |
Aug
(93) |
Sep
(86) |
Oct
(69) |
Nov
(125) |
Dec
(177) |
2008 |
Jan
(169) |
Feb
(97) |
Mar
(74) |
Apr
(113) |
May
(120) |
Jun
(334) |
Jul
(215) |
Aug
(237) |
Sep
(72) |
Oct
(189) |
Nov
(126) |
Dec
(160) |
2009 |
Jan
(180) |
Feb
(45) |
Mar
(98) |
Apr
(140) |
May
(151) |
Jun
(71) |
Jul
(107) |
Aug
(119) |
Sep
(73) |
Oct
(121) |
Nov
(14) |
Dec
(6) |
2010 |
Jan
(13) |
Feb
(9) |
Mar
(10) |
Apr
(64) |
May
(3) |
Jun
(16) |
Jul
(7) |
Aug
(23) |
Sep
(17) |
Oct
(37) |
Nov
(5) |
Dec
(8) |
2011 |
Jan
(10) |
Feb
(11) |
Mar
(77) |
Apr
(11) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: brian z. <bz...@us...> - 2001-11-20 04:55:21
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql Added Files: JDBC20DataHandler.java PyCursor.java PyConnection.java PyExtendedCursor.java zxJDBC.java DataHandler.java Fetch.java FilterDataHandler.java Log Message: initial zxJDBC checkin --- NEW FILE: JDBC20DataHandler.java --- /* * Jython Database Specification API 2.0 * * $Id: JDBC20DataHandler.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql; import java.io.*; import java.sql.*; import java.math.*; import org.python.core.*; /** * Support for JDBC 2.x type mappings, including Arrays, CLOBs and BLOBs. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class JDBC20DataHandler extends FilterDataHandler { /** * Handle JDBC 2.0 datatypes. * */ public JDBC20DataHandler(DataHandler datahandler) { super(datahandler); } /** * Handle CLOBs and BLOBs. * * @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.CLOB : if (object instanceof PyFile) { object = ((PyFile)object).read(); } String clob = (String)object.__tojava__(String.class); int length = clob.length(); InputStream stream = new ByteArrayInputStream(clob.getBytes()); stream = new BufferedInputStream(stream); stmt.setBinaryStream(index, stream, length); // Reader reader = new StringReader(clob); // reader = new BufferedReader(reader); // stmt.setCharacterStream(index, reader, length); break; case Types.BLOB : byte[] lob = null; Object jobject = null; if (object instanceof PyFile) { jobject = object.__tojava__(InputStream.class); } else { jobject = object.__tojava__(Object.class); } // it really is unfortunate that I need to send the length of the stream if (jobject instanceof InputStream) { lob = DataHandler.read(new BufferedInputStream((InputStream)jobject)); } else if (jobject instanceof byte[]) { lob = (byte[])jobject; } if (lob != null) { stmt.setBytes(index, lob); break; } default : super.setJDBCObject(stmt, index, object, type); break; } } /** * Get the object from the result set. * * @param set * @param col * @param type * @return a Python object * @throws SQLException */ 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 BigDecimal bd = set.getBigDecimal(col); obj = (bd == null) ? Py.None : Py.newFloat(bd.doubleValue()); break; case Types.CLOB : /* * It seems some drivers (well at least Informix) don't clean up after themselves * if the Clob is requested. The engine keeps a handle to an open table for each * row requested and cleans up fully only when the ResultSet or Connection is closed. * While this generally will never be noticed because the number of CLOBs or BLOBs * queried will likely be small in the event a large number are queried, it is a huge * problem. So, handle it as low as possible by managing the stream directly. I've * decided to leave this in the generic JDBC20 handler because it works for all engines * I've tested and seems to perform quite well to boot. */ Reader reader = null; try { InputStream stream = set.getBinaryStream(col); if (stream == null) { obj = Py.None; } else { reader = new InputStreamReader(stream); reader = new BufferedReader(reader); obj = Py.newString(DataHandler.read(reader)); } } finally { if (reader != null) { try { reader.close(); } catch (Exception e) {} } } break; case Types.BLOB : Blob blob = set.getBlob(col); if (blob == null) { obj = Py.None; } else { InputStream stream = null; try { stream = blob.getBinaryStream(); stream = new BufferedInputStream(stream); obj = Py.java2py(DataHandler.read(stream)); } finally { if (stream != null) { try { stream.close(); } catch (Exception e) {} } } } break; case Types.ARRAY : obj = Py.java2py(set.getArray(col).getArray()); break; default : return super.getPyObject(set, col, type); } return (set.wasNull() || (obj == null)) ? Py.None : obj; } } --- NEW FILE: PyCursor.java --- /* * Jython Database Specification API 2.0 * * $Id: PyCursor.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql; import java.io.*; import java.sql.*; import java.math.*; import java.util.*; import org.python.core.*; import com.ziclix.python.sql.util.*; /** * These objects represent a database cursor, which is used to manage the * context of a fetch operation. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class PyCursor extends PyObject implements ClassDictInit { /** Field fetch */ protected Fetch fetch; /** Field arraysize */ protected int arraysize; /** Field warnings */ protected PyObject warnings; /** Field dynamicFetch */ protected boolean dynamicFetch; /** Field connection */ protected Connection connection; /** Field datahandler */ protected DataHandler datahandler; /** Field sqlStatement */ protected PreparedStatement sqlStatement; // they are stateless instances, so we only need to instantiate it once private static DataHandler DATAHANDLER = null; // discern the correct datahandler static { DATAHANDLER = new DataHandler(); try { DATAHANDLER = new JDBC20DataHandler(DATAHANDLER); } catch (Exception e) {} } /** * Create the cursor with a static fetch. */ PyCursor(Connection connection) { this(connection, false); } /** * Create the cursor, optionally choosing the type of fetch (static or dynamic). * If dynamicFetch is true, then use a dynamic fetch. */ PyCursor(Connection connection, boolean dynamicFetch) { this.arraysize = 1; this.connection = connection; this.datahandler = DATAHANDLER; this.dynamicFetch = dynamicFetch; // constructs the appropriate Fetch among other things this.clear(); } /** Field __class__ */ public static PyClass __class__; /** * Method getPyClass * * @return PyClass * */ protected PyClass getPyClass() { return __class__; } /** Field __methods__ */ protected static PyList __methods__; /** Field __members__ */ protected static PyList __members__; static { PyObject[] m = new PyObject[7]; m[0] = new PyString("close"); m[1] = new PyString("execute"); m[2] = new PyString("executemany"); m[3] = new PyString("fetchone"); m[4] = new PyString("fetchall"); m[5] = new PyString("fetchmany"); m[6] = new PyString("callproc"); __methods__ = new PyList(m); m = new PyObject[5]; m[0] = new PyString("arraysize"); m[1] = new PyString("rowcount"); m[2] = new PyString("description"); m[3] = new PyString("datahandler"); m[4] = new PyString("warnings"); __members__ = new PyList(m); } /** * String representation of the object. * * @return a string representation of the object. */ public String toString() { return "<PyCursor object instance at " + hashCode() + ">"; } /** * Sets the attribute name to value. * * @param name * @param value */ public void __setattr__(String name, PyObject value) { if ("arraysize".equals(name)) { arraysize = ((PyInteger)value).getValue(); } else if ("datahandler".equals(name)) { this.datahandler = (DataHandler)value.__tojava__(DataHandler.class); } else { super.__setattr__(name, value); } } /** * Gets the value of the attribute name. * * @param name * @return the attribute for the given name */ public PyObject __findattr__(String name) { if ("arraysize".equals(name)) { return new PyInteger(arraysize); } else if ("__methods__".equals(name)) { return __methods__; } else if ("__members__".equals(name)) { return __members__; } else if ("description".equals(name)) { return this.fetch.getDescription(); } else if ("rowcount".equals(name)) { return new PyInteger(this.fetch.getRowCount()); } else if ("warnings".equals(name)) { return warnings; } else if ("datahandler".equals(name)) { return Py.java2py(this.datahandler); } else if ("dynamic".equals(name)) { return this.dynamicFetch ? Py.One : Py.Zero; } return super.__findattr__(name); } /** * Initializes the object's namespace. * * @param dict */ static public void classDictInit(PyObject dict) { dict.__setitem__("__version__", Py.newString("$Revision: 1.1 $").__getslice__(Py.newInteger(11), Py.newInteger(-2), null)); dict.__setitem__("fetchmany", new CursorFunc("fetchmany", 0, 1, 2, "fetch specified number of rows")); dict.__setitem__("close", new CursorFunc("close", 1, 1, "close the cursor")); dict.__setitem__("fetchall", new CursorFunc("fetchall", 2, 1, "fetch all results")); dict.__setitem__("fetchone", new CursorFunc("fetchone", 3, 1, "fetch the next result")); dict.__setitem__("nextset", new CursorFunc("nextset", 4, 1, "return next set or None")); dict.__setitem__("execute", new CursorFunc("execute", 5, 1, 4, "execute the sql expression")); dict.__setitem__("setinputsizes", new CursorFunc("setinputsizes", 6, 1, "not implemented")); dict.__setitem__("setoutputsize", new CursorFunc("setoutputsize", 7, 1, 2, "not implemented")); dict.__setitem__("callproc", new CursorFunc("callproc", 8, 1, 2, "executes a stored procedure")); dict.__setitem__("executemany", new CursorFunc("executemany", 9, 1, 3, "execute sql with the parameter list")); // hide from python dict.__setitem__("classDictInit", null); dict.__setitem__("toString", null); dict.__setitem__("connection", null); dict.__setitem__("getDataHandler", null); dict.__setitem__("addWarning", null); dict.__setitem__("fetch", null); dict.__setitem__("newFetch", null); dict.__setitem__("sqlStatement", null); dict.__setitem__("dynamicFetch", null); dict.__setitem__("getPyClass", null); } /** * Delete the cursor. * */ public void __del__() { close(); } /** * Close the cursor now (rather than whenever __del__ is called). * The cursor will be unusable from this point forward; an Error * (or subclass) exception will be raised if any operation is * attempted with the cursor. * */ public void close() { this.clear(); } /** * Return the currently bound DataHandler. */ public DataHandler getDataHandler() { return this.datahandler; } /** * Method newFetch * */ protected void newFetch() { if (this.dynamicFetch) { this.fetch = Fetch.newDynamicFetch(this); } else { this.fetch = Fetch.newStaticFetch(this); } } /** * Prepare a callable statement (stored procedure). * * @param sqlString * @throws SQLException */ protected void callableStatement(String sqlString) throws SQLException { this.sqlStatement = this.connection.prepareCall(sqlString); } /** * Prepare a statement ready for executing. * * @param sqlString * @param maxRows max number of rows to be returned * @throws SQLException */ protected void prepareStatement(String sqlString, PyObject maxRows) throws SQLException { int maxrows = 0; if (!maxRows.equals(Py.None)) { maxrows = ((Integer)maxRows.__tojava__(Integer.class)).intValue(); } this.sqlStatement = this.connection.prepareStatement(sqlString); this.sqlStatement.setMaxRows(maxrows); } /** * This method is optional since not all databases provide stored procedures. * * Call a stored database procedure with the given name. The sequence of parameters * must contain one entry for each argument that the procedure expects. The result of * the call is returned as modified copy of the input sequence. Input parameters are * left untouched, output and input/output parameters replaced with possibly new values. * * The procedure may also provide a result set as output. This must then be made available * through the standard fetchXXX() methods. */ public void callproc(String sqlString, PyObject params) { clear(); try { if (this.connection.getMetaData().supportsStoredProcedures()) { callableStatement(sqlString); execute(params, Py.None); } else { throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("noStoredProc")); } } catch (PyException e) { throw e; } catch (Exception e) { throw zxJDBC.newError(e); } } /** * Prepare a database operation (query or command) and then execute it against all * parameter sequences or mappings found in the sequence seq_of_parameters. * Modules are free to implement this method using multiple calls to the execute() * method or by using array operations to have the database process the sequence as * a whole in one call. * * The same comments as for execute() also apply accordingly to this method. * * Return values are not defined. */ public void executemany(String sqlString, PyObject params, PyObject bindings) { execute(sqlString, params, bindings, Py.Zero); } /** * Prepare and execute a database operation (query or command). * Parameters may be provided as sequence or mapping and will * be bound to variables in the operation. Variables are specified * in a database-specific notation (see the module's paramstyle * attribute for details). * * A reference to the operation will be retained by the cursor. * If the same operation object is passed in again, then the cursor * can optimize its behavior. This is most effective for algorithms * where the same operation is used, but different parameters are * bound to it (many times). * * For maximum efficiency when reusing an operation, it is best to * use the setinputsizes() method to specify the parameter types and * sizes ahead of time. It is legal for a parameter to not match the * predefined information; the implementation should compensate, possibly * with a loss of efficiency. * * The parameters may also be specified as list of tuples to e.g. insert * multiple rows in a single operation, but this kind of usage is * deprecated: executemany() should be used instead. * * Return values are not defined. * * @param sqlString sql string * @param params params for a prepared statement * @param bindings dictionary of (param index : SQLType binding) * @param maxRows integer value of max rows */ public void execute(String sqlString, PyObject params, PyObject bindings, PyObject maxRows) { clear(); try { prepareStatement(sqlString, maxRows); execute(params, bindings); } catch (PyException e) { throw e; } catch (Exception e) { throw zxJDBC.newError(e); } } /** * Perform the execution of a statement. */ protected void execute(PyObject params, PyObject bindings) throws SQLException { boolean seq = isSeq(params); // the optional argument better be a sequence if (!seq && (Py.None != params)) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, zxJDBC.getString("optionalSecond")); } boolean hasParams = (seq && (params.__len__() > 0)); // if we have a sequence of sequences, let's run through them and finish if (hasParams && isSeqSeq(params)) { for (int i = 0; i < params.__len__(); i++) { PyObject param = params.__getitem__(i); // [(3, 4)] or [(3, 4), (5, 6)] execute(param, bindings); } // we've recursed through everything, so we're done return; } if (hasParams) { // clear the statement so all new bindings take affect this.sqlStatement.clearParameters(); // [3, 4] or (3, 4) Integer binding = null; PyObject param = Py.None, index = Py.None; for (int i = 0; i < params.__len__(); i++) { binding = null; index = Py.newInteger(i); param = params.__getitem__(i); if (bindings != Py.None) { PyObject tmp = bindings.__finditem__(index); if (tmp != null) { try { binding = (Integer)tmp.__tojava__(Integer.class); } catch (ClassCastException e) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, zxJDBC.getString("bindingValue")); } } } if (binding == null) { this.datahandler.setJDBCObject(this.sqlStatement, i + 1, param); } else { this.datahandler.setJDBCObject(this.sqlStatement, i + 1, param, binding.intValue()); } } } this.datahandler.preExecute(this.sqlStatement); this.sqlStatement.execute(); create(this.sqlStatement.getResultSet()); this.datahandler.postExecute(this.sqlStatement); addWarning(this.sqlStatement.getWarnings()); return; } /** * Fetch the next row of a query result set, returning a single sequence, * or None when no more data is available. * * An Error (or subclass) exception is raised if the previous call to * executeXXX() did not produce any result set or no call was issued yet. * * @return a single sequence from the result set, or None when no more data is available */ public PyObject fetchone() { return this.fetch.fetchone(); } /** * Fetch all (remaining) rows of a query result, returning them as a sequence * of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute * can affect the performance of this operation. * * An Error (or subclass) exception is raised if the previous call to executeXXX() * did not produce any result set or no call was issued yet. * * @return a sequence of sequences from the result set, or None when no more data is available */ public PyObject fetchall() { return this.fetch.fetchall(); } /** * Fetch the next set of rows of a query result, returning a sequence of * sequences (e.g. a list of tuples). An empty sequence is returned when * no more rows are available. * * The number of rows to fetch per call is specified by the parameter. If * it is not given, the cursor's arraysize determines the number of rows * to be fetched. The method should try to fetch as many rows as indicated * by the size parameter. If this is not possible due to the specified number * of rows not being available, fewer rows may be returned. * * An Error (or subclass) exception is raised if the previous call to executeXXX() * did not produce any result set or no call was issued yet. * * Note there are performance considerations involved with the size parameter. * For optimal performance, it is usually best to use the arraysize attribute. * If the size parameter is used, then it is best for it to retain the same value * from one fetchmany() call to the next. * * @return a sequence of sequences from the result set, or None when no more data is available */ public PyObject fetchmany(int size) { return this.fetch.fetchmany(size); } /** * Move the result pointer to the next set if available. * * @return true if more sets exist, else None */ public PyObject nextset() { return this.fetch.nextset(); } /** * Create the results after a successful execution and closes the result set. * * @param rs A ResultSet. */ protected void create(ResultSet rs) { create(rs, null); } /** * Create the results after a successful execution and closes the result set. * Optionally takes a set of JDBC-indexed columns to automatically set to None * primarily to support getTypeInfo() which sets a column type of a number but * doesn't use the value so a driver is free to put anything it wants there. * * @param rs A ResultSet. * @param skipCols set of JDBC-indexed columns to automatically set as None */ protected void create(ResultSet rs, Set skipCols) { this.fetch.add(rs, skipCols); } /** * Adds a warning to the tuple and will follow the chain as necessary. */ void addWarning(SQLWarning warning) { if (warning == null) { return; } if (this.warnings == Py.None) { this.warnings = new PyList(); } PyTuple warn = new PyTuple(); // there are three parts: (reason, state, vendorCode) warn.__add__(Py.java2py(warning.getMessage())); warn.__add__(Py.java2py(warning.getSQLState())); warn.__add__(Py.newInteger(warning.getErrorCode())); // add the warning to the list ((PyList)this.warnings).append(warn); SQLWarning next = warning.getNextWarning(); if (next != null) { addWarning(next); } return; } /** * Reset the cursor state. */ protected void clear() { this.warnings = Py.None; try { this.fetch.close(); } catch (Exception e) {} finally { this.newFetch(); } try { this.sqlStatement.close(); } catch (Exception e) {} finally { this.sqlStatement = null; } } /** * @return true for any PyList, PyTuple or java.util.List */ protected boolean isSeq(PyObject object) { if ((object == null) || (object == Py.None)) { return false; } if (object.__tojava__(List.class) != Py.NoConversion) { return true; } // originally checked for __getitem__ and __len__, but this is true for PyString // and we don't want to insert one character at a time return (object instanceof PyList) || (object instanceof PyTuple); } /** * @return true for any PyList, PyTuple or java.util.List of PyLists, PyTuples or java.util.Lists */ protected boolean isSeqSeq(PyObject object) { if (isSeq(object) && (object.__len__() > 0)) { for (int i = 0; i < object.__len__(); i++) { if (!isSeq(object.__finditem__(i))) { return false; } } return true; } return false; } } /** * Class CursorFunc * * @author * @date $today.date$ * @author last modified by $Author: bzimmer $ * @date last modified on $Date: 2001/11/20 04:55:18 $ * @version $Revision: 1.1 $ * @copyright 2001 brian zimmer */ class CursorFunc extends PyBuiltinFunctionSet { /** * Constructor CursorFunc * * @param String name * @param int index * @param int argcount * @param String doc * */ CursorFunc(String name, int index, int argcount, String doc) { super(name, index, argcount, argcount, true, doc); } /** * Constructor CursorFunc * * @param String name * @param int index * @param int minargs * @param int maxargs * @param String doc * */ CursorFunc(String name, int index, int minargs, int maxargs, String doc) { super(name, index, minargs, maxargs, true, doc); } /** * Method __call__ * * @return PyObject * */ public PyObject __call__() { PyCursor cursor = (PyCursor)__self__; switch (index) { case 0 : return cursor.fetchmany(cursor.arraysize); case 1 : cursor.close(); return Py.None; case 2 : return cursor.fetchall(); case 3 : return cursor.fetchone(); case 4 : return cursor.nextset(); default : throw argCountError(0); } } /** * Method __call__ * * @param PyObject arg * * @return PyObject * */ public PyObject __call__(PyObject arg) { PyCursor cursor = (PyCursor)__self__; switch (index) { case 0 : return cursor.fetchmany(((PyInteger)arg).getValue()); case 5 : cursor.execute((String)arg.__tojava__(String.class), Py.None, Py.None, Py.None); return Py.None; case 6 : case 7 : return Py.None; case 8 : cursor.callproc((String)arg.__tojava__(String.class), Py.None); return Py.None; case 9 : cursor.executemany((String)arg.__tojava__(String.class), Py.None, Py.None); return Py.None; default : throw argCountError(1); } } /** * Method __call__ * * @param PyObject arga * @param PyObject argb * * @return PyObject * */ public PyObject __call__(PyObject arga, PyObject argb) { PyCursor cursor = (PyCursor)__self__; switch (index) { case 5 : cursor.execute((String)arga.__tojava__(String.class), argb, Py.None, Py.None); return Py.None; case 7 : return Py.None; case 8 : cursor.callproc((String)arga.__tojava__(String.class), argb); return Py.None; case 9 : cursor.executemany((String)arga.__tojava__(String.class), argb, Py.None); return Py.None; default : throw argCountError(2); } } /** * Method __call__ * * @param PyObject arga * @param PyObject argb * @param PyObject argc * * @return PyObject * */ public PyObject __call__(PyObject arga, PyObject argb, PyObject argc) { PyCursor cursor = (PyCursor)__self__; switch (index) { case 5 : cursor.execute((String)arga.__tojava__(String.class), argb, argc, Py.None); return Py.None; case 9 : cursor.executemany((String)arga.__tojava__(String.class), argb, argc); return Py.None; default : throw argCountError(3); } } /** * Method __call__ * * @param PyObject[] args * @param String[] keywords * * @return PyObject * */ public PyObject __call__(PyObject[] args, String[] keywords) { PyCursor cursor = (PyCursor)__self__; switch (index) { case 5 : PyArgParser parser = new PyArgParser(args, keywords); String sql = (String)parser.arg(0).__tojava__(String.class); PyObject params = parser.kw("params", Py.None); PyObject bindings = parser.kw("bindings", Py.None); PyObject maxrows = parser.kw("maxrows", Py.None); params = (parser.numArg() >= 2) ? parser.arg(1) : params; bindings = (parser.numArg() >= 3) ? parser.arg(2) : bindings; maxrows = (parser.numArg() >= 4) ? parser.arg(3) : maxrows; cursor.execute(sql, params, bindings, maxrows); return Py.None; default : throw argCountError(4); } } } --- NEW FILE: PyConnection.java --- /* * Jython Database Specification API 2.0 * * $Id: PyConnection.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql; import java.sql.*; import org.python.core.*; /** * A connection to the database. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class PyConnection extends PyObject implements ClassDictInit { /** Field connection */ protected Connection connection; /** Field supportsTransactions */ protected boolean supportsTransactions; /** Field __class__ */ public static PyClass __class__; /** * Method getPyClass * * @return PyClass * */ protected PyClass getPyClass() { return __class__; } /** * Create a PyConnection with the open connection. */ public PyConnection(Connection connection) throws SQLException { this.connection = connection; this.supportsTransactions = this.connection.getMetaData().supportsTransactions(); if (this.supportsTransactions) { this.connection.setAutoCommit(false); } } /** * Produces a string representation of the object. * * @return string representation of the object. */ public String toString() { try { return "<PyConnection user='" + this.connection.getMetaData().getUserName() + "', url='" + this.connection.getMetaData().getURL() + "'>"; } catch (SQLException e) { return "<PyConnection at " + hashCode() + ">"; } } /** * Method classDictInit * * @param PyObject dict * */ static public void classDictInit(PyObject dict) { dict.__setitem__("autocommit", new PyInteger(0)); dict.__setitem__("__version__", Py.newString("$Revision: 1.1 $").__getslice__(Py.newInteger(11), Py.newInteger(-2), null)); dict.__setitem__("close", new ConnectionFunc("close", 0, 0, 0, zxJDBC.getString("close"))); dict.__setitem__("commit", new ConnectionFunc("commit", 1, 0, 0, zxJDBC.getString("commit"))); dict.__setitem__("cursor", new ConnectionFunc("cursor", 2, 0, 1, zxJDBC.getString("cursor"))); dict.__setitem__("rollback", new ConnectionFunc("rollback", 3, 0, 0, zxJDBC.getString("rollback"))); // hide from python dict.__setitem__("initModule", null); dict.__setitem__("toString", null); dict.__setitem__("setConnection", null); dict.__setitem__("getPyClass", null); dict.__setitem__("connection", null); dict.__setitem__("classDictInit", null); } /** * Sets the attribute. * * @param name * @param value */ public void __setattr__(String name, PyObject value) { if ("autocommit".equals(name)) { try { if (this.supportsTransactions) { this.connection.setAutoCommit(value.__nonzero__()); } } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } return; } super.__setattr__(name, value); } /** * Finds the attribute. * * @param name the name of the attribute of interest * @return the value for the attribute of the specified name */ public PyObject __findattr__(String name) { if ("autocommit".equals(name)) { try { return connection.getAutoCommit() ? Py.One : Py.Zero; } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } else if ("dbname".equals(name)) { try { return Py.newString(this.connection.getMetaData().getDatabaseProductName()); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } else if ("dbversion".equals(name)) { try { return Py.newString(this.connection.getMetaData().getDatabaseProductVersion()); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } else if ("driverversion".equals(name)) { try { return Py.newString(this.connection.getMetaData().getDriverVersion()); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } else if ("url".equals(name)) { try { return Py.newString(this.connection.getMetaData().getURL()); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } else if ("__connection__".equals(name)) { return Py.java2py(this.connection); } return super.__findattr__(name); } /** * Close the connection now (rather than whenever __del__ is called). * The connection will be unusable from this point forward; an Error * (or subclass) exception will be raised if any operation is attempted * with the connection. The same applies to all cursor objects trying * to use the connection. * */ public void close() { try { // close the cursors too? this.connection.close(); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Commit any pending transaction to the database. Note that if the * database supports an auto-commit feature, this must be initially * off. An interface method may be provided to turn it back on. * * Database modules that do not support transactions should implement * this method with void functionality. * */ public void commit() { if (!this.supportsTransactions) { return; } try { this.connection.commit(); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * <i>This method is optional since not all databases provide transaction * support.</i> * * In case a database does provide transactions this method causes the database * to roll back to the start of any pending transaction. Closing a connection * without committing the changes first will cause an implicit rollback to be * performed. * */ void rollback() { if (!this.supportsTransactions) { return; } try { this.connection.rollback(); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Return a new Cursor Object using the connection. If the database does not * provide a direct cursor concept, the module will have to emulate cursors * using other means to the extent needed by this specification. * * @return a new cursor using this connection */ public PyCursor cursor() { return new PyExtendedCursor(this.connection); } /** * Return a new Cursor Object using the connection. If the database does not * provide a direct cursor concept, the module will have to emulate cursors * using other means to the extent needed by this specification. * * @param dynamicFetch if true, dynamically iterate the result * @return a new cursor using this connection */ public PyCursor cursor(boolean dynamicFetch) { return new PyExtendedCursor(this.connection, dynamicFetch); } } /** * Class ConnectionFunc * * @author * @date $today.date$ * @author last modified by $Author: bzimmer $ * @date last modified on $Date: 2001/11/20 04:55:18 $ * @version $Revision: 1.1 $ * @copyright 2001 brian zimmer */ class ConnectionFunc extends PyBuiltinFunctionSet { /** * Constructor ConnectionFunc * * @param String name * @param int index * @param int minargs * @param int maxargs * @param String doc * */ ConnectionFunc(String name, int index, int minargs, int maxargs, String doc) { super(name, index, minargs, maxargs, true, doc); } /** * Method __call__ * * @return PyObject * */ public PyObject __call__() { PyConnection c = (PyConnection)__self__; switch (index) { case 0 : c.close(); return Py.None; case 1 : c.commit(); return Py.None; case 2 : return c.cursor(); case 3 : c.rollback(); return Py.None; default : throw argCountError(0); } } /** * Method __call__ * * @param PyObject arg * * @return PyObject * */ public PyObject __call__(PyObject arg) { PyConnection c = (PyConnection)__self__; switch (index) { case 2 : return c.cursor(arg.__nonzero__()); default : throw argCountError(1); } } } --- NEW FILE: PyExtendedCursor.java --- /* * Jython Database Specification API 2.0 * * $Id: PyExtendedCursor.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql; import java.io.*; import java.sql.*; import java.util.*; import org.python.core.*; /** * A cursor with extensions to the DB API 2.0. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class PyExtendedCursor extends PyCursor { /** Field __class__ */ public static PyClass __class__; /** * Method getPyClass * * @return PyClass * */ protected PyClass getPyClass() { return __class__; } /** Field __members__ */ protected static PyList __members__; /** Field __methods__ */ protected static PyList __methods__; static { PyObject[] m = new PyObject[7]; m[0] = new PyString("tables"); m[1] = new PyString("columns"); m[2] = new PyString("primarykeys"); m[3] = new PyString("foreignkeys"); m[4] = new PyString("procedures"); m[5] = new PyString("procedurecolumns"); m[6] = new PyString("statistics"); __methods__ = new PyList(m); m = new PyObject[0]; __members__ = new PyList(m); } /** * Constructor PyExtendedCursor * * @param Connection connection * */ PyExtendedCursor(Connection connection) { super(connection); } /** * Constructor PyExtendedCursor * * @param Connection connection * @param boolean dynamicFetch * */ PyExtendedCursor(Connection connection, boolean dynamicFetch) { super(connection, dynamicFetch); } /** * String representation of the object. * * @return a string representation of the object. */ public String toString() { return "<PyExtendedCursor object instance at " + hashCode() + ">"; } /** * Initializes the module. * * @param dict */ static public void classDictInit(PyObject dict) { PyCursor.classDictInit(dict); dict.__setitem__("__version__", Py.newString("$Revision: 1.1 $").__getslice__(Py.newInteger(11), Py.newInteger(-2), null)); dict.__setitem__("tables", new ExtendedCursorFunc("tables", 100, 4, 4, "query for table information")); dict.__setitem__("columns", new ExtendedCursorFunc("columns", 101, 4, 4, "query for column information")); dict.__setitem__("primarykeys", new ExtendedCursorFunc("primarykeys", 102, 3, 3, "query for primary keys")); dict.__setitem__("foreignkeys", new ExtendedCursorFunc("foreignkeys", 103, 6, 6, "query for foreign keys")); dict.__setitem__("procedures", new ExtendedCursorFunc("procedures", 104, 3, 3, "query for procedures")); dict.__setitem__("procedurecolumns", new ExtendedCursorFunc("procedurecolumns", 105, 4, 4, "query for procedures columns")); dict.__setitem__("statistics", new ExtendedCursorFunc("statistics", 106, 5, 5, "description of a table's indices and statistics")); dict.__setitem__("gettypeinfo", new ExtendedCursorFunc("gettypeinfo", 107, 0, 1, "query for sql type info")); dict.__setitem__("gettabletypeinfo", new ExtendedCursorFunc("gettabletypeinfo", 108, 0, 1, "query for table types")); // hide from python dict.__setitem__("classDictInit", null); dict.__setitem__("toString", null); } /** * Only table descriptions matching the catalog, schema, table name and type * criteria are returned. They are ordered by TABLE_TYPE, TABLE_SCHEM and * TABLE_NAME. * * @param qualifier * @param owner * @param table * @param type */ protected void tables(PyObject qualifier, PyObject owner, PyObject table, PyObject type) { clear(); try { String q = (qualifier == Py.None) ? null : (String)qualifier.__tojava__(String.class); String o = (owner == Py.None) ? null : (String)owner.__tojava__(String.class); String t = (table == Py.None) ? null : (String)table.__tojava__(String.class); String[] y = null; if (type != Py.None) { if (isSeq(type)) { int len = type.__len__(); y = new String[len]; for (int i = 0; i < len; i++) { y[i] = (String)type.__getitem__(i).__tojava__(String.class); } } else { y = new String[1]; y[0] = (String)type.__tojava__(String.class); } } create(this.connection.getMetaData().getTables(q, o, t, y)); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Returns the columns for a table. * * @param qualifier * @param owner * @param table * @param column */ protected void columns(PyObject qualifier, PyObject owner, PyObject table, PyObject column) { clear(); try { String q = (qualifier == Py.None) ? null : (String)qualifier.__tojava__(String.class); String o = (owner == Py.None) ? null : (String)owner.__tojava__(String.class); String t = (table == Py.None) ? null : (String)table.__tojava__(String.class); String c = (column == Py.None) ? null : (String)column.__tojava__(String.class); create(this.connection.getMetaData().getColumns(q, o, t, c)); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Gets a description of the stored procedures available for the qualifier and owner. * * @param qualifier * @param owner * @param procedure */ protected void procedures(PyObject qualifier, PyObject owner, PyObject procedure) { clear(); try { String q = (qualifier == Py.None) ? null : (String)qualifier.__tojava__(String.class); String o = (owner == Py.None) ? null : (String)owner.__tojava__(String.class); String p = (procedure == Py.None) ? null : (String)procedure.__tojava__(String.class); create(this.connection.getMetaData().getProcedures(q, o, p)); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Gets the columns for the procedure. * * @param qualifier * @param owner * @param procedure * @param column */ protected void procedurecolumns(PyObject qualifier, PyObject owner, PyObject procedure, PyObject column) { clear(); try { String q = (qualifier == Py.None) ? null : (String)qualifier.__tojava__(String.class); String o = (owner == Py.None) ? null : (String)owner.__tojava__(String.class); String p = (procedure == Py.None) ? null : (String)procedure.__tojava__(String.class); String c = (column == Py.None) ? null : (String)column.__tojava__(String.class); create(this.connection.getMetaData().getProcedureColumns(q, o, p, c)); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Gets a description of a table's primary key columns. They are ordered by * COLUMN_NAME. * * @param qualifier a schema name * @param owner an owner name * @param table a table name */ protected void primarykeys(PyObject qualifier, PyObject owner, PyObject table) { clear(); try { String q = (qualifier == Py.None) ? null : (String)qualifier.__tojava__(String.class); String o = (owner == Py.None) ? null : (String)owner.__tojava__(String.class); String t = (table == Py.None) ? null : (String)table.__tojava__(String.class); create(this.connection.getMetaData().getPrimaryKeys(q, o, t)); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Gets a description of the foreign key columns in the foreign key table * that reference the primary key columns of the primary key table (describe * how one table imports another's key.) This should normally return a single * foreign key/primary key pair (most tables only import a foreign key from a * table once.) They are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, * and KEY_SEQ. * * @param primaryQualifier * @param primaryOwner * @param primaryTable * @param foreignQualifier * @param foreignOwner * @param foreignTable */ protected void foreignkeys(PyObject primaryQualifier, PyObject primaryOwner, PyObject primaryTable, PyObject foreignQualifier, PyObject foreignOwner, PyObject foreignTable) { clear(); try { String pq = (primaryQualifier == Py.None) ? null : (String)primaryQualifier.__tojava__(String.class); String po = (primaryOwner == Py.None) ? null : (String)primaryOwner.__tojava__(String.class); String pt = (primaryTable == Py.None) ? null : (String)primaryTable.__tojava__(String.class); String fq = (foreignQualifier == Py.None) ? null : (String)foreignQualifier.__tojava__(String.class); String fo = (foreignOwner == Py.None) ? null : (String)foreignOwner.__tojava__(String.class); String ft = (foreignTable == Py.None) ? null : (String)foreignTable.__tojava__(String.class); create(this.connection.getMetaData().getCrossReference(pq, po, pt, fq, fo, ft)); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Gets a description of a table's indices and statistics. They are ordered by * NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION. * * @param qualifier * @param owner * @param table * @param unique * @param accuracy */ protected void statistics(PyObject qualifier, PyObject owner, PyObject table, PyObject unique, PyObject accuracy) { clear(); try { String q = (qualifier == Py.None) ? null : (String)qualifier.__tojava__(String.class); String o = (owner == Py.None) ? null : (String)owner.__tojava__(String.class); String t = (table == Py.None) ? null : (String)table.__tojava__(String.class); boolean u = (unique == Py.None) ? false : ((Boolean)unique.__tojava__(Boolean.class)).booleanValue(); boolean a = (accuracy == Py.None) ? false : ((Boolean)accuracy.__tojava__(Boolean.class)).booleanValue(); Set skipCols = new HashSet(); skipCols.add(new Integer(12)); create(this.connection.getMetaData().getIndexInfo(q, o, t, u, a), skipCols); } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Gets a description of the type information for a given type. * * @param type data type for which to provide information */ protected void typeinfo(PyObject type) { clear(); try { Set skipCols = new HashSet(); skipCols.add(new Integer(16)); skipCols.add(new Integer(17)); create(this.connection.getMetaData().getTypeInfo(), skipCols); // if the type is non-null, then trim the result list down to that type only // if(type != null &&!Py.None.equals(type)) { // for(int i = 0; i < ((PyObject) this.results.get(0)).__len__(); i++) { // PyObject row = ((PyObject) this.results.get(0)).__getitem__(new PyInteger(i)); // PyObject sqlType = row.__getitem__(new PyInteger(1)); // if(type.equals(sqlType)) { // this.results.remove(0); // this.results.add(0, new PyList(new PyObject[] { // row // })); // } // } // } } catch (SQLException e) { throw zxJDBC.newError(e); } } /** * Gets a description of possible table types. */ protected void tabletypeinfo() { clear(); try { create(this.connection.getMetaData().getTableTypes()); } catch (SQLException e) { throw zxJDBC.newError(e); } } } /** * Class ExtendedCursorFunc * * @author * @date $today.date$ * @author last modified by $Author: bzimmer $ * @date last modified on $Date: 2001/11/20 04:55:18 $ * @version $Revision: 1.1 $ * @copyright 2001 brian zimmer */ class ExtendedCursorFunc extends PyBuiltinFunctionSet { /** * Constructor ExtendedCursorFunc * * @param String name * @param int index * @param int argcount * @param String doc * */ ExtendedCursorFunc(String name, int index, int argcount, String doc) { super(name, index, argcount, argcount, true, doc); } /** * Constructor ExtendedCursorFunc * * @param String name * @param int index * @param int minargs * @param int maxargs * @param String doc * */ ExtendedCursorFunc(String name, int index, int minargs, int maxargs, String doc) { super(name, index, minargs, maxargs, true, doc); } /** * Method __call__ * * @return PyObject * */ public PyObject __call__() { PyExtendedCursor cursor = (PyExtendedCursor)__self__; switch (index) { case 107 : cursor.typeinfo(Py.None); return Py.None; case 108 : cursor.tabletypeinfo(); return Py.None; default : throw argCountError(0); } } /** * Method __call__ * * @param PyObject arga * * @return PyObject * */ public PyObject __call__(PyObject arga) { PyExtendedCursor cursor = (PyExtendedCursor)__self__; switch (index) { case 107 : cursor.typeinfo(arga); return Py.None; default : throw argCountError(1); } } /** * Method __call__ * * @param PyObject arga * @param PyObject argb * @param PyObject argc * * @return PyObject * */ public PyObject __call__(PyObject arga, PyObject argb, PyObject argc) { PyExtendedCursor cursor = (PyExtendedCursor)__self__; switch (index) { case 102 : cursor.primarykeys(arga, argb, argc); return Py.None; case 104 : cursor.procedures(arga, argb, argc); return Py.None; default : throw argCountError(3); } } /** * Method fancyCall * * @param PyObject[] args * * @return PyObject * */ public PyObject fancyCall(PyObject[] args) { PyExtendedCursor cursor = (PyExtendedCursor)__self__; switch (index) { case 103 : cursor.foreignkeys(args[0], args[1], args[2], args[3], args[4], args[5]); return Py.None; case 106 : cursor.statistics(args[0], args[1], args[2], args[3], args[4]); return Py.None; default : throw argCountError(args.length); } } /** * Method __call__ * * @param PyObject arg1 * @param PyObject arg2 * @param PyObject arg3 * @param PyObject arg4 * * @return PyObject * */ public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) { PyExtendedCursor cursor = (PyExtendedCursor)__self__; switch (index) { case 100 : cursor.tables(arg1, arg2, arg3, arg4); return Py.None; case 101 : cursor.columns(arg1, arg2, arg3, arg4); return Py.None; case 105 : cursor.procedurecolumns(arg1, arg2, arg3, arg4); return Py.None; default : throw argCountError(4); } } } --- NEW FILE: zxJDBC.java --- /* * Jython Database Specification API 2.0 * * $Id: zxJDBC.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql; import java.io.*; import java.sql.*; import java.util.*; import java.text.*; import java.lang.reflect.*; import org.python.core.*; /** * Creates database connections. * * <pre> * from com.ziclix.python.sql import zxJDBC * db = zxJDBC.connect("jdbc:mysql://localhost:3306/MySql", None, None, "org.gjt.mm.mysql.Driver") * </pre> * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class zxJDBC extends PyObject implements ClassDictInit { /** Field Error */ public static PyObject Error = Py.None; /** Field Warning */ public static PyObject Warning = Py.None; /** Field InterfaceError */ public static PyObject InterfaceError = Py.None; /** Field DatabaseError */ public static PyObject DatabaseError = Py.None; /** Field InternalError */ public static PyObject InternalError = Py.None; /** Field OperationalError */ public static PyObject OperationalError = Py.None; /** Field ProgrammingError */ public static PyObject ProgrammingError = Py.None; /** Field IntegrityError */ public static PyObject IntegrityError = Py.None; /** Field DataError */ public static PyObject DataError = Py.None; /** Field NotSupportedError */ public static PyObject NotSupportedError = Py.None; /** The ResourceBundle with error messages and doc strings */ private static ResourceBundle resourceBundle = null; static { try { resourceBundle = ResourceBundle.getBundle("com.ziclix.python.sql.resource.zxJDBCMessages"); } catch (MissingResourceException e) { throw new RuntimeException("missing zxjdbc resource bundle"); } } /** * Initializes the module. * * @param dict */ public static void classDictInit(PyObject dict) { dict.__setitem__("apilevel", new PyString("2.0")); dict.__setitem__("threadsafety", new PyInteger(1)); dict.__setitem__("paramstyle", new PyString("qmark")); dict.__setitem__("__version__", Py.newString("$Revision: 1.1 $").__getslice__(Py.newInteger(11), Py.newInteger(-2), null)); dict.__setitem__("Date", new zxJDBCFunc("Date", 1, 3, 3, false, "construct a Date from year, month, day")); dict.__setitem__("Time", new zxJDBCFunc("Time", 2, 3, 3, false, "construct a Date from hour, minute, second")); dict.__setitem__("Timestamp", new zxJDBCFunc("Timestamp", 3, 6, 6, false, "construct a Timestamp from year, month, day, hour, minute, second")); dict.__setitem__("DateFromTicks", new zxJDBCFunc("DateFromTicks", 4, 1, 1, false, "construct a Date from seconds since the epoch")); dict.__setitem__("TimeFromTicks", new zxJDBCFunc("TimeFromTicks", 5, 1, 1, false, "construct a Time from seconds since the epoch")); dict.__setitem__("TimestampFromTicks", new zxJDBCFunc("TimestampFromTicks", 6, 1, 1, false, "construct a Timestamp from seconds since the epoch")); zxJDBC._addSqlTypes(dict); zxJDBC._addConnectors(dict); zxJDBC._buildExceptions(dict); // hide from python dict.__setitem__("initModule", null); dict.__setitem__("toString", null); dict.__setitem__("getPyClass", null); dict.__setitem__("classDictInit", null); dict.__setitem__("_addSqlTypes", null); dict.__setitem__("_addConnectors", null); dict.__setitem__("_buildExceptions", null); dict.__setitem__("_empty__init__", null); dict.__setitem__("buildClass", null); dict.__setitem__("createExceptionMessage", null); dict.__setitem__("newError", null); dict.__setitem__("resourceBundle", null); dict.__setitem__("getString", null); } /** Field __class__ */ public static PyClass __class__; /** * Method getPyClass * * @return PyClass * */ protected PyClass getPyClass() { return __class__; } /** * Add the types from java.sql.Types * * @param PyObject dict * * @throws PyException * */ protected static void _addSqlTypes(PyObject dict) throws PyException { PyDictionary sqltype = new PyDictionary(); dict.__setitem__("sqltype", sqltype); try { Class c = Class.forName("java.sql.Types"); Field[] fields = c.getFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; dict.__setitem__(Py.newString(f.getName()), new PyInteger(f.getInt(c))); sqltype.__setitem__(new PyInteger(f.getInt(c)), Py.newString(f.getName())); } } catch (Exception e) { throw newError(e); } return; } /** * Add all the possible connectors * * @param PyObject dict * * @throws PyException * */ protected static void _addConnectors(PyObject dict) throws PyException { PyObject connector = Py.None; Properties props = new Properties(); props.put("connect", "com.ziclix.python.sql.connect.Connect"); props.put("lookup", "com.ziclix.python.sql.connect.Lookup"); props.put("connectx", "com.ziclix.python.sql.connect.Connectx"); java.util.Enumeration names = props.propertyNames(); while (names.hasMoreElements()) { String name = ((String)names.nextElement()).trim(); String className = ((String)props.getProperty(name)).trim(); try { connector = (PyObject)Class.forName(className).newInstance(); dict.__setitem__(name, connector); Py.writeComment("zxJDBC", "loaded connector [" + className + "] as [" + name + "]"); } catch (Throwable t) { Py.writeComment("zxJDBC", "failed to load connector [" + name + "] using class [" + className + "]"); } } return; } /** * Create the exception classes and get their descriptions from the resource bundle. */ protected static void _buildExceptions(PyObject dict) { Error = buildClass("Error", Py.StandardError, "_empty__init__"); Warning = buildClass("Warning", Py.StandardError, "_empty__init__"); InterfaceError = buildClass("InterfaceError", Error, "_empty__init__"); DatabaseError = buildClass("DatabaseError", Error, "_empty__init__"); InternalError = buildClass("InternalError", DatabaseError, "_empty__init__"); OperationalError = buildClass("OperationalError", DatabaseError, "_empty__init__"); ProgrammingError = buildClass("ProgrammingError", DatabaseError, "_empty__init__"); IntegrityError = buildClass("IntegrityError", DatabaseError, "_empty__init__"); DataError = buildClass("DataError", DatabaseError, "_empty__init__"); NotSupportedError = buildClass("NotSupportedError", DatabaseError, "_empty__init__"); } /** * Method _empty__init__ * * @param PyObject[] arg * @param String[] kws * * @return PyObject * */ public static PyObject _empty__init__(PyObject[] arg, String[] kws) { PyObject dict = new PyStringMap(); dict.__setitem__("__module__", new PyString("zxJDBC")); return dict; } /** * Return the string associated with the key for the default resource bundle. It * first checks for 'key.N' where N starts at 0 and increments by one. If any indexed * key is found, the results of all the indexed values are concatenated with the line * separator. If no indexed key is found, it defaults to checking the bundle by the * key value alone. */ public static String getString(String key) { int i = 0; List lines = null; String resource = null; while (true) { try { resource = resourceBundle.getString(key + "." + (i++)); if (lines == null) { lines = new ArrayList(); } lines.add(resource); } catch (MissingResourceException e) { break; } } if ((lines == null) || (lines.size() == 0)) { resource = resourceBundle.getString(key); } else { String sep = System.getProperty("line.separator"); StringBuffer sb = new StringBuffer(); for (i = 0; i < lines.size() - 1; i++) { sb.append(lines.get(i)).append(sep); } sb.append(lines.get(lines.size() - 1)); resource = sb.toString(); } return resource; } /** * Return a formatted string. The key is used to get the format and the values * are passed, along with the format, to a MessageFormat who formats it appropriately. */ public static String getString(String key, Object[] values) { String format = getString(key); return MessageFormat.format(format, values); } /** * Return a newly instantiated PyException. */ public static PyException makeException(PyObject type, String msg) { return Py.makeException(type, Py.newString((msg == null) ? "" : msg)); } /** * Return a newly instantiated Error. */ public static PyException newError(String msg) { return zxJDBC.makeException(Error, msg); } /** * Return a newly instantiated Error. */ public static PyException newError(Throwable e) { try { return (PyException)e; } catch (ClassCastException ex) {} try { StringBuffer buffer = new StringBuffer(); createExceptionMessage((SQLException)e, buffer, 0); return newError(buffer.toString()); } catch (ClassCastException ex) {} return newError(e.getMessage()); } /** * Create SQL exception messages * * @param SQLException exception * @param StringBuffer buffer * @param int level * */ protected static void createExceptionMessage(SQLException exception, StringBuffer buffer, int level) { buffer.append(exception.getMessage()); buffer.append(" [SQLCode: " + exception.getErrorCode() + "]"); if (exception.getSQLState() != null) { buffer.append(", [SQLState: " + exception.getSQLState() + "]"); } if (exception.getNextException() != null) { buffer.append(System.getProperty("line.separator")); createExceptionMessage(exception.getNextException(), buffer, level + 1); } } /** * This function constructs an object holding a date value. */ protected static PyObject Date(int year, int month, int day) { Calendar c = Calendar.getInstance(); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DATE, day); return DateFromTicks(c.getTime().getTime() / 1000); } /** * This function constructs an object holding a time value. */ protected static PyObject Time(int hour, int minute, int second) { Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR, hour); c.set(Calendar.MINUTE, minute); c.set(Calendar.SECOND, second); return TimeFromTicks(c.getTime().getTime() / 1000); } /** * This function constructs an object holding a time stamp value. */ protected static PyObject Timestamp(int year, int month, int day, int hour, int minute, int second) { Calendar c = Calendar.getInstance(); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DATE, day); c.set(Calendar.HOUR, hour); c.set(Calendar.MINUTE, minute); c.set(Calendar.SECOND, second); c.set(Calendar.MILLISECOND, 0); return TimestampFromTicks(c.getTime().getTime() / 1000); } /** * This function constructs an object holding a date value from the * given ticks value (number of seconds since the epoch; see the * documentation of the standard Python <i>time</i> module for details). * * <i>Note:</i> The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in * seconds rather than milliseconds, so adjust any Java code accordingly. * * @param ticks number of seconds since the epoch */ protected static PyObject DateFromTicks(long ticks) { Calendar c = Calendar.getInstance(); c.setTime(new java.util.Date(ticks * 1000)); c.set(Calendar.HOUR, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); return Py.java2py(new java.sql.Date(c.getTime().getTime())); } /** * This function constructs an object holding a time value from the * given ticks value (number of seconds since the epoch; see the * documentation of the standard Python <i>time</i> module for details). * * <i>Note:</i> The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in * seconds rather than milliseconds, so adjust any Java code accordingly. * * @param ticks number of seconds since the epoch */ protected static PyObject TimeFromTicks(long ticks) { return Py.java2py(new Time(ticks * 1000)); } /** * This function constructs an object holding a time stamp value from * the given ticks value (number of... [truncated message content] |
From: brian z. <bz...@us...> - 2001-11-20 04:55:21
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/pipe/csv In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql/pipe/csv Added Files: CSVSink.java CSVString.java Log Message: initial zxJDBC checkin --- NEW FILE: CSVSink.java --- /* * Jython Database Specification API 2.0 * * $Id: CSVSink.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.pipe.csv; import java.io.*; import org.python.core.*; import com.ziclix.python.sql.pipe.Sink; /** * The CSVSink writes data out in a Comma Seperated Format. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class CSVSink implements Sink { /** Field header */ protected boolean header; /** Field delimiter */ protected String delimiter; /** Field writer */ protected PrintWriter writer; /** Field converters */ protected PyObject converters; /** * All data will be written to the given PrintWriter. * * @param writer the PrintWriter to which data will be written */ public CSVSink(PrintWriter writer) { this(writer, Py.None); } /** * All data will be written to the given PrintWriter. If * the converters param is not None, then an attempt will * be made to convert the object using the given converter. * * @param writer the PrintWriter to which data will be written * @param converters an indexed dictionary of callable objects used for converting objects to strings */ public CSVSink(PrintWriter writer, PyObject converters) { this.header = false; this.writer = writer; this.converters = converters; this.delimiter = ","; } /** * Handle the data callback and write the row out. */ public void row(PyObject row) { String[] values = new String[row.__len__()]; if (this.header) { for (int i = 0; i < row.__len__(); i++) { values[i] = this.convert(Py.newInteger(i), row.__getitem__(i)); } } else { for (int i = 0; i < row.__len__(); i++) { values[i] = row.__getitem__(i).__getitem__(0).toString(); } this.header = true; } this.println(values); } /** * Convert the object at index to a String. */ protected String convert(PyObject index, PyObject object) { if (this.converters != Py.None) { PyObject converter = this.converters.__finditem__(index); if (converter != Py.None) { object = converter.__call__(object); } } if ((object == Py.None) || (object == null)) { return ""; } return CSVString.toCSV(object.toString()); } /** * Print the row of Strings. */ protected void println(String[] row) { for (int i = 0; i < row.length - 1; i++) { this.writer.print(row[i]); this.writer.print(this.delimiter); } this.writer.println(row[row.length - 1]); } /** * Method start * */ public void start() {} /** * Method end * */ public void end() {} } --- NEW FILE: CSVString.java --- /* * Jython Database Specification API 2.0 * * $Id: CSVString.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.pipe.csv; /** * A utility class to aide in quoting CSV strings. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class CSVString { /** * The default delimiter. */ public static final String DELIMITER = ","; private CSVString() {} /** * Escape the string as needed using the default delimiter. */ public static String toCSV(String string) { return toCSV(string, CSVString.DELIMITER); } /** * Escape the string as needed using the given delimiter. */ public static String toCSV(String string, String delimiter) { String res = replace(string, "\"", "\"\""); if ((res.indexOf("\"") >= 0) || (string.indexOf(delimiter) >= 0)) { res = "\"" + res + "\""; } return res; } /** * Returns a new string resulting from replacing the first occurrence, or all occurrences, * of search string in this string with replace string. * If the string search does not occur in the character sequence represented by this object, * then this string is returned. * @param search the old string * @param replace the new string * @param all=true all occurrences of the search string are replaced * @param all=false only the first occurrence of the search string is replaced * @return a string derived from this string by replacing the first occurrence, * or every occurrence of search with replace. */ public static String replace(String original, String search, String replace, boolean all) { String valReturn = new String(""); int l = original.length(); int lo = search.length(); int ln = replace.length(); int i = 0; int j; while (i <= l) { j = original.indexOf(search, i); if (j == -1) { valReturn = valReturn.concat(original.substring(i, l)); i = l + 1; // Stop, no more occurrence. } else { valReturn = valReturn.concat(original.substring(i, j)); valReturn = valReturn.concat(replace); i = j + lo; if (!all) { // Stop, replace the first occurrence only. valReturn = valReturn.concat(original.substring(i, l)); i = l + 1; // Stop, replace the first occurrence only. } } } return valReturn; } /** * Returns a new string resulting from replacing all occurrences, * of search string in this string with replace string. * If the string search does not occur in the character sequence represented by this object, * then this string is returned. * @param search the old string * @param replace the new string * @return a string derived from this string by replacing every occurrence of search with replace. */ public static String replace(String original, String search, String replace) { return replace(original, search, replace, true); } /** * Returns a new string resulting from replacing the end of this String * from oldSuffix to newSuffix. * The original string is returned if it does not end with oldSuffix. * @param oldSuffix the old suffix * @param newSuffix the new suffix * @return a string derived from this string by replacing the end oldSuffix by newSuffix */ public static String replaceEndWith(String original, String oldSuffix, String newSuffix) { if (original.endsWith(oldSuffix)) { String st = original.substring(0, original.length() - oldSuffix.length()); return st.concat(newSuffix); } else { return original; } } } |
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); } } } |
From: brian z. <bz...@us...> - 2001-11-20 04:55:21
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/connect In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql/connect Added Files: Connectx.java Connect.java Lookup.java Log Message: initial zxJDBC checkin --- NEW FILE: Connectx.java --- /* * Jython Database Specification API 2.0 * * $Id: Connectx.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.connect; import java.sql.*; import java.util.*; import javax.sql.*; import java.lang.reflect.*; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.util.*; /** * Connect using through a javax.sql.DataSource or javax.sql.ConnectionPooledDataSource. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class Connectx extends PyObject { private final String SET = "set"; private final PyString doc = new PyString("establish a connection through a javax.sql.DataSource or javax.sql.ConnectionPooledDataSource"); /** * Constructor Connectx * */ public Connectx() {} /** * Method __findattr__ * * @param String name * * @return PyObject * */ public PyObject __findattr__(String name) { if ("__doc__".equals(name)) { return doc; } return super.__findattr__(name); } /** * Construct a javax.sql.DataSource or javax.sql.ConnectionPooledDataSource */ public PyObject __call__(PyObject[] args, String[] keywords) { Connection c = null; PyConnection pc = null; Object datasource = null; PyArgParser parser = new PyArgParser(args, keywords); try { String _class = (String)parser.arg(0).__tojava__(String.class); datasource = Class.forName(_class).newInstance(); } catch (Exception e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "unable to instantiate datasource"); } String[] kws = parser.kws(); Class clazz = datasource.getClass(); for (int i = 0; i < kws.length; i++) { String methodName = kws[i]; if (methodName == null) { continue; } Object value = parser.kw(kws[i]).__tojava__(Object.class); if (methodName.length() > SET.length()) { if (!SET.equals(methodName.substring(0, SET.length()))) { // prepend "set" invoke(datasource, SET + methodName.substring(0, 1).toUpperCase() + methodName.substring(1), value); } else { // starts with "set" so just pass it on invoke(datasource, methodName, value); } } else { // shorter than "set" so it can't be a full method name invoke(datasource, SET + methodName.substring(0, 1).toUpperCase() + methodName.substring(1), value); } } try { if (datasource instanceof DataSource) { c = ((DataSource)datasource).getConnection(); } else if (datasource instanceof ConnectionPoolDataSource) { c = ((ConnectionPoolDataSource)datasource).getPooledConnection().getConnection(); } } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } try { if ((c == null) || c.isClosed()) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "unable to establish connection"); } pc = new PyConnection(c); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } return pc; } /** * Method toString * * @return String * */ public String toString() { return "<connectx object instance at " + Py.id(this) + ">"; } /** * Method invoke * * @param Object src * @param String methodName * @param Object value * */ protected void invoke(Object src, String methodName, Object value) { Method method = null; StringBuffer exceptionMsg = new StringBuffer("method [").append(methodName).append("] using arg type ["); exceptionMsg.append(value.getClass()).append("], value [").append(value.toString()).append("]"); try { method = getMethod(src.getClass(), methodName, value.getClass()); if (method == null) { throw zxJDBC.newError("no such " + exceptionMsg); } method.invoke(src, new Object[]{ value }); } catch (IllegalAccessException e) { throw zxJDBC.newError("illegal access for " + exceptionMsg); } catch (InvocationTargetException e) { throw zxJDBC.newError("invocation target exception for " + exceptionMsg); } return; } /** * Try to find the method by the given name. If failing that, see if the valueClass * is perhaps a primitive and attempt to recurse using the primitive type. Failing * that return null. */ protected Method getMethod(Class srcClass, String methodName, Class valueClass) { Method method = null; try { method = srcClass.getMethod(methodName, new Class[]{ valueClass }); } catch (NoSuchMethodException e) { Class primitive = null; try { Field f = valueClass.getField("TYPE"); primitive = (Class)f.get(valueClass); } catch (NoSuchFieldException ex) {} catch (IllegalAccessException ex) {} catch (ClassCastException ex) {} if ((primitive != null) && primitive.isPrimitive()) { return getMethod(srcClass, methodName, primitive); } } return method; } // __class__ boilerplate -- see PyObject for details /** Field __class__ */ public static PyClass __class__; /** * Method getPyClass * * @return PyClass * */ protected PyClass getPyClass() { return __class__; } } --- NEW FILE: Connect.java --- /* * Jython Database Specification API 2.0 * * $Id: Connect.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.connect; import java.sql.*; import java.util.*; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.util.*; /** * Connect using DriverManager. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class Connect extends PyObject { private static final PyString _doc = new PyString("establish a connection through java.sql.DriverManager"); /** * Default empty constructor. */ public Connect() {} /** * Method __findattr__ * * @param String name * * @return PyObject * */ public PyObject __findattr__(String name) { if ("__doc__".equals(name)) { return _doc; } return super.__findattr__(name); } /** * Establish a connection through DriverManager. */ public PyObject __call__(PyObject[] args, String[] keywords) { Connection c = null; PyArgParser parser = new PyArgParser(args, keywords); Object arg = parser.arg(0).__tojava__(Connection.class); if (arg == Py.NoConversion) { Properties props = new Properties(); String url = null, user = null, password = null, driver = null; url = (String)parser.arg(0).__tojava__(String.class); user = (String)parser.arg(1).__tojava__(String.class); password = (String)parser.arg(2).__tojava__(String.class); driver = (String)parser.arg(3).__tojava__(String.class); if (url == null) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "no url specified"); } if (driver == null) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "no driver specified"); } // the value can't be null props.put("user", (user == null) ? "" : user); props.put("password", (password == null) ? "" : password); String[] kws = parser.kws(); for (int i = 0; i < kws.length; i++) { Object value = parser.kw(kws[i]).__tojava__(Object.class); props.put(kws[i], value); } try { Class.forName(driver); } catch (ClassNotFoundException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "driver not found"); } try { c = DriverManager.getConnection(url, props); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } else { c = (Connection)arg; } try { if ((c == null) || c.isClosed()) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "unable to establish connection"); } return new PyConnection(c); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } /** * Method toString * * @return String * */ public String toString() { return "<connect object instance at " + Py.id(this) + ">"; } // __class__ boilerplate -- see PyObject for details /** Field __class__ */ public static PyClass __class__; /** * Method getPyClass * * @return PyClass * */ protected PyClass getPyClass() { return __class__; } } --- NEW FILE: Lookup.java --- /* * Jython Database Specification API 2.0 * * $Id: Lookup.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.connect; import java.sql.*; import java.util.*; import java.lang.reflect.Field; import javax.sql.*; import javax.naming.*; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.util.*; /** * Establish a connection through a JNDI lookup. The bound object can be either a <code>DataSource</code>, * <code>ConnectionPooledDataSource</code>, <code>Connection</code> or a <code>String</code>. If it's a * <code>String</code> the value is passed to the DriverManager to obtain a connection, otherwise the * <code>Connection</code> is established using the object. * * @author brian zimmer * @author last revised by $Author: bzimmer $ * @version $Revision: 1.1 $ */ public class Lookup extends PyObject { private static final PyString _doc = new PyString("establish a connection through a JNDI lookup"); /** * Constructor Lookup * */ public Lookup() {} /** * Method __findattr__ * * @param String name * * @return PyObject * */ public PyObject __findattr__(String name) { if ("__doc__".equals(name)) { return _doc; } return super.__findattr__(name); } /** * Expects a single PyString argument which is the JNDI name of the bound Connection or DataSource. * If any keywords are passed, an attempt is made to match the keyword to a static final Field on * javax.naming.Context. If the Field is found, the value of the Field is substituted as the key * and the value of the keyword is the value put in the Hashtable environment. If the Field is not * found, the key is the keyword with no substitutions. */ public PyObject __call__(PyObject[] args, String[] keywords) { Object ref = null; Connection connection = null; Hashtable env = new Hashtable(); // figure out the correct params PyArgParser parser = new PyArgParser(args, keywords); Object jndiName = parser.arg(0).__tojava__(String.class); if ((jndiName == null) || (jndiName == Py.NoConversion)) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "lookup name is null"); } // add any Context properties String[] kws = parser.kws(); for (int i = 0; i < kws.length; i++) { String keyword = kws[i], fieldname = null; Object value = parser.kw(keyword).__tojava__(Object.class); try { Field field = Context.class.getField(keyword); fieldname = (String)field.get(Context.class); } catch (IllegalAccessException e) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, e.getMessage()); } catch (NoSuchFieldException e) { fieldname = keyword; } env.put(fieldname, value); } InitialContext context = null; try { context = new InitialContext(env); ref = context.lookup((String)jndiName); } catch (NamingException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } finally { if (context != null) { try { context.close(); } catch (NamingException e) {} } } if (ref == null) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, "object [" + jndiName + "] not found in JNDI"); } try { if (ref instanceof String) { connection = DriverManager.getConnection(((String)ref)); } else if (ref instanceof Connection) { connection = (Connection)ref; } else if (ref instanceof DataSource) { connection = ((DataSource)ref).getConnection(); } else if (ref instanceof ConnectionPoolDataSource) { connection = ((ConnectionPoolDataSource)ref).getPooledConnection().getConnection(); } } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } try { if ((connection == null) || connection.isClosed()) { throw zxJDBC.makeException(zxJDBC.DatabaseError, "unable to establish connection"); } return new PyConnection(connection); } catch (SQLException e) { throw zxJDBC.makeException(zxJDBC.DatabaseError, e.getMessage()); } } /** * Method toString * * @return String * */ public String toString() { return "<lookup object instance at " + Py.id(this) + ">"; } // __class__ boilerplate -- see PyObject for details /** Field __class__ */ public static PyClass __class__; /** * Method getPyClass * * @return PyClass * */ protected PyClass getPyClass() { return __class__; } } |
From: brian z. <bz...@us...> - 2001-11-20 04:55:21
|
Update of /cvsroot/jython/jython/Lib In directory usw-pr-cvs1:/tmp/cvs-serv7094/Lib Added Files: dbexts.py isql.py Log Message: initial zxJDBC checkin --- NEW FILE: dbexts.py --- # $Id: dbexts.py,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ """ This script provides platform independence by wrapping Python Database API 2.0 compatible drivers to allow seamless database usage across implementations. In order to use the C version, you need mxODBC and mxDateTime. In order to use the Java version, you need zxJDBC. >>> import dbexts >>> d = dbexts.dbexts() # use the default db >>> d.isql('select count(*) count from player') count ------- 13569.0 1 row affected >>> r = d.raw('select count(*) count from player') >>> r ([('count', 3, 17, None, 15, 0, 1)], [(13569.0,)]) >>> The configuration file follows the following format in a file name dbexts.ini: [default] name=development [jdbc] name=development url=jdbc:db:devurl username=root password=12345 [jdbc] name=production url=jdbc:db:produrl username=root password=12345 [odbc] name=development username=root password=12345 """ import os, string, re __author__ = "brian zimmer (bz...@zi...)" __version__ = "$Revision: 1.1 $"[11:-2] __OS__ = os.name choose = lambda bool, a, b: (bool and [a] or [b])[0] def console(rows, headers=()): """Format the results into a list of strings (one for each row): <header> <headersep> <row1> <row2> ... headers may be given as list of strings. Columns are separated by colsep; the header is separated from the result set by a line of headersep characters. The function calls stringify to format the value data into a string. It defaults to calling str() and striping leading and trailing whitespace. - copied and modified from mxODBC """ # Check row entry lengths output = [] headers = map(string.upper, list(headers)) collen = map(len,headers) output.append(headers) if rows and len(rows) > 0: for row in rows: row = map(lambda x: str(x), row) for i in range(len(row)): entry = row[i] if collen[i] < len(entry): collen[i] = len(entry) output.append(row) if len(output) == 1: affected = "0 rows affected" elif len(output) == 2: affected = "1 row affected" else: affected = "%d rows affected" % (len(output) - 1) # Format output for i in range(len(output)): row = output[i] l = [] for j in range(len(row)): l.append('%-*s' % (collen[j],row[j])) output[i] = string.join(l, " | ") # Insert header separator totallen = len(output[0]) output[1:1] = ["-"*(totallen/len("-"))] output.append("\n" + affected) return output def html(rows, headers=()): output = [] output.append('<table class="results">') output.append('<tr class="headers">') headers = map(lambda x: '<td class="header">%s</td>' % (x.upper()), list(headers)) map(output.append, headers) output.append('</tr>') if rows and len(rows) > 0: for row in rows: output.append('<tr class="row">') row = map(lambda x: '<td class="value">%s</td>' % (x), row) map(output.append, row) output.append('</tr>') output.append('</table>') return output comments = lambda x: re.compile("{.*?}", re.S).sub("", x, 0) class ex_proxy: """Wraps mxODBC to provide proxy support for zxJDBC's additional parameters.""" def __init__(self, c): self.c = c def __getattr__(self, name): if name == "execute": return self.execute elif name == "gettypeinfo": return self.gettypeinfo else: return getattr(self.c, name) def execute(self, sql, params=None, bindings=None, maxrows=None): if params: self.c.execute(sql, params) else: self.c.execute(sql) def gettypeinfo(self, typeid=None): if typeid: self.c.gettypeinfo(typeid) class executor: """Handles the insertion of values given dynamic data.""" def __init__(self, table, cols): self.cols = cols self.table = table if self.cols: self.sql = "insert into %s (%s) values (%s)" % (table, ",".join(self.cols), ",".join(("?",) * len(self.cols))) else: self.sql = "insert into %s values (%%s)" % (table) def execute(self, db, rows, bindings): assert rows and len(rows) > 0, "must have at least one row" if self.cols: sql = self.sql else: sql = self.sql % (",".join(("?",) * len(rows[0]))) db.raw(sql, rows, bindings) def connect(dbname): return dbexts(dbname) def lookup(dbname): return dbexts(jndiname=dbname) class dbexts: def __init__(self, dbname=None, cfg=None, formatter=console, autocommit=1, jndiname=None, out=None): self.verbose = 1 self.results = None self.headers = None self.datahandler = None self.autocommit = autocommit self.formatter = formatter self.out = out self.metaDataCase = lambda x: x if not jndiname: if cfg == None: cfg = os.path.join(os.path.split(__file__)[0], "dbexts.ini") if isinstance(cfg, IniParser): self.dbs = cfg else: self.dbs = IniParser(cfg) if dbname == None: dbname = self.dbs[("default", "name")] if __OS__ == 'java': from com.ziclix.python.sql import zxJDBC database = zxJDBC if not jndiname: t = self.dbs[("jdbc", dbname)] self.dburl, dbuser, dbpwd, jdbcdriver = t['url'], t['user'], t['pwd'], t['driver'] if t.has_key("datahandler"): try: datahandlerclass = string.split(t['datahandler'], ".")[-1] self.datahandler = __import__(t['datahandler'], globals(), locals(), datahandlerclass) except: pass if t.has_key("metaDataCase"): self.metaDataCase = getattr(string, t['metaDataCase']) keys = filter(lambda x: x not in ['url', 'user', 'pwd', 'driver', 'datahandler', 'name', 'metaDataCase'], t.keys()) props = {} for a in keys: props[a] = t[a] self.db = apply(database.connect, (self.dburl, dbuser, dbpwd, jdbcdriver), props) else: self.db = database.lookup(jndiname) self.db.autocommit = 0 elif __OS__ == 'nt': for modname in ["mx.ODBC.Windows", "ODBC.Windows"]: try: database = __import__(modname, globals(), locals(), "Windows") break except: continue else: raise ImportError("unable to find appropriate mx ODBC module") t = self.dbs[("odbc", dbname)] self.dburl, dbuser, dbpwd = t['url'], t['user'], t['pwd'] self.db = database.Connect(self.dburl, dbuser, dbpwd, clear_auto_commit=1) for a in database.sqltype.keys(): setattr(self, database.sqltype[a], a) del database def __str__(self): return self.dburl def __repr__(self): return self.dburl def __getattr__(self, name): if "cfg" == name: return self.dbs.cfg def close(self): """ close the connection to the database """ self.db.close() def begin(self): """ reset ivars and return a new cursor, possibly binding an auxiliary datahandler """ self.headers, self.results = None, None c = self.db.cursor() if __OS__ == 'java': if self.datahandler: c.datahandler = self.datahandler(c.datahandler) else: c = ex_proxy(c) return c def commit(self, cursor=None): """ commit the cursor and create the result set """ if cursor and cursor.description: self.headers = cursor.description self.results = cursor.fetchall() if hasattr(cursor, "nextset"): s = cursor.nextset() while s: f = cursor.fetchall() if f: self.results = choose(self.results is None, [], self.results) + f s = cursor.nextset() if self.autocommit or cursor is None: self.db.commit() if cursor: cursor.close() def rollback(self): """ rollback the cursor """ self.db.rollback() def display(self): """ using the formatter, display the results """ if self.formatter and self.verbose > 0: res = self.results if res: print >> self.out, "" for a in self.formatter(res, map(lambda x: x[0], self.headers)): print >> self.out, a print >> self.out, "" def __execute__(self, sql, params=None, bindings=None, maxrows=None): """ the primary execution method """ cur = self.begin() try: if bindings: cur.execute(sql, params, bindings, maxrows=maxrows) elif params: cur.execute(sql, params, maxrows=maxrows) else: cur.execute(sql, maxrows=maxrows) finally: self.commit(cur) def isql(self, sql, params=None, bindings=None, maxrows=None): """ execute and display the sql """ self.raw(sql, params, bindings, maxrows=maxrows) self.display() def raw(self, sql, params=None, bindings=None, delim=None, comments=comments, maxrows=None): """ execute the sql and return a tuple of (headers, results) """ if delim: headers = [] results = [] if comments: sql = comments(sql) statements = filter(lambda x: len(x) > 0, map(string.strip, string.split(sql, delim))) for a in statements: self.__execute__(a, params, bindings, maxrows=maxrows) headers.append(self.headers) results.append(self.results) self.headers = headers self.results = results else: self.__execute__(sql, params, bindings, maxrows=maxrows) return (self.headers, self.results) def pk(self, table, owner=None, schema=None): """ display the table's primary keys """ cur = self.begin() cur.primarykeys(schema, owner, self.metaDataCase(table)) self.commit(cur) self.display() def fk(self, primary_table=None, foreign_table=None, owner=None, schema=None): """ display the table's foreign keys """ cur = self.begin() if primary_table and foreign_table: cur.foreignkeys(schema, owner, self.metaDataCase(primary_table), schema, owner, self.metaDataCase(foreign_table)) elif primary_table: cur.foreignkeys(schema, owner, self.metaDataCase(primary_table), schema, owner, None) elif foreign_table: cur.foreignkeys(schema, owner, None, schema, owner, self.metaDataCase(foreign_table)) self.commit(cur) self.display() def table(self, table=None, types=("TABLE",), owner=None, schema=None): """If no table argument, displays a list of all tables. If a table argument, displays the columns of the given table.""" cur = self.begin() if table: cur.columns(schema, owner, self.metaDataCase(table), None) else: cur.tables(schema, owner, None, types) self.commit(cur) self.display() def proc(self, proc=None, owner=None, schema=None): """If no proc argument, displays a list of all procedures. If a proc argument, displays the parameters of the given procedure.""" cur = self.begin() if proc: cur.procedurecolumns(schema, owner, proc, None) else: cur.procedures(schema, owner, None) self.commit(cur) self.display() def stat(self, table, qualifier=None, owner=None, unique=0, accuracy=0): """ display the table's indicies """ cur = self.begin() cur.statistics(qualifier, owner, self.metaDataCase(table), unique, accuracy) self.commit(cur) self.display() def typeinfo(self, sqltype=None): """ display the types available for the database """ cur = self.begin() cur.gettypeinfo(sqltype) self.commit(cur) self.display() def tabletypeinfo(self): """ display the table types available for the database """ cur = self.begin() cur.gettabletypeinfo() self.commit(cur) self.display() def schema(self, table, full=0, sort=1, owner=None): """Displays a Schema object for the table. If full is true, then generates references to the table in addition to the standard fields. If sort is true, sort all the items in the schema, else leave them in db dependent order.""" print >> self.out, str(Schema(self, table, owner, full, sort)) def bulkcopy(self, dst, table, include=[], exclude=[], autobatch=0, executor=executor): """Returns a Bulkcopy object using the given table.""" if type(dst) == type(""): dst = dbexts(dst, cfg=self.dbs) bcp = Bulkcopy(dst, table, include=include, exclude=exclude, autobatch=autobatch, executor=executor) return bcp def bcp(self, src, table, where='(1=1)', params=[], include=[], exclude=[], autobatch=0, executor=executor): """Bulkcopy of rows from a src database to the current database for a given table and where clause.""" if type(src) == type(""): src = dbexts(src, cfg=self.dbs) bcp = self.bulkcopy(self, table, include, exclude, autobatch, executor) num = bcp.transfer(src, where, params) return num def unload(self, filename, sql, delimiter=",", includeheaders=1): """ Unloads the delimited results of the query to the file specified, optionally including headers. """ u = Unload(self, filename, delimiter, includeheaders) u.unload(sql) class Bulkcopy: """The idea for a bcp class came from http://object-craft.com.au/projects/sybase""" def __init__(self, dst, table, include=[], exclude=[], autobatch=0, executor=executor): self.dst = dst self.table = table self.total = 0 self.rows = [] self.autobatch = autobatch self.bindings = {} include = map(lambda x: string.lower(x), include) exclude = map(lambda x: string.lower(x), exclude) _verbose = self.dst.verbose self.dst.verbose = 0 try: self.dst.table(self.table) if self.dst.results: colmap = {} for a in self.dst.results: colmap[a[3].lower()] = a[4] cols = self.__filter__(colmap.keys(), include, exclude) for a in zip(range(len(cols)), cols): self.bindings[a[0]] = colmap[a[1]] colmap = None else: cols = self.__filter__(include, include, exclude) finally: self.dst.verbose = _verbose self.executor = executor(table, cols) def __str__(self): return "[%s].[%s]" % (self.dst, self.table) def __repr__(self): return "[%s].[%s]" % (self.dst, self.table) def __getattr__(self, name): if name == 'columns': return self.executor.cols def __filter__(self, values, include, exclude): cols = map(string.lower, values) if exclude: cols = filter(lambda x, ex=exclude: x not in ex, cols) if include: cols = filter(lambda x, inc=include: x in inc, cols) return cols def format(self, column, type): self.bindings[column] = type def done(self): if len(self.rows) > 0: return self.batch() return 0 def batch(self): self.executor.execute(self.dst, self.rows, self.bindings) cnt = len(self.rows) self.total += cnt self.rows = [] return cnt def rowxfer(self, line): self.rows.append(line) if self.autobatch: self.batch() def transfer(self, src, where="(1=1)", params=[]): sql = "select %s from %s where %s" % (string.join(self.columns, ", "), self.table, where) h, d = src.raw(sql, params) if d: map(self.rowxfer, d) return self.done() return 0 class Unload: """Unloads a sql statement to a file with optional formatting of each value.""" def __init__(self, db, filename, delimiter=",", includeheaders=1): self.db = db self.filename = filename self.delimiter = delimiter self.includeheaders = includeheaders self.formatters = {} def format(self, o): if not o: return "" o = str(o) if o.find(",") != -1: o = "\"\"%s\"\"" % (o) return o def unload(self, sql, mode="w"): headers, results = self.db.raw(sql) w = open(self.filename, mode) if self.includeheaders: w.write("%s\n" % (string.join(map(lambda x: x[0], headers), self.delimiter))) if results: for a in results: w.write("%s\n" % (string.join(map(self.format, a), self.delimiter))) w.flush() w.close() class Schema: """Produces a Schema object which represents the database schema for a table""" def __init__(self, db, table, owner=None, full=0, sort=1): self.db = db self.table = table self.owner = owner self.full = full self.sort = sort _verbose = self.db.verbose self.db.verbose = 0 try: if table: self.computeschema() finally: self.db.verbose = _verbose def computeschema(self): self.db.table(self.table, owner=self.owner) self.columns = [] # (column name, type_name, size, nullable) if self.db.results: self.columns = map(lambda x: (x[3], x[5], x[6], x[10]), self.db.results) if self.sort: self.columns.sort(lambda x, y: cmp(x[0], y[0])) self.db.fk(None, self.table) # (pk table name, pk column name, fk column name, fk name, pk name) self.imported = [] if self.db.results: self.imported = map(lambda x: (x[2], x[3], x[7], x[11], x[12]), self.db.results) if self.sort: self.imported.sort(lambda x, y: cmp(x[2], y[2])) self.exported = [] if self.full: self.db.fk(self.table, None) # (pk column name, fk table name, fk column name, fk name, pk name) if self.db.results: self.exported = map(lambda x: (x[3], x[6], x[7], x[11], x[12]), self.db.results) if self.sort: self.exported.sort(lambda x, y: cmp(x[1], y[1])) self.db.pk(self.table) self.primarykeys = [] if self.db.results: # (column name, key_seq, pk name) self.primarykeys = map(lambda x: (x[3], x[4], x[5]), self.db.results) if self.sort: self.primarykeys.sort(lambda x, y: cmp(x[1], y[1])) self.db.stat(self.table) # (non-unique, name, type, pos, column name, asc) self.indices = [] if self.db.results: idxdict = {} # mxODBC returns a row of None's, so filter it out idx = map(lambda x: (x[3], string.strip(x[5]), x[6], x[7], x[8]), filter(lambda x: x[5], self.db.results)) def cckmp(x, y): c = cmp(x[1], y[1]) if c == 0: c = cmp(x[3], y[3]) return c # sort this regardless, this gets the indicies lined up idx.sort(cckmp) for a in idx: if not idxdict.has_key(a[1]): idxdict[a[1]] = [] idxdict[a[1]].append(a) self.indices = idxdict.values() if self.sort: self.indices.sort(lambda x, y: cmp(x[0][1], y[0][1])) def __str__(self): d = [] d.append("Table") d.append(" " + self.table) d.append("\nPrimary Keys") for a in self.primarykeys: d.append(" %s {%s}" % (a[0], a[2])) d.append("\nImported (Foreign) Keys") for a in self.imported: d.append(" %s (%s.%s) {%s}" % (a[2], a[0], a[1], a[3])) if self.full: d.append("\nExported (Referenced) Keys") for a in self.exported: d.append(" %s (%s.%s) {%s}" % (a[0], a[1], a[2], a[3])) d.append("\nColumns") for a in self.columns: nullable = choose(a[3], "nullable", "non-nullable") d.append(" %-20s %s(%s), %s" % (a[0], a[1], a[2], nullable)) d.append("\nIndices") for a in self.indices: unique = choose(a[0][0], "non-unique", "unique") cname = string.join(map(lambda x: x[4], a), ", ") d.append(" %s index {%s} on (%s)" % (unique, a[0][1], cname)) return string.join(d, "\n") class IniParser: def __init__(self, cfg, key='name'): self.key = key self.records = {} self.ctypeRE = re.compile("\[(jdbc|odbc|default)\]") self.entryRE = re.compile("([a-zA-Z]+)[ \t]*=[ \t]*(.*)") self.cfg = cfg self.parse() def parse(self): fp = open(self.cfg, "r") data = fp.readlines() fp.close() lines = filter(lambda x: len(x) > 0 and x[0] not in ['#', ';'], map(string.strip, data)) current = None for i in range(len(lines)): line = lines[i] g = self.ctypeRE.match(line) if g: # a section header current = {} if not self.records.has_key(g.group(1)): self.records[g.group(1)] = [] self.records[g.group(1)].append(current) else: g = self.entryRE.match(line) if g: current[g.group(1)] = g.group(2) def __getitem__(self, (ctype, skey)): if skey == self.key: return self.records[ctype][0][skey] t = filter(lambda x, p=self.key, s=skey: x[p] == s, self.records[ctype]) if not t or len(t) > 1: raise KeyError, "invalid key ('%s', '%s')" % (ctype, skey) return t[0] def random_table_name(prefix, num_chars): import random d = [prefix, '_'] i = 0 while i < num_chars: d.append(chr(int(100 * random.random()) % 26 + ord('A'))) i += 1 return string.join(d, "") class ResultSetRow: def __init__(self, rs, row): self.row = row self.rs = rs def __getitem__(self, i): if type(i) == type(""): i = self.rs.index(i) return self.row[i] def __getslice__(self, i, j): if type(i) == type(""): i = self.rs.index(i) if type(j) == type(""): j = self.rs.index(j) return self.row[i:j] def __len__(self): return len(self.row) def __repr__(self): return str(self.row) class ResultSet: def __init__(self, headers, results=[]): self.headers = map(lambda x: x.upper(), headers) self.results = results def index(self, i): return self.headers.index(string.upper(i)) def __getitem__(self, i): return ResultSetRow(self, self.results[i]) def __getslice__(self, i, j): return map(lambda x, rs=self: ResultSetRow(rs, x), self.results[i:j]) def __repr__(self): return "<%s instance {cols [%d], rows [%d]} at %s>" % (self.__class__, len(self.headers), len(self.results), id(self)) --- NEW FILE: isql.py --- # $Id: isql.py,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ import dbexts, cmd, sys """ Isql works in conjunction with dbexts to provide an interactive environment for database work. """ __version__ = "$Revision: 1.1 $"[11:-2] class Prompt: """ This class fixes a problem with the cmd.Cmd class since it uses an ivar 'prompt' as opposed to a method 'prompt()'. To get around this, this class is plugged in as a 'prompt' attribute and when invoked the '__str__' method is called which figures out the appropriate prompt to display. I still think, even though this is clever, the attribute version of 'prompt' is poor design. """ def __init__(self, isql): self.isql = isql def __str__(self): prompt = "%s> " % (self.isql.db.dbname) if len(self.isql.sqlbuffer) > 0: prompt = "... " return prompt class IsqlCmd(cmd.Cmd): def __init__(self, db=None, delimiter=";"): cmd.Cmd.__init__(self) if db is None or type(db) == type(""): self.db = dbexts.dbexts(db) else: self.db = db self.kw = {} self.sqlbuffer = [] self.delimiter = delimiter self.prompt = Prompt(self) def do_which(self, arg): """\nPrints the current db connection parameters.\n""" print self.db return None def do_EOF(self, arg): return None def do_p(self, arg): """\nExecute a python expression.\n""" try: exec arg.strip() in globals() except: print sys.exc_info()[1] return None def do_use(self, arg): """\nUse a new database connection.\n""" self.db = dbexts.dbexts(arg.strip()) return None def do_table(self, arg): """\nPrints table meta-data. If no table name, prints all tables.\n""" if len(arg.strip()): apply(self.db.table, (arg,), self.kw) else: apply(self.db.table, (None,), self.kw) return None def do_proc(self, arg): """\nPrints store procedure meta-data.\n""" if len(arg.strip()): apply(self.db.proc, (arg,), self.kw) else: apply(self.db.proc, (None,), self.kw) return None def do_schema(self, arg): """\nPrints schema information.\n""" print self.db.schema(arg) print return None def do_delimiter(self, arg): """\nChange the delimiter.\n""" delimiter = arg.strip() if len(delimiter) > 0: self.delimiter = delimiter def do_q(self, arg): """\nQuit.\n""" return 1 def do_set(self, arg): """\nSet a parameter. Some examples:\n set owner = 'informix'\n set types = ['VIEW', 'TABLE']\nThe right hand side is evaluated using `eval()`\n""" d = filter(lambda x: len(x) > 0, map(lambda x: x.strip(), arg.split("="))) if len(d) == 1: if self.kw.has_key(d[0]): del self.kw[d[0]] else: self.kw[d[0]] = eval(d[1]) def default(self, arg): try: token = arg.strip() # is it possible the line contains the delimiter if len(token) >= len(self.delimiter): # does the line end with the delimiter if token[-1 * len(self.delimiter):] == self.delimiter: # now add all up to the delimiter self.sqlbuffer.append(token[:-1 * len(self.delimiter)]) if self.sqlbuffer: self.db.isql(" ".join(self.sqlbuffer)) self.sqlbuffer = [] return None if token: self.sqlbuffer.append(token) except: self.sqlbuffer = [] print sys.exc_info()[1] return None def emptyline(self): return None if __name__ == '__main__': import getopt try: opts, args = getopt.getopt(sys.argv[1:], "b:", []) except getopt.error, msg: print print msg print "Try `%s --help` for more information." % (sys.argv[0]) sys.exit(0) dbname = None for opt, arg in opts: if opt == '-b': dbname = arg intro = "\nisql - interactive sql (%s)\n" % (__version__) IsqlCmd(dbname).cmdloop(intro) |
From: brian z. <bz...@us...> - 2001-11-20 04:46:52
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/connect In directory usw-pr-cvs1:/tmp/cvs-serv5229/com/ziclix/python/sql/connect Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql/connect added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:46:37
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/handler In directory usw-pr-cvs1:/tmp/cvs-serv5174/com/ziclix/python/sql/handler Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql/handler added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:46:21
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/pipe/csv In directory usw-pr-cvs1:/tmp/cvs-serv5124/com/ziclix/python/sql/pipe/csv Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql/pipe/csv added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:46:08
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/pipe/db In directory usw-pr-cvs1:/tmp/cvs-serv5076/com/ziclix/python/sql/pipe/db Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql/pipe/db added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:45:57
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/pipe In directory usw-pr-cvs1:/tmp/cvs-serv5017/com/ziclix/python/sql/pipe Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql/pipe added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:44:17
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/resource In directory usw-pr-cvs1:/tmp/cvs-serv4608/com/ziclix/python/sql/resource Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql/resource added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:44:03
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/util In directory usw-pr-cvs1:/tmp/cvs-serv4507/com/ziclix/python/sql/util Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql/util added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:43:43
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql In directory usw-pr-cvs1:/tmp/cvs-serv4434/com/ziclix/python/sql Log Message: Directory /cvsroot/jython/jython/com/ziclix/python/sql added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:43:22
|
Update of /cvsroot/jython/jython/com/ziclix/python In directory usw-pr-cvs1:/tmp/cvs-serv4322/com/ziclix/python Log Message: Directory /cvsroot/jython/jython/com/ziclix/python added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:43:11
|
Update of /cvsroot/jython/jython/com/ziclix In directory usw-pr-cvs1:/tmp/cvs-serv4267/com/ziclix Log Message: Directory /cvsroot/jython/jython/com/ziclix added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:42:48
|
Update of /cvsroot/jython/jython/com In directory usw-pr-cvs1:/tmp/cvs-serv4154/com Log Message: Directory /cvsroot/jython/jython/com added to the repository |
From: Finn B. <bc...@us...> - 2001-11-19 18:55:05
|
Update of /cvsroot/jython/jython/installer In directory usw-pr-cvs1:/tmp/cvs-serv13522 Modified Files: mklist.py Log Message: Use local copies of random.py and imaplib.py. Index: mklist.py =================================================================== RCS file: /cvsroot/jython/jython/installer/mklist.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** mklist.py 2001/10/06 21:26:32 1.22 --- mklist.py 2001/11/19 18:55:00 1.23 *************** *** 92,96 **** 'htmllib.py', 'httplib.py', ! 'imaplib.py', 'imghdr.py', 'keyword.py', --- 92,96 ---- 'htmllib.py', 'httplib.py', ! #'imaplib.py', 'imghdr.py', 'keyword.py', *************** *** 120,124 **** 'pyclbr.py', 'quopri.py', ! 'random.py', 'reconvert.py', 'repr.py', --- 120,124 ---- 'pyclbr.py', 'quopri.py', ! #'random.py', 'reconvert.py', 'repr.py', |
From: Finn B. <bc...@us...> - 2001-11-19 18:54:03
|
Update of /cvsroot/jython/jython/Lib In directory usw-pr-cvs1:/tmp/cvs-serv13232 Added Files: random.py Log Message: A copy of CPython's random.py that does not use eval(). This copy can hopefully go away in jython 2.2. --- NEW FILE: random.py --- """Random variable generators. integers -------- uniform within range sequences --------- pick random element generate random permutation distributions on the real line: ------------------------------ uniform normal (Gaussian) lognormal negative exponential gamma beta distributions on the circle (angles 0 to 2pi) --------------------------------------------- circular uniform von Mises Translated from anonymously contributed C/C++ source. Multi-threading note: the random number generator used here is not thread- safe; it is possible that two calls return the same random value. However, you can instantiate a different instance of Random() in each thread to get generators that don't share state, then use .setstate() and .jumpahead() to move the generators to disjoint segments of the full period. For example, def create_generators(num, delta, firstseed=None): ""\"Return list of num distinct generators. Each generator has its own unique segment of delta elements from Random.random()'s full period. Seed the first generator with optional arg firstseed (default is None, to seed from current time). ""\" from random import Random g = Random(firstseed) result = [g] for i in range(num - 1): laststate = g.getstate() g = Random() g.setstate(laststate) g.jumpahead(delta) result.append(g) return result gens = create_generators(10, 1000000) That creates 10 distinct generators, which can be passed out to 10 distinct threads. The generators don't share state so can be called safely in parallel. So long as no thread calls its g.random() more than a million times (the second argument to create_generators), the sequences seen by each thread will not overlap. The period of the underlying Wichmann-Hill generator is 6,953,607,871,644, and that limits how far this technique can be pushed. Just for fun, note that since we know the period, .jumpahead() can also be used to "move backward in time": >>> g = Random(42) # arbitrary >>> g.random() 0.25420336316883324 >>> g.jumpahead(6953607871644L - 1) # move *back* one >>> g.random() 0.25420336316883324 """ # XXX The docstring sucks. from math import log as _log, exp as _exp, pi as _pi, e as _e from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin __all__ = ["Random","seed","random","uniform","randint","choice", "randrange","shuffle","normalvariate","lognormvariate", "cunifvariate","expovariate","vonmisesvariate","gammavariate", "stdgamma","gauss","betavariate","paretovariate","weibullvariate", "getstate","setstate","jumpahead","whseed"] def _verify(name, computed, expected): if abs(computed - expected) > 1e-7: raise ValueError( "computed value for %s deviates too much " "(computed %g, expected %g)" % (name, computed, expected)) NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) _verify('NV_MAGICCONST', NV_MAGICCONST, 1.71552776992141) TWOPI = 2.0*_pi _verify('TWOPI', TWOPI, 6.28318530718) LOG4 = _log(4.0) _verify('LOG4', LOG4, 1.38629436111989) SG_MAGICCONST = 1.0 + _log(4.5) _verify('SG_MAGICCONST', SG_MAGICCONST, 2.50407739677627) del _verify # Translated by Guido van Rossum from C source provided by # Adrian Baddeley. class Random: VERSION = 1 # used by getstate/setstate def __init__(self, x=None): """Initialize an instance. Optional argument x controls seeding, as for Random.seed(). """ self.seed(x) self.gauss_next = None ## -------------------- core generator ------------------- # Specific to Wichmann-Hill generator. Subclasses wishing to use a # different core generator should override the seed(), random(), # getstate(), setstate() and jumpahead() methods. def seed(self, a=None): """Initialize internal state from hashable object. None or no argument seeds from current time. If a is not None or an int or long, hash(a) is used instead. If a is an int or long, a is used directly. Distinct values between 0 and 27814431486575L inclusive are guaranteed to yield distinct internal states (this guarantee is specific to the default Wichmann-Hill generator). """ if a is None: # Initialize from current time import time a = long(time.time() * 256) if type(a) not in (type(3), type(3L)): a = hash(a) a, x = divmod(a, 30268) a, y = divmod(a, 30306) a, z = divmod(a, 30322) self._seed = int(x)+1, int(y)+1, int(z)+1 def random(self): """Get the next random number in the range [0.0, 1.0).""" # Wichman-Hill random number generator. # # Wichmann, B. A. & Hill, I. D. (1982) # Algorithm AS 183: # An efficient and portable pseudo-random number generator # Applied Statistics 31 (1982) 188-190 # # see also: # Correction to Algorithm AS 183 # Applied Statistics 33 (1984) 123 # # McLeod, A. I. (1985) # A remark on Algorithm AS 183 # Applied Statistics 34 (1985),198-200 # This part is thread-unsafe: # BEGIN CRITICAL SECTION x, y, z = self._seed x = (171 * x) % 30269 y = (172 * y) % 30307 z = (170 * z) % 30323 self._seed = x, y, z # END CRITICAL SECTION # Note: on a platform using IEEE-754 double arithmetic, this can # never return 0.0 (asserted by Tim; proof too long for a comment). return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0 def getstate(self): """Return internal state; can be passed to setstate() later.""" return self.VERSION, self._seed, self.gauss_next def setstate(self, state): """Restore internal state from object returned by getstate().""" version = state[0] if version == 1: version, self._seed, self.gauss_next = state else: raise ValueError("state with version %s passed to " "Random.setstate() of version %s" % (version, self.VERSION)) def jumpahead(self, n): """Act as if n calls to random() were made, but quickly. n is an int, greater than or equal to 0. Example use: If you have 2 threads and know that each will consume no more than a million random numbers, create two Random objects r1 and r2, then do r2.setstate(r1.getstate()) r2.jumpahead(1000000) Then r1 and r2 will use guaranteed-disjoint segments of the full period. """ if not n >= 0: raise ValueError("n must be >= 0") x, y, z = self._seed x = int(x * pow(171, n, 30269)) % 30269 y = int(y * pow(172, n, 30307)) % 30307 z = int(z * pow(170, n, 30323)) % 30323 self._seed = x, y, z def __whseed(self, x=0, y=0, z=0): """Set the Wichmann-Hill seed from (x, y, z). These must be integers in the range [0, 256). """ if not type(x) == type(y) == type(z) == type(0): raise TypeError('seeds must be integers') if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256): raise ValueError('seeds must be in range(0, 256)') if 0 == x == y == z: # Initialize from current time import time t = long(time.time() * 256) t = int((t&0xffffff) ^ (t>>24)) t, x = divmod(t, 256) t, y = divmod(t, 256) t, z = divmod(t, 256) # Zero is a poor seed, so substitute 1 self._seed = (x or 1, y or 1, z or 1) def whseed(self, a=None): """Seed from hashable object's hash code. None or no argument seeds from current time. It is not guaranteed that objects with distinct hash codes lead to distinct internal states. This is obsolete, provided for compatibility with the seed routine used prior to Python 2.1. Use the .seed() method instead. """ if a is None: self.__whseed() return a = hash(a) a, x = divmod(a, 256) a, y = divmod(a, 256) a, z = divmod(a, 256) x = (x + a) % 256 or 1 y = (y + a) % 256 or 1 z = (z + a) % 256 or 1 self.__whseed(x, y, z) ## ---- Methods below this point do not need to be overridden when ## ---- subclassing for the purpose of using a different core generator. ## -------------------- pickle support ------------------- def __getstate__(self): # for pickle return self.getstate() def __setstate__(self, state): # for pickle self.setstate(state) ## -------------------- integer methods ------------------- def randrange(self, start, stop=None, step=1, int=int, default=None): """Choose a random item from range(start, stop[, step]). This fixes the problem with randint() which includes the endpoint; in Python this is usually not what you want. Do not supply the 'int' and 'default' arguments. """ # This code is a bit messy to make it fast for the # common case while still doing adequate error checking istart = int(start) if istart != start: raise ValueError, "non-integer arg 1 for randrange()" if stop is default: if istart > 0: return int(self.random() * istart) raise ValueError, "empty range for randrange()" istop = int(stop) if istop != stop: raise ValueError, "non-integer stop for randrange()" if step == 1: if istart < istop: return istart + int(self.random() * (istop - istart)) raise ValueError, "empty range for randrange()" istep = int(step) if istep != step: raise ValueError, "non-integer step for randrange()" if istep > 0: n = (istop - istart + istep - 1) / istep elif istep < 0: n = (istop - istart + istep + 1) / istep else: raise ValueError, "zero step for randrange()" if n <= 0: raise ValueError, "empty range for randrange()" return istart + istep*int(self.random() * n) def randint(self, a, b): """Return random integer in range [a, b], including both end points. (Deprecated; use randrange(a, b+1).) """ return self.randrange(a, b+1) ## -------------------- sequence methods ------------------- def choice(self, seq): """Choose a random element from a non-empty sequence.""" return seq[int(self.random() * len(seq))] def shuffle(self, x, random=None, int=int): """x, random=random.random -> shuffle list x in place; return None. Optional arg random is a 0-argument function returning a random float in [0.0, 1.0); by default, the standard random.random. Note that for even rather small len(x), the total number of permutations of x is larger than the period of most random number generators; this implies that "most" permutations of a long sequence can never be generated. """ if random is None: random = self.random for i in xrange(len(x)-1, 0, -1): # pick an element in x[:i+1] with which to exchange x[i] j = int(random() * (i+1)) x[i], x[j] = x[j], x[i] ## -------------------- real-valued distributions ------------------- ## -------------------- uniform distribution ------------------- def uniform(self, a, b): """Get a random number in the range [a, b).""" return a + (b-a) * self.random() ## -------------------- normal distribution -------------------- def normalvariate(self, mu, sigma): # mu = mean, sigma = standard deviation # Uses Kinderman and Monahan method. Reference: Kinderman, # A.J. and Monahan, J.F., "Computer generation of random # variables using the ratio of uniform deviates", ACM Trans # Math Software, 3, (1977), pp257-260. random = self.random while 1: u1 = random() u2 = random() z = NV_MAGICCONST*(u1-0.5)/u2 zz = z*z/4.0 if zz <= -_log(u2): break return mu + z*sigma ## -------------------- lognormal distribution -------------------- def lognormvariate(self, mu, sigma): return _exp(self.normalvariate(mu, sigma)) ## -------------------- circular uniform -------------------- def cunifvariate(self, mean, arc): # mean: mean angle (in radians between 0 and pi) # arc: range of distribution (in radians between 0 and pi) return (mean + arc * (self.random() - 0.5)) % _pi ## -------------------- exponential distribution -------------------- def expovariate(self, lambd): # lambd: rate lambd = 1/mean # ('lambda' is a Python reserved word) random = self.random u = random() while u <= 1e-7: u = random() return -_log(u)/lambd ## -------------------- von Mises distribution -------------------- def vonmisesvariate(self, mu, kappa): # mu: mean angle (in radians between 0 and 2*pi) # kappa: concentration parameter kappa (>= 0) # if kappa = 0 generate uniform random angle # Based upon an algorithm published in: Fisher, N.I., # "Statistical Analysis of Circular Data", Cambridge # University Press, 1993. # Thanks to Magnus Kessler for a correction to the # implementation of step 4. random = self.random if kappa <= 1e-6: return TWOPI * random() a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa) b = (a - _sqrt(2.0 * a))/(2.0 * kappa) r = (1.0 + b * b)/(2.0 * b) while 1: u1 = random() z = _cos(_pi * u1) f = (1.0 + r * z)/(r + z) c = kappa * (r - f) u2 = random() if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)): break u3 = random() if u3 > 0.5: theta = (mu % TWOPI) + _acos(f) else: theta = (mu % TWOPI) - _acos(f) return theta ## -------------------- gamma distribution -------------------- def gammavariate(self, alpha, beta): # beta times standard gamma ainv = _sqrt(2.0 * alpha - 1.0) return beta * self.stdgamma(alpha, ainv, alpha - LOG4, alpha + ainv) def stdgamma(self, alpha, ainv, bbb, ccc): # ainv = sqrt(2 * alpha - 1) # bbb = alpha - log(4) # ccc = alpha + ainv random = self.random if alpha <= 0.0: raise ValueError, 'stdgamma: alpha must be > 0.0' if alpha > 1.0: # Uses R.C.H. Cheng, "The generation of Gamma # variables with non-integral shape parameters", # Applied Statistics, (1977), 26, No. 1, p71-74 while 1: u1 = random() u2 = random() v = _log(u1/(1.0-u1))/ainv x = alpha*_exp(v) z = u1*u1*u2 r = bbb+ccc*v-x if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z): return x elif alpha == 1.0: # expovariate(1) u = random() while u <= 1e-7: u = random() return -_log(u) else: # alpha is between 0 and 1 (exclusive) # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle while 1: u = random() b = (_e + alpha)/_e p = b*u if p <= 1.0: x = pow(p, 1.0/alpha) else: # p > 1 x = -_log((b-p)/alpha) u1 = random() if not (((p <= 1.0) and (u1 > _exp(-x))) or ((p > 1) and (u1 > pow(x, alpha - 1.0)))): break return x ## -------------------- Gauss (faster alternative) -------------------- def gauss(self, mu, sigma): # When x and y are two variables from [0, 1), uniformly # distributed, then # # cos(2*pi*x)*sqrt(-2*log(1-y)) # sin(2*pi*x)*sqrt(-2*log(1-y)) # # are two *independent* variables with normal distribution # (mu = 0, sigma = 1). # (Lambert Meertens) # (corrected version; bug discovered by Mike Miller, fixed by LM) # Multithreading note: When two threads call this function # simultaneously, it is possible that they will receive the # same return value. The window is very small though. To # avoid this, you have to use a lock around all calls. (I # didn't want to slow this down in the serial case by using a # lock here.) random = self.random z = self.gauss_next self.gauss_next = None if z is None: x2pi = random() * TWOPI g2rad = _sqrt(-2.0 * _log(1.0 - random())) z = _cos(x2pi) * g2rad self.gauss_next = _sin(x2pi) * g2rad return mu + z*sigma ## -------------------- beta -------------------- ## See ## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470 ## for Ivan Frohne's insightful analysis of why the original implementation: ## ## def betavariate(self, alpha, beta): ## # Discrete Event Simulation in C, pp 87-88. ## ## y = self.expovariate(alpha) ## z = self.expovariate(1.0/beta) ## return z/(y+z) ## ## was dead wrong, and how it probably got that way. def betavariate(self, alpha, beta): # This version due to Janne Sinkkonen, and matches all the std # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). y = self.gammavariate(alpha, 1.) if y == 0: return 0.0 else: return y / (y + self.gammavariate(beta, 1.)) ## -------------------- Pareto -------------------- def paretovariate(self, alpha): # Jain, pg. 495 u = self.random() return 1.0 / pow(u, 1.0/alpha) ## -------------------- Weibull -------------------- def weibullvariate(self, alpha, beta): # Jain, pg. 499; bug fix courtesy Bill Arms u = self.random() return alpha * pow(-_log(u), 1.0/beta) ## -------------------- test program -------------------- def _test_generator(n, funccall): import time print n, 'times', funccall code = compile(funccall, funccall, 'eval') sum = 0.0 sqsum = 0.0 smallest = 1e10 largest = -1e10 t0 = time.time() for i in range(n): x = eval(code) sum = sum + x sqsum = sqsum + x*x smallest = min(x, smallest) largest = max(x, largest) t1 = time.time() print round(t1-t0, 3), 'sec,', avg = sum/n stddev = _sqrt(sqsum/n - avg*avg) print 'avg %g, stddev %g, min %g, max %g' % \ (avg, stddev, smallest, largest) def _test(N=200): print 'TWOPI =', TWOPI print 'LOG4 =', LOG4 print 'NV_MAGICCONST =', NV_MAGICCONST print 'SG_MAGICCONST =', SG_MAGICCONST _test_generator(N, 'random()') _test_generator(N, 'normalvariate(0.0, 1.0)') _test_generator(N, 'lognormvariate(0.0, 1.0)') _test_generator(N, 'cunifvariate(0.0, 1.0)') _test_generator(N, 'expovariate(1.0)') _test_generator(N, 'vonmisesvariate(0.0, 1.0)') _test_generator(N, 'gammavariate(0.5, 1.0)') _test_generator(N, 'gammavariate(0.9, 1.0)') _test_generator(N, 'gammavariate(1.0, 1.0)') _test_generator(N, 'gammavariate(2.0, 1.0)') _test_generator(N, 'gammavariate(20.0, 1.0)') _test_generator(N, 'gammavariate(200.0, 1.0)') _test_generator(N, 'gauss(0.0, 1.0)') _test_generator(N, 'betavariate(3.0, 3.0)') _test_generator(N, 'paretovariate(1.0)') _test_generator(N, 'weibullvariate(1.0, 1.0)') # Test jumpahead. s = getstate() jumpahead(N) r1 = random() # now do it the slow way setstate(s) for i in range(N): random() r2 = random() if r1 != r2: raise ValueError("jumpahead test failed " + `(N, r1, r2)`) # Create one instance, seeded from current time, and export its methods # as module-level functions. The functions are not threadsafe, and state # is shared across all uses (both in the user's code and in the Python # libraries), but that's fine for most programs and is easier for the # casual user than making them instantiate their own Random() instance. _inst = Random() seed = _inst.seed random = _inst.random uniform = _inst.uniform randint = _inst.randint choice = _inst.choice randrange = _inst.randrange shuffle = _inst.shuffle normalvariate = _inst.normalvariate lognormvariate = _inst.lognormvariate cunifvariate = _inst.cunifvariate expovariate = _inst.expovariate vonmisesvariate = _inst.vonmisesvariate gammavariate = _inst.gammavariate stdgamma = _inst.stdgamma gauss = _inst.gauss betavariate = _inst.betavariate paretovariate = _inst.paretovariate weibullvariate = _inst.weibullvariate getstate = _inst.getstate setstate = _inst.setstate jumpahead = _inst.jumpahead whseed = _inst.whseed if __name__ == '__main__': _test() |
From: Finn B. <bc...@us...> - 2001-11-19 18:52:38
|
Update of /cvsroot/jython/jython/Lib In directory usw-pr-cvs1:/tmp/cvs-serv12772 Added Files: imaplib.py Log Message: A copy of CPython's imaplib that opens the socket stream with 'rb' mode. This copy should go away in jython 2.2 --- NEW FILE: imaplib.py --- """IMAP4 client. Based on RFC 2060. Public class: IMAP4 Public variable: Debug Public functions: Internaldate2tuple Int2AP ParseFlags Time2Internaldate """ # Author: Piers Lauder <pi...@cs...> December 1997. # # Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998. # String method conversion by ESR, February 2001. __version__ = "2.40" [...1086 lines suppressed...] if (cmd,args) != ('uid', ('SEARCH', 'ALL')): continue uid = dat[-1].split() if not uid: continue run('uid', ('FETCH', '%s' % uid[-1], '(FLAGS INTERNALDATE RFC822.SIZE RFC822.HEADER RFC822.TEXT)')) print '\nAll tests OK.' except: print '\nTests failed.' if not Debug: print ''' If you would like to see debugging output, try: %s -d5 ''' % sys.argv[0] raise |
From: Finn B. <bc...@us...> - 2001-11-19 17:57:14
|
Update of /cvsroot/jython/jython/Doc In directory usw-pr-cvs1:/tmp/cvs-serv28862 Modified Files: index.ht Log Message: Added links to the api docs. Index: index.ht =================================================================== RCS file: /cvsroot/jython/jython/Doc/index.ht,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** index.ht 2001/02/06 17:17:39 1.7 --- index.ht 2001/11/19 17:57:11 1.8 *************** *** 29,32 **** --- 29,37 ---- how to call Jython from a Java application. + <li>The generated JavaDoc documentation of the API is available + as <a href="api/index.html">frame</a> + and as <a href="api/overview-summary.html"> + non-frame</a> versions. + <li>You might also be interested in <a href="compile.html">building Jython from the source code</a>. |
From: Finn B. <bc...@us...> - 2001-11-15 17:15:33
|
Update of /cvsroot/jython/jython In directory usw-pr-cvs1:/tmp/cvs-serv28705 Modified Files: NEWS Log Message: Added notice about xreadline. Index: NEWS =================================================================== RCS file: /cvsroot/jython/jython/NEWS,v retrieving revision 2.37 retrieving revision 2.38 diff -C2 -d -r2.37 -r2.38 *** NEWS 2001/11/03 19:28:57 2.37 --- NEWS 2001/11/15 17:15:30 2.38 *************** *** 6,9 **** --- 6,10 ---- - The weakref module is now available. - The sys.exitfunc hook is called on exit. + - A CPython compatible xreadlines module. 29-jul-2001 Jython 2.1 alpha 3 |
From: Finn B. <bc...@us...> - 2001-11-15 08:17:20
|
Update of /cvsroot/jython/jython/Lib In directory usw-pr-cvs1:/tmp/cvs-serv8041 Modified Files: javaos.py Log Message: Fix a ValueError when faced with enviroment values with \n in the value. The patch will correctly support some form of values with \n. Some values are still not handled correctly, say: X='My\nPATH=Kevin' Such a value may cause the original PATH to overriden. Patch from Kevin Butler. Index: javaos.py =================================================================== RCS file: /cvsroot/jython/jython/Lib/javaos.py,v retrieving revision 2.10 retrieving revision 2.11 diff -C2 -d -r2.10 -r2.11 *** javaos.py 2001/11/14 17:57:26 2.10 --- javaos.py 2001/11/15 08:17:17 2.11 *************** *** 267,276 **** def _getEnvironment( self ): """Get the environment variables by spawning a subshell. """ p = self.execute( self.getEnv ) env = {} for line in self._readLines( p.getInputStream() ): ! i = line.index( '=' ) ! env[ self._keyTransform(line[:i])] = line[i+1:] return env --- 267,285 ---- def _getEnvironment( self ): """Get the environment variables by spawning a subshell. + This allows multi-line variables as long as subsequent lines do + not have '=' signs. """ p = self.execute( self.getEnv ) env = {} + key = 'firstLine' # in case first line had no '=' for line in self._readLines( p.getInputStream() ): ! try: ! i = line.index( '=' ) ! key = self._keyTransform(line[:i]) ! value = line[i+1:] ! except ValueError: ! # found no '=', so this line is part of previous value ! value = '%s\n%s' % ( value, line ) ! env[ key ] = value return env |
From: Finn B. <bc...@us...> - 2001-11-14 17:57:29
|
Update of /cvsroot/jython/jython/Lib In directory usw-pr-cvs1:/tmp/cvs-serv9736 Modified Files: javaos.py Log Message: _ShellEnv.system(): Start the stderr-reading thread before reading stdout, so that we don't see all of stdout before seeing any of stderr. Patch from Kevin. Index: javaos.py =================================================================== RCS file: /cvsroot/jython/jython/Lib/javaos.py,v retrieving revision 2.9 retrieving revision 2.10 diff -C2 -d -r2.9 -r2.10 *** javaos.py 2001/11/14 16:25:20 2.9 --- javaos.py 2001/11/14 17:57:26 2.10 *************** *** 220,228 **** def println( arg, write=sys.stdout.write ): write( arg + "\n" ) - # read stdin in main thread - self._readLines( p.getInputStream(), println ) # read stderr in secondary thread thread.start_new_thread( self._readLines, ( p.getErrorStream(), println )) return p.waitFor() --- 220,228 ---- def println( arg, write=sys.stdout.write ): write( arg + "\n" ) # read stderr in secondary thread thread.start_new_thread( self._readLines, ( p.getErrorStream(), println )) + # read stdin in main thread + self._readLines( p.getInputStream(), println ) return p.waitFor() |
From: Finn B. <bc...@us...> - 2001-11-14 16:28:37
|
Update of /cvsroot/jython/jython In directory usw-pr-cvs1:/tmp/cvs-serv10309 Modified Files: ACKNOWLEDGMENTS Log Message: Acks for the os.environ and os.system() implementation. Index: ACKNOWLEDGMENTS =================================================================== RCS file: /cvsroot/jython/jython/ACKNOWLEDGMENTS,v retrieving revision 2.12 retrieving revision 2.13 diff -C2 -d -r2.12 -r2.13 *** ACKNOWLEDGMENTS 2001/07/18 10:56:12 2.12 --- ACKNOWLEDGMENTS 2001/11/14 16:28:34 2.13 *************** *** 28,31 **** --- 28,34 ---- of bugs. + Kevin Butler have written and contributed the code for os.environ and + os.system(). + A huge thanks goes to all the members of the jpython/jython mailing lists. Other folks who have contributed to JPython and *************** *** 49,52 **** --- 52,56 ---- Robert W. Bill Durant Schoon + Phil Surette Local Variables: |
From: Finn B. <bc...@us...> - 2001-11-14 16:26:43
|
Update of /cvsroot/jython/jython In directory usw-pr-cvs1:/tmp/cvs-serv9528 Modified Files: registry Log Message: Added description of properties used by os.environ and os.system(). By Kevin Butler. Index: registry =================================================================== RCS file: /cvsroot/jython/jython/registry,v retrieving revision 2.15 retrieving revision 2.16 diff -C2 -d -r2.15 -r2.16 *** registry 2001/07/25 18:48:42 2.15 --- registry 2001/11/14 16:26:40 2.16 *************** *** 95,96 **** --- 95,113 ---- # python.jythonc.classpath = /usr/java1.2/jre/lib/rt.jar:/Jython/dist:. # python.jythonc.compileropts = +E +D -g + + # python.environment controls the type of environment + # support provided by the os module. Currently supported are: + # + # shell (default) + # Generate the environment by executing shell commands + # appropriate to the os environment. + # + # None + # Do not provide any environment or system() support. + #python.environment=shell + + # python.os controls the commands used to generate the environment. + # default is to choose commands based on the Java property "os.name". + # Some generic values are also supported: 'nt', 'dos', 'mac' and 'unix'. + #python.os=None + |