// Copyright (C) 2004 MySQL AB // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as published by // the Free Software Foundation // // There are special exceptions to the terms and conditions of the GPL // as it is applied to this software. View the full text of the // exception in file EXCEPTIONS in the directory of this software // distribution. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.Collections; namespace MySql.Data.MySqlClient { /// /// Summary description for PreparedStatement. /// internal class PreparedStatement { private Driver driver; private int statementId; private MySqlField[] paramList; private int executionCount; public PreparedStatement(Driver driver, int statementId, MySqlField[] paramList ) { this.paramList = new MySqlField[0]; this.driver = driver; this.statementId = statementId; this.paramList = paramList; executionCount = 0; } #region Properties public int StatementId { get { return statementId; } } public int NumParameters { get { return paramList.Length; } } public int ExecutionCount { get { return executionCount; } } #endregion public CommandResult Execute( MySqlParameterCollection parameters ) { if (parameters.Count < paramList.Length) throw new MySqlException( "Invalid number of parameters for statement execute" ); PacketWriter packet = new PacketWriter(); packet.Driver = (NativeDriver)driver; //TODO: support long data here // create our null bitmap BitArray nullMap = new BitArray( parameters.Count ); //metaData.Length ); for (int x=0; x < parameters.Count; x++) { if (parameters[x].Value == DBNull.Value) nullMap[x] = true; } byte[] nullMapBytes = new byte[ (parameters.Count + 7)/8 ]; if(nullMapBytes.Length > 0) // This fix problem with ArgumentException and nullMapBytes is already created and in case of length=0 there is no data to copy... nullMap.CopyTo( nullMapBytes, 0 ); // start constructing our packet packet.WriteInteger( StatementId, 4 ); packet.WriteByte( 0 ); // flags; always 0 for 4.1 packet.WriteInteger( 1, 4 ); // interation count; 1 for 4.1 packet.Write( nullMapBytes ); if (parameters != null && parameters.Count > 0) packet.WriteByte( 1 ); // rebound flag else packet.WriteByte( 0 ); //TODO: only send rebound if parms change // write out the parameter types foreach ( MySqlField param in paramList ) { MySqlParameter parm = parameters[ param.ColumnName ]; packet.WriteInteger( (long)parm.MySqlDbType, 2 ); } // now write out all non-null values foreach ( MySqlField param in paramList ) { MySqlParameter parm = parameters[ param.ColumnName ]; if (parm.Value == DBNull.Value) continue; packet.Encoding = param.Encoding; parm.Serialize( packet, true ); } // executionCount ++; // send the data packet and return the CommandResult return driver.ExecuteStatement( ((System.IO.MemoryStream)packet.Stream).ToArray() ); } } }