Commit fe2dec75 authored by Barry Lind's avatar Barry Lind

Enhancements to how queries with bind values are stored internally and sent to

the server.  Previously we allocated a new String object for the entire final
query we were sending to the database.  If you had a big query, or especially
if you had large bind values you ended up with essentially two copies in memory.
This change will reuse the existing objects and therefore should take 1/2 the
memory it does today for a given query.  This restructuring will also allow
in the future the ability to stream bytea data to the server instead of the current approach of pulling it all into memory.
I also fixed a test that was failing on a 7.2 database.
Also renamed some internal variables and some minor cleanup.

 Modified Files:
 	jdbc/org/postgresql/core/QueryExecutor.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
 	jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
parent a2a31928
......@@ -13,24 +13,26 @@ import org.postgresql.util.PSQLException;
* <p>The lifetime of a QueryExecutor object is from sending the query
* until the response has been received from the backend.
*
* $Id: QueryExecutor.java,v 1.13 2002/07/23 03:59:55 barry Exp $
* $Id: QueryExecutor.java,v 1.14 2002/08/23 20:45:49 barry Exp $
*/
public class QueryExecutor
{
private final String sql;
private final String[] m_sqlFrags;
private final Object[] m_binds;
private final java.sql.Statement statement;
private final PG_Stream pg_stream;
private final org.postgresql.jdbc1.AbstractJdbc1Connection connection;
public QueryExecutor(String sql,
public QueryExecutor(String[] p_sqlFrags, Object[] p_binds,
java.sql.Statement statement,
PG_Stream pg_stream,
java.sql.Connection connection)
throws SQLException
{
this.sql = sql;
this.m_sqlFrags = p_sqlFrags;
this.m_binds = p_binds;
this.statement = statement;
this.pg_stream = pg_stream;
this.connection = (org.postgresql.jdbc1.AbstractJdbc1Connection)connection;
......@@ -60,7 +62,7 @@ public class QueryExecutor
synchronized (pg_stream)
{
sendQuery(sql);
sendQuery();
int c;
boolean l_endQuery = false;
......@@ -129,12 +131,18 @@ public class QueryExecutor
/*
* Send a query to the backend.
*/
private void sendQuery(String query) throws SQLException
private void sendQuery() throws SQLException
{
try
{
pg_stream.SendChar('Q');
pg_stream.Send(connection.getEncoding().encode(query));
for (int i = 0 ; i < m_binds.length ; ++i) {
if (m_binds[i] == null)
throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i]));
pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
}
pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[m_binds.length]));
pg_stream.SendChar(0);
pg_stream.flush();
......
......@@ -13,7 +13,7 @@ import org.postgresql.largeobject.LargeObjectManager;
import org.postgresql.util.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.4 2002/08/16 19:34:57 davec Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.5 2002/08/23 20:45:49 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds the jdbc2
* methods. The real Connection class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Connection
......@@ -426,7 +426,26 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
*/
public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException
{
return new QueryExecutor(sql, stat, pg_stream, (java.sql.Connection)this).execute();
return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream, (java.sql.Connection)this).execute();
}
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
/*
* Send a query to the backend. Returns one of the ResultSet
* objects.
*
* <B>Note:</B> there does not seem to be any method currently
* in existance to return the update count.
*
* @param p_sqlFragmentss the SQL statement parts to be executed
* @param p_binds the SQL bind values
* @param stat The Statement associated with this query (may be null)
* @return a ResultSet holding the results
* @exception SQLException if a database error occurs
*/
public java.sql.ResultSet ExecSQL(String[] p_sqlFragments, Object[] p_binds, java.sql.Statement stat) throws SQLException
{
return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute();
}
/*
......
......@@ -15,15 +15,13 @@ import org.postgresql.util.PGbytea;
import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.4 2002/08/14 20:35:39 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.5 2002/08/23 20:45:49 barry Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1ResultSet which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2ResultSet
*/
public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet {
protected String sqlQuery = null;
//needed for updateable result set support
protected boolean updateable = false;
protected boolean doingUpdates = false;
......@@ -1254,7 +1252,9 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra
public void parseQuery() {
StringTokenizer st = new StringTokenizer(sqlQuery, " \r\t");
String[] l_sqlFragments = ((AbstractJdbc2Statement)statement).getSqlFragments();
String l_sql = l_sqlFragments[0];
StringTokenizer st = new StringTokenizer(l_sql, " \r\t");
boolean tableFound = false, tablesChecked = false;
String name = "";
......@@ -1326,11 +1326,6 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra
}
public void setSQLQuery(String sqlQuery) {
this.sqlQuery = sqlQuery;
}
private class PrimaryKey {
int index; // where in the result set is this primaryKey
String name; // what is the columnName of this primary Key
......
......@@ -8,7 +8,7 @@ import java.util.Vector;
import org.postgresql.largeobject.*;
import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.3 2002/07/25 22:45:28 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.4 2002/08/23 20:45:49 barry Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
......@@ -43,32 +43,28 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
* an update count or there are no more results
* @exception SQLException if a database access error occurs
*/
public boolean execute(String sql) throws SQLException
public boolean execute() throws SQLException
{
boolean l_return = super.execute(sql);
boolean l_return = super.execute();
//Now do the jdbc2 specific stuff
//required for ResultSet.getStatement() to work and updateable resultsets
((AbstractJdbc2ResultSet)result).setStatement((Statement)this);
// Added this so that the Updateable resultset knows the query that gave this
((AbstractJdbc2ResultSet)result).setSQLQuery(sql);
return l_return;
}
// ** JDBC 2 Extensions **
public void addBatch(String sql) throws SQLException
public void addBatch(String p_sql) throws SQLException
{
if (batch == null)
batch = new Vector();
batch.addElement(sql);
batch.addElement(p_sql);
}
public void clearBatch() throws SQLException
{
if (batch != null)
batch.removeAllElements();
batch = null;
}
public int[] executeBatch() throws SQLException
......@@ -155,7 +151,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
public void addBatch() throws SQLException
{
addBatch(compileQuery());
addBatch(this.toString());
}
public java.sql.ResultSetMetaData getMetaData() throws SQLException
......@@ -388,4 +384,9 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
}
//This is needed by AbstractJdbc2ResultSet to determine if the query is updateable or not
protected String[] getSqlFragments() {
return m_sqlFragments;
}
}
......@@ -9,7 +9,7 @@ import java.sql.*;
*
* PS: Do you know how difficult it is to type on a train? ;-)
*
* $Id: DatabaseMetaDataTest.java,v 1.11 2002/08/14 20:35:40 barry Exp $
* $Id: DatabaseMetaDataTest.java,v 1.12 2002/08/23 20:45:49 barry Exp $
*/
public class DatabaseMetaDataTest extends TestCase
......@@ -102,7 +102,10 @@ public class DatabaseMetaDataTest extends TestCase
assertTrue(dbmd.supportsMinimumSQLGrammar());
assertTrue(!dbmd.supportsCoreSQLGrammar());
assertTrue(!dbmd.supportsExtendedSQLGrammar());
assertTrue(dbmd.supportsANSI92EntryLevelSQL());
if (((org.postgresql.jdbc1.AbstractJdbc1Connection)con).haveMinimumServerVersion("7.3"))
assertTrue(dbmd.supportsANSI92EntryLevelSQL());
else
assertTrue(!dbmd.supportsANSI92EntryLevelSQL());
assertTrue(!dbmd.supportsANSI92IntermediateSQL());
assertTrue(!dbmd.supportsANSI92FullSQL());
......@@ -426,12 +429,12 @@ public class DatabaseMetaDataTest extends TestCase
assertNotNull(dbmd);
assertTrue(dbmd.getDatabaseProductName().equals("PostgreSQL"));
//The test below doesn't make sense to me, it tests that
//The test below doesn't make sense to me, it tests that
//the version of the driver = the version of the database it is connected to
//since the driver should be backwardly compatible this test is commented out
//since the driver should be backwardly compatible this test is commented out
//assertTrue(dbmd.getDatabaseProductVersion().startsWith(
// Integer.toString(pc.getDriver().getMajorVersion())
// + "."
// Integer.toString(pc.getDriver().getMajorVersion())
// + "."
// + Integer.toString(pc.getDriver().getMinorVersion())));
assertTrue(dbmd.getDriverName().equals("PostgreSQL Native Driver"));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment