mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
Initial attempt to integrate in V3 protocol support. This is still a work in
progress, although all RTs pass using the V3 protocol on a 7.4 database and also pass using the V2 protocol on a 7.3 database. SSL support is known not to work. Modified Files: jdbc/org/postgresql/PGConnection.java jdbc/org/postgresql/errors.properties jdbc/org/postgresql/core/BaseConnection.java jdbc/org/postgresql/core/Encoding.java jdbc/org/postgresql/core/Field.java jdbc/org/postgresql/core/PGStream.java jdbc/org/postgresql/core/QueryExecutor.java jdbc/org/postgresql/core/StartupPacket.java jdbc/org/postgresql/fastpath/Fastpath.java jdbc/org/postgresql/fastpath/FastpathArg.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java jdbc/org/postgresql/test/jdbc2/BlobTest.java jdbc/org/postgresql/test/jdbc2/CallableStmtTest.java jdbc/org/postgresql/test/jdbc2/MiscTest.java jdbc/org/postgresql/test/jdbc3/Jdbc3TestSuite.java
This commit is contained in:
parent
d998fac953
commit
a9983ab414
@ -9,15 +9,13 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.5 2003/04/14 10:39:51 davec Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.6 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
package org.postgresql;
|
package org.postgresql;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Vector;
|
|
||||||
import org.postgresql.core.Encoding;
|
import org.postgresql.core.Encoding;
|
||||||
import org.postgresql.fastpath.Fastpath;
|
import org.postgresql.fastpath.Fastpath;
|
||||||
import org.postgresql.largeobject.LargeObjectManager;
|
import org.postgresql.largeobject.LargeObjectManager;
|
||||||
|
@ -6,14 +6,13 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/BaseConnection.java,v 1.2 2003/04/13 04:10:07 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/BaseConnection.java,v 1.3 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
package org.postgresql.core;
|
package org.postgresql.core;
|
||||||
|
|
||||||
import java.sql.DatabaseMetaData;
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import org.postgresql.PGConnection;
|
import org.postgresql.PGConnection;
|
||||||
@ -32,6 +31,8 @@ public interface BaseConnection extends PGConnection
|
|||||||
public Encoding getEncoding() throws SQLException;
|
public Encoding getEncoding() throws SQLException;
|
||||||
public DatabaseMetaData getMetaData() throws SQLException;
|
public DatabaseMetaData getMetaData() throws SQLException;
|
||||||
public Object getObject(String type, String value) throws SQLException;
|
public Object getObject(String type, String value) throws SQLException;
|
||||||
|
public int getPGProtocolVersionMajor();
|
||||||
|
public int getPGProtocolVersionMinor();
|
||||||
public PGStream getPGStream();
|
public PGStream getPGStream();
|
||||||
public String getPGType(int oid) throws SQLException;
|
public String getPGType(int oid) throws SQLException;
|
||||||
public int getPGType(String pgTypeName) throws SQLException;
|
public int getPGType(String pgTypeName) throws SQLException;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Encoding.java,v 1.10 2003/03/07 18:39:41 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Encoding.java,v 1.11 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -140,15 +140,22 @@ public class Encoding
|
|||||||
*/
|
*/
|
||||||
public byte[] encode(String s) throws SQLException
|
public byte[] encode(String s) throws SQLException
|
||||||
{
|
{
|
||||||
|
byte[] l_return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (encoding == null)
|
if (encoding == null)
|
||||||
{
|
{
|
||||||
return s.getBytes();
|
l_return = s.getBytes();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return s.getBytes(encoding);
|
l_return = s.getBytes(encoding);
|
||||||
|
}
|
||||||
|
//Don't return null, return an empty byte[] instead
|
||||||
|
if (l_return == null) {
|
||||||
|
return new byte[0];
|
||||||
|
} else {
|
||||||
|
return l_return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (UnsupportedEncodingException e)
|
catch (UnsupportedEncodingException e)
|
||||||
|
@ -6,17 +6,14 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Field.java,v 1.1 2003/03/07 18:39:41 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Field.java,v 1.2 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
package org.postgresql.core;
|
package org.postgresql.core;
|
||||||
|
|
||||||
import java.lang.*;
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.*;
|
|
||||||
import org.postgresql.core.BaseConnection;
|
import org.postgresql.core.BaseConnection;
|
||||||
import org.postgresql.util.PSQLException;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/PGStream.java,v 1.1 2003/03/07 18:39:41 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/PGStream.java,v 1.2 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -84,6 +84,25 @@ public class PGStream
|
|||||||
Send(buf);
|
Send(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sends an integer to the back end
|
||||||
|
*
|
||||||
|
* @param val the integer to be sent
|
||||||
|
* @param siz the length of the integer in bytes (size of structure)
|
||||||
|
* @exception IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
public void SendIntegerR(int val, int siz) throws IOException
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[siz];
|
||||||
|
|
||||||
|
for (int i = 0; i < siz; i++)
|
||||||
|
{
|
||||||
|
buf[i] = (byte)(val & 0xff);
|
||||||
|
val >>= 8;
|
||||||
|
}
|
||||||
|
Send(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send an array of bytes to the backend
|
* Send an array of bytes to the backend
|
||||||
*
|
*
|
||||||
@ -273,7 +292,39 @@ public class PGStream
|
|||||||
* an array of strings
|
* an array of strings
|
||||||
* @exception SQLException if a data I/O error occurs
|
* @exception SQLException if a data I/O error occurs
|
||||||
*/
|
*/
|
||||||
public byte[][] ReceiveTuple(int nf, boolean bin) throws SQLException
|
public byte[][] ReceiveTupleV3(int nf, boolean bin) throws SQLException
|
||||||
|
{
|
||||||
|
//TODO: use l_msgSize
|
||||||
|
int l_msgSize = ReceiveIntegerR(4);
|
||||||
|
int i;
|
||||||
|
int l_nf = ReceiveIntegerR(2);
|
||||||
|
byte[][] answer = new byte[l_nf][0];
|
||||||
|
|
||||||
|
for (i = 0 ; i < l_nf ; ++i)
|
||||||
|
{
|
||||||
|
int l_size = ReceiveIntegerR(4);
|
||||||
|
boolean isNull = l_size == -1;
|
||||||
|
if (isNull)
|
||||||
|
answer[i] = null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
answer[i] = Receive(l_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a tuple from the back end. A tuple is a two dimensional
|
||||||
|
* array of bytes
|
||||||
|
*
|
||||||
|
* @param nf the number of fields expected
|
||||||
|
* @param bin true if the tuple is a binary tuple
|
||||||
|
* @return null if the current response has no more tuples, otherwise
|
||||||
|
* an array of strings
|
||||||
|
* @exception SQLException if a data I/O error occurs
|
||||||
|
*/
|
||||||
|
public byte[][] ReceiveTupleV2(int nf, boolean bin) throws SQLException
|
||||||
{
|
{
|
||||||
int i, bim = (nf + 7) / 8;
|
int i, bim = (nf + 7) / 8;
|
||||||
byte[] bitmask = Receive(bim);
|
byte[] bitmask = Receive(bim);
|
||||||
@ -313,7 +364,7 @@ public class PGStream
|
|||||||
* @return array of bytes received
|
* @return array of bytes received
|
||||||
* @exception SQLException if a data I/O error occurs
|
* @exception SQLException if a data I/O error occurs
|
||||||
*/
|
*/
|
||||||
private byte[] Receive(int siz) throws SQLException
|
public byte[] Receive(int siz) throws SQLException
|
||||||
{
|
{
|
||||||
byte[] answer = new byte[siz];
|
byte[] answer = new byte[siz];
|
||||||
Receive(answer, 0, siz);
|
Receive(answer, 0, siz);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/QueryExecutor.java,v 1.21 2003/05/07 03:03:30 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/QueryExecutor.java,v 1.22 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -15,10 +15,8 @@ package org.postgresql.core;
|
|||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
import org.postgresql.Driver;
|
||||||
import org.postgresql.util.PSQLException;
|
import org.postgresql.util.PSQLException;
|
||||||
import org.postgresql.jdbc1.AbstractJdbc1Connection;
|
|
||||||
import org.postgresql.jdbc1.AbstractJdbc1ResultSet;
|
|
||||||
import org.postgresql.jdbc1.AbstractJdbc1Statement;
|
|
||||||
|
|
||||||
public class QueryExecutor
|
public class QueryExecutor
|
||||||
{
|
{
|
||||||
@ -95,6 +93,19 @@ public class QueryExecutor
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private BaseResultSet execute() throws SQLException
|
private BaseResultSet execute() throws SQLException
|
||||||
|
{
|
||||||
|
if (connection.getPGProtocolVersionMajor() == 3) {
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("Using Protocol Version3 to send query");
|
||||||
|
return executeV3();
|
||||||
|
} else {
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("Using Protocol Version2 to send query");
|
||||||
|
return executeV2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseResultSet executeV3() throws SQLException
|
||||||
{
|
{
|
||||||
|
|
||||||
StringBuffer errorMessage = null;
|
StringBuffer errorMessage = null;
|
||||||
@ -107,7 +118,111 @@ public class QueryExecutor
|
|||||||
synchronized (pgStream)
|
synchronized (pgStream)
|
||||||
{
|
{
|
||||||
|
|
||||||
sendQuery();
|
sendQueryV3();
|
||||||
|
|
||||||
|
int c;
|
||||||
|
boolean l_endQuery = false;
|
||||||
|
while (!l_endQuery)
|
||||||
|
{
|
||||||
|
c = pgStream.ReceiveChar();
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'A': // Asynchronous Notify
|
||||||
|
int pid = pgStream.ReceiveInteger(4);
|
||||||
|
String msg = pgStream.ReceiveString(connection.getEncoding());
|
||||||
|
connection.addNotification(new org.postgresql.core.Notification(msg, pid));
|
||||||
|
break;
|
||||||
|
case 'B': // Binary Data Transfer
|
||||||
|
receiveTupleV3(true);
|
||||||
|
break;
|
||||||
|
case 'C': // Command Status
|
||||||
|
receiveCommandStatusV3();
|
||||||
|
break;
|
||||||
|
case 'D': // Text Data Transfer
|
||||||
|
receiveTupleV3(false);
|
||||||
|
break;
|
||||||
|
case 'E': // Error Message
|
||||||
|
|
||||||
|
// it's possible to get more than one error message for a query
|
||||||
|
// see libpq comments wrt backend closing a connection
|
||||||
|
// so, append messages to a string buffer and keep processing
|
||||||
|
// check at the bottom to see if we need to throw an exception
|
||||||
|
|
||||||
|
if ( errorMessage == null )
|
||||||
|
errorMessage = new StringBuffer();
|
||||||
|
|
||||||
|
int l_elen = pgStream.ReceiveIntegerR(4);
|
||||||
|
errorMessage.append(connection.getEncoding().decode(pgStream.Receive(l_elen-4)));
|
||||||
|
// keep processing
|
||||||
|
break;
|
||||||
|
case 'I': // Empty Query
|
||||||
|
int t = pgStream.ReceiveChar();
|
||||||
|
break;
|
||||||
|
case 'N': // Error Notification
|
||||||
|
int l_nlen = pgStream.ReceiveIntegerR(4);
|
||||||
|
statement.addWarning(connection.getEncoding().decode(pgStream.Receive(l_nlen-4)));
|
||||||
|
break;
|
||||||
|
case 'P': // Portal Name
|
||||||
|
String pname = pgStream.ReceiveString(connection.getEncoding());
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
//TODO: handle parameter status messages
|
||||||
|
int l_len = pgStream.ReceiveIntegerR(4);
|
||||||
|
String l_pStatus = connection.getEncoding().decode(pgStream.Receive(l_len-4));
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("ParameterStatus="+ l_pStatus);
|
||||||
|
break;
|
||||||
|
case 'T': // MetaData Field Description
|
||||||
|
receiveFieldsV3();
|
||||||
|
break;
|
||||||
|
case 'Z':
|
||||||
|
// read ReadyForQuery
|
||||||
|
//TODO: use size better
|
||||||
|
if (pgStream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup");
|
||||||
|
//TODO: handle transaction status
|
||||||
|
char l_tStatus = (char)pgStream.ReceiveChar();
|
||||||
|
l_endQuery = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new PSQLException("postgresql.con.type",
|
||||||
|
new Character((char) c));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// did we get an error during this query?
|
||||||
|
if ( errorMessage != null )
|
||||||
|
throw new SQLException( errorMessage.toString() );
|
||||||
|
|
||||||
|
|
||||||
|
//if an existing result set was passed in reuse it, else
|
||||||
|
//create a new one
|
||||||
|
if (rs != null)
|
||||||
|
{
|
||||||
|
rs.reInit(fields, tuples, status, update_count, insert_oid, binaryCursor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rs = statement.createResultSet(fields, tuples, status, update_count, insert_oid, binaryCursor);
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseResultSet executeV2() throws SQLException
|
||||||
|
{
|
||||||
|
|
||||||
|
StringBuffer errorMessage = null;
|
||||||
|
|
||||||
|
if (pgStream == null)
|
||||||
|
{
|
||||||
|
throw new PSQLException("postgresql.con.closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (pgStream)
|
||||||
|
{
|
||||||
|
|
||||||
|
sendQueryV2();
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
boolean l_endQuery = false;
|
boolean l_endQuery = false;
|
||||||
@ -123,13 +238,13 @@ public class QueryExecutor
|
|||||||
connection.addNotification(new org.postgresql.core.Notification(msg, pid));
|
connection.addNotification(new org.postgresql.core.Notification(msg, pid));
|
||||||
break;
|
break;
|
||||||
case 'B': // Binary Data Transfer
|
case 'B': // Binary Data Transfer
|
||||||
receiveTuple(true);
|
receiveTupleV2(true);
|
||||||
break;
|
break;
|
||||||
case 'C': // Command Status
|
case 'C': // Command Status
|
||||||
receiveCommandStatus();
|
receiveCommandStatusV2();
|
||||||
break;
|
break;
|
||||||
case 'D': // Text Data Transfer
|
case 'D': // Text Data Transfer
|
||||||
receiveTuple(false);
|
receiveTupleV2(false);
|
||||||
break;
|
break;
|
||||||
case 'E': // Error Message
|
case 'E': // Error Message
|
||||||
|
|
||||||
@ -154,7 +269,7 @@ public class QueryExecutor
|
|||||||
String pname = pgStream.ReceiveString(connection.getEncoding());
|
String pname = pgStream.ReceiveString(connection.getEncoding());
|
||||||
break;
|
break;
|
||||||
case 'T': // MetaData Field Description
|
case 'T': // MetaData Field Description
|
||||||
receiveFields();
|
receiveFieldsV2();
|
||||||
break;
|
break;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
l_endQuery = true;
|
l_endQuery = true;
|
||||||
@ -188,7 +303,48 @@ public class QueryExecutor
|
|||||||
/*
|
/*
|
||||||
* Send a query to the backend.
|
* Send a query to the backend.
|
||||||
*/
|
*/
|
||||||
private void sendQuery() throws SQLException
|
private void sendQueryV3() throws SQLException
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < m_binds.length ; i++ )
|
||||||
|
{
|
||||||
|
if ( m_binds[i] == null )
|
||||||
|
throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[][] l_parts = new byte[(m_binds.length*2)+1][];
|
||||||
|
int j = 0;
|
||||||
|
int l_msgSize = 4;
|
||||||
|
Encoding l_encoding = connection.getEncoding();
|
||||||
|
pgStream.SendChar('Q');
|
||||||
|
for (int i = 0 ; i < m_binds.length ; ++i)
|
||||||
|
{
|
||||||
|
l_parts[j] = l_encoding.encode(m_sqlFrags[i]);
|
||||||
|
l_msgSize += l_parts[j].length;
|
||||||
|
j++;
|
||||||
|
l_parts[j] = l_encoding.encode(m_binds[i].toString());
|
||||||
|
l_msgSize += l_parts[j].length;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
l_parts[j] = l_encoding.encode(m_sqlFrags[m_binds.length]);
|
||||||
|
l_msgSize += l_parts[j].length;
|
||||||
|
pgStream.SendInteger(l_msgSize+1,4);
|
||||||
|
for (int k = 0; k < l_parts.length; k++) {
|
||||||
|
pgStream.Send(l_parts[k]);
|
||||||
|
}
|
||||||
|
pgStream.SendChar(0);
|
||||||
|
pgStream.flush();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new PSQLException("postgresql.con.ioerror", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a query to the backend.
|
||||||
|
*/
|
||||||
|
private void sendQueryV2() throws SQLException
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < m_binds.length ; i++ )
|
for ( int i = 0; i < m_binds.length ; i++ )
|
||||||
{
|
{
|
||||||
@ -220,11 +376,27 @@ public class QueryExecutor
|
|||||||
*
|
*
|
||||||
* @param isBinary set if the tuple should be treated as binary data
|
* @param isBinary set if the tuple should be treated as binary data
|
||||||
*/
|
*/
|
||||||
private void receiveTuple(boolean isBinary) throws SQLException
|
private void receiveTupleV3(boolean isBinary) throws SQLException
|
||||||
{
|
{
|
||||||
if (fields == null)
|
if (fields == null)
|
||||||
throw new PSQLException("postgresql.con.tuple");
|
throw new PSQLException("postgresql.con.tuple");
|
||||||
Object tuple = pgStream.ReceiveTuple(fields.length, isBinary);
|
Object tuple = pgStream.ReceiveTupleV3(fields.length, isBinary);
|
||||||
|
if (isBinary)
|
||||||
|
binaryCursor = true;
|
||||||
|
if (maxRows == 0 || tuples.size() < maxRows)
|
||||||
|
tuples.addElement(tuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive a tuple from the backend.
|
||||||
|
*
|
||||||
|
* @param isBinary set if the tuple should be treated as binary data
|
||||||
|
*/
|
||||||
|
private void receiveTupleV2(boolean isBinary) throws SQLException
|
||||||
|
{
|
||||||
|
if (fields == null)
|
||||||
|
throw new PSQLException("postgresql.con.tuple");
|
||||||
|
Object tuple = pgStream.ReceiveTupleV2(fields.length, isBinary);
|
||||||
if (isBinary)
|
if (isBinary)
|
||||||
binaryCursor = true;
|
binaryCursor = true;
|
||||||
if (maxRows == 0 || tuples.size() < maxRows)
|
if (maxRows == 0 || tuples.size() < maxRows)
|
||||||
@ -234,7 +406,36 @@ public class QueryExecutor
|
|||||||
/*
|
/*
|
||||||
* Receive command status from the backend.
|
* Receive command status from the backend.
|
||||||
*/
|
*/
|
||||||
private void receiveCommandStatus() throws SQLException
|
private void receiveCommandStatusV3() throws SQLException
|
||||||
|
{
|
||||||
|
//TODO: better handle the msg len
|
||||||
|
int l_len = pgStream.ReceiveIntegerR(4);
|
||||||
|
//read l_len -5 bytes (-4 for l_len and -1 for trailing \0)
|
||||||
|
status = connection.getEncoding().decode(pgStream.Receive(l_len-5));
|
||||||
|
//now read and discard the trailing \0
|
||||||
|
pgStream.Receive(1);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Now handle the update count correctly.
|
||||||
|
if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE"))
|
||||||
|
{
|
||||||
|
update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));
|
||||||
|
}
|
||||||
|
if (status.startsWith("INSERT"))
|
||||||
|
{
|
||||||
|
insert_oid = Long.parseLong(status.substring(1 + status.indexOf(' '),
|
||||||
|
status.lastIndexOf(' ')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException nfe)
|
||||||
|
{
|
||||||
|
throw new PSQLException("postgresql.con.fathom", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Receive command status from the backend.
|
||||||
|
*/
|
||||||
|
private void receiveCommandStatusV2() throws SQLException
|
||||||
{
|
{
|
||||||
|
|
||||||
status = pgStream.ReceiveString(connection.getEncoding());
|
status = pgStream.ReceiveString(connection.getEncoding());
|
||||||
@ -261,7 +462,33 @@ public class QueryExecutor
|
|||||||
/*
|
/*
|
||||||
* Receive the field descriptions from the back end.
|
* Receive the field descriptions from the back end.
|
||||||
*/
|
*/
|
||||||
private void receiveFields() throws SQLException
|
private void receiveFieldsV3() throws SQLException
|
||||||
|
{
|
||||||
|
//TODO: use the msgSize
|
||||||
|
//TODO: use the tableOid, and tablePosition
|
||||||
|
if (fields != null)
|
||||||
|
throw new PSQLException("postgresql.con.multres");
|
||||||
|
int l_msgSize = pgStream.ReceiveIntegerR(4);
|
||||||
|
int size = pgStream.ReceiveIntegerR(2);
|
||||||
|
fields = new Field[size];
|
||||||
|
|
||||||
|
for (int i = 0; i < fields.length; i++)
|
||||||
|
{
|
||||||
|
String typeName = pgStream.ReceiveString(connection.getEncoding());
|
||||||
|
int tableOid = pgStream.ReceiveIntegerR(4);
|
||||||
|
int tablePosition = pgStream.ReceiveIntegerR(2);
|
||||||
|
int typeOid = pgStream.ReceiveIntegerR(4);
|
||||||
|
int typeLength = pgStream.ReceiveIntegerR(2);
|
||||||
|
int typeModifier = pgStream.ReceiveIntegerR(4);
|
||||||
|
int formatType = pgStream.ReceiveIntegerR(2);
|
||||||
|
//TODO: use the extra values coming back
|
||||||
|
fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Receive the field descriptions from the back end.
|
||||||
|
*/
|
||||||
|
private void receiveFieldsV2() throws SQLException
|
||||||
{
|
{
|
||||||
if (fields != null)
|
if (fields != null)
|
||||||
throw new PSQLException("postgresql.con.multres");
|
throw new PSQLException("postgresql.con.multres");
|
||||||
|
@ -5,7 +5,7 @@ import java.io.IOException;
|
|||||||
/**
|
/**
|
||||||
* Sent to the backend to initialize a newly created connection.
|
* Sent to the backend to initialize a newly created connection.
|
||||||
*
|
*
|
||||||
* $Id: StartupPacket.java,v 1.3 2003/03/07 18:39:42 barry Exp $
|
* $Id: StartupPacket.java,v 1.4 2003/05/29 03:21:32 barry Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class StartupPacket
|
public class StartupPacket
|
||||||
@ -30,6 +30,31 @@ public class StartupPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(PGStream stream) throws IOException
|
public void writeTo(PGStream stream) throws IOException
|
||||||
|
{
|
||||||
|
if (protocolMajor == 3) {
|
||||||
|
v3WriteTo(stream);
|
||||||
|
} else {
|
||||||
|
v2WriteTo(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void v3WriteTo(PGStream stream) throws IOException
|
||||||
|
{
|
||||||
|
stream.SendInteger(4 + 4 + "user".length() + 1 + user.length() + 1 + "database".length() +1 + database.length() + 1 + 1, 4);
|
||||||
|
stream.SendInteger(protocolMajor, 2);
|
||||||
|
stream.SendInteger(protocolMinor, 2);
|
||||||
|
stream.Send("user".getBytes());
|
||||||
|
stream.SendChar(0);
|
||||||
|
stream.Send(user.getBytes());
|
||||||
|
stream.SendChar(0);
|
||||||
|
stream.Send("database".getBytes());
|
||||||
|
stream.SendChar(0);
|
||||||
|
stream.Send(database.getBytes());
|
||||||
|
stream.SendChar(0);
|
||||||
|
stream.SendChar(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void v2WriteTo(PGStream stream) throws IOException
|
||||||
{
|
{
|
||||||
stream.SendInteger(4 + 4 + SM_DATABASE + SM_USER + SM_OPTIONS + SM_UNUSED + SM_TTY, 4);
|
stream.SendInteger(4 + 4 + SM_DATABASE + SM_USER + SM_OPTIONS + SM_UNUSED + SM_TTY, 4);
|
||||||
stream.SendInteger(protocolMajor, 2);
|
stream.SendInteger(protocolMajor, 2);
|
||||||
|
@ -18,6 +18,7 @@ postgresql.con.misc:A connection error has occurred: {0}
|
|||||||
postgresql.con.multres:Cannot handle multiple result groups.
|
postgresql.con.multres:Cannot handle multiple result groups.
|
||||||
postgresql.con.pass:The password property is missing. It is mandatory.
|
postgresql.con.pass:The password property is missing. It is mandatory.
|
||||||
postgresql.con.refused:Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
|
postgresql.con.refused:Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
|
||||||
|
postgresql.con.scm:SCM credentials authentication is not supported by this driver.
|
||||||
postgresql.con.setup:Protocol error. Session setup failed.
|
postgresql.con.setup:Protocol error. Session setup failed.
|
||||||
postgresql.con.sslfail:An error occured while getting setting up the SSL connection.
|
postgresql.con.sslfail:An error occured while getting setting up the SSL connection.
|
||||||
postgresql.con.sslnotsupported:The server does not support SSL
|
postgresql.con.sslnotsupported:The server does not support SSL
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/fastpath/Attic/Fastpath.java,v 1.12 2003/03/07 18:39:42 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/fastpath/Attic/Fastpath.java,v 1.13 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -61,6 +61,129 @@ public class Fastpath
|
|||||||
* @exception SQLException if a database-access error occurs.
|
* @exception SQLException if a database-access error occurs.
|
||||||
*/
|
*/
|
||||||
public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException
|
public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException
|
||||||
|
{
|
||||||
|
if (conn.haveMinimumServerVersion("7.4")) {
|
||||||
|
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", 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
|
||||||
|
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':
|
||||||
|
if ( errorMessage == null )
|
||||||
|
errorMessage = new StringBuffer();
|
||||||
|
|
||||||
|
int l_elen = stream.ReceiveIntegerR(4);
|
||||||
|
errorMessage.append(conn.getEncoding().decode(stream.Receive(l_elen-4)));
|
||||||
|
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");
|
||||||
|
//TODO: handle transaction status
|
||||||
|
char l_tStatus = (char)stream.ReceiveChar();
|
||||||
|
l_endQuery = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new PSQLException("postgresql.fp.protocol", new Character((char)c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( errorMessage != null )
|
||||||
|
throw new PSQLException("postgresql.fp.error", errorMessage.toString());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object fastpathV2(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException
|
||||||
{
|
{
|
||||||
// added Oct 7 1998 to give us thread safety
|
// added Oct 7 1998 to give us thread safety
|
||||||
synchronized (stream)
|
synchronized (stream)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/fastpath/Attic/FastpathArg.java,v 1.4 2003/03/07 18:39:42 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/fastpath/Attic/FastpathArg.java,v 1.5 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -100,5 +100,17 @@ public class FastpathArg
|
|||||||
s.Send(bytes);
|
s.Send(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int sendSize()
|
||||||
|
{
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 4+bytes.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* Copyright (c) 2003, PostgreSQL Global Development Group
|
* Copyright (c) 2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.18 2003/03/19 04:06:20 barry Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.19 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -76,11 +76,10 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
private String this_url;
|
private String this_url;
|
||||||
private String cursor = null; // The positioned update cursor name
|
private String cursor = null; // The positioned update cursor name
|
||||||
|
|
||||||
// These are new for v6.3, they determine the current protocol versions
|
private int PGProtocolVersionMajor = 2;
|
||||||
// supported by this version of the driver. They are defined in
|
private int PGProtocolVersionMinor = 0;
|
||||||
// src/include/libpq/pqcomm.h
|
public int getPGProtocolVersionMajor() { return PGProtocolVersionMajor; }
|
||||||
protected static final int PG_PROTOCOL_LATEST_MAJOR = 2;
|
public int getPGProtocolVersionMinor() { return PGProtocolVersionMinor; }
|
||||||
protected static final int PG_PROTOCOL_LATEST_MINOR = 0;
|
|
||||||
|
|
||||||
private static final int AUTH_REQ_OK = 0;
|
private static final int AUTH_REQ_OK = 0;
|
||||||
private static final int AUTH_REQ_KRB4 = 1;
|
private static final int AUTH_REQ_KRB4 = 1;
|
||||||
@ -88,6 +87,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
private static final int AUTH_REQ_PASSWORD = 3;
|
private static final int AUTH_REQ_PASSWORD = 3;
|
||||||
private static final int AUTH_REQ_CRYPT = 4;
|
private static final int AUTH_REQ_CRYPT = 4;
|
||||||
private static final int AUTH_REQ_MD5 = 5;
|
private static final int AUTH_REQ_MD5 = 5;
|
||||||
|
private static final int AUTH_REQ_SCM = 6;
|
||||||
|
|
||||||
|
|
||||||
// These are used to cache oids, PGTypes and SQLTypes
|
// These are used to cache oids, PGTypes and SQLTypes
|
||||||
@ -140,7 +140,7 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
PG_HOST = host;
|
PG_HOST = host;
|
||||||
PG_STATUS = CONNECTION_BAD;
|
PG_STATUS = CONNECTION_BAD;
|
||||||
|
|
||||||
if (info.getProperty("ssl") != null && this_driver.sslEnabled())
|
if (info.getProperty("ssl") != null && Driver.sslEnabled())
|
||||||
{
|
{
|
||||||
useSSL = true;
|
useSSL = true;
|
||||||
}
|
}
|
||||||
@ -207,6 +207,20 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
throw new PSQLException ("postgresql.con.failed", e);
|
throw new PSQLException ("postgresql.con.failed", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Now do the protocol work
|
||||||
|
if (haveMinimumCompatibleVersion("7.4")) {
|
||||||
|
openConnectionV3(host,port,info,database,url,d,password);
|
||||||
|
} else {
|
||||||
|
openConnectionV2(host,port,info,database,url,d,password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openConnectionV3(String p_host, int p_port, Properties p_info, String p_database, String p_url, Driver p_d, String p_password) throws SQLException
|
||||||
|
{
|
||||||
|
PGProtocolVersionMajor = 3;
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("Using Protocol Version3");
|
||||||
|
|
||||||
// Now we need to construct and send an ssl startup packet
|
// Now we need to construct and send an ssl startup packet
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -260,8 +274,315 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
// Now we need to construct and send a startup packet
|
// Now we need to construct and send a startup packet
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
new StartupPacket(PG_PROTOCOL_LATEST_MAJOR,
|
new StartupPacket(PGProtocolVersionMajor,
|
||||||
PG_PROTOCOL_LATEST_MINOR,
|
PGProtocolVersionMinor,
|
||||||
|
PG_USER,
|
||||||
|
p_database).writeTo(pgStream);
|
||||||
|
|
||||||
|
// now flush the startup packets to the backend
|
||||||
|
pgStream.flush();
|
||||||
|
|
||||||
|
// Now get the response from the backend, either an error message
|
||||||
|
// or an authentication request
|
||||||
|
int areq = -1; // must have a value here
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int beresp = pgStream.ReceiveChar();
|
||||||
|
String salt = null;
|
||||||
|
byte [] md5Salt = new byte[4];
|
||||||
|
switch (beresp)
|
||||||
|
{
|
||||||
|
case 'E':
|
||||||
|
// An error occured, so pass the error message to the
|
||||||
|
// user.
|
||||||
|
//
|
||||||
|
// The most common one to be thrown here is:
|
||||||
|
// "User authentication failed"
|
||||||
|
//
|
||||||
|
int l_elen = pgStream.ReceiveIntegerR(4);
|
||||||
|
if (l_elen > 30000) {
|
||||||
|
//if the error length is > than 30000 we assume this is really a v2 protocol
|
||||||
|
//server so try again with a v2 connection
|
||||||
|
//need to create a new connection and try again
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pgStream = new PGStream(p_host, p_port);
|
||||||
|
}
|
||||||
|
catch (ConnectException cex)
|
||||||
|
{
|
||||||
|
// Added by Peter Mount <peter@retep.org.uk>
|
||||||
|
// ConnectException is thrown when the connection cannot be made.
|
||||||
|
// we trap this an return a more meaningful message for the end user
|
||||||
|
throw new PSQLException ("postgresql.con.refused");
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new PSQLException ("postgresql.con.failed", e);
|
||||||
|
}
|
||||||
|
openConnectionV2(p_host, p_port, p_info, p_database, p_url, p_d, p_password);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new PSQLException("postgresql.con.misc",encoding.decode(pgStream.Receive(l_elen-4)));
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
// Get the message length
|
||||||
|
int l_msgLen = pgStream.ReceiveIntegerR(4);
|
||||||
|
// Get the type of request
|
||||||
|
areq = pgStream.ReceiveIntegerR(4);
|
||||||
|
// Get the crypt password salt if there is one
|
||||||
|
if (areq == AUTH_REQ_CRYPT)
|
||||||
|
{
|
||||||
|
byte[] rst = new byte[2];
|
||||||
|
rst[0] = (byte)pgStream.ReceiveChar();
|
||||||
|
rst[1] = (byte)pgStream.ReceiveChar();
|
||||||
|
salt = new String(rst, 0, 2);
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("Crypt salt=" + salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or get the md5 password salt if there is one
|
||||||
|
if (areq == AUTH_REQ_MD5)
|
||||||
|
{
|
||||||
|
|
||||||
|
md5Salt[0] = (byte)pgStream.ReceiveChar();
|
||||||
|
md5Salt[1] = (byte)pgStream.ReceiveChar();
|
||||||
|
md5Salt[2] = (byte)pgStream.ReceiveChar();
|
||||||
|
md5Salt[3] = (byte)pgStream.ReceiveChar();
|
||||||
|
salt = new String(md5Salt, 0, 4);
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("MD5 salt=" + salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now send the auth packet
|
||||||
|
switch (areq)
|
||||||
|
{
|
||||||
|
case AUTH_REQ_OK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTH_REQ_KRB4:
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("postgresql: KRB4");
|
||||||
|
throw new PSQLException("postgresql.con.kerb4");
|
||||||
|
|
||||||
|
case AUTH_REQ_KRB5:
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("postgresql: KRB5");
|
||||||
|
throw new PSQLException("postgresql.con.kerb5");
|
||||||
|
|
||||||
|
case AUTH_REQ_SCM:
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("postgresql: SCM");
|
||||||
|
throw new PSQLException("postgresql.con.scm");
|
||||||
|
|
||||||
|
|
||||||
|
case AUTH_REQ_PASSWORD:
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("postgresql: PASSWORD");
|
||||||
|
pgStream.SendChar('p');
|
||||||
|
pgStream.SendInteger(5 + p_password.length(), 4);
|
||||||
|
pgStream.Send(p_password.getBytes());
|
||||||
|
pgStream.SendChar(0);
|
||||||
|
pgStream.flush();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTH_REQ_CRYPT:
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("postgresql: CRYPT");
|
||||||
|
String crypted = UnixCrypt.crypt(salt, p_password);
|
||||||
|
pgStream.SendChar('p');
|
||||||
|
pgStream.SendInteger(5 + crypted.length(), 4);
|
||||||
|
pgStream.Send(crypted.getBytes());
|
||||||
|
pgStream.SendChar(0);
|
||||||
|
pgStream.flush();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTH_REQ_MD5:
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("postgresql: MD5");
|
||||||
|
byte[] digest = MD5Digest.encode(PG_USER, p_password, md5Salt);
|
||||||
|
pgStream.SendChar('p');
|
||||||
|
pgStream.SendInteger(5 + digest.length, 4);
|
||||||
|
pgStream.Send(digest);
|
||||||
|
pgStream.SendChar(0);
|
||||||
|
pgStream.flush();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new PSQLException("postgresql.con.auth", new Integer(areq));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new PSQLException("postgresql.con.authfail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (areq != AUTH_REQ_OK);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new PSQLException("postgresql.con.failed", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int beresp;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
beresp = pgStream.ReceiveChar();
|
||||||
|
switch (beresp)
|
||||||
|
{
|
||||||
|
case 'Z':
|
||||||
|
//ready for query
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
int l_msgLen = pgStream.ReceiveIntegerR(4);
|
||||||
|
if (l_msgLen != 12) throw new PSQLException("postgresql.con.setup");
|
||||||
|
pid = pgStream.ReceiveIntegerR(4);
|
||||||
|
ckey = pgStream.ReceiveIntegerR(4);
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
int l_elen = pgStream.ReceiveIntegerR(4);
|
||||||
|
throw new PSQLException("postgresql.con.backend",encoding.decode(pgStream.Receive(l_elen-4)));
|
||||||
|
case 'N':
|
||||||
|
int l_nlen = pgStream.ReceiveIntegerR(4);
|
||||||
|
addWarning(encoding.decode(pgStream.Receive(l_nlen-4)));
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
//TODO: handle parameter status messages
|
||||||
|
int l_len = pgStream.ReceiveIntegerR(4);
|
||||||
|
String l_pStatus = encoding.decode(pgStream.Receive(l_len-4));
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("ParameterStatus="+ l_pStatus);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("invalid state="+ (char)beresp);
|
||||||
|
throw new PSQLException("postgresql.con.setup");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (beresp != 'Z');
|
||||||
|
// read ReadyForQuery
|
||||||
|
if (pgStream.ReceiveIntegerR(4) != 5) throw new PSQLException("postgresql.con.setup");
|
||||||
|
//TODO: handle transaction status
|
||||||
|
char l_tStatus = (char)pgStream.ReceiveChar();
|
||||||
|
|
||||||
|
// "pg_encoding_to_char(1)" will return 'EUC_JP' for a backend compiled with multibyte,
|
||||||
|
// otherwise it's hardcoded to 'SQL_ASCII'.
|
||||||
|
// If the backend doesn't know about multibyte we can't assume anything about the encoding
|
||||||
|
// used, so we denote this with 'UNKNOWN'.
|
||||||
|
//Note: begining with 7.2 we should be using pg_client_encoding() which
|
||||||
|
//is new in 7.2. However it isn't easy to conditionally call this new
|
||||||
|
//function, since we don't yet have the information as to what server
|
||||||
|
//version we are talking to. Thus we will continue to call
|
||||||
|
//getdatabaseencoding() until we drop support for 7.1 and older versions
|
||||||
|
//or until someone comes up with a conditional way to run one or
|
||||||
|
//the other function depending on server version that doesn't require
|
||||||
|
//two round trips to the server per connection
|
||||||
|
|
||||||
|
final String encodingQuery =
|
||||||
|
"case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else getdatabaseencoding() end";
|
||||||
|
|
||||||
|
// Set datestyle and fetch db encoding in a single call, to avoid making
|
||||||
|
// more than one round trip to the backend during connection startup.
|
||||||
|
|
||||||
|
|
||||||
|
BaseResultSet resultSet
|
||||||
|
= execSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";");
|
||||||
|
|
||||||
|
if (! resultSet.next())
|
||||||
|
{
|
||||||
|
throw new PSQLException("postgresql.con.failed", "failed getting backend encoding");
|
||||||
|
}
|
||||||
|
String version = resultSet.getString(1);
|
||||||
|
dbVersionNumber = extractVersionNumber(version);
|
||||||
|
|
||||||
|
String dbEncoding = resultSet.getString(2);
|
||||||
|
encoding = Encoding.getEncoding(dbEncoding, p_info.getProperty("charSet"));
|
||||||
|
//In 7.3 we are forced to do a second roundtrip to handle the case
|
||||||
|
//where a database may not be running in autocommit mode
|
||||||
|
//jdbc by default assumes autocommit is on until setAutoCommit(false)
|
||||||
|
//is called. Therefore we need to ensure a new connection is
|
||||||
|
//initialized to autocommit on.
|
||||||
|
//We also set the client encoding so that the driver only needs
|
||||||
|
//to deal with utf8. We can only do this in 7.3 because multibyte
|
||||||
|
//support is now always included
|
||||||
|
if (haveMinimumServerVersion("7.3"))
|
||||||
|
{
|
||||||
|
BaseResultSet acRset =
|
||||||
|
//TODO: if protocol V3 we can set the client encoding in startup
|
||||||
|
execSQL("set client_encoding = 'UNICODE'");
|
||||||
|
//set encoding to be unicode
|
||||||
|
encoding = Encoding.getEncoding("UNICODE", null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise object handling
|
||||||
|
initObjectTypes();
|
||||||
|
|
||||||
|
// Mark the connection as ok, and cleanup
|
||||||
|
PG_STATUS = CONNECTION_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openConnectionV2(String host, int port, Properties info, String database, String url, Driver d, String password) throws SQLException
|
||||||
|
{
|
||||||
|
PGProtocolVersionMajor = 2;
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("Using Protocol Version2");
|
||||||
|
|
||||||
|
// Now we need to construct and send an ssl startup packet
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (useSSL) {
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("Asking server if it supports ssl");
|
||||||
|
pgStream.SendInteger(8,4);
|
||||||
|
pgStream.SendInteger(80877103,4);
|
||||||
|
|
||||||
|
// now flush the ssl packets to the backend
|
||||||
|
pgStream.flush();
|
||||||
|
|
||||||
|
// Now get the response from the backend, either an error message
|
||||||
|
// or an authentication request
|
||||||
|
int beresp = pgStream.ReceiveChar();
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("Server response was (S=Yes,N=No): "+(char)beresp);
|
||||||
|
switch (beresp)
|
||||||
|
{
|
||||||
|
case 'E':
|
||||||
|
// An error occured, so pass the error message to the
|
||||||
|
// user.
|
||||||
|
//
|
||||||
|
// The most common one to be thrown here is:
|
||||||
|
// "User authentication failed"
|
||||||
|
//
|
||||||
|
throw new PSQLException("postgresql.con.misc", pgStream.ReceiveString(encoding));
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
// Server does not support ssl
|
||||||
|
throw new PSQLException("postgresql.con.sslnotsupported");
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
// Server supports ssl
|
||||||
|
if (Driver.logDebug)
|
||||||
|
Driver.debug("server does support ssl");
|
||||||
|
Driver.makeSSL(pgStream);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new PSQLException("postgresql.con.sslfail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new PSQLException("postgresql.con.failed", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now we need to construct and send a startup packet
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new StartupPacket(PGProtocolVersionMajor,
|
||||||
|
PGProtocolVersionMinor,
|
||||||
PG_USER,
|
PG_USER,
|
||||||
database).writeTo(pgStream);
|
database).writeTo(pgStream);
|
||||||
|
|
||||||
@ -486,7 +807,6 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
PG_STATUS = CONNECTION_OK;
|
PG_STATUS = CONNECTION_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the instance of org.postgresql.Driver
|
* Return the instance of org.postgresql.Driver
|
||||||
* that created this connection
|
* that created this connection
|
||||||
@ -775,6 +1095,35 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
* @exception SQLException if a database access error occurs
|
* @exception SQLException if a database access error occurs
|
||||||
*/
|
*/
|
||||||
public void close() throws SQLException
|
public void close() throws SQLException
|
||||||
|
{
|
||||||
|
if (haveMinimumCompatibleVersion("7.4")) {
|
||||||
|
closeV3();
|
||||||
|
} else {
|
||||||
|
closeV2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeV3() throws SQLException
|
||||||
|
{
|
||||||
|
if (pgStream != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pgStream.SendChar('X');
|
||||||
|
pgStream.SendInteger(0,4);
|
||||||
|
pgStream.flush();
|
||||||
|
pgStream.close();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
pgStream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeV2() throws SQLException
|
||||||
{
|
{
|
||||||
if (pgStream != null)
|
if (pgStream != null)
|
||||||
{
|
{
|
||||||
@ -887,29 +1236,11 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
return ;
|
return ;
|
||||||
if (autoCommit)
|
if (autoCommit)
|
||||||
{
|
{
|
||||||
if (haveMinimumServerVersion("7.3"))
|
|
||||||
{
|
|
||||||
//We do the select to ensure a transaction is in process
|
|
||||||
//before we do the commit to avoid warning messages
|
|
||||||
//from issuing a commit without a transaction in process
|
|
||||||
//NOTE this is done in two network roundtrips to work around
|
|
||||||
//a server bug in 7.3 where the select wouldn't actually start
|
|
||||||
//a new transaction if in the same command as the commit
|
|
||||||
execSQL("select 1;");
|
|
||||||
execSQL("commit; set autocommit = on;");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
execSQL("end");
|
execSQL("end");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (haveMinimumServerVersion("7.3"))
|
if (haveMinimumServerVersion("7.1"))
|
||||||
{
|
|
||||||
execSQL("set autocommit = off; " + getIsolationLevelSQL());
|
|
||||||
}
|
|
||||||
else if (haveMinimumServerVersion("7.1"))
|
|
||||||
{
|
{
|
||||||
execSQL("begin;" + getIsolationLevelSQL());
|
execSQL("begin;" + getIsolationLevelSQL());
|
||||||
}
|
}
|
||||||
@ -948,11 +1279,8 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
{
|
{
|
||||||
if (autoCommit)
|
if (autoCommit)
|
||||||
return ;
|
return ;
|
||||||
if (haveMinimumServerVersion("7.3"))
|
//TODO: delay starting new transaction until first command
|
||||||
{
|
if (haveMinimumServerVersion("7.1"))
|
||||||
execSQL("commit; " + getIsolationLevelSQL());
|
|
||||||
}
|
|
||||||
else if (haveMinimumServerVersion("7.1"))
|
|
||||||
{
|
{
|
||||||
execSQL("commit;begin;" + getIsolationLevelSQL());
|
execSQL("commit;begin;" + getIsolationLevelSQL());
|
||||||
}
|
}
|
||||||
@ -976,14 +1304,8 @@ public abstract class AbstractJdbc1Connection implements BaseConnection
|
|||||||
{
|
{
|
||||||
if (autoCommit)
|
if (autoCommit)
|
||||||
return ;
|
return ;
|
||||||
if (haveMinimumServerVersion("7.3"))
|
//TODO: delay starting transaction until first command
|
||||||
{
|
if (haveMinimumServerVersion("7.1"))
|
||||||
//we don't automatically start a transaction
|
|
||||||
//but let the server functionality automatically start
|
|
||||||
//one when the first statement is executed
|
|
||||||
execSQL("rollback; " + getIsolationLevelSQL());
|
|
||||||
}
|
|
||||||
else if (haveMinimumServerVersion("7.1"))
|
|
||||||
{
|
{
|
||||||
execSQL("rollback; begin;" + getIsolationLevelSQL());
|
execSQL("rollback; begin;" + getIsolationLevelSQL());
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import java.sql.*;
|
|||||||
import org.postgresql.largeobject.*;
|
import org.postgresql.largeobject.*;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Id: BlobTest.java,v 1.7 2002/08/14 20:35:40 barry Exp $
|
* $Id: BlobTest.java,v 1.8 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
* Some simple tests based on problems reported by users. Hopefully these will
|
* Some simple tests based on problems reported by users. Hopefully these will
|
||||||
* help prevent previous problems from re-occuring ;-)
|
* help prevent previous problems from re-occuring ;-)
|
||||||
@ -188,7 +188,7 @@ public class BlobTest extends TestCase
|
|||||||
result = result && f == -1 && b == -1;
|
result = result && f == -1 && b == -1;
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
System.out.println("\nBlob compare failed at " + c + " of " + blob.size());
|
assertTrue("Blob compare failed at " + c + " of " + blob.size(), false);
|
||||||
|
|
||||||
blob.close();
|
blob.close();
|
||||||
fis.close();
|
fis.close();
|
||||||
|
@ -56,7 +56,6 @@ public class CallableStmtTest extends TestCase
|
|||||||
|
|
||||||
public void testGetDouble () throws Throwable
|
public void testGetDouble () throws Throwable
|
||||||
{
|
{
|
||||||
// System.out.println ("Testing CallableStmt Types.DOUBLE");
|
|
||||||
CallableStatement call = con.prepareCall (func + pkgName + "getDouble (?) }");
|
CallableStatement call = con.prepareCall (func + pkgName + "getDouble (?) }");
|
||||||
call.setDouble (2, (double)3.04);
|
call.setDouble (2, (double)3.04);
|
||||||
call.registerOutParameter (1, Types.DOUBLE);
|
call.registerOutParameter (1, Types.DOUBLE);
|
||||||
@ -67,7 +66,6 @@ public class CallableStmtTest extends TestCase
|
|||||||
|
|
||||||
public void testGetInt () throws Throwable
|
public void testGetInt () throws Throwable
|
||||||
{
|
{
|
||||||
// System.out.println ("Testing CallableStmt Types.INTEGER");
|
|
||||||
CallableStatement call = con.prepareCall (func + pkgName + "getInt (?) }");
|
CallableStatement call = con.prepareCall (func + pkgName + "getInt (?) }");
|
||||||
call.setInt (2, 4);
|
call.setInt (2, 4);
|
||||||
call.registerOutParameter (1, Types.INTEGER);
|
call.registerOutParameter (1, Types.INTEGER);
|
||||||
@ -78,7 +76,6 @@ public class CallableStmtTest extends TestCase
|
|||||||
|
|
||||||
public void testGetNumeric () throws Throwable
|
public void testGetNumeric () throws Throwable
|
||||||
{
|
{
|
||||||
// System.out.println ("Testing CallableStmt Types.NUMERIC");
|
|
||||||
CallableStatement call = con.prepareCall (func + pkgName + "getNumeric (?) }");
|
CallableStatement call = con.prepareCall (func + pkgName + "getNumeric (?) }");
|
||||||
call.setBigDecimal (2, new java.math.BigDecimal(4));
|
call.setBigDecimal (2, new java.math.BigDecimal(4));
|
||||||
call.registerOutParameter (1, Types.NUMERIC);
|
call.registerOutParameter (1, Types.NUMERIC);
|
||||||
@ -90,7 +87,6 @@ public class CallableStmtTest extends TestCase
|
|||||||
|
|
||||||
public void testGetString () throws Throwable
|
public void testGetString () throws Throwable
|
||||||
{
|
{
|
||||||
// System.out.println ("Testing CallableStmt Types.VARCHAR");
|
|
||||||
CallableStatement call = con.prepareCall (func + pkgName + "getString (?) }");
|
CallableStatement call = con.prepareCall (func + pkgName + "getString (?) }");
|
||||||
call.setString (2, "foo");
|
call.setString (2, "foo");
|
||||||
call.registerOutParameter (1, Types.VARCHAR);
|
call.registerOutParameter (1, Types.VARCHAR);
|
||||||
|
@ -5,7 +5,7 @@ import junit.framework.TestCase;
|
|||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Id: MiscTest.java,v 1.8 2002/09/06 21:23:06 momjian Exp $
|
* $Id: MiscTest.java,v 1.9 2003/05/29 03:21:32 barry Exp $
|
||||||
*
|
*
|
||||||
* Some simple tests based on problems reported by users. Hopefully these will
|
* Some simple tests based on problems reported by users. Hopefully these will
|
||||||
* help prevent previous problems from re-occuring ;-)
|
* help prevent previous problems from re-occuring ;-)
|
||||||
@ -79,7 +79,6 @@ public class MiscTest extends TestCase
|
|||||||
public void xtestLocking()
|
public void xtestLocking()
|
||||||
{
|
{
|
||||||
|
|
||||||
System.out.println("testing lock");
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Connection con = TestUtil.openDB();
|
Connection con = TestUtil.openDB();
|
||||||
|
Loading…
Reference in New Issue
Block a user