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

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

/*
 * Jython Database Specification API 2.0
 *
 * $Id: PyConnection.java 3248 2007-05-30 05:19:19Z cgroves $
 *
 * 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.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.python.core.ClassDictInit;
import org.python.core.Py;
import org.python.core.PyBuiltinMethodSet;
import org.python.core.PyClass;
import org.python.core.PyInteger;
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyString;
import com.ziclix.python.sql.util.PyArgParser;

/**
 * A connection to the database.
 *
 * @author brian zimmer
 * @author last revised by $Author: cgroves $
 * @version $Revision: 3248 $
 */
public class PyConnection extends PyObject implements ClassDictInit {

    /**
     * Field closed
     */
    protected boolean closed;

    /**
     * Field connection
     */
    protected Connection connection;

    /**
     * Field supportsTransactions
     */
    protected boolean supportsTransactions;

    /**
     * Field cursors
     */
    private Set cursors;

    /**
     * Field statements
     */
    private Set statements;

    /**
     * Field __class__
     */
    public static PyClass __class__;

    /**
     * Method getPyClass
     *
     * @return PyClass
     */
    protected PyClass getPyClass() {
        return __class__;
    }

    /**
     * Field __members__
     */
    protected static PyList __members__;

    /**
     * Field __methods__
     */
    protected static PyList __methods__;

    static {
        PyObject[] m = new PyObject[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;
        this.cursors = new HashSet();
        this.connection = connection;
        this.statements = new HashSet();
        this.supportsTransactions = this.connection.getMetaData().supportsTransactions();

        if (this.supportsTransactions) {
            this.connection.setAutoCommit(false);
        }
    }

    /**
     * Produces a string representation of the object.
     *
     * @return string representation of the object.
     */
    public String toString() {

        try {
            return "";
        } catch (SQLException e) {
            return "";
        }
    }

    /**
     * Method classDictInit
     *
     * @param dict
     */
    static public void classDictInit(PyObject dict) {

        dict.__setitem__("autocommit", new PyInteger(0));
        dict.__setitem__("__version__", Py.newString("$Revision: 3248 $").__getslice__(Py.newInteger(11), Py.newInteger(-2), null));
        dict.__setitem__("close", new ConnectionFunc("close", 0, 0, 0, zxJDBC.getString("close")));
        dict.__setitem__("commit", new ConnectionFunc("commit", 1, 0, 0, zxJDBC.getString("commit")));
        dict.__setitem__("cursor", new ConnectionFunc("cursor", 2, 0, 4, zxJDBC.getString("cursor")));
        dict.__setitem__("rollback", new ConnectionFunc("rollback", 3, 0, 0, zxJDBC.getString("rollback")));
        dict.__setitem__("nativesql", new ConnectionFunc("nativesql", 4, 1, 1, zxJDBC.getString("nativesql")));

        // hide from python
        dict.__setitem__("initModule", null);
        dict.__setitem__("toString", null);
        dict.__setitem__("setConnection", null);
        dict.__setitem__("getPyClass", null);
        dict.__setitem__("connection", null);
        dict.__setitem__("classDictInit", null);
        dict.__setitem__("cursors", null);
    }

    /**
     * Sets the attribute.
     *
     * @param name
     * @param value
     */
    public void __setattr__(String name, PyObject value) {

        if ("autocommit".equals(name)) {
            try {
                if (this.supportsTransactions) {
                    this.connection.setAutoCommit(value.__nonzero__());
                }
            } catch (SQLException e) {
                throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
            }

            return;
        }

        super.__setattr__(name, value);
    }

    /**
     * Finds the attribute.
     *
     * @param name the name of the attribute of interest
     * @return the value for the attribute of the specified name
     */
    public PyObject __findattr__(String name) {

        if ("autocommit".equals(name)) {
            try {
                return connection.getAutoCommit() ? Py.One : Py.Zero;
            } catch (SQLException e) {
                throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
            }
        } else if ("dbname".equals(name)) {
            try {
                return Py.newString(this.connection.getMetaData().getDatabaseProductName());
            } catch (SQLException e) {
                throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
            }
        } else if ("dbversion".equals(name)) {
            try {
                return Py.newString(this.connection.getMetaData().getDatabaseProductVersion());
            } catch (SQLException e) {
                throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
            }
        } else if ("drivername".equals(name)) {
            try {
                return Py.newString(this.connection.getMetaData().getDriverName());
            } catch (SQLException e) {
                throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
            }
        } else if ("driverversion".equals(name)) {
            try {
                return Py.newString(this.connection.getMetaData().getDriverVersion());
            } catch (SQLException e) {
                throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
            }
        } else if ("url".equals(name)) {
            try {
                return Py.newString(this.connection.getMetaData().getURL());
            } catch (SQLException e) {
                throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
            }
        } else if ("__connection__".equals(name)) {
            return Py.java2py(this.connection);
        } else if ("__cursors__".equals(name)) {
            return Py.java2py(Collections.unmodifiableSet(this.cursors));
        } else if ("__statements__".equals(name)) {
            return Py.java2py(Collections.unmodifiableSet(this.statements));
        } else if ("__methods__".equals(name)) {
            return __methods__;
        } else if ("__members__".equals(name)) {
            return __members__;
        } else if ("closed".equals(name)) {
            return Py.newBoolean(closed);
        }

        return super.__findattr__(name);
    }

    /**
     * Close the connection now (rather than whenever __del__ is called).
     * The connection will be unusable from this point forward; an Error
     * (or subclass) exception will be raised if any operation is attempted
     * with the connection. The same applies to all cursor objects trying
     * to use the connection.
     */
    public void close() {

        if (closed) {
            throw zxJDBC.makeException(zxJDBC.ProgrammingError, "connection is closed");
        }

        // mark ourselves closed now so that any callbacks we
        // get from closing down cursors and statements to not
        // try and modify our internal sets
        this.closed = true;

        synchronized (this.cursors) {

            // close the cursors
            for (Iterator i = this.cursors.iterator(); i.hasNext();) {
                ((PyCursor) i.next()).close();
            }

            this.cursors.clear();
        }

        synchronized (this.statements) {

            // close the cursors
            for (Iterator i = this.statements.iterator(); i.hasNext();) {
                ((PyStatement) i.next()).close();
            }

            this.statements.clear();
        }

        try {
            this.connection.close();
        } catch (SQLException e) {
            throw zxJDBC.makeException(e);
        }
    }

    /**
     * Commit any pending transaction to the database. Note that if the
     * database supports an auto-commit feature, this must be initially
     * off. An interface method may be provided to turn it back on.
     * 

* Database modules that do not support transactions should implement * this method with void functionality. */ public void commit() { if (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 { 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); } } class ConnectionFunc extends PyBuiltinMethodSet { ConnectionFunc(String name, int index, int minargs, int maxargs, String doc) { super(name, index, minargs, maxargs, doc, PyConnection.class); } public PyObject __call__() { PyConnection c = (PyConnection) __self__; switch (index) { case 0: c.close(); return Py.None; case 1: c.commit(); return Py.None; case 2: return c.cursor(); case 3: c.rollback(); return Py.None; default : throw info.unexpectedCall(0, false); } } 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); } } public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3) { PyConnection c = (PyConnection) __self__; switch (index) { case 2: return c.cursor(arg1.__nonzero__(), arg2, arg3); default : throw info.unexpectedCall(3, false); } } 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