/*


    ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    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.
    ========== licence end


*/

package com.sap.dbtech.jdbc.packet;

import java.io.*;

import com.sap.dbtech.util.*;
import com.sap.dbtech.util.security.SCRAMMD5;
import com.sap.dbtech.jdbc.translators.ConversionExceptionSapDB;
import com.sap.dbtech.rte.comm.*;
import com.sap.dbtech.vsp001.*;

import java.sql.ResultSet;

/**
 *
 */
public class RequestPacket extends SQLPacket
{
    private static String ApplID="ODB";
    private static String ApplVers="70400";
    private boolean isAvailable = false;
    private int packetLength;
    private int packetSegments;
    private int segmLength;
    private int maxNumberOfSegm = defaultmaxNumberOfSegm_C;
    private int segmParts;
    protected int partLength;
    private int partArguments;
    private int replyReserve;
    private int currentSqlMode = SqlMode.SessionSqlmode_C;
    public static final boolean reset_C = true;
    public static final boolean append_C = false;
    public static final int resultCountSize_C = 6;
    public static final int defaultmaxNumberOfSegm_C = 6; //default maximum number of segments for a request packet
    public static final int reserveFor2ndSegment_C = 8192; //8kB reserve size in order paket if more than 1 segment will be used
    public static final int reserveForReply_C =
            Segment.Part_O - Part.Data_O + 200;
    /**
     * SQLPacket constructor comment.
     */
    public RequestPacket(StructuredMem rawPacket)
    {
        this (rawPacket, RteC.asciiClient_C, null,null);
    }
    /**
     * RequestPacket constructor comment.
     */
    public RequestPacket(StructuredMem rawPacket, int clientEncodinng, String applID, String applVers)
    {
        super (rawPacket);
        if (rawPacket!=null) this.initPacket (clientEncodinng, applID, applVers);
    }
    /**
     *
     * @param bytes byte[]
     */
    public void addBytes (byte [] bytes) {
        this.mem.putBytes (bytes, this.dataPos ());
        this.partLength += bytes.length;
    }
    /**
     *
     * @param cursorName java.lang.String
     */
    public void addCursorPart (String cursorName) {
        if ((cursorName != null) && (cursorName.length () != 0)) {
            this.newPart (PartKind.Resulttablename_C);
            this.addString (cursorName);
            ++this.partArguments;
            this.closePart ();
        }
    }
    
    public void addErrorTextPart(String errortext) {
        if ((errortext != null) && (errortext.length () != 0)) {
            this.newPart (PartKind.Errortext_C);
            this.addString (errortext.substring(0, 255)); // limit the length
            ++this.partArguments;
            this.closePart ();
        }
    }
    
    public void setSQLState(String sqlstate)
    {
        if(sqlstate.length() == 5) {
            this.mem.putBytes(sqlstate.getBytes(), this.segmOffs + Segment.SqlState_O, 5);
        }
    }
    
    public void setErrorCode(int errorcode)
    {
        this.mem.putInt2(errorcode, this.segmOffs + Segment.Returncode_O);
    }
    
    /**
     *
     * @param cursorName java.lang.String
     */
    public void addFeatureRequestPart (byte[] features) {
        if ((features != null) && (features.length != 0)) {
          this.newPart (PartKind.Feature_C);
          this.addBytes(features);
          this.incrPartArguments(features.length/2);
          this.closePart ();
        }
    }
    /**
     *
     * @param cursorName java.lang.String
     */
    public void addParseidPart (byte [] parseID) throws java.sql.SQLException {
      if (parseID != null) {
        this.newPart (PartKind.Parsid_C);
        this.addBytes (parseID);
        this.partArguments = 1;
        this.closePart ();
     }
     else{
       throw new com.sap.dbtech.jdbc.exceptions.SQLExceptionSapDB(
             MessageTranslator.translate(MessageKey.ERROR_INTERNAL_INVALIDPARSEID));
     }
    }
    /**
     *
     * @param bytes byte[]
     */
    public void addDataBytes (byte [] bytes) {
        this.mem.putInt1 (0, this.dataPos ());
        this.mem.putBytes (bytes, this.dataPos () + 1);
        this.partLength += bytes.length + 1;
    }
    /**
     *
     *
     */
    public void addNullData (int len) {
        this.mem.putInt1 (-1, this.dataPos ());
        // this.mem.putBytes (bytes, this.dataPos () + 1);
        this.partLength += len + 1;
    }
    /**
     *
     * @param data   String
     */
    public void addDataString (String data) {
        this.mem.putInt1 ((int) ' ', this.dataPos ());
        this.partLength += this.mem.putString (data, this.dataPos () + 1) + 1;
    }
    /**
     *
     * @param count int
     */
    public void addFetchCount (int count) {
        this.newPart (PartKind.Resultcount_C);
        this.addBytes (VDNNumber.long2number (count));
        ++this.partArguments;
        this.setMassCommand ();
    }
    /**
     *
     *
     */
    public void addResultCount (int count) {
        this.newPart (PartKind.Resultcount_C);
        byte [] fullNumber = VDNNumber.long2number (count);
        byte [] countNumber = new byte [resultCountSize_C];
        System.arraycopy (fullNumber, 0, countNumber, 0, (resultCountSize_C < fullNumber.length)?resultCountSize_C:fullNumber.length);
        this.addDataBytes (countNumber);
        ++this.partArguments;
    }
    /**
     *
     *
     */
    public void addUndefResultCount () {
        this.newPart (PartKind.Resultcount_C);
        this.addNullData (resultCountSize_C);
        ++this.partArguments;
    }
    /**
     *
     * @param name java.lang.String
     */
    public void addResultsetName (String name) {
        this.newPart (PartKind.Resulttablename_C);
        this.addString (name);
    }
    /**
     *
     * @param bytes byte[]
     */
    public void addString (String data) {
        this.partLength += this.mem.putString (data, this.dataPos ());
    }
    public void addStringThrowExc (String data) throws ConversionExceptionSapDB{
        this.partLength += this.mem.putStringThrowExc (data, this.dataPos ());
    }
    /**
     *
     * @return int
     */
    public void closePacket () {
        this.closeSegment ();
        this.mem.putInt4 (this.packetLength-Packet.Segment_O, Packet.VarpartLen_O);
        this.mem.putInt2 (this.packetSegments, Packet.NoOfSegm_O);
    }
    /**
     *
     * @return int
     */
    private void closePart () {
        this.closePart (this.partLength, this.partArguments);
    }
    /**
     *
     * @return int
     */
    void closePart (int extent, int arguments) {
        if (this.partOffs == -1) {
            return;
        }
        this.mem.putInt4 (extent, this.partOffs + Part.BufLen_O);
        this.mem.putInt2 (arguments, this.partOffs + Part.ArgCount_O);
        this.segmLength += this.aligned (extent + Part.Data_O);
        this.partOffs = -1;
        this.partLength = -1;
        this.partArguments = -1;
        return;
    }
    /**
     *
     * @return int
     */
    private void closeSegment () {
        if (this.segmOffs == -1) {
            return;
        }
        this.closePart ();
        this.mem.putInt4 (this.segmLength, this.segmOffs + Segment.Len_O);
        this.mem.putInt2 (this.segmParts, this.segmOffs + Segment.NoOfParts_O);
        this.packetLength += this.segmLength;
        this.segmOffs = -1;
        this.segmLength = -1;
        this.segmParts = -1;
        return;
    }
    /**
     *
     * @return int
     */
    protected int dataPos () {
        return this.partOffs + Part.Data_O + this.partLength;
    }
    /**
     *
     * @param pid byte[]
     * @param reset boolean
     */
    public boolean dropPid (byte [] pid, boolean reset) {
        if (reset) {
            this.resetPacket ();
        } else {
            if(this.segmOffs != -1) {
                closeSegment();
            }
            int remainingSpace = this.size () - this.packetLength
                - Segment.Part_O - Part.Data_O
                - this.replyReserve
                - reserveForReply_C
                - 12 // length("drop parseid")
                - Segment.Part_O - Part.Data_O
                - 12; // pid.length
            if(remainingSpace <=0
               || this.packetSegments >= this.maxNumberOfSegm) {
                return false;
            }
        }
        this.newSegment (CmdMessType.Dbs_C, false, false, ResultSet.TYPE_SCROLL_INSENSITIVE);
        this.newPart (PartKind.Command_C);
        this.partArguments = 1;
        this.addString ("Drop Parseid");
        this.newPart (PartKind.Parsid_C);
        this.partArguments = 1;
        this.addBytes (pid);
        return true;
    }
        /**
     *
     * @param pid byte[]
     */
    public boolean dropPidAddtoParsidPart (byte [] pid) {
       int remainingSpace = this.size () - this.packetLength
                - Segment.Part_O - Part.Data_O
                - this.replyReserve
                - reserveForReply_C
                - this.partLength
                - 12; // pid.length
       if(remainingSpace <=0) {
                return false;
       }
        this.addBytes (pid);
        ++this.partArguments;
        return true;
    }
    /**
     *
     * @param stream PrintStream
     * @param maxBuf int
     */
    int dumpSegment (PrintStream stream, int maxBuf, int segmPos) {
        /*
         * dump segment header
         */
        stream.println ("   <SEGMENT ");
        stream.println ("    type=\"REQUEST\"");
        stream.println ("    index=\""+this.getInt2 (segmPos + Segment.OwnIndex_O)+"\"");
        stream.println ("    offset=\""+this.getInt4 (segmPos + Segment.Offs_O)+"\"");
        stream.println ("    length=\""+this.getInt4 (segmPos + Segment.Len_O)+"\"");
        stream.println ("    number_of_parts=\""+this.getInt2 (segmPos + Segment.NoOfParts_O)+"\"");

//        StringUtil.fprintfs (stream, "    REQUEST %d at %d for %d bytes, %d Parts\n",
//            new Object [] {
//            new Integer (this.getInt2 (segmPos + Segment.OwnIndex_O)),
//                new Integer (this.getInt4 (segmPos + Segment.Offs_O)),
//                new Integer (this.getInt4 (segmPos + Segment.Len_O)),
//                new Integer (this.getInt2 (segmPos + Segment.NoOfParts_O)),
//        });
        StringUtil.fprintfs (stream, "    <! Detailed info skipped >\n",
            new Object [] {
            // this.getString (segmPos + Segment.SqlState_O, 5),
            // new Integer (this.getInt2 (segmPos + Segment.Returncode_O)),
            // new Integer (this.getInt4 (segmPos + Segment.ErrorPos_O)),
            // new Integer (this.getInt2 (segmPos + Segment.ExternWarning_O)),
            // new Integer (this.getInt2 (segmPos + Segment.InternWarning_O)),
            // new Integer (this.getInt2 (segmPos + Segment.FunctionCode_O)),
        });
        /*
         * dump parts
         */
        int partCount = this.getInt2 (segmPos + Segment.NoOfParts_O);
        int pos = segmPos + Segment.Part_O;
        for (int i = 0; i < partCount; ++i) {
            pos += this.dumpPart (stream, maxBuf, pos);
        }
        stream.println ("   </SEGMENT> ");
        return this.getInt4 (segmPos + Segment.Len_O);
    }
    /**
     *
     */
    private void flushVariables () {
        this.mem.putInt4 (this.packetLength-Packet.Segment_O, Packet.VarpartLen_O);
        this.mem.putInt2 (this.packetSegments, Packet.NoOfSegm_O);
        if (this.segmOffs != -1) {
            this.mem.putInt4 (this.segmLength, this.segmOffs + Segment.Len_O);
            this.mem.putInt2 (this.segmParts, this.segmOffs + Segment.NoOfParts_O);
        }
        if (this.partOffs != - 1) {
            this.mem.putInt4 (this.partLength, this.partOffs + Part.BufLen_O);
            this.mem.putInt2 (this.partArguments, this.partOffs + Part.ArgCount_O);
        }
    }
    /**
     *
     */
    public void incrPartArguments () {
        ++partArguments;
    }
    /**
     *
     */
    public void incrPartArguments (int count) {
        partArguments+=count;
    }
    /**
     *
     * @return void
     */
     public void initHello () {
         this.resetPacket ();
         this.newSegment (CmdMessType.Hello_C, false, false, ResultSet.TYPE_SCROLL_INSENSITIVE);
     }

    /**
     *
     * @return int
     */
    public void initDbs (boolean autocommit, int scrollableCursor) {
        this.initDbs (reset_C, autocommit, scrollableCursor);
    }
    /**
     *
     * @return int
     */
    public void initDbs (boolean reset, boolean autocommit, int scrollableCursor) {
        if (reset) {
            this.resetPacket ();
        }
        this.newSegment (CmdMessType.Dbs_C, autocommit, false, scrollableCursor);
        this.newPart (PartKind.Command_C);
        this.partArguments = 1;
    }
    /**
     *
     * @return int
     */
    public void initDbsCommand (boolean autocommit, String cmd, int scrollableCursor) throws ConversionExceptionSapDB 
    {
        this.initDbsCommand (cmd, reset_C, autocommit, scrollableCursor);
    }
    /**
     *
     * @return int
     */
    public boolean initDbsCommand (String cmd, boolean reset, boolean autocommit, int scrollableCursor) throws ConversionExceptionSapDB{
        if (!reset) {
            this.closeSegment ();
            int remainingSpace = this.size () - this.packetLength
                - Segment.Part_O - Part.Data_O
                - this.replyReserve
                - reserveForReply_C;
            if (remainingSpace < cmd.length ()
                || this.packetSegments >= this.maxNumberOfSegm) {
                return false;
            }
        }
        this.initDbs (reset, autocommit, scrollableCursor);
        this.addStringThrowExc (cmd);
        this.partArguments = 1;
        return true;
    }
    /**
     *
     */
    public boolean
    initSyntaxOnlyCommand (
        String cmd)
    {
        this.resetPacket ();
        this.newSegment (CmdMessType.Syntax_C, false, false, ResultSet.TYPE_SCROLL_INSENSITIVE);
        this.newPart (PartKind.Command_C);
        this.partArguments = 1;
        this.addString (cmd);
        return true;
    }
    /**
     *
     * @return int
     */
    public void initExecute (byte [] parseID, boolean autocommit, int scrollableCursor) throws java.sql.SQLException{
        this.resetPacket ();
        this.newSegment (CmdMessType.Execute_C, autocommit, false, scrollableCursor);
        this.addParseidPart(parseID);
    }
    /**
     *
     * @return int
     */
    public DataPart initGetval (boolean autocommit) {
        this.resetPacket ();
        this.newSegment (CmdMessType.Getval_C, autocommit, false, ResultSet.TYPE_SCROLL_INSENSITIVE);
        return this.newDataPart (PartKind.Longdata_C);
    }
    /**
     *
     * @return int
     */
    public void initMFetch (byte [] parseID, int count, boolean autocommit) {
        /*
         * init packet with fetch pid
         */
        this.resetPacket ();
        this.newSegment (CmdMessType.Execute_C, autocommit, false, ResultSet.TYPE_SCROLL_INSENSITIVE);
        this.newPart (PartKind.Parsid_C);
        this.addBytes (parseID);
        this.partArguments = 1;

        this.addResultCount(count);

        this.setMassCommand ();
    }
    /**
     *
     */
    private void initPacket (int clientEncoding, String applID, String applVers)
    {
        StructuredMem packet = this.mem;

        if (applID != null)
          RequestPacket.ApplID = applID;
        if (ApplVers != null){
          try {
            int vers = Integer.parseInt(applVers);
            if (vers >= 60210 && vers <= 100000)
              RequestPacket.ApplVers = applVers;
          }
          catch (NumberFormatException  ignore) {}
        }
        packet.putInt1 (clientEncoding, Packet.MessCode_O);
        packet.putInt1 (RteC.notSwapped_C, Packet.MessSwap_O);
        packet.putString (ApplVers, Packet.ApplVersion_O);
        packet.putString (RequestPacket.ApplID, Packet.Appl_O);
        packet.putInt4 (packet.size () - Packet.Segment_O, Packet.VarpartSize_O);
        this.packetLength = Packet.Segment_O;
    }
    /**
     *
     * @return int
     */
    public void initParse (boolean reset, boolean parseagain) {
        if (reset) {
            this.resetPacket ();
        }
        this.newSegment (CmdMessType.Parse_C, false, parseagain, ResultSet.TYPE_SCROLL_INSENSITIVE);
        this.newPart (PartKind.Command_C);
        return;
    }
    /**
    *
    * @return int
    */
   public boolean initChallengeResponse(String user, byte[] challenge) throws ConversionExceptionSapDB{
       this.initDbsCommand(false,"CONNECT "+user+"  AUTHENTICATION", ResultSet.TYPE_SCROLL_INSENSITIVE);
       this.closePart();
       DataPartVariable data = this.newVarDataPart();
       data.addRow(2);
       data.putBytes(SCRAMMD5.algorithmname.getBytes(),data.extent);
       data.addArg(data.extent,0);
       data.putBytes(challenge,data.extent);
       data.addArg(data.extent,0);
       data.close();
       return true;
   }
   public void addClientProofPart(byte[] clientProof){
       DataPartVariable data = this.newVarDataPart();
       data.addRow(2);
       data.putBytes(SCRAMMD5.algorithmname.getBytes(),data.extent);
       data.addArg(data.extent,0);
       data.putBytes(clientProof,data.extent);
       data.addArg(data.extent,0);
       data.close();
   }

   public void addClientIDPart(String clientID){
       this.newPart(PartKind.Clientid_C);
       this.addDataString(clientID);
       this.partArguments = 1;
   }
    /**
     *
     * @return int
     */
    public int initParseCommand (String cmd, boolean reset, boolean parseagain) throws ConversionExceptionSapDB{
        this.initParse (reset, parseagain);
        this.addStringThrowExc(cmd);
        this.partArguments = 1;
        return this.partLength;
    }
    /**
     *
     * @return int
     * @param partKind int
     */
    private void initPart (int partKind) {
        StructuredMem packet = this.mem;
        int pos;

        ++this.segmParts;
        this.partOffs = this.segmOffs + this.segmLength;
        this.partLength = 0;
        this.partArguments = 0;
        pos = this.partOffs;
        packet.putInt1 (partKind, pos + Part.PartKind_O);
        packet.putInt1 (0, pos + Part.Attributes_O);
        packet.putInt2 (1, pos + Part.ArgCount_O);
        packet.putInt4 (this.segmOffs - Packet.Segment_O, pos + Part.SegmOffs_O);
        packet.putInt4 (Part.Data_O, pos + Part.BufLen_O);
        packet.putInt4 (packet.size () - pos, pos + Part.BufSize_O);
        return;
    }
    /**
     *
     */
    public DataPart initPutval (boolean autocommit) {
        this.resetPacket ();
        this.newSegment (CmdMessType.Putval_C,autocommit, false, ResultSet.TYPE_SCROLL_INSENSITIVE);
        return this.newDataPart (PartKind.Longdata_C);
    }
    /**
     *
     */
    protected int
    createSegment (int segmKind)
    {
        StructuredMem packet = this.mem;
        int pos = this.packetLength;
        this.segmOffs = pos;
        this.segmLength = Segment.Part_O;
        this.segmParts = 0;
        ++packetSegments;
        packet.putInt4 (0, pos + Segment.Len_O);
        packet.putInt4 (pos - Packet.Segment_O, pos + Segment.Offs_O);
        packet.putInt2 (0, pos + Segment.NoOfParts_O);
        packet.putInt2 (packetSegments, pos + Segment.OwnIndex_O);
        packet.putInt1 (segmKind, pos + Segment.SegmKind_O);
        return pos;
    }
    
    public void
    dropSegment ()
    {
        --packetSegments;
    }
    /**
     *
     */
    private void initSegment (int messKind, boolean autocommit, boolean parseagain, int resultSetType) {
        StructuredMem packet = this.mem;
        int pos = this.createSegment (SegmKind.Cmd_C);
        // request segment
        packet.putInt1 (messKind, pos + Segment.MessType_O);
        packet.putInt1 (this.currentSqlMode, pos + Segment.SqlMode_O);
        packet.putInt1 (Producer.UserCmd_C, pos + Segment.Producer_O);
        packet.putInt1 ((autocommit)?1:0, pos + Segment.CommitImmediateley_O);
        packet.putInt1 (0, pos + Segment.IgnoreCostwarning_O);
        packet.putInt1 (0, pos + Segment.Prepare_O);
        packet.putInt1 (0, pos + Segment.WithInfo_O);
        packet.putInt1 (0, pos + Segment.MassCmd_O);
        if(parseagain) {
            packet.putInt1 (1, pos + Segment.ParsingAgain_O);
        } else {
            packet.putInt1 (0, pos + Segment.ParsingAgain_O);
        }
        if(resultSetType != ResultSet.TYPE_FORWARD_ONLY) {
            packet.putInt1 (SegmentCommandOption.sp1co_scrollable_cursor_on, pos + Segment.CommandOptions_O);
        } else {
            packet.putInt1 (0, pos + Segment.CommandOptions_O);
        }
        return;
    }
    /**
     *
     * @return int
     */
    public int length () {
        return this.packetLength;
    }
    /**
    *
    * @return com.sap.dbtech.jdbc.packet.DataPart
    */
   private DataPartVariable newVarDataPart () {
       int partDataOffs;
       DataPartVariable result;

       this.newPart (PartKind.Vardata_C);
       partDataOffs = this.partOffs + Part.Data_O;
       result = new DataPartVariable (this.getPointer (partDataOffs), this);
       return result;
   }
   public  DataPart newDataPart (boolean varData) {
     if (varData)
         return this.newVarDataPart();
     else
         return this.newDataPart();
   }
    /**
     *
     * @return com.sap.dbtech.jdbc.packet.DataPart
     */
    private DataPart newDataPart () {
        return this.newDataPart (PartKind.Data_C);
    }
    /**
     *
     * @return com.sap.dbtech.jdbc.packet.DataPart
     */
    public DataPart newDataPart (int partKind) {
        int partDataOffs;
        DataPart result;

        this.newPart (partKind);
        partDataOffs = this.partOffs + Part.Data_O;
        result = new DataPartFixed (this.getPointer (partDataOffs), this);
        return result;
    }
    /**
     *
     * @param messKind int
     */
    public void newPart (int partKind) {
        this.closePart ();
        this.initPart (partKind);
    }
    /**
     *
     * @param messKind int
     */
    private void newSegment (int messKind, boolean autocommit, boolean parseagain, int resultSetType) {
        this.closeSegment ();
        this.initSegment (messKind, autocommit, parseagain, resultSetType);
        if (this.packetSegments==2)
          this.replyReserve += reserveFor2ndSegment_C;
        else
          this.replyReserve += reserveForReply_C;
    }
    /**
     *
     */
    public void initializePacket (short maxSegment) {
      this.resetPacket();
      this.maxNumberOfSegm = maxSegment;
    }
    /**
     *
     */
    private void resetPacket () {
        this.packetLength = Packet.Segment_O;
        this.packetSegments = 0;
        this.segmOffs = -1;
        this.segmLength = -1;
        this.segmParts = -1;
        this.maxNumberOfSegm = defaultmaxNumberOfSegm_C;
        this.partOffs = -1;
        this.partLength = -1;
        this.partArguments = -1;
        this.replyReserve = 0;
    }
    /**
     *
     * @return int
     */
    public static int resultCountPartSize () {
        return Part.Data_O + resultCountSize_C + 8 /* alignment */;
    }
    /**
     *
     */
    public void setMaxSegment (short maxSegment) {
        this.maxNumberOfSegm = maxSegment;
    }
    /**
     *
     */
    public void setInternalMode () {
        this.putInt1 (SqlMode.Internal_C, this.segmOffs + Segment.SqlMode_O);
    }
    /**
     *
     * @param available boolean
     */
    public void setAvailability (boolean available) {
        this.isAvailable = available;
    }
    /**
     *
     */
    public void setInternalCmd () {
        this.mem.putInt1 (Producer.InternalCmd_C,
            this.segmOffs + Segment.Producer_O);
    }
    /**
     *
     */
    public void setMassCommand () {
        this.putInt1 (1, this.segmOffs + Segment.MassCmd_O);
    }
    /**
     *
     */
    public void
    setWithInfo ()
    {
        this.putInt1 (1, this.segmOffs + Segment.WithInfo_O);
    }
    /**
     *
     * @return int
     * @param newMode int
     */
    public int switchSqlMode (int newMode) {
        int result = this.currentSqlMode;

        this.currentSqlMode = newMode;
        return result;
    }
    /**
     *
     */
    void
    addPartAttribute (
        int attribute)
    {
        int attrOffset = this.partOffs + Part.Attributes_O;
        int currentAttribute = this.getInt1 (attrOffset);
        currentAttribute |= attribute;
        this.putInt1(currentAttribute, attrOffset);
    }

        /**
         * @param autocommit Whether autocommit is used.
         * @return The data part of the 1st segment.
         */
        public DataPart initStreamCommand(boolean autocommit) {
                this.resetPacket ();
                this.newSegment (CmdMessType.Dbs_C,autocommit, false, ResultSet.TYPE_SCROLL_INSENSITIVE);
                return this.newDataPart (PartKind.Data_C);
        }

   public boolean isUnicodePacket(){
     return false;  
   }

}
