content: /*
   * Copyright 1999-2012 Alibaba Group.
   *  
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *  
   *      http://www.apache.org/licenses/LICENSE-2.0
   *  
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.alibaba.cobar.net.mysql;
  
  import java.io.UnsupportedEncodingException;
  
  import com.alibaba.cobar.mysql.BindValue;
  import com.alibaba.cobar.mysql.BindValueUtil;
  import com.alibaba.cobar.mysql.MySQLMessage;
  import com.alibaba.cobar.mysql.PreparedStatement;
  
  /**
   * <pre>
   *  Bytes                      Name
   *  -----                      ----
   *  1                          code
   *  4                          statement_id
   *  1                          flags
   *  4                          iteration_count 
   *  (param_count+7)/8          null_bit_map
   *  1                          new_parameter_bound_flag (if new_params_bound == 1:)
   *  n*2                        type of parameters
   *  n                          values for the parameters   
   *  --------------------------------------------------------------------------------
   *  code:                      always COM_EXECUTE
   *  
   *  statement_id:              statement identifier
   *  
   *  flags:                     reserved for future use. In MySQL 4.0, always 0.
   *                             In MySQL 5.0: 
   *                               0: CURSOR_TYPE_NO_CURSOR
   *                               1: CURSOR_TYPE_READ_ONLY
   *                               2: CURSOR_TYPE_FOR_UPDATE
   *                               4: CURSOR_TYPE_SCROLLABLE
   *  
   *  iteration_count:           reserved for future use. Currently always 1.
   *  
   *  null_bit_map:              A bitmap indicating parameters that are NULL.
   *                             Bits are counted from LSB, using as many bytes
   *                             as necessary ((param_count+7)/8)
   *                             i.e. if the first parameter (parameter 0) is NULL, then
   *                             the least significant bit in the first byte will be 1.
   *  
   *  new_parameter_bound_flag:  Contains 1 if this is the first time
   *                             that "execute" has been called, or if
   *                             the parameters have been rebound.
   *  
   *  type:                      Occurs once for each parameter; 
   *                             The highest significant bit of this 16-bit value
   *                             encodes the unsigned property. The other 15 bits
   *                             are reserved for the type (only 8 currently used).
   *                             This block is sent when parameters have been rebound
   *                             or when a prepared statement is executed for the 
   *                             first time.
   * 
   *  values:                    for all non-NULL values, each parameters appends its value
   *                             as described in Row Data Packet: Binary (column values)
   * @see http://dev.mysql.com/doc/internals/en/execute-packet.html
   * </pre>
   * 
   * @author xianmao.hexm 2012-8-28
   */
  public class ExecutePacket extends MySQLPacket {
  
      public byte code;
      public long statementId;
      public byte flags;
      public long iterationCount;
      public byte[] nullBitMap;
      public byte newParameterBoundFlag;
      public BindValue[] values;
      protected PreparedStatement pstmt;
  
      public ExecutePacket(PreparedStatement pstmt) {
          this.pstmt = pstmt;
          this.values = new BindValue[pstmt.getParametersNumber()];
      }
  
      public void read(byte[] data, String charset) throws UnsupportedEncodingException {
          MySQLMessage mm = new MySQLMessage(data);
          packetLength = mm.readUB3();
          packetId = mm.read();
          code = mm.read();
          statementId = mm.readUB4();
          flags = mm.read();
          iterationCount = mm.readUB4();
  
          // 读取NULL指示器数据
          int parameterCount = values.length;
          nullBitMap = new byte[(parameterCount + 7) / 8];
          for (int i = 0; i < nullBitMap.length; i++) {
              nullBitMap[i] = mm.read();
          }
  
          // 当newParameterBoundFlag==1时，更新参数类型。
          newParameterBoundFlag = mm.read();
          if (newParameterBoundFlag == (byte) 1) {
              for (int i = 0; i < parameterCount; i++) {
                  pstmt.getParametersType()[i] = mm.readUB2();
              }
          }
  
          // 设置参数类型和读取参数值
          byte[] nullBitMap = this.nullBitMap;
          for (int i = 0; i < parameterCount; i++) {
              BindValue bv = new BindValue();
              bv.type = pstmt.getParametersType()[i];
              if ((nullBitMap[i / 8] & (1 << (i & 7))) != 0) {
                  bv.isNull = true;
              } else {
                  BindValueUtil.read(mm, bv, charset);
              }
              values[i] = bv;
          }
      }
  
      @Override
      public int calcPacketSize() {
          // TODO Auto-generated method stub
          return 0;
      }
  
      @Override
      protected String getPacketInfo() {
          return "MySQL Execute Packet";
      }
  
  }
  