summaryrefslogtreecommitdiff
path: root/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
diff options
context:
space:
mode:
authorPostgreSQL Daemon <webmaster@postgresql.org>2004-01-19 20:07:14 +0000
committerPostgreSQL Daemon <webmaster@postgresql.org>2004-01-19 20:07:14 +0000
commit2a9bf5b33d0b82e9f483f6a5ced9d71e1c009441 (patch)
tree8c0c38494985b8dbfd2311b5be51fa76a271ba17 /src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
parent9bd681a5220186230e0ea0f718a71af7ebe4b560 (diff)
downloadpostgresql-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.java430
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();
- }
-}
-