Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.misc -> Re: HELP: Dynamic SQL/Pro*C++ core dumps

Re: HELP: Dynamic SQL/Pro*C++ core dumps

From: Ken Dougan <kdougan_at_panther.ab.ca>
Date: Mon, 08 Feb 1999 16:07:17 -0700
Message-ID: <36BF6E25.EC9AA8D5@panther.ab.ca>


By the way, I have the test program running and I thought you might be interested in the working source. After you run it though you can see that a double inserted as 1.1111111111e111 is NOT returned as inserted. It actually returns

1111111111111111419130920033087031241842622669656883858001193965689775666308169623874335331159460917210068811776.000000
when it should be
1111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000.  
That is,
"if (1.111111111111111e111 == v_double )" is FALSE.

Any suggestions?
Thanks.
Ken

SQL> desc foo;

 Name                            Null?    Type
 ------------------------------- -------- ----
 I                                        NUMBER(4)
 L                                        NUMBER(12)
 F                                        NUMBER
 D                                        NUMBER

=====================================

#include <stdlib.h>
#include <stdio.h>

#include <string.h>
#include <malloc.h>

#include <iostream.h>

extern "C" {
EXEC SQL INCLUDE sqlca;
EXEC SQL INCLUDE sqlda;
EXEC SQL INCLUDE sqlcpr;

/* The ORACA=YES option must be specified to enable use of the ORACA */ EXEC ORACLE OPTION (ORACA=YES);   void sql_error(char *msg);
extern void sqlclu( struct SQLDA* );
extern SQLDA *sqlald(int, unsigned int, unsigned int); extern void sqlnul( unsigned short*, unsigned short*, int* ); extern void sqlprc( unsigned long*, int*, int*); };

int main( int argc, char** argv ) {
  char vtest[50];
  int _type;
  int v_int;
  long v_long;
  float v_float;
  double v_double;
  int v_bv_int = 1;

  int i;                    /* counter variable */
  int nullok;               /* holder variable for sqlnul() return */
  int prec;                 /* holder variable for sqlprec() */
  int scale;                /* holder variable for sqlprec() */

  SQLDA* sqlda_bv;          /* declare sqlda for bind variables */
  SQLDA* sqlda_sli;         /* declare sqlda for select list items */

  EXEC SQL BEGIN DECLARE SECTION;
  VARCHAR username[21];
  VARCHAR password[21];
  EXEC SQL END DECLARE SECTION;

  strcpy((char*)username.arr, "sdb3");
  username.len = strlen((const char*)username.arr);
  strcpy((char*)password.arr, "sdb3");
  password.len = strlen((const char*)password.arr);

  EXEC SQL WHENEVER SQLERROR DO sql_error("Oracle error");

  EXEC SQL CONNECT :username IDENTIFIED BY :password;

/* sqlald(max # of SLI items, max SLI name length, max BV name length)
*/
/* NB: When allocating for a select decriptor always set param 3 to
'0' */
  sqlda_bv = sqlald(3,10,10);
  sqlda_sli = sqlald(4,10,0);

/* set max # of BVs */

  sqlda_bv->N=3;
/* set max # of SLIs */

  sqlda_sli->N=4;

  EXEC SQL PREPARE stmt1 FROM "select i, l, f, d from foo where i = :id";

  EXEC SQL DECLARE curs1 CURSOR FOR stmt1;

  EXEC SQL DESCRIBE BIND VARIABLES FOR stmt1 INTO sqlda_bv;

/* Allocate storage for BVs */

  sqlda_bv->N=sqlda_bv->F; /* reset N to the value in F */

  for(i=1;i<sqlda_bv->F+1;i++) {

      /*  Setup the I (Indicator Variable) value */
      sqlda_bv->I[i-1]=(short *)malloc(sizeof(short *));  
      *sqlda_bv->I[i-1]=0;     /*  or set to -1 if NULL value    */
  
      /*  Setup the T (Datatype) value */
      /* sqlda_bv->T[i-1]=1; */
      sqlda_bv->T[i-1]=3; /*  integer */
  
      /*  Setup the L (Length) value */
      /* sqlda_bv->L[i-1]=strlen((const char*)v_bv_val); */
      sqlda_bv->L[i-1]= sizeof(int);
  
      /*  Setup the V (Value/Address) value */
      /* sqlda_bv->V[i-1]=v_bv_val; */
      sqlda_bv->V[i-1]=(char*)&v_bv_int;
  }

  EXEC SQL OPEN curs1 USING DESCRIPTOR sqlda_bv;

  EXEC SQL DESCRIBE SELECT LIST FOR stmt1 INTO sqlda_sli;

/* printf("\nHere's the value:\t%i",sqlca.sqlerrd[2]); */
/* exit(0); */
  

/* Allocate storage for SLIs */

  sqlda_sli->N=sqlda_sli->F; /* reset N to the value in F */

  for(i=1;i<sqlda_sli->F+1;i++)
    {

      /*  Reset the null bit value */
      sqlnul((unsigned short*)&sqlda_sli->T[i-1], 
            (unsigned short*)&sqlda_sli->T[i-1], &nullok);

      /*  Setup the I (Indicator Variable) value */
      sqlda_sli->I[i-1]=(short *)malloc(sizeof(short *));  
      if (i == 1) _type = 3;  /*  INTEGER */
      if (i == 2) _type = 8;  /*  LONG */
      if (i == 3) _type = 4;  /*  FLOAT */
      if (i == 4) _type = 2;  /*  NUMBER -- but handle like FLOAT */
      /*  Setup the L (Length) value and the T (Datatype) value */
      switch( _type )
	{
	  /*  VARCHAR2 */
	case  1: sqlda_sli->T[i-1] = 1;
	  break;

	  /*  NUMBER -- FLOAT into double */
	case  2: sqlprc((unsigned long*)&sqlda_sli->L[i-1],&prec,&scale);
	  /* sqlda_sli->L[i-1] = sizeof(int); */
	  sqlda_sli->L[i-1] = sizeof(double);
	  sqlda_sli->T[i-1] = 4;
	  sqlda_sli->V[i-1]=(char*) &v_double;
	  break;
        
	  /*  INTEGER */
	case  3: 
	  /* sqlda_sli->L[i-1] = sizeof(int); */
	  sqlda_sli->L[i-1] = sizeof(int);
	  sqlda_sli->T[i-1] = 3;
	  sqlda_sli->V[i-1]=(char*) &v_int;
	  break;
        
	  /*  FLOAT (this is never the case since 4 never occurs */
	case  4: sqlprc((unsigned long*)&sqlda_sli->L[i-1],&prec,&scale);
	  sqlda_sli->L[i-1] = sizeof(float);
	  sqlda_sli->T[i-1] = 4;
	  /*  Store to a variable */
	  sqlda_sli->V[i-1]=(char*) &v_float;
	  /*  Store to a sqlda */
	  /*  sqlda_sli->V[i-1]=(char *)malloc((size_t)sqlda_sli->L[i-1]); */
	  break;

	  /*  PACKED DECIMAL */
	case  7: break;

	  /*  LONG */
	case  8: sqlprc((unsigned long*)&sqlda_sli->L[i-1],&prec,&scale);
	  /* sqlda_sli->L[i-1] = sizeof(int); */
	  sqlda_sli->L[i-1] = sizeof(long); 
          /* internally to Oracle a number has a defined precision,
             therefore, NUMBER(p) is a long if p is greater than the
             precision of MAXINT */
	  sqlda_sli->T[i-1] = 3;
	  sqlda_sli->V[i-1]=(char*) &v_long;
          v_long = 0l;
	  break;
        
	  /*  LONG RAW */
	case 24: sqlda_sli->L[i-1] = 240;
	  break;
	}

      /*  Setup the V (Value/Address) value (check for numbers!!) */
      if (sqlda_sli->T[i-1]!=2 && sqlda_sli->T[i-1]!=4)
	sqlda_sli->V[i-1]=(char *)malloc((size_t)sqlda_sli->L[i-1]);
    }

  EXEC SQL FETCH curs1 USING DESCRIPTOR sqlda_sli;

  printf("insert into foo values (1, 1111111, 1.111e1, 1.111111111111111e111);\n");
  v_int = *((int*)(sqlda_sli->V[0]));
  printf( "sli int: %i \n", *((int*)(sqlda_sli->V[0])) );   printf( " v_int: %i \n", v_int );
  v_long = *((long*)(sqlda_sli->V[1]));   printf( "sli long: %d \n", *((long*)(sqlda_sli->V[1])) );   printf( " v_long: %d \n", v_long );   v_float = *((float*)(sqlda_sli->V[2]));   printf( "sli float: %f \n", *((float*)(sqlda_sli->V[2])) );   printf( " v_float: %f \n", v_float );   v_double = *((double*)(sqlda_sli->V[3]));

  printf( "sli double: %e \n",  *((double*)(sqlda_sli->V[3])) );
  printf( "  v_double: %e \n",  v_double );
  printf( "sli double: %f \n",  *((double*)(sqlda_sli->V[3])) );
  printf( "  v_double: %f \n",  v_double );
  if (1.111111111111111e111 == v_double ) {
     printf("1.111111111111111e111 == v_double\n");
  } else {
     printf("WARNING:  1.111111111111111e111 != v_double\n");
  }

/* Deallocate storage for SLIs, BVs, and SQLDAs */

/* Handle SLI deallocations */

  for(i=1;i<sqlda_sli->F+1;i++)
    {

      free(sqlda_sli->V[i-1]); 
      free(sqlda_sli->I[i-1]); 

    }

/* Handle BV deallocations */

  for(i=1;i<sqlda_bv->F+1;i++)
    {

      free(sqlda_bv->V[i-1]); 
      free(sqlda_bv->I[i-1]); 

    }

/* Handle sqlda deallocations */

  sqlclu(sqlda_bv);
  sqlclu(sqlda_sli);

  EXEC SQL CLOSE curs1;

  return 0;
}

void sql_error(char *msg)
{

    cout << endl << msg << endl;

    sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
    oraca.orastxt.orastxtc[oraca.orastxt.orastxtl] = '\0';
    oraca.orasfnm.orasfnmc[oraca.orasfnm.orasfnml] = '\0';
    cout << sqlca.sqlerrm.sqlerrmc << endl;
    cout << "in " << oraca.orastxt.orastxtc << endl;     cout << "on line " << oraca.oraslnr << " of " << oraca.orasfnm.orasfnmc

         << endl << endl;

   /* Disable ORACLE error checking to avoid an infinite loop
    * should another error occur within this routine.
    */

   EXEC SQL WHENEVER SQLERROR CONTINUE;    // Roll back any pending changes and disconnect from Oracle.    EXEC SQL ROLLBACK RELEASE;
   exit(1);
} Received on Mon Feb 08 1999 - 17:07:17 CST

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US