.CM  SCRIPT , Version - 1.1 , last edited by peter
.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 1998-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VPR03SC$
.tt 2 $$$
.TT 3 $BurkhardD$SAPDB-ABAP-Stream-IO-Interface$$2000-11-30$
***********************************************************
.nf

.nf

.nf

    ========== licence begin  GPL
    Copyright (c) 1998-2005 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
.fo


.fo


.fo
.nf
.sp
MODULE  : SAPDB-ABAP-Stream-IO-Interface
=========
.sp
Purpose : 
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

#define CPR_INFO_UDT         (CPR_INFO_STRING+1)
#define CPR_INFO_ABAP_HANDLE (CPR_INFO_STRING+2)
#define CPR_VABAPHANDLE      (CPR_VODATE+1)

#ifdef __cplusplus
extern "C" {
#endif
void p03sABAPError(struct SQLERROR *sqlemp, char *szStr, char cbErrorCode);
#ifdef __cplusplus
}
#endif

.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : BurkhardD
.sp
.cp 3
Created : 1998-01-23
.sp
.cp 3
Version : 1998-01-23
.sp
.cp 3
Release :      Date : 2000-11-30
.sp
***********************************************************
.sp
.cp 20
.fo
.oc _/1
Specification:
.sp 3 

.CM *-END-* specification -------------------------------
.sp 2.fo
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
/*PRETTY */

#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <ctype.h>
#include "livecachetypes.h" /* no check */
&if $OS = UNIX	
#include <unistd.h>
&else
#include <EXCPT.H>
&endif

#ifndef DEBUG
#line 483 "vpr03sc"
#endif

/********  vsp26  proceduren  **********/
extern s26new_part_init (tsp1_packet *packet_ptr, tsp1_segment *segm_ptr, tsp1_part **part_ptr);
extern s26finish_part (tsp1_packet *packet_ptr, tsp1_part *part_ptr);
extern int s26nextpart (tsp1_part** part_ptr);
extern void s26find_part (tsp1_segment *segm_ptr, char part_kind, tsp1_part **part_ptr);
extern tsp00_Int4 s26size_new_part (tsp1_packet_ptr packet_ptr, tsp1_segment* segm);

extern void sqlnul (short *, short *, int *);

int 
pr03WriteProc(SQLABAPWriteProc *WriteProc, 
	      SQL_LC_ABAPTabParm *StreamParam,   
	      unsigned char *pOutputStream,
	      int cbRowCount,
              int cbBufSize,
              void* pMask,
              boolean old);

int 
pr03ReadProc(SQLABAPReadProc *ReadProc, 
	      SQL_LC_ABAPTabParm *StreamParam,   
	      unsigned char *pInputStream,
	      int cbPartLenMax, 
	      int *cbBufSize,
	      int *cbRowCount,
	      void* pMask,
             boolean old);

void p03sABAPError(struct SQLERROR *sqlemp, char *szStr, char cbErrorCode)
{
  if (szStr) {
    size_t len = strlen(szStr);
    sqlemp->elzu = sp1ce_notok;
    memset(sqlemp->etext, ' ', sizeof(sqlemp->elzu));
    if (len > 0)
      memcpy((char*)sqlemp->etext, szStr, len);
  }
  else {
    sqlemp->elzu = sp1ce_ok;
  }
  p03cseterror (sqlemp, cbErrorCode);
}

SQLStreamDesc *p03sGetABAPDescriptor(void *sqlda, sqlint2 sqldbmode, OmsTypeInt4 ABAPTabId)
{
  SQLStreamDesc *descp=NULL;
  switch (sqldbmode) {
  case CPR_KIND_ORACLE:{}
  case CPR_KIND_SAPR3:{
    SQLDA *da=sqlda;
    int i;
    int null;
    for (i=0;i<da->F;i++) {
      short T; 
      sqlnul ((short*)&da->T[i], &T, &null);
      if (T == SQL_ORA_ABAP_HANDLE) {
	if (ABAPTabId) {
	  if (((SQLStreamDesc *)(da->V[i]))->StreamParam->C_1.ABAPTab.hABAPTab.ABAPTabId != ABAPTabId)
	    continue;
	}
	descp = (SQLStreamDesc *)da->V[i];
	break;
      }
    }
    break;
  }
  case CPR_KIND_INTERNAL: {
    sqldatype *da = (sqldatype *) sqlda;
    int i;
    for (i=0;i<da->sqln;i++) {
      if (da->sqlvar[i].hostvartype == CPR_VABAPHANDLE) {
	if (ABAPTabId) {
	  if (((SQLStreamDesc *)(da->sqlvar[i].hostvaraddr))->StreamParam->C_1.ABAPTab.hABAPTab.ABAPTabId != ABAPTabId)
	    continue;
	}
	descp = (SQLStreamDesc *)da->sqlvar[i].hostvaraddr;
	break;
      }
    }
  }
  }  
  return(descp);
}

SQLStreamDesc *pr03sGetHostVarABAPDescriptor(tpr04_ParamContainer *Param, sqlxatype *sqlxa, OmsTypeInt4 ABAPTabId)
{
  SQLStreamDesc *StreamDesc = NULL;
  if (Param) {
    tpr04_ParamDesc *ParamDesc;
    Param->OpenCont(Param);
    while(ParamDesc = Param->EnumDesc(Param)) {
      tsp00_Int2 fType = Param->GetHostVarType(ParamDesc);
      SQLStreamDesc *Desc = (SQLStreamDesc *)Param->GetHostVarAddr(ParamDesc);
      if (fType == CPR_VABAPHANDLE) {
	if (Desc && Desc->StreamParam->C_1.ABAPTab.hABAPTab.ABAPTabId == ABAPTabId) {
	  StreamDesc = Desc;	  
	  break;
	}
      }
    }
    Param->CloseCont(Param);
  }
  return StreamDesc;
}

void p03sSendABAPReturnPacket(struct tpr01_SQLDesc *SQLDesc, sqlratype * sqlra, sqlgaentry * gaentry, char *ptr, tsp00_Int4 cbLen, struct SQLERROR *sqlemp)
{
  tsp1_packet   *pck=NULL;
  tsp1_part     *part_ptr=NULL;
  pck = p03cpacketinit (SQLDesc, sqlra, gaentry, (char)sp1m_dbs);
  if (pck) {
    s26new_part_init (pck, sqlra->rasegptr, &part_ptr);
    if (part_ptr) {	  
      part_ptr->sp1p_part_header.sp1p_part_kind = (char)sp1pk_data;
      memcpy(part_ptr->sp1p_buf, ptr, cbLen);
      part_ptr->sp1p_part_header.sp1p_buf_len = cbLen;
      s26finish_part (pck, part_ptr);
      p03initsqlem (sqlemp);
      pr03PacketReqRec(SQLDesc->ConDesc, sqlemp);
    }
  }
}

void p03sSendABAPErrorPacket(struct tpr01_SQLDesc *SQLDesc, sqlratype * sqlra, sqlgaentry * gaentry, 
char *szErrorText, char error, struct SQLERROR *sqlemp)
{
  tsp1_packet *pck=NULL;
  tsp1_part   *part_ptr=NULL;
  tsp00_Int4    cbLen;
  struct SQLERROR em;     /* localer Error um ueberschreiben zu verhindern*/
  if (sqlemp->ereturncode == 0) {
    p03sABAPError(sqlemp, szErrorText, error);        
  }
  pck = p03cpacketinit (SQLDesc, sqlra, gaentry, (char)sp1m_dbs);
  if (pck) {
    tsp1_segment_header *seghp = (tsp1_segment_header *)&pck->sp1_segm;
    s26new_part_init (pck, sqlra->rasegptr, &part_ptr);
    if (part_ptr) {	  
      seghp->sp1r_returncode = sqlemp->ereturncode;
      part_ptr->sp1p_part_header.sp1p_part_kind = sp1pk_errortext;
      cbLen = PR07MAX(part_ptr->sp1p_part_header.sp1p_buf_len, sqlemp->etextlen);
      memcpy(part_ptr->sp1p_buf, sqlemp->etext, cbLen);
      part_ptr->sp1p_part_header.sp1p_buf_len = cbLen;
      s26finish_part (pck, part_ptr);
      p03initsqlem (&em);
      pr03PacketReqRec(SQLDesc->ConDesc, &em);
    }
  }
  if (em.ereturncode != 0) {
    if (sqlemp->ereturncode == 0) {    /* alten aber nicht ueberschreiben */
      memcpy(sqlemp, &em, sizeof(em));
    }
  }
}

void p03sPutStream(struct tpr01_SQLDesc *SQLDesc, sqlratype * sqlra, sqlgaentry * gaentry, 
SQL_LC_ABAPTabParm *StreamParam, tsp00_Int4 cbRowCount, 
SQLABAPReadProc *ReadProc, struct SQLERROR *sqlemp, boolean old, boolean first, boolean *last, void* pHiddenMask)
{
  tsp1_packet   *pck=NULL;
  tsp1_part     *part_ptr=NULL;
  int retcode = SQL_ABAP_OK;
  char szStr[30];

  tsp00_Int4 cbPartLenMax;
  unsigned char *pInputStream;
  if (!old) {
    p04trint4(sqlra, "PUTSTREAM EXT", cbRowCount);
  } else {
    p04trint4(sqlra, "PUTSTREAM", cbRowCount);
  }
  if (first)
    pck = p03cpacketinit (SQLDesc, sqlra, gaentry, (char)sp1m_dbs);
  else
    pck = SQLDesc->ConDesc->SegmDesc->packetPtr;
  if (pck) {
    s26new_part_init (pck, sqlra->rasegptr, &part_ptr);
    if (part_ptr) {	  
      part_ptr->sp1p_part_header.sp1p_part_kind = (char)sp1pk_data;
      part_ptr->sp1p_part_header.sp1p_arg_count = 0;
      cbPartLenMax = part_ptr->sp1p_part_header.sp1p_buf_size;
      pInputStream = part_ptr->sp1p_buf;
    }
  }
  else {
    p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, "", cpr_memory_allocation_faild, sqlemp);
    return;
  }
  if (part_ptr) {
    tsp00_Int4 cbBufSize = 0;
    p04trint4(sqlra, "PartLenMax", cbPartLenMax);
    retcode = pr03ReadProc(ReadProc, StreamParam, pInputStream, cbPartLenMax, &cbBufSize, &cbRowCount, pHiddenMask, old);
    if (retcode == SQL_ABAP_EXCEPTION) {
      p03sABAPError(sqlemp, "", cpr_abap_exception);
      p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, "", cpr_abap_exception, sqlemp);
      return;
    }
    if (SQL_ABAP_NO_MORE_DATA == retcode) {
      part_ptr->sp1p_part_header.sp1p_attributes[0] = 1 << sp1pa_last_packet;
      retcode = SQL_ABAP_OK;
    } 
    else {
      *last = 1;
    }
    if (retcode == SQL_ABAP_OK) {
      part_ptr->sp1p_part_header.sp1p_arg_count= cbRowCount;
      part_ptr->sp1p_part_header.sp1p_buf_len  = cbBufSize;
      p04trint4(sqlra, "RowCount", part_ptr->sp1p_part_header.sp1p_arg_count);
      p04trint4(sqlra, "BufSize", part_ptr->sp1p_part_header.sp1p_buf_len);
      s26finish_part (pck, part_ptr);
      if (s26size_new_part (pck, sqlra->rasegptr) <= 0)
      {
        /* no next part possible */
        *last = true;
      }
      if (*last) {
        p03initsqlem (sqlemp);
        pr03PacketReqRec(SQLDesc->ConDesc, sqlemp);
      }
    } 
    else {
      sprintf(szStr, "ReadProc failed (%d)", retcode);
      p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, szStr, cpr_abap_desc_not_set, sqlemp);
      return;
    }  
  }
  else {
    p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, "", cpr_memory_allocation_faild, sqlemp);
  }
}

void p03sGetStream(struct tpr01_SQLDesc *SQLDesc, sqlratype * sqlra, sqlgaentry * gaentry, 
SQL_LC_ABAPTabParm *StreamParam, SQLABAPWriteProc *WriteProc, 
struct SQLERROR *sqlemp, boolean old,  tsp1_part **curr_part_ptr, boolean last)
{
  tsp1_packet   *pck=NULL;
  tsp1_part     *part_ptr=NULL;
  int retcode = SQL_ABAP_OK;

  unsigned char *pOutputStream;
  tsp00_Int4 cbRowCount=0;
  tsp00_Int4 cbBufSize=0;
  void*      pHiddenMask = 0;
  /*part_ptr = pr03PartFind(sqlra, sp1pk_data);*/
  part_ptr = *curr_part_ptr;
  if (part_ptr->sp1p_part_header.sp1p_buf_len > sizeof(tsp00_Int4))
  {
      pHiddenMask = &part_ptr->sp1p_buf[sizeof(tsp00_Int4)];
  } 
  s26nextpart(&part_ptr);  
  *curr_part_ptr = part_ptr;
  if (part_ptr) {
    pOutputStream = part_ptr->sp1p_buf;
    cbRowCount = part_ptr->sp1p_part_header.sp1p_arg_count;
    cbBufSize = part_ptr->sp1p_part_header.sp1p_buf_len;
    if (!old) {    
      p04trint4(sqlra, "GETSTREAM EXT", cbRowCount);
    } else {
      p04trint4(sqlra, "GETSTREAM", cbRowCount);
    }
    p04trint4(sqlra, "BufSize", cbBufSize);
    if (cbRowCount <= 0 ) {
      retcode = SQL_ABAP_NO_MORE_DATA;
      p03sSendABAPReturnPacket(SQLDesc, sqlra, gaentry, (char*)&retcode, sizeof(retcode), sqlemp);	        
    }
    else {
      retcode = pr03WriteProc(WriteProc, StreamParam, pOutputStream, cbRowCount, cbBufSize, pHiddenMask, old);
      if (retcode == SQL_ABAP_EXCEPTION) {
	p03sABAPError(sqlemp, "", cpr_abap_exception);
	p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, "", cpr_abap_exception, sqlemp);
	return;
      }
      if (retcode == SQL_ABAP_OK) {
      if (last)
	p03sSendABAPReturnPacket(SQLDesc, sqlra, gaentry, (char*)&retcode, sizeof(retcode), sqlemp);	  
      }	  
      else {
	char szStr[30];
	sprintf(szStr, "WriteProc failed (%d)", retcode);
	p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, szStr, cpr_abap_desc_not_set, sqlemp);
      }
    }
  }
  else {
    p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, "", cpr_memory_allocation_faild, sqlemp);
    return;
  }
}

typedef struct tpr03_SaveValues {
  tsp00_Int2 xakano;
  tsp00_Int2 raactsession;
} tpr03_SaveValues;

void pr03sBeforeCallBack(sqlcatype *sqlca, sqlxatype *sqlxa, tpr03_SaveValues *pSaves)
{
  pSaves->xakano = sqlxa->xakano;
  pSaves->raactsession = sqlca->sqlrap->raactsession;
}

void pr03sAfterCallBack(sqlcatype *sqlca, sqlxatype *sqlxa, tpr03_SaveValues *pSaves)
{
  sqlxa->xakano = pSaves->xakano;
  sqlca->sqlrap->raactsession = pSaves->raactsession;
}

extern tpr_pcVersion *p07pcversion;
void p03sABAPStream(sqlcatype *sqlca, sqlxatype *sqlxa, sqlgaentry *gaentry)
{
  tsp1_part *part_ptr;
  sqlratype *sqlrap = sqlca->sqlrap;
  sqlgatype *sqlgap = sqlca->sqlgap;
  sqlkaentry *ka = sqlxa->sqlkap+sqlxa->xakano-1;
  SQLStreamDesc *descp=NULL;
  tsp00_Int4 cbParamCount=0;
  tpr04_ParamContainer *Param=NULL;
  int tabCount=0;
  int maxFree;
  boolean isInStream;
&ifndef SQLODBC
  static boolean old_streams = true;
  static boolean isVersionChecked=false;   
  if (!isVersionChecked) {
    isVersionChecked =true;
    if (!p07pcversion 
        || (p07pcversion && strcmp(p07pcversion->szVersion, SQL_PC_OLD_STREAM_SUPPORT_S) <= 0)) {
      old_streams = true;    
    } else {
      old_streams = false;    
    }
  }
&else
  boolean old_streams = false;
&endif
  M90TRACE (M90_TR_ENTRY, "p03sABAPStream", 0);
  
  if (sqlca->sqlemp->ereturncode == 0 && sqlrap) {
    struct SQLERROR *sqlemp = sqlca->sqlemp;
    do {
      OmsTypeInt4 ABAPTabIds[16];
      int         requiredRows[16];
      void*       hiddenMask[16];
      int part_kind = sp1pk_abap_istream;
      int ix;
      boolean last = false;
      tsp1_segment   *segp= (sqlrap) ? (tsp1_segment*)sqlrap->rasegptr : NULL;
      tabCount      = 0;
      maxFree       = -1;
      if (!(part_ptr = pr03PartFindDirect(sqlrap, part_kind))) {
        isInStream = false;
        part_kind = sp1pk_abap_ostream;
        part_ptr = pr03PartFindDirect(sqlrap, part_kind);
        if (part_ptr) 
        {
            tabCount = segp->variant.C_1.sp1s_segm_header_F.variant.C_1.sp1s_no_of_parts_F / 2;
            if (tabCount > 1) {
                part_ptr = pr03PartFindDirect(sqlrap, part_kind);
                if (!part_ptr) {
                  p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "Missing output stream part", 
                                          cpr_invalid_commandstate, sqlemp);
                  return;
                }
            }
            memcpy(&ABAPTabIds[0], part_ptr->sp1p_buf, sizeof(ABAPTabIds[0]));
            requiredRows[0] = part_ptr->sp1p_part_header.sp1p_arg_count;
         }
      }
      else
      {
          int partCount = segp->variant.C_1.sp1s_segm_header_F.variant.C_1.sp1s_no_of_parts_F;
          isInStream    = true; 
          part_ptr = pr03PartFindDirect(sqlrap, part_kind);
          if (part_ptr 
              && part_ptr->sp1p_part_header.sp1p_part_kind == sp1pk_abap_istream
              && part_ptr->sp1p_part_header.sp1p_buf_len >= sizeof(ABAPTabIds[0])) {
            int maskLen = part_ptr->sp1p_part_header.sp1p_buf_len - sizeof(ABAPTabIds[tabCount-1]);
            memcpy(&ABAPTabIds[0], part_ptr->sp1p_buf, sizeof(ABAPTabIds[0]));
            requiredRows[0] = part_ptr->sp1p_part_header.sp1p_arg_count;
            if (maskLen > 0)
            {
                hiddenMask[0] = malloc(maskLen);
                if (hiddenMask[0])
                {
                    memcpy (hiddenMask[0], &part_ptr->sp1p_buf[sizeof(ABAPTabIds[0])], maskLen);
                    maxFree = 0;
                }
                else
                {
                    /* TODO error handling */
                }
            } 
            else
            {
                hiddenMask[0] = 0;
            }
            tabCount = 1;
          }
          else {
            p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "Missing input stream part", 
                                   cpr_invalid_commandstate, sqlemp);
            return;
          }
          for (ix = 1; ix < partCount; ++ix)
          {
              s26nextpart(&part_ptr);
              if (part_ptr 
                  && part_ptr->sp1p_part_header.sp1p_part_kind == sp1pk_abap_istream
                  && part_ptr->sp1p_part_header.sp1p_buf_len >= sizeof(ABAPTabIds[tabCount-1])) {
                  int maskLen = part_ptr->sp1p_part_header.sp1p_buf_len - sizeof(ABAPTabIds[tabCount-1]);
                  memcpy(&ABAPTabIds[tabCount], part_ptr->sp1p_buf, sizeof(ABAPTabIds[tabCount]));
                  requiredRows[tabCount] = part_ptr->sp1p_part_header.sp1p_arg_count;
                  if (maskLen > 0)
                  {
                      hiddenMask[tabCount] = malloc(maskLen);
                      if (hiddenMask[tabCount])
                      {
                          memcpy (hiddenMask[tabCount], &part_ptr->sp1p_buf[sizeof(ABAPTabIds[tabCount])], maskLen);
                          maxFree = tabCount;
                      }
                      else
                      {
                          /* TODO error handling */
                      }
                  } 
                  else
                  {
                      hiddenMask[tabCount] = 0;
                  }
                  ++tabCount;
                  if (16 == tabCount) break;    
              }
              else {
                p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "Missing input stream part", 
                                        cpr_invalid_commandstate, sqlemp);
                return;
              }
          }
      }
      for (ix = 0; ix < tabCount; ++ ix)
      {
          p04trint4(sqlrap, "TabId", ABAPTabIds[ix]);
&ifndef SQLODBC
          if (ka->kapacount > 0) {
            if (!Param) 
              Param = pr04NewParamContainer(sqlxa);
            descp = pr03sGetHostVarABAPDescriptor(Param, sqlxa, ABAPTabIds[ix]);
          }
          else
&endif
            descp = p03sGetABAPDescriptor(sqlca->sqlcxap->xasqldap, 
                                          sqlca->sqldbmode, ABAPTabIds[ix]);
          if (!descp) {
            char szTmp[100];
            sprintf(szTmp, "Descriptor for TabID(%d) undefined", ABAPTabIds[ix]);
            p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, szTmp, cpr_abap_desc_not_set, sqlemp);
          }
          if (isInStream)
          {
            if (descp->ReadProc) {
&ifndef SQLODBC
                tpr03_SaveValues SaveValues;
                pr03sBeforeCallBack(sqlca, sqlxa, &SaveValues);
&endif
                last = (ix == tabCount - 1); 
                p03sPutStream(sqlxa->xaSQLDesc, sqlrap, gaentry, descp->StreamParam, requiredRows[ix], 
                   descp->ReadProc, sqlemp, old_streams, 0 == ix, &last, hiddenMask[ix]);          
&ifndef SQLODBC
                pr03sAfterCallBack(sqlca, sqlxa, &SaveValues);
&endif
            }
            else {
              p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "ReadProc undefined", cpr_abap_desc_not_set, sqlemp);
            }
          }
          else {
            if (descp->WriteProc) {
&ifndef SQLODBC
            tpr03_SaveValues SaveValues;
            pr03sBeforeCallBack(sqlca, sqlxa, &SaveValues);
&endif
            last = (ix + 1 == tabCount);
            p03sGetStream(sqlxa->xaSQLDesc, sqlrap, gaentry, descp->StreamParam, 
               descp->WriteProc, sqlemp, old_streams, &part_ptr, last);
&ifndef SQLODBC
            pr03sAfterCallBack(sqlca, sqlxa, &SaveValues);
            
&endif
            if (sqlemp->ereturncode != 0) break;
            if (!last) {
                s26nextpart(&part_ptr);
                if (part_ptr 
                    && part_ptr->sp1p_part_header.sp1p_part_kind == sp1pk_abap_ostream
                    && part_ptr->sp1p_part_header.sp1p_buf_len >= sizeof(ABAPTabIds[ix+1])) {
                  memcpy(&ABAPTabIds[ix+1], part_ptr->sp1p_buf, sizeof(ABAPTabIds[ix+1]));
                }
                else {
                  p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "Missing output stream part", 
                                          cpr_invalid_commandstate, sqlemp);
                }
            }
            }
            else {
              p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "WriteProc undefined", 
                                      cpr_abap_desc_not_set, sqlemp);
            }
          }
          if (Param) {
             pr04DeleteParamContainer(Param);
             Param = 0;
          }
          if (last) break;
      } /* end for */
      for (ix = 0; ix <= maxFree; ++ix)
      {     
          free(hiddenMask[ix]);
      }
    } while (sqlemp->ereturncode == 0 && part_ptr);
    p03csqlemptosqlca (sqlca, sqlemp);
  }
  M90TRACE (M90_TR_EXIT, "p03sABAPStream", 0);
}

.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :        765
*-PRETTY-*  lines of code :       2101        PRETTY  3.09 
*-PRETTY-*  lines in file :       3233         1992-11-23 
.PA 
