src.com.ziclix.python.sql.PyConnection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython Show documentation
Show all versions of jython Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
/*
* Jython Database Specification API 2.0
*
*
* Copyright (c) 2001 brian zimmer
*
*/
package com.ziclix.python.sql;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.WeakHashMap;
import java.util.Set;
import org.python.core.ClassDictInit;
import org.python.core.ContextManager;
import org.python.core.Py;
import org.python.core.PyBuiltinMethodSet;
import org.python.core.PyException;
import org.python.core.PyInteger;
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyUnicode;
import org.python.core.ThreadState;
import org.python.core.Traverseproc;
import org.python.core.Visitproc;
import com.ziclix.python.sql.util.PyArgParser;
/**
* A connection to the database.
*
* @author brian zimmer
*/
public class PyConnection extends PyObject implements ClassDictInit, ContextManager, Traverseproc {
/** True if closed. */
protected boolean closed;
/** Whether transactions are supported. */
protected boolean supportsTransactions;
/** Whether multiple ResultSets are supported. */
protected boolean supportsMultipleResultSets;
/** The underlying java.sql.Connection. */
protected Connection connection;
/** Underlying cursors. */
private Set cursors;
/** Underlying statements. */
private Set statements;
/** Field __members__ */
protected static PyList __members__;
/** Field __methods__ */
protected static PyList __methods__;
static {
PyObject[] m = new PyObject[5];
m[0] = new PyString("close");
m[1] = new PyString("commit");
m[2] = new PyString("cursor");
m[3] = new PyString("rollback");
m[4] = new PyString("nativesql");
__methods__ = new PyList(m);
m = new PyObject[10];
m[0] = new PyString("autocommit");
m[1] = new PyString("dbname");
m[2] = new PyString("dbversion");
m[3] = new PyString("drivername");
m[4] = new PyString("driverversion");
m[5] = new PyString("url");
m[6] = new PyString("__connection__");
m[7] = new PyString("__cursors__");
m[8] = new PyString("__statements__");
m[9] = new PyString("closed");
__members__ = new PyList(m);
}
/**
* Create a PyConnection with the open connection.
*
* @param connection
* @throws SQLException
*/
public PyConnection(Connection connection) throws SQLException {
this.closed = false;
cursors = Collections.newSetFromMap(new WeakHashMap());
cursors = Collections.synchronizedSet(cursors);
this.connection = connection;
statements = Collections.newSetFromMap(new WeakHashMap());
statements = Collections.synchronizedSet(statements);
this.supportsTransactions = this.connection.getMetaData().supportsTransactions();
this.supportsMultipleResultSets =
this.connection.getMetaData().supportsMultipleResultSets();
if (this.supportsTransactions) {
this.connection.setAutoCommit(false);
}
}
/**
* Produces a string representation of the object.
*
* @return string representation of the object.
*/
@Override
public String toString() {
try {
return String.format("", Py.idstr(this),
connection.getMetaData().getUserName(),
connection.getMetaData().getURL());
} catch (SQLException e) {
return String.format("
* Database modules that do not support transactions should implement this method with
* void functionality.
*/
public void commit() {
if (closed) {
throw zxJDBC.makeException(zxJDBC.ProgrammingError, "connection is closed");
}
if (!this.supportsTransactions) {
return;
}
try {
this.connection.commit();
} catch (SQLException e) {
throw zxJDBC.makeException(e);
}
}
/**
* This method is optional since not all databases provide transaction support.
*
* 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.
*/
public void rollback() {
if (closed) {
throw zxJDBC.makeException(zxJDBC.ProgrammingError, "connection is closed");
}
if (!this.supportsTransactions) {
return;
}
try {
this.connection.rollback();
} catch (SQLException e) {
throw zxJDBC.makeException(e);
}
}
/**
* Converts the given SQL statement into the system's native SQL grammar. A driver may
* convert the JDBC sql grammar into its system's native SQL grammar prior to sending
* it; this method returns the native form of the statement that the driver would have
* sent.
*
* @param nativeSQL
* @return the native form of this statement
*/
public PyObject nativesql(PyObject nativeSQL) {
if (closed) {
throw zxJDBC.makeException(zxJDBC.ProgrammingError, "connection is closed");
}
if (nativeSQL == Py.None) {
return Py.None;
}
try {
if (nativeSQL instanceof PyUnicode) {
return Py.newUnicode(this.connection.nativeSQL(nativeSQL.toString()));
}
return Py.newString(this.connection.nativeSQL(nativeSQL.__str__().toString()));
} catch (SQLException e) {
throw zxJDBC.makeException(e);
}
}
/**
* Return a new Cursor Object using the connection. If the database does not provide a
* direct cursor concept, the module will have to emulate cursors using other means to
* the extent needed by this specification.
*
* @return a new cursor using this connection
*/
public PyCursor cursor() {
return cursor(false);
}
/**
* Return a new Cursor Object using the connection. If the database does not provide a
* direct cursor concept, the module will have to emulate cursors using other means to
* the extent needed by this specification.
*
* @param dynamicFetch if true, dynamically iterate the result
* @return a new cursor using this connection
*/
public PyCursor cursor(boolean dynamicFetch) {
return this.cursor(dynamicFetch, Py.None, Py.None);
}
/**
* Return a new Cursor Object using the connection. If the database does not provide a
* direct cursor concept, the module will have to emulate cursors using other means to
* the extent needed by this specification.
*
* @param dynamicFetch if true, dynamically iterate the result
* @param rsType the type of the underlying ResultSet
* @param rsConcur the concurrency of the underlying ResultSet
* @return a new cursor using this connection
*/
public PyCursor cursor(boolean dynamicFetch, PyObject rsType, PyObject rsConcur) {
if (closed) {
throw zxJDBC.makeException(zxJDBC.ProgrammingError, "connection is closed");
}
PyCursor cursor = new PyExtendedCursor(this, dynamicFetch, rsType, rsConcur);
this.cursors.add(cursor);
return cursor;
}
/**
* Remove an open PyCursor.
*
* @param cursor
*/
void remove(PyCursor cursor) {
if (closed) {
return;
}
this.cursors.remove(cursor);
}
/**
* Method register
*
* @param statement statement
*/
void add(PyStatement statement) {
if (closed) {
return;
}
this.statements.add(statement);
}
/**
* Method contains
*
* @param statement statement
* @return boolean
*/
boolean contains(PyStatement statement) {
if (closed) {
return false;
}
return this.statements.contains(statement);
}
public PyObject __enter__(ThreadState ts) {
return this;
}
public PyObject __enter__() {
return this;
}
public boolean __exit__(ThreadState ts, PyException exception) {
if (exception == null) {
commit();
} else {
rollback();
}
return false;
}
public boolean __exit__(PyObject type, PyObject value, PyObject traceback) {
if (type == null || type == Py.None) {
commit();
} else {
rollback();
}
return false;
}
/* Traverseproc implementation */
@Override
public int traverse(Visitproc visit, Object arg) {
int retVal;
for (PyObject ob: cursors) {
if (ob != null) {
retVal = visit.visit(ob, arg);
if (retVal != 0) {
return retVal;
}
}
}
for (PyObject ob: statements) {
if (ob != null) {
retVal = visit.visit(ob, arg);
if (retVal != 0) {
return retVal;
}
}
}
return 0;
}
@Override
public boolean refersDirectlyTo(PyObject ob) {
if (ob == null) {
return false;
}
if (cursors != null && cursors.contains(ob)) {
return true;
} else if (statements != null && statements.contains(ob)) {
return true;
} else {
return false;
}
}
}
class ConnectionFunc extends PyBuiltinMethodSet {
ConnectionFunc(String name, int index, int minargs, int maxargs, String doc) {
super(name, index, minargs, maxargs, doc, PyConnection.class);
}
@Override
public PyObject __call__() {
PyConnection c = (PyConnection) __self__;
switch (index) {
case 0:
c.close();
return Py.None;
case 1:
c.commit();
return Py.None;
case 2:
return c.cursor();
case 3:
c.rollback();
return Py.None;
case 5:
return c.__enter__();
default:
throw info.unexpectedCall(0, false);
}
}
@Override
public PyObject __call__(PyObject arg) {
PyConnection c = (PyConnection) __self__;
switch (index) {
case 2:
return c.cursor(arg.__nonzero__());
case 4:
return c.nativesql(arg);
default:
throw info.unexpectedCall(1, false);
}
}
@Override
public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3) {
PyConnection c = (PyConnection) __self__;
switch (index) {
case 2:
return c.cursor(arg1.__nonzero__(), arg2, arg3);
case 6:
return Py.newBoolean(c.__exit__(arg1, arg2, arg3));
default:
throw info.unexpectedCall(3, false);
}
}
@Override
public PyObject __call__(PyObject[] args, String[] keywords) {
PyConnection c = (PyConnection) __self__;
PyArgParser parser = new PyArgParser(args, keywords);
switch (index) {
case 2:
PyObject dynamic = parser.kw("dynamic", Py.None);
PyObject rstype = parser.kw("rstype", Py.None);
PyObject rsconcur = parser.kw("rsconcur", Py.None);
dynamic = (parser.numArg() >= 1) ? parser.arg(0) : dynamic;
rstype = (parser.numArg() >= 2) ? parser.arg(1) : rstype;
rsconcur = (parser.numArg() >= 3) ? parser.arg(2) : rsconcur;
return c.cursor(dynamic.__nonzero__(), rstype, rsconcur);
default:
throw info.unexpectedCall(args.length, true);
}
}
}