All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ziclix.python.sql.PyConnection Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 2.7.4
Show newest version
/*
 * 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); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy