📄 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 + -