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: Samuele P. <ped...@us...> - 2001-11-23 02:16:40
|
Update of /cvsroot/jython/jython/Tools/jythonc In directory usw-pr-cvs1:/tmp/cvs-serv25114 Modified Files: BaseEvaluator.py Object.py proxies.py Log Message: + resetting imp_accu with null for gc; same as in interp. + removed last(?) occurrences of fragile Py.tojava(PyObject obj,String className). Index: BaseEvaluator.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/BaseEvaluator.py,v retrieving revision 2.12 retrieving revision 2.13 diff -C2 -d -r2.12 -r2.13 *** BaseEvaluator.py 2001/10/28 14:46:20 2.12 --- BaseEvaluator.py 2001/11/23 02:16:37 2.13 *************** *** 306,309 **** --- 306,311 ---- module.getattr(modname).makeReference(code))) + stmts.append(jast.Set(imp_accu,jast.Null)) + return stmts Index: Object.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/Object.py,v retrieving revision 2.4 retrieving revision 2.5 diff -C2 -d -r2.4 -r2.5 *** Object.py 2000/10/13 19:06:01 2.4 --- Object.py 2001/11/23 02:16:38 2.5 *************** *** 135,139 **** tname = type.__name__ tojava = jast.InvokeStatic('Py', 'tojava', ! [code, jast.StringConstant(tname)]) return jast.Cast(tname, tojava) --- 135,139 ---- tname = type.__name__ tojava = jast.InvokeStatic('Py', 'tojava', ! [code, jast.GetStaticAttribute(tname,'class')]) return jast.Cast(tname, tojava) Index: proxies.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/proxies.py,v retrieving revision 2.14 retrieving revision 2.15 diff -C2 -d -r2.14 -r2.15 *** proxies.py 2001/11/22 23:58:45 2.14 --- proxies.py 2001/11/23 02:16:38 2.15 *************** *** 59,65 **** r = jast.InvokeStatic("Py", "py2"+ret.__name__, [code]) else: r = jast.InvokeStatic("Py", "tojava", ! [code, jast.StringConstant(ret.__name__)]) ! r = jast.Cast(typeName(ret), r) return jast.Return(r) --- 59,66 ---- r = jast.InvokeStatic("Py", "py2"+ret.__name__, [code]) else: + typname = typeName(ret) r = jast.InvokeStatic("Py", "tojava", ! [code, jast.GetStaticAttribute(typname,'class')]) ! r = jast.Cast(typname, r) return jast.Return(r) |
From: Samuele P. <ped...@us...> - 2001-11-22 23:58:48
|
Update of /cvsroot/jython/jython/Tools/jythonc In directory usw-pr-cvs1:/tmp/cvs-serv5401 Modified Files: PythonModule.py proxies.py Log Message: Fix for [ #451746 ] jythonc --deep jpy$packages problem Index: PythonModule.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/PythonModule.py,v retrieving revision 2.16 retrieving revision 2.17 diff -C2 -d -r2.16 -r2.17 *** PythonModule.py 2001/11/21 11:37:25 2.16 --- PythonModule.py 2001/11/22 23:58:45 2.17 *************** *** 329,340 **** #Properties and packages for registry ! def getMainProperties(self): ! return jast.Identifier("jpy$mainProperties") ! def getProxyProperties(self): ! return jast.Identifier("jpy$proxyProperties") ! def getPackages(self): ! return jast.Identifier("jpy$packages") def dumpDictionary(self, dict, field): --- 329,349 ---- #Properties and packages for registry ! def getMainProperties(self,qual=0): ! if qual: ! return jast.GetStaticAttribute(self.name,"jpy$mainProperties") ! else: ! return jast.Identifier("jpy$mainProperties") ! def getProxyProperties(self,qual=0): ! if qual: ! return jast.GetStaticAttribute(self.name,"jpy$proxyProperties") ! else: ! return jast.Identifier("jpy$proxyProperties") ! def getPackages(self,qual=0): ! if qual: ! return jast.GetStaticAttribute(self.name,"jpy$packages") ! else: ! return jast.Identifier("jpy$packages") def dumpDictionary(self, dict, field): *************** *** 395,399 **** self.name+'.'+self.pyinner.name), "class"), jast.Identifier('newargs'), ! self.getPackages(), self.getMainProperties(), self.getFrozen(), jast.StringArray(self.modules.keys())] --- 404,408 ---- self.name+'.'+self.pyinner.name), "class"), jast.Identifier('newargs'), ! self.getPackages(qual=1), self.getMainProperties(qual=1), self.getFrozen(), jast.StringArray(self.modules.keys())] Index: proxies.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/proxies.py,v retrieving revision 2.13 retrieving revision 2.14 diff -C2 -d -r2.13 -r2.14 *** proxies.py 2001/11/21 11:41:41 2.13 --- proxies.py 2001/11/22 23:58:45 2.14 *************** *** 130,135 **** self.module = module if module is not None: ! self.packages = module.getPackages() ! self.properties = module.getProxyProperties() self.modname = module.name if module.package is not None: --- 130,135 ---- self.module = module if module is not None: ! self.packages = module.getPackages(qual=1) ! self.properties = module.getProxyProperties(qual=1) self.modname = module.name if module.package is not None: |
From: Samuele P. <ped...@us...> - 2001-11-22 23:56:31
|
Update of /cvsroot/jython/bugtests In directory usw-pr-cvs1:/tmp/cvs-serv4658 Added Files: test341.py test341c1.py test341c2.py Log Message: added bugtest 341 for [ #451746 ] jythonc --deep jpy$packages problem --- NEW FILE: test341.py --- """ [ #451746 ] jythonc --deep jpy$packages problem """ import support support.compileJPythonc("test341c1.py", deep=1 , output="test341.err") #raise support.TestError("" + `x`) --- NEW FILE: test341c1.py --- from test341c2 import test341c2 class bar(test341c2): pass --- NEW FILE: test341c2.py --- import java class test341c2(java.lang.Object): pass |
From: brian z. <bz...@us...> - 2001-11-22 05:59:30
|
Update of /cvsroot/jython/jython/Doc In directory usw-pr-cvs1:/tmp/cvs-serv24832 Modified Files: zxjdbc.ht Log Message: added dbexts documentation Index: zxjdbc.ht =================================================================== RCS file: /cvsroot/jython/jython/Doc/zxjdbc.ht,v retrieving revision 2.1 retrieving revision 2.2 diff -C2 -d -r2.1 -r2.2 *** zxjdbc.ht 2001/11/22 05:43:08 2.1 --- zxjdbc.ht 2001/11/22 05:59:27 2.2 *************** *** 27,31 **** <pre> ! Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC --- 27,31 ---- <pre> ! Jython 2.1b1 on java1.4.0-beta3 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC *************** *** 44,48 **** <pre> ! Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC --- 44,48 ---- <pre> ! Jython 2.1b1 on java1.4.0-beta3 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC *************** *** 78,82 **** <pre> ! Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC --- 78,82 ---- <pre> ! Jython 2.1b1 on java1.4.0-beta3 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC *************** *** 255,259 **** <pre> ! Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC --- 255,259 ---- <pre> ! Jython 2.1b1 on java1.4.0-beta3 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC *************** *** 301,303 **** --- 301,461 ---- handling prepared statement >>> + </pre> + + <h3>dbexts</h3> + + <p> + dbexts is a wrapper around DB API 2.0 compliant database modules. It currently supports zxJDBC and mxODBC but could easily be modified to support others. It allows developers to write scripts without knowledge of the implementation language of Python (either C or Java). It also greatly eases the burden of database coding as much of the functionality of the Python API is exposed through easier to use methods. + </p> + + <h3>Configuration file</h3> + <p> + dbexts needs a configuration file in order to create a connection. The configuration file has the following format: + <pre> + [default] + name=mysql_ziclix + + [jdbc] + name=mysql_ziclix + url=jdbc:mysql://localhost/ziclix + user= + pwd= + driver=org.gjt.mm.mysql.Driver + datahandler=com.ziclix.python.sql.handler.MySQLDataHandler + + [jdbc] + name=ora_ziclix + url=jdbc:oracle:thin:@localhost:1521:ziclix + user=ziclix + pwd=ziclix + driver=oracle.jdbc.driver.OracleDriver + datahandler=com.ziclix.python.sql.handler.OracleDataHandler + </pre> + + <h3>API</h3> + dbexts will default to looking for a file named 'dbexts.ini' in the same directory as dbexts.py but can optionally be passed a filename to the <code>cfg</code> attribute. + </p> + <dl> + <dt><p><code class="methodname">__init__(self, dbname=None, cfg=None, resultformatter=format_resultset, autocommit=1)</code></p></dt> + + <dd> + The initialization method for the dbexts class. If <code>dbname</code> is None, the default connection, as specified in the <code>cfg</code> file will be used. + </dd> + + <dt><p><code class="methodname">isql(self, sql, params=None, bindings=None, maxrows=None)</code></p></dt> + + <dd> + Interactively execute sql statement. If <i>self.verbose</i> is true, then the results (if any) are displayed using the result formatting method. If <code>maxrows</code> is specified, only <i>maxrows</i> are displayed. + </dd> + + <dt><p><code class="methodname">raw(self, sql, params=None, bindings=None, delim=None, comments=comments)</code></p></dt> + + <dd> + Executes the sql statement with params and bindings as necessary. Returns a tuple consisting of (headers, results). + </dd> + + <dt><p><code class="methodname">schema(table, full=0, sort=1)</code></p></dt> + + <dd> + Displays the schema (indicies, foreign keys, primary keys and columns) for the table parameter. If <code>full</code> is true, also compute the exported (or referenced) keys. If <code>sort</code> is true (the default), sort the column names. + <pre> + >>> d.schema("store") + Table + store + + Primary Keys + store_id {store_3} + + Imported (Foreign) Keys + location (city.city_id) {store_7} + + Exported (Referenced) Keys + store_id (site_store.store_id) {site_store_8} + + Columns + location int(4), non-nullable + store_id serial(4), non-nullable + store_name varchar(32), non-nullable + + Indices + unique index {523_8115} on (store_id) + unique index {store_ix_1} on (store_name) + >>> + </pre> + + </dd> + + <dt><p><code class="methodname">table(table=None, types=("TABLE",), owner=None, schema=None)</code></p></dt> + + <dd> + If no table argument, displays a list of all tables. If a table argument, displays the columns of the given table. + </dd> + + <dt><p><code class="methodname">proc(self, proc=None, owner=None, schema=None)</code></p></dt> + + <dd> + If no proc argument, displays a list of all procedures. If a proc argument, displays the parameters of the given procedure. + </dd> + + <dt><p><code class="methodname">bcp(src, table, where='(1=1)', parameters=[], selective=[], ignorelist=[], autobatch=0)</code></p></dt> + + <dd> + <i>B</i>ulk <i>C</i>o<i>p</i>y from one database/table to another. The current instance of dbexts is the source database to which the results of the query on the foreign database will be inserted. An optional <code>where</code> clause can narrow the number of rows to be copied. + </dd> + + </dl> + + <p>The following are generally not called since <code>isql</code> and <code>raw</code> can handle almost all cases.</p> + + <dl> + <dt><p><code class="methodname">begin(self)</code></p></dt> + + <dd> + Creates a new cursor. + </dd> + + <dt><p><code class="methodname">rollback(self)</code></p></dt> + + <dd> + Rollback all the statements since the creation of the cursor. + </dd> + + <dt><p><code class="methodname">commit(self, cursor=None, maxrows=None)</code></p></dt> + + <dd> + Commit all the statements since the creation of the cursor. + </dd> + + <dt><p><code class="methodname">display(self)</code></p></dt> + + <dd> + Display the results using the formatter. + </dd> + + </dl> + + <h3>Example session</h3> + + <pre> + Jython 2.1b1 on java1.4.0-beta3 (JIT: null) + Type "copyright", "credits" or "license" for more information. + >>> from dbexts import dbexts + >>> d = dbexts() + >>> d.isql("create table store (store_id int, store_name varchar(32), location int)") + >>> d.isql("insert into store values (?, ?, ?)", [(1, "amazon.com", 3), (2, "egghead.com", 4)]) + >>> d.isql("insert into store values (?, ?, ?)", [(15, "800.com", 1), (19, "fogdog.com", 3)]) + >>> d.isql("insert into store values (?, ?, ?)", [(5, "nike.com", 4)]) + >>> d.isql("select * from store order by store_name") + + STORE_ID | STORE_NAME | LOCATION + --------------------------------- + 15 | 800.com | 1 + 1 | amazon.com | 3 + 2 | egghead.com | 4 + 19 | fogdog.com | 3 + 5 | nike.com | 4 + + 5 rows affected + + >>> </pre> |
From: brian z. <bz...@us...> - 2001-11-22 05:43:50
|
Update of /cvsroot/jython/jython In directory usw-pr-cvs1:/tmp/cvs-serv22862 Modified Files: LICENSE.txt Log Message: added zxJDBC info Index: LICENSE.txt =================================================================== RCS file: /cvsroot/jython/jython/LICENSE.txt,v retrieving revision 2.3 retrieving revision 2.4 diff -C2 -d -r2.3 -r2.4 *** LICENSE.txt 2000/11/25 21:30:56 2.3 --- LICENSE.txt 2001/11/22 05:43:47 2.4 *************** *** 2,6 **** ======================= ! JPython was created in late 1997 by Jim Hugunin. Jim was also the primary developer while he was at CNRI. In February 1999 Barry Warsaw took over as primary developer and released JPython version 1.1. --- 2,6 ---- ======================= ! JPython was created in late 1997 by Jim Hugunin. Jim was also the primary developer while he was at CNRI. In February 1999 Barry Warsaw took over as primary developer and released JPython version 1.1. *************** *** 13,20 **** Lib/LICENSE file for details. ! The oro regular expresion matcher is covered by the apache license. See the org/apache/LICENSE file for details. ! Jython changes Software License. --- 13,22 ---- Lib/LICENSE file for details. ! The oro regular expresion matcher is covered by the apache license. See the org/apache/LICENSE file for details. ! The zxJDBC package was written by Brian Zimmer and originally licensed ! under the GNU Public License. The package is now covered by the Jython ! Software License. Jython changes Software License. *************** *** 24,53 **** All rights reserved. ! Redistribution and use in source and binary forms, with or without ! modification, are permitted provided that the following conditions are met: ! - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ! - Redistributions in binary form must reproduce the above copyright ! notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ! - Neither the name of the Jython Developers nor the names of ! its contributors may be used to endorse or promote products ! derived from this software without specific prior written permission. ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ! ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- 26,55 ---- All rights reserved. ! Redistribution and use in source and binary forms, with or without ! modification, are permitted provided that the following conditions are met: ! - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ! - Redistributions in binary form must reproduce the above copyright ! notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ! - Neither the name of the Jython Developers nor the names of ! its contributors may be used to endorse or promote products ! derived from this software without specific prior written permission. ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ! ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
From: brian z. <bz...@us...> - 2001-11-22 05:43:11
|
Update of /cvsroot/jython/jython/Doc In directory usw-pr-cvs1:/tmp/cvs-serv22772/Doc Modified Files: compile.ht links.h Added Files: zxjdbc.ht Log Message: added zxJDBC documentation --- NEW FILE: zxjdbc.ht --- Title: zxJDBC <h3>Database connectivity in Jython</h3> <p>The zxJDBC package provides a nearly 100% <a href="http://www.python.org">Python</a> <a href="http://www.python.org/topics/database/DatabaseAPI-2.0.html"> DB API 2.0</a> compliant interface for database connectivity in <a href="http://jython.sourceforge.net/">Jython</a>. It is implemented entirely in <a href="http://www.javasoft.com">Java</a> and makes use of the <a href="http://www.javasoft.com/jdbc">JDBC</a> API. This means any database capable of being accessed through JDBC, either directly or using the JDBC-ODBC bridge, can be manipulated using zxJDBC.</p> <h3>Getting a Connection</h3> <p>First, make sure a valid JDBC driver is in your classpath. Then start Jython and import the zxJDBC connection factory.</p> <h4>Using a Driver</h4> <p>The most common way to establish a connection is through a Driver. Simply supply the database, username, password and JDBC driver classname to the connect method. If your driver requires special arguments, pass them into the <code>connect</code> method as standard Python keyword arguments. You will be returned a connection object.</p> <pre> Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC >>> d, u, p, v = "jdbc:mysql://localhost/test", None, None, "org.gjt.mm.mysql.Driver" >>> db = zxJDBC.connect(d, u, p, v) <i><b>optionally</b></i> >>> db = zxJDBC.connect(d, u, p, v, CHARSET='iso_1') >>> </pre> <a name="connectx"/> <h4>Using a DataSource (or ConnectionPooledDataSource)</h4> <p>The only required argument is the fully-qualified classname of the DataSource, all keywords will use JavaBeans reflection to set properties on the DataSource.</p> <pre> Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC >>> params = {} >>> params['serverName'] = 'localhost' >>> params['databaseName'] = 'ziclix' >>> params['user'] = None >>> params['password'] = None >>> params['port'] = 3306 >>> db = apply(zxJDBC.connectx, ("org.gjt.mm.mysql.MysqlDataSource",), params) >>> </pre> <h4>Using a JNDI lookup</h4> <p>It is possible for zxJDBC to use a Connection found through a JNDI lookup. This is particularly useful in an application server (such as when using PyServlet). The bound object can be either a String, Connection, DataSource or ConnectionPooledDataSource. The <code>lookup</code> will figure out the instance type and access the Connection accordingly,</p> <p>The only required argument is the JNDI lookup name. All keyword arguments will be converted to their proper <a href="http://java.sun.com/j2se/1.3/docs/api/javax/naming/Context.html">Context</a> field value if the keyword matches one of the constants. If a field name does not exist for the keyword, it will passed as declared. The resulting environment will be used to build the <a href="http://java.sun.com/j2se/1.3/docs/api/javax/naming/InitialContext.html">InitialContext</a>. </p> <p><i>This example uses the simple Sun FileSystem JNDI reference implementation. Please consult the JNDI implementation you intend to use for the InitialContextFactory classname as well as the connection URL.</i></p> <pre> Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC >>> jndiName = "/temp/jdbc/mysqldb" >>> factory = "com.sun.jndi.fscontext.RefFSContextFactory" >>> db = zxJDBC.lookup(jndiName, INITIAL_CONTEXT_FACTORY=factory) >>> </pre> <h3><a name="dynamiccursor"/>Getting a Cursor</h3> <p> In order execute any operation, a cursor is required from the connection. There are two different kinds of cursors: <i>static</i> and <i>dynamic</i>. </p> <p> The primary difference between the two is the way they manage the underlying ResultSet. In the <i>static</i> version, the entire ResultSet is iterated immediately, the data converted and stored with the cursor and the ResultSet closed. This allows the cursor to know the rowcount (not available otherwise within JDBC) and set the <code>.rowcount</code> attribute properly. The major disadvantage to this approach is the space/time constraints might be extraordinary. </p> <p> The solution to the problem are <i>dynamic</i> cursors which keep a handle to the open ResultSet and iterate as required. This drastically decreases memory consumption and increases perceived response time because no work is done until asked. The drawback is the <code>.rowcount</code> attribute can never be accurately set. </p> <p> To execute a query simply provide the SQL expression and call <code> execute</code>. The cursor now has a <code>description</code> attribute detailing the column information. To navigate the result set, call one of the <code>fetch</code> methods and a list of tuples will be returned. </p> <pre> >>> c = db.cursor() # this gets a static cursor <i><b>or</b></i> >>> c = db.cursor(1) # this gets a dynamic cursor >>> c.execute("select count(*) c from player") >>> c.description [('c', 3, 17, None, 15, 0, 1)] >>> for a in c.fetchall(): ... print a ... (13569,) >>> </pre> <p>When finished, close the connections.</p> <pre> >>> c.close() >>> db.close() >>> </pre> <h3>Standard extensions to the Python DB API</h3> <dl> <dt><p><code class="methodname">connection.dbname</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getDatabaseProductName()"> DatabaseMetaData.getDatabaseProductName</a></dd> <dt><p><code class="methodname">connection.dbversion</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getDatabaseProductVersion()"> DatabaseMetaData.getDatabaseProductVersion</a></dd> <dt><p><code class="methodname">cursor.tables(qualifier,owner,table,type)</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[])"> DatabaseMetaData.getTables</a></dd> <dt><p><code class="methodname">cursor.columns(qualifier,owner,table,column)</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)"> DatabaseMetaData.getColumns</a></dd> <dt><p><code class="methodname">cursor.foreignkeys(primary_qualifier,primary_owner,pimary_table, foreign_qualifier,foreign_owner,foreign_table)</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getCrossReference(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)"> DatabaseMetaData.getCrossReference</a></dd> <dt><p><code class="methodname">cursor.primarykeys(qualifier,owner,table)</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getPrimaryKeys(java.lang.String, java.lang.String, java.lang.String)"> DatabaseMetaData.getPrimaryKeys</a></dd> <dt><p><code class="methodname">cursor.procedures(qualifier,owner,procedure)</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getProcedures(java.lang.String, java.lang.String, java.lang.String)"> DatabaseMetaData.getProcedures</a></dd> <dt><p><code class="methodname">cursor.procedurecolumns(qualifier,owner,procedure,column)</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getProcedureColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)"> DatabaseMetaData.getProcedureColumns</a></dd> <dt><p><code class="methodname">cursor.statistics(qualifier,owner,table,unique,accuracy)</code></p></dt> <dd>Same as <a href="http://java.sun.com/j2se/1.3/docs/api/java/sql/DatabaseMetaData.html#getIndexInfo(java.lang.String, java.lang.String, java.lang.String, boolean, boolean)"> DatabaseMetaData.getIndexInfo</a></dd> </dl> <h3><a name="bindings"/>Datatype mapping callbacks through DataHandler</h3> <p>The DataHandler interface has three methods for handling type mappings. They are called at two different times, one when fetching and the other when binding objects for use in a prepared statement. I have chosen this architecture for type binding because I noticed a number of discrepancies in how different JDBC drivers handled database types, in particular the additional types available in later JDBC versions.</p> <dl> <dt><p><code class="methodname">public PyObject getPyObject(ResultSet set, int col, int type);</code></p></dt> <dd>This method is called upon fetching data from the database. Given the JDBC type, return the appropriate PyObject subclass from the Java object at column col in the ResultSet set.</dd> <dt><p><code class="methodname">public Object getJDBCObject(PyObject object, int type);</code></p></dt> <dd>This method is called when a PreparedStatement is created through use of the <code>execute</code> method. When the parameters are being bound to the statement, the DataHandler gets a callback to map the type. This is only called if type bindings are present.</dd> <dt><p><code class="methodname">public Object getJDBCObject(PyObject object);</code></p></dt> <dd>This method is called when no type bindings are present during the execution of a PreparedStatement.</dd> <dt><p><code class="methodname">public void preExecute(Statement stmt) throws SQLException;</code></p></dt> <dd>A callback prior to each execution of the statement. If the statement is a PreparedStatement (created when parameters are sent to the <code>execute</code> method), all the parameters will have been set.</dd> <dt><p><code class="methodname">public void postExecute(Statement stmt) throws SQLException;</code></p></dt> <dd>A callback after successfully executing the statement. This is particularly useful for cases such as auto-incrementing columns where the statement knows the inserted value.</dd> </dl> <p>It is simple to use these callbacks to achieve the desired result for your database driver. In the majority of cases nothing needs to be done to get the correct datatype mapping. However, in the cases where drivers differ from the spec or handle values differently, the DataHandler callbacks should provide the solution.</p> <h4>Example DataHandler for Informix booleans</h4> <p>One such case where a driver needs a special mapping is Informix booleans. The are represented as the characters 't' and 'f' in the database and have their own type <code>boolean</code>. You can see from the example below, without the special DataHandler, the boolean type mapping fails.</p> <pre> Jython 2.1a3 on java1.3.0 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> from com.ziclix.python.sql import zxJDBC >>> zxJDBC.autocommit = 0 >>> d, u, p, v = "database", "user", "password", "com.informix.jdbc.IfxDriver" >>> db = zxJDBC.connect(d, u, p, v) >>> c = db.cursor() >>> c.execute("create table g (a boolean)") >>> c.execute("insert into g values (?)", [1]) Traceback (innermost last): File "<console>", line 1, in ? Error: No cast from integer to boolean. [SQLCode: -9634] >>> from com.ziclix.python.sql.informix import InformixDataHandler >>> c.datahandler = InformixDataHandler(c.datahandler) >>> c.execute("insert into g values (?)", [1], {0:zxJDBC.OTHER}) >>> </pre> <p>As you can see, the default handler fails to convert the Python <code>1</code> into an Informix boolean because the IfxDriver treats booleans as JDBC type <code>OTHER</code>. The InformixDataHandler is intimately aware of the IfxDriver mappings and understands how to interpret Python values as booleans when the JDBC type is <code>OTHER</code>.</p> <p>This functionality is also useful in handling the more advanced JDBC 2.0 types <code>CLOB</code>, <code>BLOB</code> and <code> Array</code>.</p> <p>You can also implement the DataHandler from within Jython as in this simple example:</p> <pre> >>> class PyHandler(DataHandler): >>> def __init__(self, handler): >>> self.handler = handler >>> def getPyObject(self, set, col, datatype): >>> return self.handler.getPyObject(set, col, datatype) >>> def getJDBCObject(self, object, datatype): >>> print "handling prepared statement" >>> return self.handler.getJDBCObject(object, datatype) >>> >>> c.datahandler = PyHandler(c.datahandler) >>> c.execute("insert into g values (?)", [1]) handling prepared statement >>> </pre> Index: compile.ht =================================================================== RCS file: /cvsroot/jython/jython/Doc/compile.ht,v retrieving revision 2.5 retrieving revision 2.6 diff -C2 -d -r2.5 -r2.6 *** compile.ht 2001/08/06 18:26:49 2.5 --- compile.ht 2001/11/22 05:43:08 2.6 *************** *** 13,21 **** <ul> ! <li>The source directories from CVS or the nightly buils contain both makefiles and a build.xml file. Only the build.xml is updated at this time. We are using ant-1.2 to compile the sources and create the .jar file. <p> ! The build.xml file will search for a properties file called <code>ant.properties</code> which can contain values to control paths and local options. My <code>ant.properties</code> file look like this: --- 13,21 ---- <ul> ! <li>The source directories from CVS or the nightly buils contain both makefiles and a build.xml file. Only the build.xml is updated at this time. We are using ant-1.2 to compile the sources and create the .jar file. <p> ! The build.xml file will search for a properties file called <code>ant.properties</code> which can contain values to control paths and local options. My <code>ant.properties</code> file look like this: *************** *** 43,56 **** scp.command=scp scp.user=bckfnn </pre></blockquote> <p> ! <li>Some of the sources in the org.python.parser package are generated ! from python.jtt file by the JavaCC parser generator. If you need to ! make changes to the grammar file you will need to download this JavaCC. The generated files are also in the distribution, so usually this is not necessary. ! <P>To regenerate the parser from the grammar, run jjtree on python.jjt, and then run javacc on the resulting python.jj. This should produce all of the required source files to build the org.python.parser package. --- 43,65 ---- scp.command=scp scp.user=bckfnn + + # Needed for building zxJDBC DataHandlers + # If missing, the appropriate DataHandler will not be built + oracle.jar=d:/java/lib/classes12.zip + mysql.jar=d:/java/lib/mm.mysql-2.0.6.jar + informix.jar=d:/java/lib/ifxjdbc.jar;d:/java/lib/ifxjdbcx.jar + postgresql.jar=d:/java/lib/postgresql.jar + jdbc.jar=d:/java/lib/jdbc2_0-stdext.jar + </pre></blockquote> <p> ! <li>Some of the sources in the org.python.parser package are generated ! from python.jtt file by the JavaCC parser generator. If you need to ! make changes to the grammar file you will need to download this JavaCC. The generated files are also in the distribution, so usually this is not necessary. ! <P>To regenerate the parser from the grammar, run jjtree on python.jjt, and then run javacc on the resulting python.jj. This should produce all of the required source files to build the org.python.parser package. *************** *** 72,80 **** <li>One of the sources depends on the servlet classes and can only compile when servlet.jar is included on the classpath. Again, the build.xml have ! a conditional check and will not compile the PyServlet class if the servlet classes isn't available during compilation. <p> ! <li>The CVS only contain a few of the standard python modules. The rest most come from a CPython installation. Setting this up can be performed by creating a file ".jython" in your home directory and including a line like --- 81,89 ---- <li>One of the sources depends on the servlet classes and can only compile when servlet.jar is included on the classpath. Again, the build.xml have ! a conditional check and will not compile the PyServlet class if the servlet classes isn't available during compilation. <p> ! <li>The CVS only contain a few of the standard python modules. The rest most come from a CPython installation. Setting this up can be performed by creating a file ".jython" in your home directory and including a line like *************** *** 85,89 **** <li>The PyXML sources (the content of ./Lib/xml) is not included in the ! CVS repository. This is mainly because PyXML is developed and released in its own time cycle. To install PyXML support in a CVS version, the ant properties <code>PyXmlHome</code> and <code>python.home</code> must be configured and --- 94,98 ---- <li>The PyXML sources (the content of ./Lib/xml) is not included in the ! CVS repository. This is mainly because PyXML is developed and released in its own time cycle. To install PyXML support in a CVS version, the ant properties <code>PyXmlHome</code> and <code>python.home</code> must be configured and *************** *** 91,98 **** </ul> ! <P>If you have further interest in the Jython source and Jython's ! continued development, you can read the archives for the <a href="http://www.geocrawler.com/lists/3/SourceForge/7018/0/"> ! Jython-dev mailing list</a> or you can <a href="http://lists.sourceforge.net/mailman/listinfo/jython-dev">join</a> the list. --- 100,107 ---- </ul> ! <P>If you have further interest in the Jython source and Jython's ! continued development, you can read the archives for the <a href="http://www.geocrawler.com/lists/3/SourceForge/7018/0/"> ! Jython-dev mailing list</a> or you can <a href="http://lists.sourceforge.net/mailman/listinfo/jython-dev">join</a> the list. Index: links.h =================================================================== RCS file: /cvsroot/jython/jython/Doc/links.h,v retrieving revision 2.3 retrieving revision 2.4 diff -C2 -d -r2.3 -r2.4 *** links.h 2001/02/01 13:32:30 2.3 --- links.h 2001/11/22 05:43:08 2.4 *************** *** 14,17 **** --- 14,18 ---- <li><a href="jythonc.html">Building applets, servlets, beans...</a> <li><a href="jreload.html">Reloading java classes</a> + <li><a href="zxjdbc.html">zxJDBC</a> <h3>Python Docs (exits)</h3> <li><a href="http://www.python.org/doc/tut/tut.html">Python Tutorial</a> |
From: brian z. <bz...@us...> - 2001-11-22 05:41:50
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql In directory usw-pr-cvs1:/tmp/cvs-serv22601/com/ziclix/python/sql Modified Files: PyCursor.java Log Message: fixed jikes warning on thrown exceptions Index: PyCursor.java =================================================================== RCS file: /cvsroot/jython/jython/com/ziclix/python/sql/PyCursor.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PyCursor.java 2001/11/20 04:55:18 1.1 --- PyCursor.java 2001/11/22 05:41:48 1.2 *************** *** 57,61 **** try { DATAHANDLER = new JDBC20DataHandler(DATAHANDLER); ! } catch (Exception e) {} } --- 57,61 ---- try { DATAHANDLER = new JDBC20DataHandler(DATAHANDLER); ! } catch (Throwable t) {} } |
From: brian z. <bz...@us...> - 2001-11-22 00:36:50
|
Update of /cvsroot/jython/jython/installer In directory usw-pr-cvs1:/tmp/cvs-serv23436/installer Modified Files: mklist.py Log Message: fixed a typo Index: mklist.py =================================================================== RCS file: /cvsroot/jython/jython/installer/mklist.py,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** mklist.py 2001/11/20 04:57:57 1.24 --- mklist.py 2001/11/22 00:36:47 1.25 *************** *** 220,231 **** listfiles(None, "org/python/util", *javafiles) listfiles(None, "Lib/jxxload_help", *javafiles) ! listfiles(None, "com/ziclix/python/sql", *.javafiles) ! listfiles(None, "com/ziclix/python/sql/util", *.javafiles) ! listfiles(None, "com/ziclix/python/sql/resource", *.javafiles) ! listfiles(None, "com/ziclix/python/sql/pipe", *.javafiles) ! listfiles(None, "com/ziclix/python/sql/pipe/db", *.javafiles) ! listfiles(None, "com/ziclix/python/sql/pipe/csv", *.javafiles) ! listfiles(None, "com/ziclix/python/sql/handler", *.javafiles) ! listfiles(None, "com/ziclix/python/sql/connect", *.javafiles) comment("Library modules from CPython") --- 220,231 ---- listfiles(None, "org/python/util", *javafiles) listfiles(None, "Lib/jxxload_help", *javafiles) ! listfiles(None, "com/ziclix/python/sql", *javafiles) ! listfiles(None, "com/ziclix/python/sql/util", *javafiles) ! listfiles(None, "com/ziclix/python/sql/resource", *javafiles) ! listfiles(None, "com/ziclix/python/sql/pipe", *javafiles) ! listfiles(None, "com/ziclix/python/sql/pipe/db", *javafiles) ! listfiles(None, "com/ziclix/python/sql/pipe/csv", *javafiles) ! listfiles(None, "com/ziclix/python/sql/handler", *javafiles) ! listfiles(None, "com/ziclix/python/sql/connect", *javafiles) comment("Library modules from CPython") |
From: Finn B. <bc...@us...> - 2001-11-21 11:43:35
|
Update of /cvsroot/jython/jython/org/python/core In directory usw-pr-cvs1:/tmp/cvs-serv18182 Modified Files: Py.java Log Message: Fix for [ #480390 ] main() does not throw exceptions. Add a throw clause to the runMain() method signature and don't print the exception in runMain(). Instead the exception must be printed by one of the callers of runMain() which typically is the JVM. Index: Py.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/core/Py.java,v retrieving revision 2.54 retrieving revision 2.55 diff -C2 -d -r2.54 -r2.55 *** Py.java 2001/11/21 11:21:21 2.54 --- Py.java 2001/11/21 11:43:32 2.55 *************** *** 797,801 **** String[] props, String frozenPackage, ! String[] modules) { //System.err.println("main: "+module); --- 797,801 ---- String[] props, String frozenPackage, ! String[] modules) throws Exception { //System.err.println("main: "+module); *************** *** 814,820 **** PyObject mod = imp.createFromCode("__main__", code); } catch (PyException e) { - Py.printException(e); Py.getSystemState().callExitFunc(); ! System.exit(-1); } Py.getSystemState().callExitFunc(); --- 814,819 ---- PyObject mod = imp.createFromCode("__main__", code); } catch (PyException e) { Py.getSystemState().callExitFunc(); ! throw e; } Py.getSystemState().callExitFunc(); |
From: Finn B. <bc...@us...> - 2001-11-21 11:41:44
|
Update of /cvsroot/jython/jython/Tools/jythonc In directory usw-pr-cvs1:/tmp/cvs-serv17316 Modified Files: proxies.py Log Message: Fix for [ #480390 ] main() does not throw exceptions. Use a different property lists to the initProxy() and the runMain(). In initProxy() we still want to see java exception, in runMain() it is now the JVM that prints the exception thrown from the main() method. Index: proxies.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/proxies.py,v retrieving revision 2.12 retrieving revision 2.13 diff -C2 -d -r2.12 -r2.13 *** proxies.py 2001/06/30 01:03:13 2.12 --- proxies.py 2001/11/21 11:41:41 2.13 *************** *** 131,135 **** if module is not None: self.packages = module.getPackages() ! self.properties = module.getProperties() self.modname = module.name if module.package is not None: --- 131,135 ---- if module is not None: self.packages = module.getPackages() ! self.properties = module.getProxyProperties() self.modname = module.name if module.package is not None: |
From: Finn B. <bc...@us...> - 2001-11-21 11:37:28
|
Update of /cvsroot/jython/jython/Tools/jythonc In directory usw-pr-cvs1:/tmp/cvs-serv16750 Modified Files: PythonModule.py Log Message: Fix for [ #480390 ] main() does not throw exceptions. Add a throw clause to the generated main() method. Also give a different property lists to the initProxy() and the runMain(). In initProxy() we still want to see java exception, in runMain() it is now the JVM that prints the exception thrown from the main() method. Index: PythonModule.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/PythonModule.py,v retrieving revision 2.15 retrieving revision 2.16 diff -C2 -d -r2.15 -r2.16 *** PythonModule.py 2001/11/21 11:24:22 2.15 --- PythonModule.py 2001/11/21 11:37:25 2.16 *************** *** 225,236 **** ! defaultProps = { ! ## now redundant ! ## "python.packages.paths": "", ! ## "python.packages.directories": "", "python.options.showJavaExceptions": "true", "python.modules.builtin": "exceptions:org.python.core.exceptions", } --- 225,237 ---- ! defaultProxyProps = { "python.options.showJavaExceptions": "true", "python.modules.builtin": "exceptions:org.python.core.exceptions", } + defaultMainProps = { + "python.modules.builtin": "exceptions:org.python.core.exceptions", + } + *************** *** 248,252 **** def __init__(self, name, filename="<unknown>", packages = [], ! properties=defaultProps, frozen=1): package = None dot = name.rfind('.') --- 249,254 ---- def __init__(self, name, filename="<unknown>", packages = [], ! proxyProperties=defaultProxyProps, ! mainProperties=defaultMainProps, frozen=1): package = None dot = name.rfind('.') *************** *** 270,274 **** self.packages = packages ! self.properties = properties self.innerClasses = [] --- 272,277 ---- self.packages = packages ! self.proxyProperties = proxyProperties ! self.mainProperties = mainProperties self.innerClasses = [] *************** *** 326,331 **** #Properties and packages for registry ! def getProperties(self): ! return jast.Identifier("jpy$properties") def getPackages(self): --- 329,337 ---- #Properties and packages for registry ! def getMainProperties(self): ! return jast.Identifier("jpy$mainProperties") ! ! def getProxyProperties(self): ! return jast.Identifier("jpy$proxyProperties") def getPackages(self): *************** *** 340,344 **** def dumpProperties(self): ! return self.dumpDictionary(self.properties, self.getProperties()) def dumpPackages(self): --- 346,355 ---- def dumpProperties(self): ! return [ ! self.dumpDictionary(self.mainProperties, ! self.getMainProperties()), ! self.dumpDictionary(self.proxyProperties, ! self.getProxyProperties()) ! ] def dumpPackages(self): *************** *** 384,388 **** self.name+'.'+self.pyinner.name), "class"), jast.Identifier('newargs'), ! self.getPackages(), self.getProperties(), self.getFrozen(), jast.StringArray(self.modules.keys())] --- 395,399 ---- self.name+'.'+self.pyinner.name), "class"), jast.Identifier('newargs'), ! self.getPackages(), self.getMainProperties(), self.getFrozen(), jast.StringArray(self.modules.keys())] *************** *** 390,394 **** maincode = jast.Block(code) meths.append(jast.Method("main", "public static", ! ["void", ("String[]", "args")], maincode)) return meths --- 401,406 ---- maincode = jast.Block(code) meths.append(jast.Method("main", "public static", ! ["void", ("String[]", "args")], maincode, ! ["java.lang.Exception"])) return meths |
From: Finn B. <bc...@us...> - 2001-11-21 11:24:25
|
Update of /cvsroot/jython/jython/Tools/jythonc In directory usw-pr-cvs1:/tmp/cvs-serv14671 Modified Files: PythonModule.py Log Message: Fix for [ #480373 ] Can't find _PyInner with classloader. dumpMain(): Load the _PyInner class in the main class and pass the loaded class to Py.runMain(). Index: PythonModule.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/PythonModule.py,v retrieving revision 2.14 retrieving revision 2.15 diff -C2 -d -r2.14 -r2.15 *** PythonModule.py 2001/05/27 18:50:56 2.14 --- PythonModule.py 2001/11/21 11:24:22 2.15 *************** *** 381,386 **** code.append(jast.InvokeStatic("System", "arraycopy", args)) ! args = [jast.StringConstant(self.getclassname( ! self.name+'$'+self.pyinner.name)), jast.Identifier('newargs'), self.getPackages(), self.getProperties(), --- 381,386 ---- code.append(jast.InvokeStatic("System", "arraycopy", args)) ! args = [jast.GetStaticAttribute(self.getclassname( ! self.name+'.'+self.pyinner.name), "class"), jast.Identifier('newargs'), self.getPackages(), self.getProperties(), |
From: Finn B. <bc...@us...> - 2001-11-21 11:22:48
|
Update of /cvsroot/jython/jython/org/python/compiler In directory usw-pr-cvs1:/tmp/cvs-serv14230 Modified Files: JavaMaker.java Log Message: Fix for [ #480373 ] Can't find _PyInner with classloader. Load the _PyInner class in the main class. That way it gets loaded by the same classloader. Index: JavaMaker.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/compiler/JavaMaker.java,v retrieving revision 2.12 retrieving revision 2.13 diff -C2 -d -r2.12 -r2.13 *** JavaMaker.java 2001/10/28 17:13:42 2.12 --- JavaMaker.java 2001/11/21 11:22:45 2.13 *************** *** 143,148 **** ClassFile.PUBLIC | ClassFile.STATIC); ! // Load the name of the Python module to run code.ldc(pythonModule); // Load in any command line arguments code.aload(0); --- 143,153 ---- ClassFile.PUBLIC | ClassFile.STATIC); ! // Load the class of the Python module to run ! int forname = code.pool.Methodref( ! "java/lang/Class","forName", ! "(Ljava/lang/String;)Ljava/lang/Class;"); code.ldc(pythonModule); + code.invokestatic(forname); + // Load in any command line arguments code.aload(0); *************** *** 153,157 **** int runMain = code.pool.Methodref( "org/python/core/Py", "runMain", ! "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Z)V"); code.invokestatic(runMain); code.return_(); --- 158,162 ---- int runMain = code.pool.Methodref( "org/python/core/Py", "runMain", ! "(Ljava/lang/Class;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Z)V"); code.invokestatic(runMain); code.return_(); |
From: Finn B. <bc...@us...> - 2001-11-21 11:21:23
|
Update of /cvsroot/jython/jython/org/python/core In directory usw-pr-cvs1:/tmp/cvs-serv13985 Modified Files: Py.java Log Message: Fix for [ #480373 ] Can't find _PyInner with classloader. Pass in the loaded _PyInner class instead of the classname. Index: Py.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/core/Py.java,v retrieving revision 2.53 retrieving revision 2.54 diff -C2 -d -r2.53 -r2.54 *** Py.java 2001/11/03 19:42:40 2.53 --- Py.java 2001/11/21 11:21:21 2.54 *************** *** 793,797 **** } ! public static void runMain(String module, String[] args, String[] packages, String[] props, --- 793,797 ---- } ! public static void runMain(Class mainClass, String[] args, String[] packages, String[] props, *************** *** 801,813 **** //System.err.println("main: "+module); - Class mainClass=null; - try { - // ??pending: should use Py.findClass? - mainClass = Class.forName(module); - } catch (ClassNotFoundException exc) { - System.err.println("Error running main. Can't find: "+module); - System.exit(-1); - } - initProperties(args, packages, props, frozenPackage, modules, mainClass.getClassLoader()); --- 801,804 ---- *************** *** 818,822 **** code = ((PyRunnable)mainClass.newInstance()).getMain(); } catch (Throwable t) { ! System.err.println("Invalid class: "+module+"$py"); System.exit(-1); } --- 809,813 ---- code = ((PyRunnable)mainClass.newInstance()).getMain(); } catch (Throwable t) { ! System.err.println("Invalid class: "+mainClass.getName()+"$py"); System.exit(-1); } |
From: Finn B. <bc...@us...> - 2001-11-21 11:11:42
|
Update of /cvsroot/jython/bugtests In directory usw-pr-cvs1:/tmp/cvs-serv11254 Modified Files: driver.py Log Message: Increased range to 350 tests. Index: driver.py =================================================================== RCS file: /cvsroot/jython/bugtests/driver.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** driver.py 2001/08/19 14:40:13 1.5 --- driver.py 2001/11/21 11:11:39 1.6 *************** *** 17,21 **** warnings = "-w" in opts ! for i in range(340): m = None n = "test%3.3d" % i --- 17,21 ---- warnings = "-w" in opts ! for i in range(350): m = None n = "test%3.3d" % i |
From: Finn B. <bc...@us...> - 2001-11-21 11:10:46
|
Update of /cvsroot/jython/bugtests In directory usw-pr-cvs1:/tmp/cvs-serv11085 Added Files: test340.py test340c.py test340j.java Log Message: Test for [ #480390 ] main() does not throw exceptions. --- NEW FILE: test340.py --- """ [ #480390 ] main() does not throw exceptions """ import support support.compileJPythonc("test340c.py", core=1, jar="test340.jar", output="test340.err") support.compileJava("test340j.java") rc = support.runJava("test340j", classpath=".", expectError=1) if rc != 42: support.TestError("Did not catch exception correctly %d" % rc) --- NEW FILE: test340c.py --- import java.lang.Exception raise java.lang.Exception --- NEW FILE: test340j.java --- import java.net.*; import java.lang.reflect.*; public class test340j { public static void main(String[] args) { try { String jar = "./test340.jar"; URLClassLoader theLoader = new URLClassLoader(new URL[] { new URL("file:" + jar)}); Object theLoadedClass = Class.forName("test340c", true, theLoader). newInstance(); String[] array = new String[] {}; Method main = theLoadedClass.getClass(). getMethod("main", new Class[] { array.getClass() }); main.invoke(theLoadedClass, new Object[] {new String[] {}}); } catch (Throwable t) { System.exit(42); } System.exit(43); } } |
From: Samuele P. <ped...@us...> - 2001-11-20 16:52:26
|
Update of /cvsroot/jython/jython/Tools/jythonc In directory usw-pr-cvs1:/tmp/cvs-serv17047 Modified Files: ObjectFactory.py compile.py Log Message: fix for [ #449956 ] jythonc 2.1a3 --package problem. Index: ObjectFactory.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/ObjectFactory.py,v retrieving revision 2.10 retrieving revision 2.11 diff -C2 -d -r2.10 -r2.11 *** ObjectFactory.py 2001/07/09 20:23:30 2.10 --- ObjectFactory.py 2001/11/20 16:52:23 2.11 *************** *** 208,212 **** self.pySupername = full_py self.supername = modname - self.supername = ':'+self.supername # ':' => Compiler will in case prefix this with opts.javapackage def isSuperclassJava(self): --- 208,211 ---- *************** *** 254,258 **** if cls: if cls.value.isSuperclassJava(): ! self._takeSupername(cls.value,mod,modname = modname) continue --- 253,259 ---- if cls: if cls.value.isSuperclassJava(): ! # pass no modname but just mod, ! # javapackage should be included ! self._takeSupername(cls.value,mod) continue Index: compile.py =================================================================== RCS file: /cvsroot/jython/jython/Tools/jythonc/compile.py,v retrieving revision 2.19 retrieving revision 2.20 diff -C2 -d -r2.19 -r2.20 *** compile.py 2001/06/30 01:03:13 2.19 --- compile.py 2001/11/20 16:52:23 2.20 *************** *** 314,320 **** if pyc.isSuperclassJava(): supername, pySupername = pyc.supername, pyc.pySupername - if supername and supername[0] == ':': - supername = supername[1:] - if self.javapackage: supername = self.javapackage + '.' + supername return proxies.JavaProxy(pyc.name, (supername, pySupername), pyc.javaclasses, methods, module, pyc.issuperproxy) --- 314,317 ---- |
From: Samuele P. <ped...@us...> - 2001-11-20 16:49:06
|
Update of /cvsroot/jython/bugtests In directory usw-pr-cvs1:/tmp/cvs-serv15433 Added Files: test339.py test339c.py Log Message: bugtest 339 for [ #449956 ] jythonc 2.1a3 --package problem --- NEW FILE: test339.py --- """ [ #449956 ] jythonc 2.1a3 --package problem """ import support support.compileJPythonc("test339c.py", package="test339p", output="test339.err") #raise support.TestError("" + `x`) --- NEW FILE: test339c.py --- import java import test339c class spam(java.lang.Object): pass class eggs1(spam): pass class eggs2(test339c.spam): pass |
From: Samuele P. <ped...@us...> - 2001-11-20 16:47:34
|
Update of /cvsroot/jython/bugtests/test339p In directory usw-pr-cvs1:/tmp/cvs-serv15172/test339p Log Message: Directory /cvsroot/jython/bugtests/test339p added to the repository |
From: brian z. <bz...@us...> - 2001-11-20 04:59:01
|
Update of /cvsroot/jython/jython In directory usw-pr-cvs1:/tmp/cvs-serv8066 Modified Files: build.xml Log Message: add com/ziclix Index: build.xml =================================================================== RCS file: /cvsroot/jython/jython/build.xml,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** build.xml 2001/08/19 14:39:33 1.16 --- build.xml 2001/11/20 04:58:58 1.17 *************** *** 2,9 **** <project name="jython" default="jar" basedir="."> <target name="init"> ! <property name="sourceDir" value="." /> ! <property name="outputDir" value="build" /> ! <property name="apidocDir" value="Doc/api" /> <property name="debug" value="off" /> <property name="optimize" value="on" /> --- 2,33 ---- <project name="jython" default="jar" basedir="."> + + <!-- + This propery should be specified in the ant.property file + property name="javaccHome2" value="/opt/javacc2.0/bin/lib" + --> + + <!-- Give users a change to override editing this file. --> + <property file="ant.properties" /> + + <!-- =================================================================== --> + <!-- Classpaths --> + <!-- =================================================================== --> + <path id="main.classpath"> + <pathelement path="${informix.jar}"/> + <pathelement path="${oracle.jar}"/> + <pathelement path="${mysql.jar}"/> + <pathelement path="${postgresql.jar}"/> + <pathelement path="${jndi.jar}"/> + <pathelement path="${jdbc.jar}"/> + <pathelement path="${java.class.path}"/> + <pathelement location="${build.classes}"/> + </path> + <target name="init"> ! ! <property name="sourceDir" value="${basedir}" /> ! <property name="outputDir" value="${basedir}/build" /> ! <property name="apidocDir" value="${basedir}/Doc/api" /> <property name="debug" value="off" /> <property name="optimize" value="on" /> *************** *** 14,22 **** <available classname="org.gnu.readline.Readline" property="readline" /> ! <!-- This propery should be specified in the ant.property file ! property name="javaccHome2" value="/opt/javacc2.0/bin/lib" /--> ! <!-- Give users a change to override editing this file--> ! <property file="ant.properties" /> </target> --- 38,77 ---- <available classname="org.gnu.readline.Readline" property="readline" /> ! <available property="informix.present" ! classname="com.informix.jdbc.IfxDriver" ! classpath="${informix.jar}" ! /> ! <available property="mysql.present" ! classname="org.gjt.mm.mysql.Driver" ! classpath="${mysql.jar}" ! /> ! <available property="postgresql.present" ! classname="org.postgresql.Driver" ! classpath="${postgresql.jar}" ! /> ! <available property="oracle.present" ! classname="oracle.jdbc.driver.OracleDriver" ! classpath="${oracle.jar}" ! /> ! <available property="jndi.present" ! classname="javax.naming.Context" ! classpath="${jndi.jar}" ! /> ! <available property="javax.sql.present" ! classname="javax.sql.DataSource" ! classpath="${jdbc.jar}" ! /> ! <echo>--- Build environment for ${ant.project.name} ---</echo> ! <echo>--- Flags (Note: If the {property name} is displayed, then the component is not present)</echo> ! <echo/> ! <echo>--- Optional Libraries ---</echo> ! <echo>oracle = ${oracle.present}</echo> ! <echo>informix = ${informix.present}</echo> ! <echo>mysql = ${mysql.present}</echo> ! <echo>postgresql = ${postgresql.present}</echo> ! <echo>jndi = ${jndi.present}</echo> ! <echo>jdbc = ${javax.sql.present}</echo> ! </target> *************** *** 40,45 **** <target name="tree" depends="prepare"> ! <jjtree ! javacchome="${javaccHome2}" target="org/python/parser/python.jjt" outputdirectory="org/python/parser/" --- 95,100 ---- <target name="tree" depends="prepare"> ! <jjtree ! javacchome="${javaccHome2}" target="org/python/parser/python.jjt" outputdirectory="org/python/parser/" *************** *** 48,53 **** <target name="parser" depends="tree"> ! <javacc ! javacchome="${javaccHome2}" target="org/python/parser/python.jj" outputdirectory="org/python/parser/" --- 103,108 ---- <target name="parser" depends="tree"> ! <javacc ! javacchome="${javaccHome2}" target="org/python/parser/python.jj" outputdirectory="org/python/parser/" *************** *** 58,66 **** </target> ! <!-- Only do this task if our environment is java2. --> <target name="check.javaversion" unless="java2"> ! <property name="exclude.java2.files" value="**/CollectionProxy2.java, **/Java2Accessibility.java, --- 113,121 ---- </target> ! <!-- Only do this task if our environment is java2. --> <target name="check.javaversion" unless="java2"> ! <property name="exclude.java2.files" value="**/CollectionProxy2.java, **/Java2Accessibility.java, *************** *** 75,89 **** <target name="check.servlet" unless="servlet"> ! <property name="exclude.servlet.files" value="**/PyServlet.java"/> </target> <target name="check.weakref" unless="weakref"> ! <property name="exclude.weakref.files" value="**/_weakref.java"/> </target> <target name="check.readline" unless="readline"> ! <property name="exclude.readline.files" value="**/ReadlineConsole.java"/> </target> --- 130,144 ---- <target name="check.servlet" unless="servlet"> ! <property name="exclude.servlet.files" value="**/PyServlet.java"/> </target> <target name="check.weakref" unless="weakref"> ! <property name="exclude.weakref.files" value="**/_weakref.java"/> </target> <target name="check.readline" unless="readline"> ! <property name="exclude.readline.files" value="**/ReadlineConsole.java"/> </target> *************** *** 95,127 **** <target name="compile" depends="prepare,parser,checks"> ! <javac ! srcdir="${sourceDir}/" ! includes="org/**" ! destdir="${outputDir}/" ! excludes="org/python/parser/python.java, ! ${exclude.java2.files}, ! ${exclude.servlet.files}, ! ${exclude.weakref.files}, ! ${exclude.readline.files}" debug="${debug}" ! optimize="${optimize}" ! /> ! <javac ! srcdir="${sourceDir}/Lib" includes="jxxload_help/**" ! destdir="${outputDir}/" debug="${debug}" optimize="${optimize}" /> ! <copy file="org/python/modules/ucnhash.dat" todir="${outputDir}/org/python/modules" /> </target> <target name="jar" depends="compile"> ! <jar jarfile="jython.jar" ! basedir="${outputDir}" ! includes="**/*.class,**/ucnhash.dat" /> </target> --- 150,198 ---- <target name="compile" depends="prepare,parser,checks"> ! <javac ! srcdir="${sourceDir}/" ! destdir="${outputDir}/" debug="${debug}" ! optimize="${optimize}"> ! <include name="org/**"/> ! <include name="com/**"/> ! <exclude name="org/python/parser/python.java"/> ! <exclude name="${exclude.java2.files}"/> ! <exclude name="${exclude.servlet.files}"/> ! <exclude name="${exclude.weakref.files}"/> ! <exclude name="${exclude.readline.files}"/> ! <exclude name="**/handler/InformixDataHandler.java" unless="informix.present"/> ! <exclude name="**/handler/MySQLDataHandler.java" unless="mysql.present"/> ! <exclude name="**/handler/OracleDataHandler.java" unless="oracle.present"/> ! <exclude name="**/handler/PostgresqlDataHandler.java" unless="postgresql.present"/> ! <exclude name="**/connect/Lookup.java" unless="jndi.present"/> ! <exclude name="**/connect/Lookup.java" unless="javax.sql.present"/> ! <exclude name="**/connect/Connectx.java" unless="javax.sql.present"/> ! <classpath refid="main.classpath"/> ! </javac> ! <javac ! srcdir="${sourceDir}/Lib" includes="jxxload_help/**" ! destdir="${outputDir}/" debug="${debug}" optimize="${optimize}" /> ! <copy file="org/python/modules/ucnhash.dat" todir="${outputDir}/org/python/modules" /> + + <copy todir="${outputDir}/com"> + <fileset dir="${sourceDir}/com"> + <include name="**/*.properties"/> + </fileset> + </copy> + </target> <target name="jar" depends="compile"> ! <jar jarfile="jython.jar" ! basedir="${outputDir}" ! includes="**/*.class,**/ucnhash.dat,**/*.properties" /> </target> *************** *** 130,137 **** <javadoc sourcepath="${sourceDir}" destdir="${apidocDir}" ! Public="Yes" packagenames="org.python.core, ! org.python.util" ! Windowtitle="Jython API documentation" bottom="<a href='http://www.jython.org'>Jython homepage</a>" /> --- 201,209 ---- <javadoc sourcepath="${sourceDir}" destdir="${apidocDir}" ! public="true" packagenames="org.python.core, ! org.python.util, ! com.ziclix.python.sql" ! windowtitle="Jython API documentation" bottom="<a href='http://www.jython.org'>Jython homepage</a>" /> *************** *** 160,165 **** </target> ! <target name="all" depends="init,clean,prepare,parser,compile,jar"> ! </target> </project> --- 232,236 ---- </target> ! <target name="all" depends="init,clean,prepare,parser,compile,jar"/> </project> |
From: brian z. <bz...@us...> - 2001-11-20 04:58:00
|
Update of /cvsroot/jython/jython/installer In directory usw-pr-cvs1:/tmp/cvs-serv7817/installer Modified Files: mklist.py Log Message: added com/ziclix/** packages Index: mklist.py =================================================================== RCS file: /cvsroot/jython/jython/installer/mklist.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** mklist.py 2001/11/19 18:55:00 1.23 --- mklist.py 2001/11/20 04:57:57 1.24 *************** *** 11,20 **** else: rootdir = os.path.join(d, mask) ! fl = glob.glob(rootdir) for f in fl: ! if os.path.basename(f) in exclude: continue ! # After this, the name is a true mess of different # path seperator chars. Attempt to clean this by making # the jar contain only unix seps. --- 11,20 ---- else: rootdir = os.path.join(d, mask) ! fl = glob.glob(rootdir) for f in fl: ! if os.path.basename(f) in exclude: continue ! # After this, the name is a true mess of different # path seperator chars. Attempt to clean this by making # the jar contain only unix seps. *************** *** 152,157 **** # New CPython files added in Jython ! 'pstats.py', ! 'code.py', 'codecs.py', #'re.py', --- 152,157 ---- # New CPython files added in Jython ! 'pstats.py', ! 'code.py', 'codecs.py', #'re.py', *************** *** 220,223 **** --- 220,231 ---- listfiles(None, "org/python/util", *javafiles) listfiles(None, "Lib/jxxload_help", *javafiles) + listfiles(None, "com/ziclix/python/sql", *.javafiles) + listfiles(None, "com/ziclix/python/sql/util", *.javafiles) + listfiles(None, "com/ziclix/python/sql/resource", *.javafiles) + listfiles(None, "com/ziclix/python/sql/pipe", *.javafiles) + listfiles(None, "com/ziclix/python/sql/pipe/db", *.javafiles) + listfiles(None, "com/ziclix/python/sql/pipe/csv", *.javafiles) + listfiles(None, "com/ziclix/python/sql/handler", *.javafiles) + listfiles(None, "com/ziclix/python/sql/connect", *.javafiles) comment("Library modules from CPython") |
From: brian z. <bz...@us...> - 2001-11-20 04:55:22
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/util In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql/util Added Files: BCP.java PyArgParser.java Queue.java QueueClosedException.java Log Message: initial zxJDBC checkin --- NEW FILE: BCP.java --- /* * Jython Database Specification API 2.0 * * $Id: BCP.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.util; import java.util.*; import java.lang.reflect.*; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.pipe.*; import com.ziclix.python.sql.pipe.db.*; import com.ziclix.python.sql.handler.*; /** * A class to perform efficient Bulk CoPy of database tables. */ public class BCP extends PyObject implements ClassDictInit { /** Field sourceDH, destDH */ protected Class sourceDH, destDH; /** Field batchsize, queuesize */ protected int batchsize, queuesize; /** Field source, destination */ protected PyConnection source, destination; /** * The source connection will produce the rows while the destination * connection will consume the rows and coerce as necessary for the * destination database. */ public BCP(PyConnection source, PyConnection destination) { this(source, destination, -1); } /** * The source connection will produce the rows while the destination * connection will consume the rows and coerce as necessary for the * destination database. * * @param batchsize used to batch the inserts on the destination */ public BCP(PyConnection source, PyConnection destination, int batchsize) { this.source = source; this.destination = destination; this.destDH = null; this.sourceDH = null; this.batchsize = batchsize; this.queuesize = 0; } // __class__ boilerplate -- see PyObject for details /** 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[1]; m[0] = new PyString("bcp"); __methods__ = new PyList(m); m = new PyObject[6]; m[0] = new PyString("source"); m[1] = new PyString("destination"); m[2] = new PyString("batchsize"); m[3] = new PyString("queuesize"); m[4] = new PyString("sourceDataHandler"); m[5] = new PyString("destinationDataHandler"); __members__ = new PyList(m); } /** * String representation of the object. * * @return a string representation of the object. */ public String toString() { return "<BCP object instance at " + hashCode() + ">"; } /** * Sets the attribute name to value. * * @param name * @param value */ public void __setattr__(String name, PyObject value) { if ("destinationDataHandler".equals(name)) { this.destDH = (Class)value.__tojava__(Class.class); } else if ("sourceDataHandler".equals(name)) { this.sourceDH = (Class)value.__tojava__(Class.class); } else if ("batchsize".equals(name)) { this.batchsize = ((Number)value.__tojava__(Number.class)).intValue(); } else if ("queuesize".equals(name)) { this.queuesize = ((Number)value.__tojava__(Number.class)).intValue(); } 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 ("destinationDataHandler".equals(name)) { return Py.java2py(this.destDH); } else if ("sourceDataHandler".equals(name)) { return Py.java2py(this.sourceDH); } else if ("batchsize".equals(name)) { return Py.newInteger(this.batchsize); } else if ("queuesize".equals(name)) { return Py.newInteger(this.queuesize); } 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__("bcp", new BCPFunc("bcp", 0, 1, 2, zxJDBC.getString("bcp"))); dict.__setitem__("batchsize", Py.newString(zxJDBC.getString("batchsize"))); dict.__setitem__("queuesize", Py.newString(zxJDBC.getString("queuesize"))); // hide from python dict.__setitem__("classDictInit", null); dict.__setitem__("toString", null); dict.__setitem__("PyClass", null); dict.__setitem__("getPyClass", null); dict.__setitem__("sourceDH", null); dict.__setitem__("destDH", null); } /** * Bulkcopy data from one database to another. * * @param fromTable the table in question on the source database * @param where an optional where clause, defaults to '(1=1)' if null * @param params optional params to substituted in the where clause * @param include the columns to be queried from the source, '*' if None * @param exclude the columns to be excluded from insertion on the destination, all if None * @param toTable if non-null, the table in the destination db, otherwise the same table name as the source * @param bindings the optional bindings for the destination, this allows morphing of types during the copy * @return the count of the total number of rows bulk copied, -1 if the query returned no rows */ protected PyObject bcp(String fromTable, String where, PyObject params, PyObject include, PyObject exclude, String toTable, PyObject bindings) { Pipe pipe = new Pipe(); String _toTable = (toTable == null) ? fromTable : toTable; DBSource source = new DBSource(this.source, sourceDH, fromTable, where, include, params); DBSink sink = new DBSink(this.destination, destDH, _toTable, exclude, bindings, this.batchsize); return pipe.pipe(source, sink).__sub__(Py.newInteger(1)); } } /** * Class BCPFunc * * @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 BCPFunc extends PyBuiltinFunctionSet { /** * Constructor BCPFunc * * @param String name * @param int index * @param int argcount * @param String doc * */ BCPFunc(String name, int index, int argcount, String doc) { super(name, index, argcount, argcount, true, doc); } /** * Constructor BCPFunc * * @param String name * @param int index * @param int minargs * @param int maxargs * @param String doc * */ BCPFunc(String name, int index, int minargs, int maxargs, String doc) { super(name, index, minargs, maxargs, true, doc); } /** * Method __call__ * * @param PyObject arg * * @return PyObject * */ public PyObject __call__(PyObject arg) { BCP bcp = (BCP)__self__; switch (index) { case 0 : String table = (String)arg.__tojava__(String.class); if (table == null) { throw Py.ValueError(zxJDBC.getString("invalidTableName")); } PyObject count = bcp.bcp(table, null, Py.None, Py.None, Py.None, null, Py.None); return count; default : throw argCountError(1); } } /** * Method __call__ * * @param PyObject arga * @param PyObject argb * * @return PyObject * */ public PyObject __call__(PyObject arga, PyObject argb) { BCP bcp = (BCP)__self__; switch (index) { case 0 : String table = (String)arga.__tojava__(String.class); if (table == null) { throw Py.ValueError(zxJDBC.getString("invalidTableName")); } String where = (String)argb.__tojava__(String.class); PyObject count = bcp.bcp(table, where, Py.None, Py.None, Py.None, null, Py.None); return count; 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) { BCP bcp = (BCP)__self__; switch (index) { case 0 : String table = (String)arga.__tojava__(String.class); if (table == null) { throw Py.ValueError(zxJDBC.getString("invalidTableName")); } String where = (String)argb.__tojava__(String.class); PyObject count = bcp.bcp(table, where, argc, Py.None, Py.None, null, Py.None); return count; default : throw argCountError(3); } } /** * Method __call__ * * @param PyObject[] args * @param String[] keywords * * @return PyObject * */ public PyObject __call__(PyObject[] args, String[] keywords) { BCP bcp = (BCP)__self__; switch (index) { case 0 : /* * B.bcp(table, [where=None, params=None, include=None, exclude=None, toTable=None, bindings=None]) */ String where = null; PyObject params = Py.None; PyArgParser parser = new PyArgParser(args, keywords); String table = (String)parser.arg(0, Py.None).__tojava__(String.class); if (table == null) { throw Py.ValueError(zxJDBC.getString("invalidTableName")); } // 'where' can be the second argument or a keyword if (parser.numArg() >= 2) { where = (String)parser.arg(1, Py.None).__tojava__(String.class); } if (where == null) { where = (String)parser.kw("where", Py.None).__tojava__(String.class); } // 'params' can be the third argument or a keyword if (parser.numArg() >= 3) { params = parser.arg(2, Py.None); } if (params == Py.None) { params = parser.kw("params", Py.None); } String toTable = (String)parser.kw("toTable", Py.None).__tojava__(String.class); PyObject include = parser.kw("include", Py.None); PyObject exclude = parser.kw("exclude", Py.None); PyObject bindings = parser.kw("bindings", Py.None); PyObject count = bcp.bcp(table, where, params, include, exclude, toTable, bindings); return count; default : throw argCountError(3); } } } --- NEW FILE: PyArgParser.java --- /* * Jython Database Specification API 2.0 * * $Id: PyArgParser.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.util; import java.io.*; import java.sql.*; import java.math.*; import java.util.*; import org.python.core.*; /** * Parse the args and kws for a method call. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class PyArgParser extends Object { /** Field keywords */ protected Map keywords; /** Field arguments */ protected PyObject[] arguments; /** * Construct a parser with the arguments and keywords. */ public PyArgParser(PyObject[] args, String[] kws) { this.keywords = new HashMap(); this.arguments = null; parse(args, kws); } /** * Method parse * * @param PyObject[] args * @param String[] kws * */ protected void parse(PyObject[] args, String[] kws) { // walk backwards through the kws and build the map int largs = args.length; if (kws != null) { for (int i = kws.length - 1; i >= 0; i--) { keywords.put(kws[i], args[--largs]); } } this.arguments = new PyObject[largs]; System.arraycopy(args, 0, this.arguments, 0, largs); } /** * How many keywords? */ public int numKw() { return this.keywords.keySet().size(); } /** * Does the keyword exist? */ public boolean hasKw(String kw) { return this.keywords.containsKey(kw); } /** * Return the value for the keyword, raise a KeyError if the keyword does * not exist. */ public PyObject kw(String kw) { if (!hasKw(kw)) { throw Py.KeyError(kw); } return (PyObject)this.keywords.get(kw); } /** * Return the value for the keyword, return the default if the keyword does * not exist. */ public PyObject kw(String kw, PyObject def) { if (!hasKw(kw)) { return def; } return (PyObject)this.keywords.get(kw); } /** * Get the array of keywords. */ public String[] kws() { return (String[])this.keywords.keySet().toArray(new String[0]); } /** * Get the number of arguments. */ public int numArg() { return this.arguments.length; } /** * Return the argument at the given index, raise an IndexError if out of range. */ public PyObject arg(int index) { if ((index >= 0) && (index <= this.arguments.length - 1)) { return this.arguments[index]; } throw Py.IndexError("index out of range"); } /** * Return the argument at the given index, or the default if the index is out of range. */ public PyObject arg(int index, PyObject def) { if ((index >= 0) && (index <= this.arguments.length - 1)) { return this.arguments[index]; } return def; } } --- NEW FILE: Queue.java --- /* * Jython Database Specification API 2.0 * * $Id: Queue.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.util; import java.util.LinkedList; /** * This queue blocks until closed or an element is enqueued. If the queue * reaches capacity, the dequeue thread gets priority in order to bring the * queue size under a certain threshold. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class Queue { /** Field closed */ protected boolean closed; /** Field queue */ protected LinkedList queue; /** Field capacity, threshold */ protected int capacity, threshold; /** * Instantiate a blocking queue with no bounded capacity. */ public Queue() { this(0); } /** * Instantiate a blocking queue with the specified capacity. */ public Queue(int capacity) { this.closed = false; this.capacity = capacity; this.queue = new LinkedList(); this.threshold = (int)(this.capacity * 0.75f); } /** * Enqueue an object and notify all waiting Threads. */ public synchronized void enqueue(Object element) throws InterruptedException { if (closed) { throw new QueueClosedException(); } this.queue.addLast(element); this.notify(); /* * Block while the capacity of the queue has been breached. */ while ((this.capacity > 0) && (this.queue.size() >= this.capacity)) { this.wait(); if (closed) { throw new QueueClosedException(); } } } /** * Blocks until an object is dequeued or the queue is closed. */ public synchronized Object dequeue() throws InterruptedException { while (this.queue.size() <= 0) { this.wait(); if (closed) { throw new QueueClosedException(); } } Object object = this.queue.removeFirst(); // if space exists, notify the other threads if (this.queue.size() < this.threshold) { this.notify(); } return object; } /** * Close the queue and notify all waiting Threads. */ public synchronized void close() { this.closed = true; this.notifyAll(); } } --- NEW FILE: QueueClosedException.java --- /* * Jython Database Specification API 2.0 * * $Id: QueueClosedException.java,v 1.1 2001/11/20 04:55:18 bzimmer Exp $ * * Copyright (c) 2001 brian zimmer <bz...@zi...> * */ package com.ziclix.python.sql.util; /** * This exception is thrown when the queue is closed and an operation is attempted. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class QueueClosedException extends RuntimeException { /** * Constructor QueueClosedException * */ public QueueClosedException() { super(); } /** * Constructor QueueClosedException * * @param String msg * */ public QueueClosedException(String msg) { super(msg); } } |
From: brian z. <bz...@us...> - 2001-11-20 04:55:22
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/resource In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql/resource Added Files: zxJDBCMessages.properties Log Message: initial zxJDBC checkin --- NEW FILE: zxJDBCMessages.properties --- # doc strings Error=Exception that is the base class of all other error exceptions. Warning=Exception raised for important warnings like data truncations \ while inserting, etc. InterfaceError=Exception raised for errors that are related to the database \ interface rather than the database itself. DatabaseError=Exception raised for errors that are related to the database. InternalError=Exception raised when the database encounters an internal error, \ e.g. the cursor is not valid anymore, the transaction is out of sync, etc. OperationalError=Exception raised for errors that are related to the database's \ operation and not necessarily under the control of the programmer, e.g. an \ unexpected disconnect occurs, the data source name is not found, a transaction \ could not be processed, a memory allocation error occurred during processing, etc. ProgrammingError=Exception raised for programming errors, e.g. table not found or \ already exists, syntax error in the SQL statement, wrong number of parameters \ specified, etc. IntegrityError=Exception raised when the relational integrity of the database is \ affected, e.g. a foreign key check fails. DataError=Exception raised for errors that are due to problems with the processed \ data like division by zero, numeric value out of range, etc. NotSupportedError=Exception raised in case a method or database API was used which \ is not supported by the database, e.g. requesting a .rollback() on a connection that \ does not support transaction or has transactions turned off. # BCP bcp.0=bcp(table, [where=None, params=None, include=None, exclude=None, toTable=None, bindings=None]) bcp.1=\ Copies data resulting from a query on the source to the appropriate table on the \ destination. Returns the count of the total number of rows bulk copied or -1 if the \ query on the source returned no rows. If the destination excludes all the columns an \ Error will be raised. bcp.2=\ table - the table to query on the source database bcp.3=\ where - an optional where clause, defaults to (1=1) if None bcp.4=\ params - optional params to substituted in the where clause bcp.5=\ include - the columns to be queried from the source, * if None bcp.6=\ exclude - the columns to be excluded from insertion on the destination, all if None bcp.7=\ toTable - if non-None, the table in the destination db, otherwise the same table as the source bcp.8=\ bindings - the optional bindings for the destination, this allows morphing of types during the copy batchsize=the batch interval for inserts queuesize=the maximum number of objects the queue can hold, 0 means unbounded (the default) # PyConnection close.0=Close the connection now (rather than whenever __del__ is called). close.1=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. commit.0=Commit any pending transaction to the database. commit.1=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. cursor.0=cursor([dynamic=0]) cursor.1=\ Return a new Cursor Object using the connection. cursor.2=\ dynamic - If non-zero, return a Cursor that does NOT iterate the results immediately. cursor.3=\ This greatly increases the performance of large result sets, but fails to cursor.4=\ set the .rowcount attribute on the Cursor. cursor.5=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. rollback.0=This method is optional since not all databases provide transaction support. rollback.1=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. # exception messages noStoredProc=stored procedures not implemented in db optionalSecond=optional second argument must be a list or tuple bindingValue=binding value must be a valid integer type from java.sql.Types onlyOneResultSet=dynamic fetch allows only one result set inconsistentRowCount=number of rows queried [{0,integer}] does not match number of rows inserted [{1,integer}] invalidCons=invalid constructor for class [{0}] noColInfo=unable to obtain column info excludedAllCols=excluded all columns invalidTableName=invalid table name [None] errorSettingIndex=error setting index [{0}], type [{1}] |
From: brian z. <bz...@us...> - 2001-11-20 04:55:22
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/pipe/db In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql/pipe/db Added Files: BaseDB.java DBSink.java DBSource.java Log Message: initial zxJDBC checkin --- NEW FILE: BaseDB.java --- /* * Jython Database Specification API 2.0 * * $Id: BaseDB.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.db; import java.util.*; import java.lang.reflect.*; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.handler.*; /** * Abstract class to assist in generating cursors. * * @author brian zimmer * @version $Revision: 1.1 $ */ public abstract class BaseDB { /** Field cursor */ protected PyCursor cursor; /** Field dataHandler */ protected Class dataHandler; /** Field tableName */ protected String tableName; /** Field connection */ protected PyConnection connection; /** * Construct the helper. */ public BaseDB(PyConnection connection, Class dataHandler, String tableName) { this.tableName = tableName; this.dataHandler = dataHandler; this.connection = connection; this.cursor = this.cursor(); } /** * Create a new constructor and optionally bind a new DataHandler. The new DataHandler must act as * a Decorator, having a single argument constructor of another DataHandler. The new DataHandler is * then expected to delegate all calls to the original while enhancing the functionality in any matter * desired. This allows additional functionality without losing any previous work or requiring any * complicated inheritance dependencies. */ protected PyCursor cursor() { PyCursor cursor = this.connection.cursor(true); DataHandler origDataHandler = cursor.getDataHandler(), newDataHandler = null; if ((origDataHandler != null) && (this.dataHandler != null)) { Constructor cons = null; try { Class[] args = new Class[1]; args[0] = DataHandler.class; cons = this.dataHandler.getConstructor(args); } catch (Exception e) { return cursor; } if (cons == null) { String msg = zxJDBC.getString("invalidCons", new Object[]{ this.dataHandler.getName() }); throw zxJDBC.newError(msg); } try { Object[] args = new Object[1]; args[0] = origDataHandler; newDataHandler = (DataHandler)cons.newInstance(args); } catch (Exception e) { return cursor; } if (newDataHandler != null) { cursor.__setattr__("datahandler", Py.java2py(newDataHandler)); } } return cursor; } } --- NEW FILE: DBSink.java --- /* * Jython Database Specification API 2.0 * * $Id: DBSink.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.db; import java.util.*; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.pipe.*; import com.ziclix.python.sql.handler.*; /** * A database consumer. All data transferred will be inserted into the appropriate table. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class DBSink extends BaseDB implements Sink { /** Field sql */ protected String sql; /** Field exclude */ protected Set exclude; /** Field rows */ protected PyList rows; /** Field batchsize */ protected int batchsize; /** Field bindings */ protected PyObject bindings; /** Field indexedBindings */ protected PyDictionary indexedBindings; /** * Constructor for handling the consumption of data. * * @param connection the database connection * @param dataHandler a custom DataHandler for the cursor, can be None * @param tableName the table to insert the data * @param exclude the columns to be excluded from insertion on the destination, all if None * @param bindings the optional bindings for the destination, this allows morphing of types during the copy * @param batchsize the optional batchsize for the inserts */ public DBSink(PyConnection connection, Class dataHandler, String tableName, PyObject exclude, PyObject bindings, int batchsize) { super(connection, dataHandler, tableName); this.sql = null; this.rows = new PyList(); this.bindings = bindings; this.batchsize = batchsize; this.exclude = new HashSet(); this.indexedBindings = new PyDictionary(); if (exclude != Py.None) { for (int i = 0; i < exclude.__len__(); i++) { PyObject lowered = Py.newString(((PyString)exclude.__getitem__(i)).lower()); this.exclude.add(lowered); } } } /** * Return true if the key (converted to lowercase) is not found in the exclude list. */ protected boolean excluded(PyObject key) { PyObject lowered = Py.newString(((PyString)key).lower()); return this.exclude.contains(lowered); } /** * Create the insert statement given the header row. */ protected void createSql(PyObject row) { // this should be the column info if ((row == Py.None) || (row.__len__() == 0)) { // if there are no columns, what's the point? throw zxJDBC.newError(zxJDBC.getString("noColInfo")); } int index = 0, len = row.__len__(); PyObject entry = Py.None, col = Py.None, pyIndex = Py.None; StringBuffer sb = new StringBuffer("insert into ").append(this.tableName).append(" ("); /* * Iterate through the columns and pull out the names for use in the insert * statement and the types for use in the bindings. The tuple is of the form * (column name, column type). */ for (int i = 0; i < len - 1; i++) { entry = row.__getitem__(i); col = entry.__getitem__(0); if (!this.excluded(col)) { // add to the list sb.append(col).append(","); // add the binding pyIndex = Py.newInteger(index++); try { this.indexedBindings.__setitem__(pyIndex, this.bindings.__getitem__(col)); } catch (Exception e) { // either a KeyError or this.bindings is None or null this.indexedBindings.__setitem__(pyIndex, entry.__getitem__(1)); } } } entry = row.__getitem__(len - 1); col = entry.__getitem__(0); if (!this.excluded(col)) { sb.append(col); pyIndex = Py.newInteger(index++); try { this.indexedBindings.__setitem__(pyIndex, this.bindings.__getitem__(col)); } catch (Exception e) { // either a KeyError or this.bindings is None or null this.indexedBindings.__setitem__(pyIndex, entry.__getitem__(1)); } } sb.append(") values ("); for (int i = 1; i < len; i++) { sb.append("?,"); } sb.append("?)"); if (index == 0) { throw zxJDBC.makeException(zxJDBC.ProgrammingError, zxJDBC.getString("excludedAllCols")); } this.sql = sb.toString(); } /** * Handle the row. Insert the data into the correct table and columns. No updates are done. */ public void row(PyObject row) { if (this.sql != null) { if (this.batchsize <= 0) { // no batching, just go ahead each time this.cursor.execute(this.sql, row, this.indexedBindings, Py.None); this.connection.commit(); } else { this.rows.append(row); int len = rows.__len__(); if (len % this.batchsize == 0) { this.cursor.execute(this.sql, this.rows, this.indexedBindings, Py.None); this.connection.commit(); this.rows = new PyList(); } } } else { this.createSql(row); } } /** * Method start * */ public void start() {} /** * Handles flushing any buffers and closes the cursor. */ public void end() { // finish what we started try { int len = this.rows.__len__(); if (len > 0) { this.cursor.execute(this.sql, this.rows, this.indexedBindings, Py.None); this.connection.commit(); } } finally { this.cursor.close(); } } } --- NEW FILE: DBSource.java --- /* * Jython Database Specification API 2.0 * * $Id: DBSource.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.db; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.pipe.*; import com.ziclix.python.sql.handler.*; /** * A database source. Given a PyConnection and information about the query, produce the data. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class DBSource extends BaseDB implements Source { /** Field sql */ protected String sql; /** Field sentHeader */ protected boolean sentHeader; /** Field params, include */ protected PyObject params, include; /** * Constructor for handling the generation of data. * * @param connection the database connection * @param dataHandler a custom DataHandler for the cursor, can be None * @param tableName the table in question on the source database * @param where an optional where clause, defaults to '(1=1)' if null * @param include the columns to be queried from the source, '*' if None * @param params optional params to substituted in the where clause */ public DBSource(PyConnection connection, Class dataHandler, String tableName, String where, PyObject include, PyObject params) { super(connection, dataHandler, tableName); this.params = params; this.include = include; this.sentHeader = false; this.sql = this.createSql(where); } /** * Create the sql string given the where clause. */ protected String createSql(String where) { // create the sql statement, using the columns if available StringBuffer sb = new StringBuffer("select "); if ((this.include == Py.None) || (this.include.__len__() == 0)) { sb.append("*"); } else { for (int i = 1; i < this.include.__len__(); i++) { sb.append(this.include.__getitem__(i)).append(","); } sb.append(this.include.__getitem__(this.include.__len__() - 1)); } sb.append(" from ").append(this.tableName); sb.append(" where ").append((where == null) ? "(1=1)" : where); String sql = sb.toString(); return sql; } /** * Return the next row in the result set. The first row returned will be column information. */ public PyObject next() { if (this.sentHeader) { // Py.None will be sent when all done, so this will close down the queue return this.cursor.fetchone(); } else { this.cursor.execute(this.sql, this.params, Py.None, Py.None); PyObject description = this.cursor.__findattr__("description"); // we can't insert if we don't know column names if ((description == Py.None) || (description.__len__() == 0)) { // let the destination worry about handling the empty set return Py.None; } int len = description.__len__(); PyObject[] columns = new PyObject[len]; for (int i = 0; i < len; i++) { PyObject[] colInfo = new PyObject[2]; // col name colInfo[0] = description.__getitem__(i).__getitem__(0); // col type colInfo[1] = description.__getitem__(i).__getitem__(1); columns[i] = new PyTuple(colInfo); } PyObject row = new PyTuple(columns); Py.writeDebug("db-source", row.toString()); this.sentHeader = true; return row; } } /** * Method start * */ public void start() {} /** * Close the cursor. */ public void end() { if (this.cursor != null) { this.cursor.close(); } } } |
From: brian z. <bz...@us...> - 2001-11-20 04:55:22
|
Update of /cvsroot/jython/jython/com/ziclix/python/sql/pipe In directory usw-pr-cvs1:/tmp/cvs-serv7094/com/ziclix/python/sql/pipe Added Files: Pipe.java Sink.java Source.java Log Message: initial zxJDBC checkin --- NEW FILE: Pipe.java --- /* * Jython Database Specification API 2.0 * * $Id: Pipe.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; import org.python.core.*; import com.ziclix.python.sql.*; import com.ziclix.python.sql.util.*; /** * Manager for a Sink and Source. The Pipe creates a Queue through which the Source * can feed data to the Sink. Both Sink and Source run in their own thread and can * are completely independent of the other. When the Source pushes None onto the * Queue, the piping is stopped and the Sink finishes processing all the remaining * data. This class is especially useful for loading/copying data from one database * or table to another. * * @author brian zimmer * @version $Revision: 1.1 $ */ public class Pipe { /** * Default empty constructor. */ public Pipe() {} /** * Start the processing of the Source->Sink. * * @param source the data generator * @param sink the consumer of the data * @return the number of rows seen (this includes the header row) */ public PyObject pipe(Source source, Sink sink) { Queue queue = new Queue(); SourceRunner sourceRunner = new SourceRunner(queue, source); SinkRunner sinkRunner = new SinkRunner(queue, sink); sourceRunner.start(); sinkRunner.start(); try { sourceRunner.join(); } catch (InterruptedException e) { queue.close(); throw zxJDBC.newError(e); } try { sinkRunner.join(); } catch (InterruptedException e) { queue.close(); throw zxJDBC.newError(e); } /* * This is interesting territory. I originally tried to store the the Throwable in the Thread instance * and then re-throw it here, but whenever I tried, I would get an NPE in the construction of the * PyTraceback required for the PyException. I tried calling .fillInStackTrace() but that didn't work * either. So I'm left with getting the String representation and throwing that. At least it gives * the relevant error messages, but the stack is lost. This might have something to do with a Java * issue I don't completely understand, such as what happens for an Exception whose Thread is no longer * running? Anyways, if anyone knows what to do I would love to hear about it. */ if (sourceRunner.threwException()) { throw zxJDBC.newError(sourceRunner.getException().toString()); } if (sinkRunner.threwException()) { throw zxJDBC.newError(sinkRunner.getException().toString()); } // if the source count is -1, no rows were queried if (sinkRunner.getCount() == 0) { return Py.newInteger(0); } // Assert that both sides handled the same number of rows. I know doing the check up front kinda defeats // the purpose of the assert, but there's no need to create the buffer if I don't need it and I still // want to throw the AssertionError if required if ((sourceRunner.getCount() - sinkRunner.getCount()) != 0) { Integer[] counts = { new Integer(sourceRunner.getCount()), new Integer(sinkRunner.getCount()) }; String msg = zxJDBC.getString("inconsistentRowCount", counts); Py.assert(Py.Zero, Py.newString(msg)); } return Py.newInteger(sinkRunner.getCount()); } } /** * Class PipeRunner * * @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 */ abstract class PipeRunner extends Thread { /** Field counter */ protected int counter; /** Field queue */ protected Queue queue; /** Field exception */ protected Throwable exception; /** * Constructor PipeRunner * * @param Queue queue * */ public PipeRunner(Queue queue) { this.counter = 0; this.queue = queue; this.exception = null; } /** * The total number of rows handled. */ public int getCount() { return this.counter; } /** * Method run * */ public void run() { try { this.pipe(); } catch (QueueClosedException e) { /* * thrown by a closed queue when any operation is performed. we know * at this point that nothing else can happen to the queue and that * both producer and consumer will stop since one closed the queue * by throwing an exception (below) and the other is here. */ return; } catch (Throwable e) { this.exception = e.fillInStackTrace(); this.queue.close(); } } /** * Handle the source/destination specific copying. */ abstract protected void pipe() throws InterruptedException; /** * Return true if the thread terminated because of an uncaught exception. */ public boolean threwException() { return this.exception != null; } /** * Return the uncaught exception. */ public Throwable getException() { return this.exception; } } /** * Class SourceRunner * * @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 SourceRunner extends PipeRunner { /** Field source */ protected Source source; /** * Constructor SourceRunner * * @param Queue queue * @param Source source * */ public SourceRunner(Queue queue, Source source) { super(queue); this.source = source; } /** * Method pipe * * @throws InterruptedException * */ protected void pipe() throws InterruptedException { PyObject row = Py.None; this.source.start(); try { while ((row = this.source.next()) != Py.None) { this.queue.enqueue(row); this.counter++; } } finally { try { this.queue.enqueue(Py.None); } finally { this.source.end(); } } } } /** * Class SinkRunner * * @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 SinkRunner extends PipeRunner { /** Field sink */ protected Sink sink; /** * Constructor SinkRunner * * @param Queue queue * @param Sink sink * */ public SinkRunner(Queue queue, Sink sink) { super(queue); this.sink = sink; } /** * Method pipe * * @throws InterruptedException * */ protected void pipe() throws InterruptedException { PyObject row = Py.None; this.sink.start(); try { while ((row = (PyObject)this.queue.dequeue()) != Py.None) { this.sink.row(row); this.counter++; } } finally { this.sink.end(); } } } --- NEW FILE: Sink.java --- /* * Jython Database Specification API 2.0 * * $Id: Sink.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; import org.python.core.PyObject; /** * A Sink acts as a data consumer. The Pipe is responsible for pushing data * to the Sink as generated by the Source. * * @author brian zimmer * @version $Revision: 1.1 $ */ public interface Sink { /** * Invoked at the start of the data pipelining session. */ public void start(); /** * Invoked for each row of data. In general, the first row of data will * consist of header information in the format:<br/> * [(colName, colType), ...] * and in the format:<br/> * (colData, colData, ...) * for all other data. */ public void row(PyObject row); /** * Invoked at the end of the data pipelining session. This is useful for * flushing any buffers or handling any cleanup. This method is guaranteed * to be called. */ public void end(); } --- NEW FILE: Source.java --- /* * Jython Database Specification API 2.0 * * $Id: Source.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; import org.python.core.PyObject; /** * A Source produces data to be consumed by a Sink. The data can be generated * from anywhere, but must follow the format detail in next(). * * @author brian zimmer * @version $Revision: 1.1 $ * @see #next * @see Sink */ public interface Source { /** * Invoked at the start of processing. */ public void start(); /** * Return the next row from the source. * The following format:<br> * [(colName, colType), (colName, colType), ...] * for headers and:<br/> * [(col), (colName, colType), ...] * for all other data must be used. */ public PyObject next(); /** * Invoked at the end of processing. This method is guarenteed to be called. */ public void end(); } |