📄 preparedstatement.java
字号:
/*
* MM JDBC Drivers for MySQL
*
* $Id: PreparedStatement.java,v 1.6 2002/05/07 21:25:58 mark_matthews 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: PreparedStatement.java,v 1.6 2002/05/07 21:25:58 mark_matthews Exp $
*/
package com.mysql.jdbc;
import java.io.*;
import java.math.*;
import java.sql.*;
import java.text.*;
import java.util.*;
public class PreparedStatement extends com.mysql.jdbc.Statement
{
protected static SimpleDateFormat _TSDF =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private String _Sql = null;
private byte[][] _TemplateStrings = null;
protected String[] _ParameterStrings = null;
protected InputStream[] _ParameterStreams = null;
protected boolean[] _IsStream = null;
protected boolean[] _IsNull = null;
private boolean _has_limit_clause = false;
private byte[] _bi = new byte[4096];
private Buffer _SendPacket = null;
private boolean _useTrueBoolean = false;
private static java.util.Hashtable templateCache = new java.util.Hashtable();
private char _firstChar;
class EndPoint
{
int begin;
int end;
EndPoint(int b, int e)
{
begin = b;
end = e;
}
}
/**
* 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);
_useTrueBoolean = _conn.getIO().versionMeetsMinimum(3, 21, 23);
_firstChar = Character.toUpperCase(Sql.charAt(0));
_has_limit_clause = (Sql.toUpperCase().indexOf("LIMIT") != -1);
char[] statementAsChars = Sql.toCharArray();
int statementLength = statementAsChars.length;
int placeHolderCount = 0;
for (int i = 0; i < statementLength; i++)
{
if (statementAsChars[i] == '?')
{
placeHolderCount++;
}
}
// _TemplateStrings = (byte[][])templateCache.get(Sql);
//if (_TemplateStrings == null) {
Vector V = new Vector(placeHolderCount + 1);
boolean inQuotes = false;
int lastParmEnd = 0, i;
_Sql = Sql;
_conn = Conn;
int pre1 = 0;
int pre2 = 0;
for (i = 0; i < statementLength; ++i)
{
int c = statementAsChars[i];
if (c == '\'' && pre1 == '\\' && pre2 == '\\')
{
inQuotes = !inQuotes;
}
else if (c == '\'' && pre1 != '\\')
{
inQuotes = !inQuotes;
}
if (c == '?' && !inQuotes)
{
//V.addElement(_Sql.substring (lastParmEnd, i));
V.addElement(new EndPoint(lastParmEnd, i));
lastParmEnd = i + 1;
}
pre2 = pre1;
pre1 = c;
}
//V.addElement(_Sql.substring (lastParmEnd, _Sql.length()));
V.addElement(new EndPoint(lastParmEnd, statementLength));
_TemplateStrings = new byte[V.size()][];
String Encoding = null;
if (_conn.useUnicode())
{
Encoding = _conn.getEncoding();
}
for (i = 0; i < _TemplateStrings.length; i++)
{
if (Encoding == null)
{
// String str = (String)V.elementAt(i);
//int len = str.length();
//byte[] buf = new byte[len];
//for (int j = 0; j < len; j++) {
// buf[j] = (byte)str.charAt(j);
//}
//_TemplateStrings[i] = buf;
EndPoint ep = (EndPoint) V.elementAt(i);
int end = ep.end;
int begin = ep.begin;
int len = end - begin;
byte[] buf = new byte[len];
for (int j = 0; j < len; j++)
{
buf[j] = (byte) statementAsChars[begin + j];
}
_TemplateStrings[i] = buf;
}
else
{
try
{
EndPoint ep = (EndPoint) V.elementAt(i);
int end = ep.end;
int begin = ep.begin;
int len = end - begin;
String temp = new String(statementAsChars, begin, len);
_TemplateStrings[i] = temp.getBytes(Encoding);
}
catch (java.io.UnsupportedEncodingException ue)
{
throw new SQLException(ue.toString());
}
}
}
// templateCache.put(Sql, _TemplateStrings);
// }
_ParameterStrings = new String[_TemplateStrings.length - 1];
_ParameterStreams = new InputStream[_TemplateStrings.length - 1];
_IsStream = new boolean[_TemplateStrings.length - 1];
_IsNull = new boolean[_TemplateStrings.length - 1];
clearParameters();
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
{
if (_SendPacket == null)
{
_SendPacket =
new Buffer(_conn.getNetBufferLength(), _conn.getMaxAllowedPacket());
}
else
{
_SendPacket.clear();
}
_SendPacket.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 && _ParameterStreams[i] == null)
{
throw new java.sql.SQLException(
"No value specified for parameter " + (i + 1),
"07001");
}
//if (Encoding != null) {
_SendPacket.writeBytesNoNull(_TemplateStrings[i]);
//}
//else {
// _SendPacket.writeStringNoNull(_TemplateStrings[i]);
//}
if (_IsStream[i])
{
_SendPacket.writeBytesNoNull(streamToBytes(_ParameterStreams[i]));
}
else
{
if (Encoding != null)
{
_SendPacket.writeStringNoNull(_ParameterStrings[i], Encoding);
}
else
{
_SendPacket.writeStringNoNull(_ParameterStrings[i]);
}
}
}
_SendPacket.writeBytesNoNull(_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, _maxRows, _SendPacket);
}
else
{
if (_maxRows <= 0)
{
_conn.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1);
}
else
{
_conn.execSQL("SET OPTION SQL_SELECT_LIMIT=" + _maxRows, -1);
}
_results = _conn.execSQL(null, -1, _SendPacket);
if (OldCatalog != null)
{
_conn.setCatalog(OldCatalog);
}
}
}
else
{
_results = _conn.execSQL(null, -1, _SendPacket);
}
if (OldCatalog != null)
{
_conn.setCatalog(OldCatalog);
}
}
_lastInsertId = _results.getUpdateID();
_nextResults = _results;
_results.setConnection(_conn);
_results.setResultSetType(_resultSetType);
_results.setResultSetConcurrency(_resultSetConcurrency);
_results.setStatement(this);
return (java.sql.ResultSet) _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
{
return executeUpdate(_ParameterStrings, _ParameterStreams, _IsStream, _IsNull);
}
/**
* Added to allow batch-updates
*/
protected int executeUpdate(
String[] ParameterStrings,
InputStream[] ParameterStreams,
boolean[] IsStream,
boolean[] IsNull)
throws java.sql.SQLException
{
if (_SendPacket == null)
{
_SendPacket =
new Buffer(_conn.getNetBufferLength(), _conn.getMaxAllowedPacket());
}
else
{
_SendPacket.clear();
}
_SendPacket.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 && ParameterStreams[i] == null)
{
throw new java.sql.SQLException(
"No value specified for parameter " + (i + 1),
"07001");
}
//if (Encoding != null) {
_SendPacket.writeBytesNoNull(_TemplateStrings[i]);
//}
//else {
// _SendPacket.writeStringNoNull(_TemplateStrings[i]);
//}
if (IsStream[i])
{
_SendPacket.writeBytesNoNull(streamToBytes(ParameterStreams[i]));
}
else
{
if (Encoding != null)
{
_SendPacket.writeStringNoNull(ParameterStrings[i], Encoding);
}
else
{
_SendPacket.writeStringNoNull(ParameterStrings[i]);
}
}
}
//if (Encoding != null) {
_SendPacket.writeBytesNoNull(_TemplateStrings[ParameterStrings.length]);
// }
// else {
// _SendPacket.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);
}
//
// Only apply max_rows to selects
//
if (_conn.useMaxRows())
{
_conn.execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1);
}
RS = _conn.execSQL(null, -1, _SendPacket);
if (OldCatalog != null)
{
_conn.setCatalog(OldCatalog);
}
}
if (RS.reallyResult())
{
throw new java.sql.SQLException("Results returned for UPDATE ONLY.", "01S03");
}
else
{
_updateCount = RS.getUpdateCount();
int truncated_updateCount = 0;
if (_updateCount > Integer.MAX_VALUE)
{
truncated_updateCount = Integer.MAX_VALUE;
}
else
{
truncated_updateCount = (int) _updateCount;
}
_lastInsertId = RS.getUpdateID();
return truncated_updateCount;
}
}
/**
* Set a parameter to SQL NULL
*
* <p><B>Note:</B> You must specify the parameters SQL type (although
* MySQL 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");
_IsNull[parameterIndex - 1] = true;
}
/**
* 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
{
if (_useTrueBoolean)
{
set(parameterIndex, x ? "'1'" : "'0'");
}
else
{
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, String.valueOf(x));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -