📄 preparedstatement.java
字号:
/*
* MM JDBC Drivers for MySQL
*
* $Id: PreparedStatement.java,v 1.2 1998/08/25 00:53:47 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.
*/
/**
* A SQL Statement is pre-compiled and stored in a PreparedStatement object.
* This object can then be used to efficiently execute this statement multiple
* times.
*
* <p><B>Note:</B> The setXXX methods for setting IN parameter values must
* specify types that are compatible with the defined SQL type of the input
* parameter. For instance, if the IN parameter has SQL type Integer, then
* setInt should be used.
*
* <p>If arbitrary parameter type conversions are required, then the setObject
* method should be used with a target SQL type.
*
* @see java.sql.ResultSet
* @see java.sql.PreparedStatement
* @author Mark Matthews <mmatthew@worldserver.com>
* @version $Id$
*/
package org.gjt.mm.mysql;
import java.io.*;
import java.math.*;
import java.sql.*;
import java.text.*;
import java.util.*;
public class PreparedStatement extends org.gjt.mm.mysql.Statement
implements java.sql.PreparedStatement
{
private String _Sql = null;
private String[] _TemplateStrings = null;
private String[] _ParameterStrings = null;
private InputStream[] _ParameterStreams = null;
private boolean[] _IsStream = null;
private Connection _Conn = null;
private boolean _do_concat = false;
private boolean _has_limit_clause = false;
/**
* Constructor for the PreparedStatement class.
* Split the SQL statement into segments - separated by the arguments.
* When we rebuild the thing with the arguments, we can substitute the
* args and join the whole thing together.
*
* @param conn the instanatiating connection
* @param sql the SQL statement with ? for IN markers
* @exception java.sql.SQLException if something bad occurs
*/
public PreparedStatement(Connection Conn, String Sql, String Catalog) throws java.sql.SQLException
{
super(Conn, Catalog);
if (Sql.indexOf("||") != -1) {
_do_concat = true;
}
_has_limit_clause = (Sql.toUpperCase().indexOf("LIMIT") != -1);
Vector V = new Vector();
boolean inQuotes = false;
int lastParmEnd = 0, i;
_Sql = Sql;
_Conn = Conn;
for (i = 0; i < _Sql.length(); ++i) {
int c = _Sql.charAt(i);
if (c == '\'')
inQuotes = !inQuotes;
if (c == '?' && !inQuotes)
{
V.addElement(_Sql.substring (lastParmEnd, i));
lastParmEnd = i + 1;
}
}
V.addElement(_Sql.substring (lastParmEnd, _Sql.length()));
_TemplateStrings = new String[V.size()];
_ParameterStrings = new String[V.size() - 1];
_ParameterStreams = new InputStream[V.size() - 1];
_IsStream = new boolean[V.size() - 1];
clearParameters();
for (i = 0 ; i < _TemplateStrings.length; ++i) {
_TemplateStrings[i] = (String)V.elementAt(i);
}
for (int j = 0; j < _ParameterStrings.length; j++) {
_IsStream[j] = false;
}
}
/**
* A Prepared SQL query is executed and its ResultSet is returned
*
* @return a ResultSet that contains the data produced by the
* query - never null
* @exception java.sql.SQLException if a database access error occurs
*/
public java.sql.ResultSet executeQuery() throws java.sql.SQLException
{
boolean do_escape_processing = _escapeProcessing;
_escapeProcessing = false; // Do escape processing part-by-part
Buffer Packet = new Buffer(MysqlIO.getMaxBuf());
Packet.writeByte((byte)MysqlDefs.QUERY);
String Encoding = null;
if (_Conn.useUnicode()) {
Encoding = _Conn.getEncoding();
}
try {
for (int i = 0 ; i < _ParameterStrings.length ; ++i) {
if (_ParameterStrings[i] == null &&
(_IsStream[i] && _ParameterStreams[i] == null)) {
throw new java.sql.SQLException("No value specified for parameter " + (i + 1), "07001");
}
if (Encoding != null) {
Packet.writeStringNoNull(_TemplateStrings[i], Encoding);
}
else {
Packet.writeStringNoNull(_TemplateStrings[i]);
}
if (_IsStream[i]) {
Packet.writeBytesNoNull(streamToBytes(_ParameterStreams[i]));
}
else {
if (do_escape_processing) {
_ParameterStrings[i] = _Escaper.escapeSQL(_ParameterStrings[i]);
}
if (Encoding != null) {
Packet.writeStringNoNull(_ParameterStrings[i], Encoding);
}
else {
Packet.writeStringNoNull(_ParameterStrings[i]);
}
}
}
if (Encoding != null) {
Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length], Encoding);
}
else {
Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length]);
}
}
catch (java.io.UnsupportedEncodingException UE) {
throw new SQLException("Unsupported character encoding '" + Encoding + "'");
}
if (_Results != null) {
_Results.close();
}
// We need to execute this all together
// So synchronize on the Connection's mutex (because
// even queries going through there synchronize
// on the same mutex.
synchronized (_Conn.getMutex()) {
String OldCatalog = null;
if (!_Conn.getCatalog().equals(_Catalog)) {
OldCatalog = _Conn.getCatalog();
_Conn.setCatalog(_Catalog);
}
if (_Conn.useMaxRows()) {
// 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).
if (_has_limit_clause) {
_Results = _Conn.execSQL(null, _max_rows, Packet);
}
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(null, -1, Packet);
if (OldCatalog != null) {
_Conn.setCatalog(OldCatalog);
}
}
}
else {
_Results = _Conn.execSQL(null, -1, Packet);
}
if (OldCatalog != null) {
_Conn.setCatalog(OldCatalog);
}
}
_last_insert_id = _Results.getUpdateID();
_NextResults = _Results;
_Results.setConnection(_Conn);
_escapeProcessing = do_escape_processing;
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.
*
* @return either the row count for INSERT, UPDATE or DELETE; or
* 0 for SQL statements that return nothing.
* @exception java.sql.SQLException if a database access error occurs
*/
public int executeUpdate() throws java.sql.SQLException
{
boolean do_escape_processing = _escapeProcessing;
_escapeProcessing = false;
Buffer Packet = new Buffer(MysqlIO.getMaxBuf());
Packet.writeByte((byte)MysqlDefs.QUERY);
String Encoding = null;
if (_Conn.useUnicode()) {
Encoding = _Conn.getEncoding();
}
try {
for (int i = 0 ; i < _ParameterStrings.length ; ++i) {
if (_ParameterStrings[i] == null &&
(_IsStream[i] && _ParameterStreams[i] == null)) {
throw new java.sql.SQLException("No value specified for parameter " + (i + 1), "07001");
}
if (Encoding != null) {
Packet.writeStringNoNull(_TemplateStrings[i], Encoding);
}
else {
Packet.writeStringNoNull(_TemplateStrings[i]);
}
if (_IsStream[i]) {
Packet.writeBytesNoNull(streamToBytes(_ParameterStreams[i]));
}
else {
if (do_escape_processing) {
_ParameterStrings[i] = _Escaper.escapeSQL(_ParameterStrings[i]);
}
if (Encoding != null) {
Packet.writeStringNoNull(_ParameterStrings[i], Encoding);
}
else {
Packet.writeStringNoNull(_ParameterStrings[i]);
}
}
}
if (Encoding != null) {
Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length], Encoding);
}
else {
Packet.writeStringNoNull(_TemplateStrings[_ParameterStrings.length]);
}
}
catch (java.io.UnsupportedEncodingException UE) {
throw new SQLException("Unsupported character encoding '" + Encoding + "'");
}
// 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(null, -1, Packet);
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();
_escapeProcessing = do_escape_processing;
return truncated_update_count;
}
}
/**
* Set a parameter to SQL NULL
*
* <p><B>Note:</B> You must specify the parameters SQL type (although
* PostgreSQL ignores it)
*
* @param parameterIndex the first parameter is 1, etc...
* @param sqlType the SQL type code defined in java.sql.Types
* @exception java.sql.SQLException if a database access error occurs
*/
public void setNull(int parameterIndex, int sqlType) throws java.sql.SQLException
{
set(parameterIndex, "null");
}
/**
* Set a parameter to a Java boolean value. The driver converts this
* to a SQL BIT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception java.sql.SQLException if a database access error occurs
*/
public void setBoolean(int parameterIndex, boolean x) throws java.sql.SQLException
{
set(parameterIndex, x ? "'t'" : "'f'");
}
/**
* Set a parameter to a Java byte value. The driver converts this to
* a SQL TINYINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception java.sql.SQLException if a database access error occurs
*/
public void setByte(int parameterIndex, byte x) throws java.sql.SQLException
{
set(parameterIndex, (new Integer(x)).toString());
}
/**
* Set a parameter to a Java short value. The driver converts this
* to a SQL SMALLINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception java.sql.SQLException if a database access error occurs
*/
public void setShort(int parameterIndex, short x) throws java.sql.SQLException
{
set(parameterIndex, (new Integer(x)).toString());
}
/**
* Set a parameter to a Java int value. The driver converts this to
* a SQL INTEGER value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception java.sql.SQLException if a database access error occurs
*/
public void setInt(int parameterIndex, int x) throws java.sql.SQLException
{
set(parameterIndex, (new Integer(x)).toString());
}
/**
* Set a parameter to a Java long value. The driver converts this to
* a SQL BIGINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception java.sql.SQLException if a database access error occurs
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -