|
What this is
Other links
The source code
/*
* MM JDBC Drivers for MySQL
*
* $Id: Statement.java,v 1.2 1998/08/25 00:53:48 mmatthew Exp $
*
* Copyright (C) 1998 Mark Matthews <mmatthew@worldserver.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* See the COPYING file located in the top-level-directory of
* the archive of this library for complete text of license.
*
* Some portions:
*
* Copyright (c) 1996 Bradley McLean / Jeffrey Medeiros
* Modifications Copyright (c) 1996/1997 Martin Rode
* Copyright (c) 1997 Peter T Mount
*/
/**
* A Statement object is used for executing a static SQL statement and
* obtaining the results produced by it.
*
* <p>Only one ResultSet per Statement can be open at any point in time.
* Therefore, if the reading of one ResultSet is interleaved with the
* reading of another, each must have been generated by different
* Statements. All statement execute methods implicitly close a
* statement's current ResultSet if an open one exists.
*
* @see java.sql.Statement
* @see ResultSet
* @author Mark Matthews <mmatthew@worldserver.com>
* @version $Id$
*/
package org.gjt.mm.mysql;
import java.sql.*;
public class Statement implements java.sql.Statement
{
Connection _Conn = null; // The connection who created us
ResultSet _Results = null; // The current results
ResultSet _NextResults = null; // The next result set
SQLWarning _Warnings = null; // The warnings chain.
int _timeout = 0; // The timeout for a query
boolean _escapeProcessing = true; // escape processing flag
EscapeProcessor _Escaper = null; // The escape processor
int _max_field_size = MysqlIO.MAXBUF;
int _max_rows = -1;
long _update_count = -1;
long _last_insert_id = -1;
String _Catalog = null;
/**
* Constructor for a Statement. It simply sets the connection
* that created us.
*
* @param c the Connection instantation that creates us
*/
public Statement(Connection C, String Catalog)
{
if (Driver.trace) {
Object[] Args = {C};
Debug.methodCall(this, "constructor", Args);
}
_Conn = C;
_Escaper = new EscapeProcessor();
_Catalog = Catalog;
}
/**
* Execute a SQL statement that retruns a single ResultSet
*
* @param Sql typically a static SQL SELECT statement
* @return a ResulSet that contains the data produced by the query
* @exception java.sql.SQLException if a database access error occurs
*/
public java.sql.ResultSet executeQuery(String Sql) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {Sql};
Debug.methodCall(this, "executeQuery", Args);
}
if (_escapeProcessing) {
Sql = _Escaper.escapeSQL(Sql);
}
if (Sql.indexOf("||") != -1) {
Sql = _Escaper.doConcat(Sql);
}
if (_Results != null) {
_Results.close();
}
// If there isn't a limit clause in the SQL
// then limit the number of rows to return in
// an efficient manner. Only do this if
// setMaxRows() hasn't been used on any Statements
// generated from the current Connection (saves
// a query, and network traffic).
synchronized (_Conn.getMutex()) {
String OldCatalog = null;
if (!_Conn.getCatalog().equals(_Catalog)) {
OldCatalog = _Conn.getCatalog();
_Conn.setCatalog(_Catalog);
}
if (_Conn.useMaxRows()) {
// We need to execute this all together
// So synchronize on the Connection's mutex (because
// even queries going through there synchronize
// on the connection
if (Sql.toUpperCase().indexOf("LIMIT") != -1) {
_Results = _Conn.execSQL(Sql, _max_rows);
}
else {
if (_max_rows <= 0) {
_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT="
+ MysqlDefs.MAX_ROWS, -1);
}
else {
_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT=" + _max_rows,-1);
}
_Results = _Conn.execSQL(Sql, -1);
if (OldCatalog != null) {
_Conn.setCatalog(OldCatalog);
}
}
}
else {
_Results = _Conn.execSQL(Sql, -1);
}
if (OldCatalog != null) {
_Conn.setCatalog(OldCatalog);
}
}
_last_insert_id = _Results.getUpdateID();
_NextResults = _Results;
_Results.setConnection(_Conn);
return _Results;
}
/**
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition
* SQL statements that return nothing such as SQL DDL statements
* can be executed
*
* Any IDs generated for AUTO_INCREMENT fields can be retrieved
* by casting this Statement to org.gjt.mm.mysql.Statement and
* calling the getLastInsertID() method.
*
* @param Sql a SQL statement
* @return either a row count, or 0 for SQL commands
* @exception java.sql.SQLException if a database access error occurs
*/
public int executeUpdate(String Sql) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {Sql};
Debug.methodCall(this, "executeUpdate", Args);
}
if (_escapeProcessing) {
Sql = _Escaper.escapeSQL(Sql);
}
if (Sql.indexOf("||") != -1) {
Sql = _Escaper.doConcat(Sql);
}
// The checking and changing of catalogs
// must happen in sequence, so synchronize
// on the same mutex that _Conn is using
ResultSet RS = null;
synchronized (_Conn.getMutex()) {
String OldCatalog = null;
if (!_Conn.getCatalog().equals(_Catalog)) {
OldCatalog = _Conn.getCatalog();
_Conn.setCatalog(_Catalog);
}
RS = _Conn.execSQL(Sql, -1);
RS.setConnection(_Conn);
if (OldCatalog != null) {
_Conn.setCatalog(OldCatalog);
}
}
if (RS.reallyResult()) {
throw new java.sql.SQLException("Results returned for UPDATE ONLY.", "01S03");
}
else {
_update_count = RS.getUpdateCount();
int truncated_update_count = 0;
if (_update_count > Integer.MAX_VALUE) {
truncated_update_count = Integer.MAX_VALUE;
}
else {
truncated_update_count = (int)_update_count;
}
_last_insert_id = RS.getUpdateID();
return truncated_update_count;
}
}
/**
* In many cases, it is desirable to immediately release a
* Statement's database and JDBC resources instead of waiting
* for this to happen when it is automatically closed. The
* close method provides this immediate release.
*
* <p>Note: A Statement is automatically closed when it is
* garbage collected. When a Statement is closed, its current
* ResultSet, if one exists, is also closed.
*
* @exception java.sql.SQLException if a database access error occurs
*/
public void close() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "close", Args);
}
_Results = null;
_Conn = null;
_Warnings = null;
_Escaper = null;
}
/**
* The maxFieldSize limit (in bytes) is the maximum amount of
* data returned for any column value; it only applies to
* BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
* columns. If the limit is exceeded, the excess data is silently
* discarded.
*
* @return the current max column size limit; zero means unlimited
* @exception java.sql.SQLException if a database access error occurs
*/
public int getMaxFieldSize() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getMaxFieldSize", Args);
}
return _max_field_size; // Init. set to MAXBUFFER in MysqlIO
}
/**
* Sets the maxFieldSize
*
* @param max the new max column size limit; zero means unlimited
* @exception java.sql.SQLException if size exceeds buffer size
*/
public void setMaxFieldSize(int max) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {new Integer(max)};
Debug.methodCall(this, "setMaxFieldSize", Args);
}
if (max > MysqlIO.MAXBUF)
throw new java.sql.SQLException("Attempt to set max field size > " + MysqlIO.MAXBUF + " (compile time default)", "S1009");
else
_max_field_size = max;
}
/**
* The maxRows limit is set to limit the number of rows that
* any ResultSet can contain. If the limit is exceeded, the
* excess rows are silently dropped.
*
* @return the current maximum row limit; zero means unlimited
* @exception java.sql.SQLException if a database access error occurs
*/
public int getMaxRows() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getMaxRows", Args);
}
if (_max_rows <=0) {
return 0;
}
else {
return _max_rows;
}
}
/**
* Set the maximum number of rows
*
* @param max the new max rows limit; zero means unlimited
* @exception java.sql.SQLException if a database access error occurs
* @see getMaxRows
*/
public void setMaxRows(int max) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {new Integer(max)};
Debug.methodCall(this, "setMaxRows", Args);
}
if (max > MysqlDefs.MAX_ROWS) {
throw new java.sql.SQLException("setMaxRows() out of range. " + max + " > " + MysqlDefs.MAX_ROWS + ".", "S1009");
}
if (max == 0) {
max = -1;
}
_max_rows = max;
// Most people don't use setMaxRows()
// so don't penalize them
// with the extra query it takes
// to do it efficiently unless we need
// to.
_Conn.maxRowsChanged();
}
/**
* If escape scanning is on (the default), the driver will do escape
* substitution before sending the SQL to the database.
*
* @param enable true to enable; false to disable
* @exception java.sql.SQLException if a database access error occurs
*/
public void setEscapeProcessing(boolean enable) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {new Boolean(enable)};
Debug.methodCall(this, "setEscapeProcessing", Args);
}
_escapeProcessing = enable;
}
/**
* The queryTimeout limit is the number of seconds the driver
* will wait for a Statement to execute. If the limit is
* exceeded, a java.sql.SQLException is thrown.
*
* @return the current query timeout limit in seconds; 0 = unlimited
* @exception java.sql.SQLException if a database access error occurs
*/
public int getQueryTimeout() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getQueryTimeout", Args);
}
return _timeout;
}
/**
* Sets the queryTimeout limit
*
* @param seconds - the new query timeout limit in seconds
* @exception java.sql.SQLException if a database access error occurs
*/
public void setQueryTimeout(int seconds) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {new Integer(seconds)};
Debug.methodCall(this, "setQueryTimeout", Args);
}
_timeout = seconds;
}
/**
* Cancel can be used by one thread to cancel a statement that
* is being executed by another thread. However this driver
* is synchronous, so this really has no meaning - we
* define it as a no-op (i.e. you can't cancel, but there is no
* error if you try.)
*
* @exception java.sql.SQLException only because thats the spec.
*/
public void cancel() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "cancel", Args);
}
// No-op
}
/**
* The first warning reported by calls on this Statement is
* returned. A Statement's execute methods clear its java.sql.SQLWarning
* chain. Subsequent Statement warnings will be chained to this
* java.sql.SQLWarning.
*
* <p>The Warning chain is automatically cleared each time a statement
* is (re)executed.
*
* <p>Note: If you are processing a ResultSet then any warnings
* associated with ResultSet reads will be chained on the ResultSet
* object.
*
* @return the first java.sql.SQLWarning on null
* @exception java.sql.SQLException if a database access error occurs
*/
public java.sql.SQLWarning getWarnings() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getWarnings", Args);
}
return _Warnings;
}
/**
* After this call, getWarnings returns null until a new warning
* is reported for this Statement.
*
* @exception java.sql.SQLException if a database access error occurs (why?)
*/
public void clearWarnings() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "clearWarnings", Args);
}
_Warnings = null;
}
/**
* setCursorName defines the SQL cursor name that will be used by
* subsequent execute methods. This name can then be used in SQL
* positioned update/delete statements to identify the current row
* in the ResultSet generated by this statement. If a database
* doesn't support positioned update/delete, this method is a
* no-op.
*
* <p>Note: This MySQL driver does not support cursors.
*
*
* @param name the new cursor name
* @exception java.sql.SQLException if a database access error occurs
*/
public void setCursorName(String Name) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {Name};
Debug.methodCall(this, "setCursorName", Args);
}
// No-op
}
/**
* Execute a SQL statement that may return multiple results. We
* don't have to worry about this since we do not support multiple
* ResultSets. You can use getResultSet or getUpdateCount to
* retrieve the result.
*
* @param sql any SQL statement
* @return true if the next result is a ResulSet, false if it is
* an update count or there are no more results
* @exception java.sql.SQLException if a database access error occurs
*/
public boolean execute(String Sql) throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = {Sql};
Debug.methodCall(this, "execute", Args);
}
if (_escapeProcessing) {
Sql = _Escaper.escapeSQL(Sql);
}
if (Sql.indexOf("||") != -1) {
Sql = _Escaper.doConcat(Sql);
}
if (_Results != null) {
_Results.close();
}
ResultSet RS = null;
// If there isn't a limit clause in the SQL
// then limit the number of rows to return in
// an efficient manner. Only do this if
// setMaxRows() hasn't been used on any Statements
// generated from the current Connection (saves
// a query, and network traffic).
synchronized (_Conn.getMutex()) {
String OldCatalog = null;
if (!_Conn.getCatalog().equals(_Catalog)) {
OldCatalog = _Conn.getCatalog();
_Conn.setCatalog(_Catalog);
}
if (_Conn.useMaxRows()) {
if (Sql.toUpperCase().indexOf("LIMIT") != -1) {
RS = _Conn.execSQL(Sql, _max_rows);
}
else {
if (_max_rows <= 0) {
_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT="
+ MysqlDefs.MAX_ROWS, -1);
}
else {
_Conn.execSQL("SET OPTION SQL_SELECT_LIMIT=" + _max_rows,-1);
}
RS = _Conn.execSQL(Sql, -1);
}
}
else {
RS = _Conn.execSQL(Sql, -1);
}
if (OldCatalog != null) {
_Conn.setCatalog(OldCatalog);
}
}
_last_insert_id = RS.getUpdateID();
if (RS != null) {
_Results = RS;
}
RS.setConnection(_Conn);
return (RS != null && RS.reallyResult());
}
/**
* getResultSet returns the current result as a ResultSet. It
* should only be called once per result.
*
* @return the current result set; null if there are no more
* @exception java.sql.SQLException if a database access error occurs (why?)
*/
public java.sql.ResultSet getResultSet() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getResultSet", Args);
}
return _Results;
}
/**
* getUpdateCount returns the current result as an update count,
* if the result is a ResultSet or there are no more results, -1
* is returned. It should only be called once per result.
*
* @return the current result as an update count.
* @exception java.sql.SQLException if a database access error occurs
*/
public int getUpdateCount() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getUpdateCount", Args);
}
if (_Results == null) {
return -1;
}
if (_Results.reallyResult()) {
return -1;
}
int truncated_update_count = 0;
if (_Results.getUpdateCount() > Integer.MAX_VALUE) {
truncated_update_count = Integer.MAX_VALUE;
}
else {
truncated_update_count = (int)_Results.getUpdateCount();
}
return truncated_update_count;
}
/**
* getLongUpdateCount returns the current result as an update count,
* if the result is a ResultSet or there are no more results, -1
* is returned. It should only be called once per result.
*
* <p>
* This method returns longs as MySQL server versions newer than
* 3.22.4 return 64-bit values for update counts
*
* @return the current result as an update count.
* @exception java.sql.SQLException if a database access error occurs
*/
public long getLongUpdateCount()
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getLongUpdateCount", Args);
}
if (_Results == null) {
return -1;
}
if (_Results.reallyResult()) {
return -1;
}
return _update_count;
}
/**
* getLastInsertID returns the value of the auto_incremented key
* after an executeQuery() or excute() call.
*
* <p>
* This gets around the un-threadsafe behavior of
* "select LAST_INSERT_ID()" which is tied to the Connection
* that created this Statement, and therefore could have had
* many INSERTS performed before one gets a chance to call
* "select LAST_INSERT_ID()".
*
* @return the last update ID.
*/
public long getLastInsertID()
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getLastInsertID", Args);
}
return _last_insert_id;
}
/**
* getMoreResults moves to a Statement's next result. If it returns
* true, this result is a ResulSet.
*
* @return true if the next ResultSet is valid
* @exception java.sql.SQLException if a database access error occurs
*/
public boolean getMoreResults() throws java.sql.SQLException
{
if (Driver.trace) {
Object[] Args = new Object[0];
Debug.methodCall(this, "getMoreResults", Args);
}
if (_NextResults != null) {
_Results = _NextResults;
_NextResults = null;
return true;
}
else {
return false;
}
}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.