diff options
author | PostgreSQL Daemon <webmaster@postgresql.org> | 2004-01-19 20:07:14 +0000 |
---|---|---|
committer | PostgreSQL Daemon <webmaster@postgresql.org> | 2004-01-19 20:07:14 +0000 |
commit | 2a9bf5b33d0b82e9f483f6a5ced9d71e1c009441 (patch) | |
tree | 8c0c38494985b8dbfd2311b5be51fa76a271ba17 /src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java | |
parent | 9bd681a5220186230e0ea0f718a71af7ebe4b560 (diff) | |
download | postgresql-2a9bf5b33d0b82e9f483f6a5ced9d71e1c009441.tar.gz |
JDBC is now on GBorg
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java')
-rw-r--r-- | src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java | 430 |
1 files changed, 0 insertions, 430 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java deleted file mode 100644 index e883615265..0000000000 --- a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java +++ /dev/null @@ -1,430 +0,0 @@ -/*------------------------------------------------------------------------- - * - * Fastpath.java - * This class implements the Fastpath api. - * - * Copyright (c) 2003, PostgreSQL Global Development Group - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java,v 1.20 2003/12/18 03:27:14 davec Exp $ - * - *------------------------------------------------------------------------- - */ -package org.postgresql.fastpath; - -import java.io.IOException; -import java.sql.SQLException; -import java.sql.ResultSet; -import java.util.Hashtable; -import org.postgresql.Driver; -import org.postgresql.core.BaseConnection; -import org.postgresql.core.PGStream; -import org.postgresql.util.PSQLException; -import org.postgresql.util.PSQLState; - -/* - * This class implements the Fastpath api. - * - * <p>This is a means of executing functions imbeded in the org.postgresql - * backend from within a java application. - * - * <p>It is based around the file src/interfaces/libpq/fe-exec.c - * - */ -public class Fastpath -{ - // This maps the functions names to their id's (possible unique just - // to a connection). - protected Hashtable func = new Hashtable(); - - protected BaseConnection conn; // our connection - protected PGStream stream; // the network stream - - /* - * Initialises the fastpath system - * - * @param conn BaseConnection to attach to - * @param stream The network stream to the backend - */ - public Fastpath(BaseConnection conn, PGStream stream) - { - this.conn = conn; - this.stream = stream; - } - - /* - * Send a function call to the PostgreSQL backend - * - * @param fnid Function id - * @param resulttype True if the result is an integer, false for other results - * @param args FastpathArguments to pass to fastpath - * @return null if no data, Integer if an integer result, or byte[] otherwise - * @exception SQLException if a database-access error occurs. - */ - public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException - { - if (conn.getPGProtocolVersionMajor() == 3) { - return fastpathV3(fnid, resulttype, args); - } else { - return fastpathV2(fnid, resulttype, args); - } - } - - private Object fastpathV3(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException - { - // added Oct 7 1998 to give us thread safety - synchronized (stream) - { - // send the function call - try - { - int l_msgLen = 0; - l_msgLen += 16; - for (int i=0;i < args.length;i++) - l_msgLen += args[i].sendSize(); - - stream.SendChar('F'); - stream.SendInteger(l_msgLen,4); - stream.SendInteger(fnid, 4); - stream.SendInteger(1,2); - stream.SendInteger(1,2); - stream.SendInteger(args.length,2); - - for (int i = 0;i < args.length;i++) - args[i].send(stream); - - stream.SendInteger(1,2); - - // This is needed, otherwise data can be lost - stream.flush(); - - } - catch (IOException ioe) - { - throw new PSQLException("postgresql.fp.send", PSQLState.COMMUNICATION_ERROR, new Integer(fnid), ioe); - } - - // Now handle the result - - // Now loop, reading the results - Object result = null; // our result - PSQLException error = null; - int c; - boolean l_endQuery = false; - while (!l_endQuery) - { - c = stream.ReceiveChar(); - - switch (c) - { - case 'A': // Asynchronous Notify - int pid = stream.ReceiveInteger(4); - String msg = stream.ReceiveString(conn.getEncoding()); - conn.addNotification(new org.postgresql.core.Notification(msg, pid)); - break; - //------------------------------ - // Error message returned - case 'E': - int l_elen = stream.ReceiveIntegerR(4); - String totalMessage = conn.getEncoding().decode(stream.Receive(l_elen-4)); - PSQLException l_error = PSQLException.parseServerError(totalMessage); - - if (error != null) { - error.setNextException(l_error); - } else { - error = l_error; - } - - break; - //------------------------------ - // Notice from backend - case 'N': - int l_nlen = stream.ReceiveIntegerR(4); - conn.addWarning(conn.getEncoding().decode(stream.Receive(l_nlen-4))); - break; - - case 'V': - int l_msgLen = stream.ReceiveIntegerR(4); - int l_valueLen = stream.ReceiveIntegerR(4); - - if (l_valueLen == -1) - { - //null value - } - else if (l_valueLen == 0) - { - result = new byte[0]; - } - else - { - // Return an Integer if - if (resulttype) - result = new Integer(stream.ReceiveIntegerR(l_valueLen)); - else - { - byte buf[] = new byte[l_valueLen]; - stream.Receive(buf, 0, l_valueLen); - result = buf; - } - } - break; - - case 'Z': - //TODO: use size better - if (stream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup", PSQLState.CONNECTION_UNABLE_TO_CONNECT); - //TODO: handle transaction status - char l_tStatus = (char)stream.ReceiveChar(); - l_endQuery = true; - break; - - default: - throw new PSQLException("postgresql.fp.protocol", PSQLState.COMMUNICATION_ERROR, new Character((char)c)); - } - } - - if ( error != null ) - throw error; - - return result; - } - } - - private Object fastpathV2(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException - { - // added Oct 7 1998 to give us thread safety - synchronized (stream) - { - // send the function call - try - { - // 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding - // that confuses the backend. The 0 terminates the command line. - stream.SendInteger(70, 1); - stream.SendInteger(0, 1); - - stream.SendInteger(fnid, 4); - stream.SendInteger(args.length, 4); - - for (int i = 0;i < args.length;i++) - args[i].send(stream); - - // This is needed, otherwise data can be lost - stream.flush(); - - } - catch (IOException ioe) - { - //Should be sending exception as second arg. - throw new PSQLException("postgresql.fp.send", PSQLState.COMMUNICATION_ERROR, new Integer(fnid), ioe); - } - - // Now handle the result - - // Now loop, reading the results - Object result = null; // our result - StringBuffer errorMessage = null; - int c; - boolean l_endQuery = false; - while (!l_endQuery) - { - c = stream.ReceiveChar(); - - switch (c) - { - case 'A': // Asynchronous Notify - //TODO: do something with this - int pid = stream.ReceiveInteger(4); - String msg = stream.ReceiveString(conn.getEncoding()); - break; - - //------------------------------ - // Error message returned - case 'E': - if ( errorMessage == null ) - errorMessage = new StringBuffer(); - errorMessage.append(stream.ReceiveString(conn.getEncoding())); - break; - - //------------------------------ - // Notice from backend - case 'N': - conn.addWarning(stream.ReceiveString(conn.getEncoding())); - break; - - case 'V': - int l_nextChar = stream.ReceiveChar(); - if (l_nextChar == 'G') - { - int sz = stream.ReceiveIntegerR(4); - // Return an Integer if - if (resulttype) - result = new Integer(stream.ReceiveIntegerR(sz)); - else - { - byte buf[] = new byte[sz]; - stream.Receive(buf, 0, sz); - result = buf; - } - //There should be a trailing '0' - int l_endChar = stream.ReceiveChar(); - } - else - { - //it must have been a '0', thus no results - } - break; - - case 'Z': - l_endQuery = true; - break; - - default: - throw new PSQLException("postgresql.fp.protocol", PSQLState.COMMUNICATION_ERROR, new Character((char)c)); - } - } - - if ( errorMessage != null ) - throw new PSQLException("postgresql.fp.error", PSQLState.COMMUNICATION_ERROR, errorMessage.toString()); - - return result; - } - } - - /* - * Send a function call to the PostgreSQL backend by name. - * - * Note: the mapping for the procedure name to function id needs to exist, - * usually to an earlier call to addfunction(). - * - * This is the prefered method to call, as function id's can/may change - * between versions of the backend. - * - * For an example of how this works, refer to org.postgresql.largeobject.LargeObject - * - * @param name Function name - * @param resulttype True if the result is an integer, false for other - * results - * @param args FastpathArguments to pass to fastpath - * @return null if no data, Integer if an integer result, or byte[] otherwise - * @exception SQLException if name is unknown or if a database-access error - * occurs. - * @see org.postgresql.largeobject.LargeObject - */ - public Object fastpath(String name, boolean resulttype, FastpathArg[] args) throws SQLException - { - if (Driver.logDebug) - Driver.debug("Fastpath: calling " + name); - return fastpath(getID(name), resulttype, args); - } - - /* - * This convenience method assumes that the return value is an Integer - * @param name Function name - * @param args Function arguments - * @return integer result - * @exception SQLException if a database-access error occurs or no result - */ - public int getInteger(String name, FastpathArg[] args) throws SQLException - { - Integer i = (Integer)fastpath(name, true, args); - if (i == null) - throw new PSQLException("postgresql.fp.expint", name); - return i.intValue(); - } - - /* - * This convenience method assumes that the return value is an Integer - * @param name Function name - * @param args Function arguments - * @return byte[] array containing result - * @exception SQLException if a database-access error occurs or no result - */ - public byte[] getData(String name, FastpathArg[] args) throws SQLException - { - return (byte[])fastpath(name, false, args); - } - - /* - * This adds a function to our lookup table. - * - * <p>User code should use the addFunctions method, which is based upon a - * query, rather than hard coding the oid. The oid for a function is not - * guaranteed to remain static, even on different servers of the same - * version. - * - * @param name Function name - * @param fnid Function id - */ - public void addFunction(String name, int fnid) - { - func.put(name, new Integer(fnid)); - } - - /* - * This takes a ResultSet containing two columns. Column 1 contains the - * function name, Column 2 the oid. - * - * <p>It reads the entire ResultSet, loading the values into the function - * table. - * - * <p><b>REMEMBER</b> to close() the resultset after calling this!! - * - * <p><b><em>Implementation note about function name lookups:</em></b> - * - * <p>PostgreSQL stores the function id's and their corresponding names in - * the pg_proc table. To speed things up locally, instead of querying each - * function from that table when required, a Hashtable is used. Also, only - * the function's required are entered into this table, keeping connection - * times as fast as possible. - * - * <p>The org.postgresql.largeobject.LargeObject class performs a query upon it's startup, - * and passes the returned ResultSet to the addFunctions() method here. - * - * <p>Once this has been done, the LargeObject api refers to the functions by - * name. - * - * <p>Dont think that manually converting them to the oid's will work. Ok, - * they will for now, but they can change during development (there was some - * discussion about this for V7.0), so this is implemented to prevent any - * unwarranted headaches in the future. - * - * @param rs ResultSet - * @exception SQLException if a database-access error occurs. - * @see org.postgresql.largeobject.LargeObjectManager - */ - public void addFunctions(ResultSet rs) throws SQLException - { - while (rs.next()) - { - func.put(rs.getString(1), new Integer(rs.getInt(2))); - } - } - - /* - * This returns the function id associated by its name - * - * <p>If addFunction() or addFunctions() have not been called for this name, - * then an SQLException is thrown. - * - * @param name Function name to lookup - * @return Function ID for fastpath call - * @exception SQLException is function is unknown. - */ - public int getID(String name) throws SQLException - { - Integer id = (Integer)func.get(name); - - // may be we could add a lookup to the database here, and store the result - // in our lookup table, throwing the exception if that fails. - // We must, however, ensure that if we do, any existing ResultSet is - // unaffected, otherwise we could break user code. - // - // so, until we know we can do this (needs testing, on the TODO list) - // for now, we throw the exception and do no lookups. - if (id == null) - throw new PSQLException("postgresql.fp.unknown", PSQLState.UNEXPECTED_ERROR, name); - - return id.intValue(); - } -} - |