.CM  SCRIPT , Version - 1.1 , last edited by peter
.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 1998-2004 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


    ========== licence begin  GPL
    Copyright (c) 1998-2004 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
.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 "precom/abaphndl.h"
&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 void s26find_part (tsp1_segment *segm_ptr, char part_kind, tsp1_part **part_ptr);
extern void sqlnul (short *, short *, int *);

int 
pr03WriteProc(SQLABAPWriteProc *WriteProc, 
	      SQL_LC_ABAPTabParm *StreamParam,   
	      unsigned char *pOutputStream,
	      int cbRowCount);

int 
pr03ReadProc(SQLABAPReadProc *ReadProc, 
	      SQL_LC_ABAPTabParm *StreamParam,   
	      unsigned char *pInputStream,
	      int cbPartLenMax, 
	      int *cbRowSize,
	      int *cbRowCount);

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++) {
      unsigned short T; 
      sqlnul (&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;
  }
  }  
  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)
{
  tsp1_packet   *pck=NULL;
  tsp1_part     *part_ptr=NULL;
  int retcode = SQL_ABAP_OK;
  char szStr[30];

  tsp00_Int4 cbPartLenMax;
  unsigned char *pInputStream;
  p04trint4(sqlra, "PUTSTREAM", cbRowCount);
  p04trint4(sqlra, "ABAPTabId", StreamParam->C_1.ABAPTab.hABAPTab.ABAPTabId);
  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;
      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 cbRowSize = 0;
    retcode = pr03ReadProc(ReadProc, StreamParam, pInputStream, cbPartLenMax, &cbRowSize, &cbRowCount);
    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;
    } 
    if (retcode == SQL_ABAP_OK) {
      part_ptr->sp1p_part_header.sp1p_arg_count= cbRowCount;
  	  part_ptr->sp1p_part_header.sp1p_buf_len  = cbRowSize;
	    p04trint4(sqlra, "Rows", part_ptr->sp1p_part_header.sp1p_arg_count);
	    p04trint4(sqlra, "Length", part_ptr->sp1p_part_header.sp1p_buf_len);
  	  s26finish_part (pck, part_ptr);
  	  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)
{
  tsp1_packet   *pck=NULL;
  tsp1_part     *part_ptr=NULL;
  int retcode = SQL_ABAP_OK;

  unsigned char *pOutputStream;
  tsp00_Int4 cbRowCount=0;
  part_ptr = pr03PartFind(sqlra, sp1pk_data);
  if (part_ptr) {
    pOutputStream = part_ptr->sp1p_buf;
    cbRowCount = part_ptr->sp1p_part_header.sp1p_arg_count;
    p04trint4(sqlra, "GETSTREAM", cbRowCount);
    p04trint4(sqlra, "ABAPTabId", StreamParam->C_1.ABAPTab.hABAPTab.ABAPTabId);
    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);
      if (retcode == SQL_ABAP_EXCEPTION) {
	p03sABAPError(sqlemp, "", cpr_abap_exception);
	p03sSendABAPErrorPacket(SQLDesc, sqlra, gaentry, "", cpr_abap_exception, sqlemp);
	return;
      }
      if (retcode == SQL_ABAP_OK) {
	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;
}

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;
  M90TRACE (M90_TR_ENTRY, "p03sABAPStream", 0);
  
  if (sqlca->sqlemp->ereturncode == 0 && sqlrap) {
    struct SQLERROR *sqlemp = sqlca->sqlemp;
    do {
      int part_kind = sp1pk_abap_istream;
      if (!(part_ptr = pr03PartFind(sqlrap, part_kind))) {
	part_kind = sp1pk_abap_ostream;
	part_ptr = pr03PartFind(sqlrap, part_kind);
      }
      if (part_ptr) {
	tsp00_Int4 NumberOfRows=part_ptr->sp1p_part_header.sp1p_arg_count;
	OmsTypeInt4 ABAPTabId;
	if (part_ptr->sp1p_part_header.sp1p_buf_len >= sizeof(ABAPTabId)) {
	  memcpy(&ABAPTabId, part_ptr->sp1p_buf, sizeof(ABAPTabId));
	  p04trint4(sqlrap, "ABAPTabId", ABAPTabId);
	  if (ka->kapacount > 0) {
	    if (!Param) 
	      Param = pr04NewParamContainer(sqlxa);
	    descp = pr03sGetHostVarABAPDescriptor(Param, sqlxa, ABAPTabId);
	  }
	  else {
	    descp = p03sGetABAPDescriptor(sqlca->sqlcxap->xasqldap, 
					  sqlca->sqldbmode, ABAPTabId);
	  }
	}
	if (descp) {
	  switch(part_kind) {
	  case (sp1pk_abap_istream): {
	    if (descp->ReadProc) {
	      tpr03_SaveValues SaveValues;
	      pr03sBeforeCallBack(sqlca, sqlxa, &SaveValues);
	      p03sPutStream(sqlxa->xaSQLDesc, sqlrap, gaentry, descp->StreamParam, NumberOfRows, 
			    descp->ReadProc, sqlemp);	        
	      pr03sAfterCallBack(sqlca, sqlxa, &SaveValues);
	    }
	    else {
	      p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "ReadProc undefined", cpr_abap_desc_not_set, sqlemp);
	    }
	    break;
	  }
	  case (sp1pk_abap_ostream): {
	    if (descp->WriteProc) {
	      tpr03_SaveValues SaveValues;
	      pr03sBeforeCallBack(sqlca, sqlxa, &SaveValues);
	      p03sGetStream(sqlxa->xaSQLDesc, sqlrap, gaentry, descp->StreamParam, 
			    descp->WriteProc, sqlemp);
	      pr03sAfterCallBack(sqlca, sqlxa, &SaveValues);
	    }
	    else {
	      p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "WriteProc undefined", cpr_abap_desc_not_set, sqlemp);
	    }
	    break;
	  }	    
	  } 
	} /* ABAP decsriptor found */
	else {
	  p03sSendABAPErrorPacket(sqlxa->xaSQLDesc, sqlrap, gaentry, "Descriptor undefined", cpr_abap_desc_not_set, sqlemp);
	}
      } /* ABAP part found */
    } while (sqlemp->ereturncode == 0 && part_ptr);
    if (Param)
      pr04DeleteParamContainer(Param);
    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 
