Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit51acf97

Browse files
author
Barry Lind
committed
Applied patch submitted by Nic Ferrier with some cleanups of his previous
patch to add cursor based queries. Modified Files: jdbc/org/postgresql/core/BaseConnection.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
1 parent3fd5fae commit51acf97

File tree

2 files changed

+84
-110
lines changed

2 files changed

+84
-110
lines changed

‎src/interfaces/jdbc/org/postgresql/core/BaseConnection.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Copyright (c) 2003, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/BaseConnection.java,v 1.1 2003/03/07 18:39:41 barry Exp $
9+
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/BaseConnection.java,v 1.2 2003/04/13 04:10:07 barry Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -27,6 +27,7 @@ public interface BaseConnection extends PGConnection
2727
publicvoidcancelQuery()throwsSQLException;
2828
publicStatementcreateStatement()throwsSQLException;
2929
publicBaseResultSetexecSQL(Strings)throwsSQLException;
30+
publicbooleangetAutoCommit()throwsSQLException;
3031
publicStringgetCursorName()throwsSQLException;
3132
publicEncodinggetEncoding()throwsSQLException;
3233
publicDatabaseMetaDatagetMetaData()throwsSQLException;
@@ -38,6 +39,7 @@ public interface BaseConnection extends PGConnection
3839
publicintgetSQLType(StringpgTypeName)throwsSQLException;
3940
publicbooleanhaveMinimumCompatibleVersion(Stringver)throwsSQLException;
4041
publicbooleanhaveMinimumServerVersion(Stringver)throwsSQLException;
42+
publicvoidsetAutoCommit(booleanautoCommit)throwsSQLException;
4143
publicvoidsetCursorName(Stringcursor)throwsSQLException;
4244

4345
}

‎src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java

Lines changed: 81 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@
1313
importorg.postgresql.largeobject.*;
1414
importorg.postgresql.util.*;
1515

16-
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.18 2003/03/07 18:39:44 barry Exp $
16+
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.19 2003/04/13 04:10:07 barry Exp $
1717
* This class defines methods of the jdbc1 specification. This class is
1818
* extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
1919
* methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
2020
*/
2121
publicabstractclassAbstractJdbc1StatementimplementsBaseStatement
2222
{
23-
24-
// The connection who created us
23+
// The connection who created us
2524
protectedBaseConnectionconnection;
2625

2726
/** The warnings chain. */
@@ -58,6 +57,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
5857

5958
protectedString[]m_bindTypes =newString[0];
6059
protectedStringm_statementName =null;
60+
protectedbooleanm_statementIsCursor =false;
6161

6262
privatebooleanm_useServerPrepare =false;
6363
privatestaticintm_preparedCount =1;
@@ -159,14 +159,16 @@ public java.sql.ResultSet executeQuery(String p_sql) throws SQLException
159159
{
160160
try
161161
{
162-
connection.execSQL("DEALLOCATE " +m_statementName);
162+
if (!m_statementIsCursor)
163+
connection.execSQL("DEALLOCATE " +m_statementName);
163164
}
164165
catch (Exceptione)
165166
{
166167
}
167168
finally
168169
{
169170
m_statementName =null;
171+
m_statementIsCursor =false;
170172
m_origSqlFragments =null;
171173
m_executeSqlFragments =null;
172174
}
@@ -183,11 +185,8 @@ public java.sql.ResultSet executeQuery(String p_sql) throws SQLException
183185
*/
184186
publicjava.sql.ResultSetexecuteQuery()throwsSQLException
185187
{
186-
if (fetchSize >0)
187-
this.executeWithCursor();
188-
else
189-
this.execute();
190-
188+
this.execute();
189+
191190
while (result !=null && !result.reallyResultSet())
192191
result = (BaseResultSet)result.getNext();
193192
if (result ==null)
@@ -268,9 +267,13 @@ public boolean execute(String p_sql) throws SQLException
268267
* Some prepared statements return multiple results; the execute method
269268
* handles these complex statements as well as the simpler form of
270269
* statements handled by executeQuery and executeUpdate
270+
*
271+
* This method also handles the translation of the query into a cursor based
272+
* query if the user has specified a fetch size and set the connection
273+
* into a non-auto commit state.
271274
*
272275
* @return true if the next result is a ResultSet; false if it is an
273-
**update count or there are no more results
276+
* update count or there are no more results
274277
* @exception SQLException if a database access error occurs
275278
*/
276279
publicbooleanexecute()throwsSQLException
@@ -353,10 +356,75 @@ public boolean execute() throws SQLException
353356
}
354357
}
355358

356-
// New in 7.1, pass Statement so that ExecSQL can customise to it
359+
// Use a cursor if directed and in a transaction.
360+
elseif (fetchSize >0 && !connection.getAutoCommit())
361+
{
362+
// The first thing to do is transform the statement text into the cursor form.
363+
String[]cursorBasedSql =newString[m_sqlFragments.length];
364+
// Pinch the prepared count for our own nefarious purposes.
365+
StringstatementName ="JDBC_CURS_" +m_preparedCount++;
366+
// Setup the cursor decleration.
367+
// Note that we don't need a BEGIN because we've already
368+
// made sure we're executing inside a transaction.
369+
StringcursDecl ="DECLARE " +statementName +" CURSOR FOR ";
370+
StringendCurs =" FETCH FORWARD " +fetchSize +" FROM " +statementName +";";
371+
372+
// Copy the real query to the curs decleration.
373+
try
374+
{
375+
// Need to confirm this with Barry Lind.
376+
if (cursorBasedSql.length >1)
377+
thrownewIllegalStateException("cursor fetches not supported with prepared statements.");
378+
for (inti =0;i <cursorBasedSql.length;i++)
379+
{
380+
if (i ==0)
381+
{
382+
if (m_sqlFragments[i].trim().toUpperCase().startsWith("DECLARE "))
383+
thrownewIllegalStateException("statement is already cursor based.");
384+
cursorBasedSql[i] =cursDecl;
385+
}
386+
387+
if (cursorBasedSql[i] !=null)
388+
cursorBasedSql[i] +=m_sqlFragments[i];
389+
else
390+
cursorBasedSql[i] =m_sqlFragments[i];
391+
392+
if (i ==cursorBasedSql.length -1)
393+
{
394+
// We have to be smart about adding the delimitting ";"
395+
if (m_sqlFragments[i].endsWith(";"))
396+
cursorBasedSql[i] +=endCurs;
397+
else
398+
cursorBasedSql[i] += (";" +endCurs);
399+
}
400+
elseif (m_sqlFragments[i].indexOf(";") > -1)
401+
{
402+
thrownewIllegalStateException("multiple statements not "
403+
+"allowed with cursor based querys.");
404+
}
405+
}
406+
407+
// Make the cursor based query the one that will be used.
408+
if (org.postgresql.Driver.logDebug)
409+
org.postgresql.Driver.debug("using cursor based sql with cursor name " +statementName);
410+
411+
// Do all of this after exceptions have been thrown.
412+
m_statementName =statementName;
413+
m_statementIsCursor =true;
414+
m_sqlFragments =cursorBasedSql;
415+
}
416+
catch (IllegalStateExceptione)
417+
{
418+
// Something went wrong generating the cursor based statement.
419+
if (org.postgresql.Driver.logDebug)
420+
org.postgresql.Driver.debug(e.getMessage());
421+
}
422+
}
423+
424+
// New in 7.1, pass Statement so that ExecSQL can customise to it
357425
result =QueryExecutor.execute(m_sqlFragments,
358-
m_binds,
359-
this);
426+
m_binds,
427+
this);
360428

361429
//If we are executing a callable statement function set the return data
362430
if (isFunction)
@@ -379,102 +447,6 @@ public boolean execute() throws SQLException
379447
return (result !=null &&result.reallyResultSet());
380448
}
381449
}
382-
383-
/** version of execute which converts the query to a cursor.
384-
*/
385-
publicbooleanexecuteWithCursor()throwsSQLException
386-
{
387-
if (isFunction && !returnTypeSet)
388-
thrownewPSQLException("postgresql.call.noreturntype");
389-
if (isFunction)
390-
{// set entry 1 to dummy entry..
391-
m_binds[0] ="";// dummy entry which ensured that no one overrode
392-
m_bindTypes[0] =PG_TEXT;
393-
// and calls to setXXX (2,..) really went to first arg in a function call..
394-
}
395-
396-
// New in 7.1, if we have a previous resultset then force it to close
397-
// This brings us nearer to compliance, and helps memory management.
398-
// Internal stuff will call ExecSQL directly, bypassing this.
399-
if (result !=null)
400-
{
401-
java.sql.ResultSetrs =getResultSet();
402-
if (rs !=null)
403-
rs.close();
404-
}
405-
406-
// I've pretty much ignored server prepared statements... can declare and prepare be
407-
// used together?
408-
// It's trivial to change this: you just have to resolve this issue
409-
// of how to work out whether there's a function call. If there isn't then the first
410-
// element of the array must be the bit that you extend to become the cursor
411-
// decleration.
412-
// The last thing that can go wrong is when the user supplies a cursor statement
413-
// directly: the translation takes no account of that. I think we should just look
414-
// for declare and stop the translation if we find it.
415-
416-
// The first thing to do is transform the statement text into the cursor form.
417-
String[]origSqlFragments =m_sqlFragments;
418-
m_sqlFragments =newString[origSqlFragments.length];
419-
System.arraycopy(origSqlFragments,0,m_sqlFragments,0,origSqlFragments.length);
420-
// Pinch the prepared count for our own nefarious purposes.
421-
m_statementName ="JDBC_CURS_" +m_preparedCount++;
422-
// The static bit to prepend to all querys.
423-
StringcursDecl ="BEGIN; DECLARE " +m_statementName +" CURSOR FOR ";
424-
StringendCurs =" FETCH FORWARD " +fetchSize +" FROM " +m_statementName +";";
425-
426-
// Add the real query to the curs decleration.
427-
// This is the bit that really makes the presumption about
428-
// m_sqlFragments not being a function call.
429-
if (m_sqlFragments.length <1)
430-
m_sqlFragments[0] =cursDecl +"SELECT NULL;";
431-
432-
elseif (m_sqlFragments.length <2)
433-
{
434-
if (m_sqlFragments[0].endsWith(";"))
435-
m_sqlFragments[0] =cursDecl +m_sqlFragments[0] +endCurs;
436-
else
437-
m_sqlFragments[0] =cursDecl +m_sqlFragments[0] +";" +endCurs;
438-
}
439-
else
440-
{
441-
m_sqlFragments[0] =cursDecl +m_sqlFragments[0];
442-
if (m_sqlFragments[m_sqlFragments.length -1].endsWith(";"))
443-
m_sqlFragments[m_sqlFragments.length -1] +=endCurs;
444-
else
445-
m_sqlFragments[m_sqlFragments.length -1] += (";" +endCurs);
446-
}
447-
448-
result =QueryExecutor.execute(m_sqlFragments,
449-
m_binds,
450-
this);
451-
452-
//If we are executing a callable statement function set the return data
453-
if (isFunction)
454-
{
455-
if (!result.reallyResultSet())
456-
thrownewPSQLException("postgresql.call.noreturnval");
457-
if (!result.next ())
458-
thrownewPSQLException ("postgresql.call.noreturnval");
459-
callResult =result.getObject(1);
460-
intcolumnType =result.getMetaData().getColumnType(1);
461-
if (columnType !=functionReturnType)
462-
{
463-
Object[]arr =
464-
{"java.sql.Types=" +columnType,
465-
"java.sql.Types=" +functionReturnType
466-
};
467-
thrownewPSQLException ("postgresql.call.wrongrtntype",arr);
468-
}
469-
result.close ();
470-
returntrue;
471-
}
472-
else
473-
{
474-
return (result !=null &&result.reallyResultSet());
475-
}
476-
}
477-
478450

479451
/*
480452
* setCursorName defines the SQL cursor name that will be used by

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp