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: PRO*C Unknown # of variables, Unknown Types

Re: PRO*C Unknown # of variables, Unknown Types

From: DriftWood <drift_wood_at_my-deja.com>
Date: Tue, 07 Mar 2000 18:27:27 GMT
Message-ID: <8a3hmb$1e1$1@nnrp1.deja.com>


Here is an example that works on Windows, the ideas are the same though regardless of platform. OCI is much more elegant when it comes to doing this sort of thing...

/*begin DM4SAM.H*/

/*
Dynamic SQL statement parser written in Pro*C using Dynamic SQL Method 4

Pass it an arbitrary SQL Satement and it will write the results to a file.
*/

int Disconnect(void);
int Connect(char *username, char *password, char *alias); void RecordToFile( int *rc, long *RecordSelected, char *TempFile, char *stmt);
void RemoveSpace(char *s);

/*end DM4SAM.H*/

/*begin DM4SAM.PC*/
/*

	Example of dynamic SQL method 4 using Pro*C, you send it a
	select statement and it writes the results to a file...
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>

#include <sqlproto.h> /*Pro*C headers*/

#include "DM4SAM.H"
#define MAX_PATHNAME_SIZE 127

/* This is maximum number of columns allowable in an single table -but- not necessarily the maximum number of columns in a return set due to joins, calculated columns, etc */
#define MAX_ITEMS 254

#define MAX_VNAME_LEN 30 /*Maximum variable name size*/
#define MAX_INAME_LEN 30 /*Maximum Indicator variable name size*/

/* char WinMsg[128]; */

EXEC ORACLE OPTION (ORACA=YES); EXEC ORACLE OPTION (RELEASE_CURSOR=YES); /* host variables used in embedded SQL*/ EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR user[20];
    VARCHAR pswd[20];
    VARCHAR rdbms[20];
    char sql_statement[1024];
    EXEC SQL VAR sql_statement IS STRING(1024); EXEC SQL END DECLARE SECTION;

EXEC SQL INCLUDE sqlca;
EXEC SQL INCLUDE sqlda;
EXEC SQL INCLUDE oraca;


/* further SQLLIB function prototype definitions */

extern SQLDA *sqlald();
extern void sqlnul();

/*

	Macro to copy a target NULL terminated string into
   	a destination VARCHAR2 structure, this presumes that the
	VARCHAR variable was declared large enough to hold the
	target string.
*/

#define V_COPY(v,s) strcpy(v.arr,s); \
v.len = strlen(s); /* establish an RDBMS connection

*/
int Connect(char *username, char *password, char *alias) {
    V_COPY(user,username)
    V_COPY(pswd,password)
    V_COPY(rdbms,alias)

    EXEC SQL CONNECT :user IDENTIFIED BY :pswd USING :rdbms;     if (sqlca.sqlcode < 0) {
	  return 0;
	  }
	return 1;

}

/*

        disconnect from the RDBMS
*/
int Disconnect(void)
{

    EXEC SQL COMMIT WORK RELEASE;
    if (sqlca.sqlcode < 0) {

	  return 0;
	  }
	return 1;

}

/*

        record the data to file...
*/
void RecordToFile( int *rc,

			 long *RecordSelected,
			 char *TempFile,
			 char *stmt)
{
    FILE  *fp;                   /* handle to output file */
    char  *pSQL;                /* local pointer to SQL stmt */
    char  *pFILE;               /* local pointer to file name */
    SQLDA *bind_descriptor;      /* descriptor area for bind variables
*/

    SQLDA *select_descriptor; /* descriptor area for select list items */

    int i, null_ok, precision, scale;

    char   buf[128];             /* temporary work buffer */
    char  *tbuf;                 /* temporary work buffer */

#define SQLCA_INIT

    pSQL = stmt;
    pFILE = TempFile;

    if ((fp = fopen( pFILE,"w+")) == NULL) {

         MessageBox(NULL, "Problem opening output File", pFILE, MB_OK);
        *rc = -1;
	   return;
      }

    oraca.orastxtf = ORASTFERR;

        /*allocate the Bind descriptor*/
    if ((bind_descriptor =

            sqlald(MAX_ITEMS, MAX_VNAME_LEN, MAX_INAME_LEN)) == (SQLDA *) 0)

    {

        MessageBox(NULL,"Cannot allocate memory for Bind descriptor.","test Src",MB_OK);

        *rc = -1;
        return;

    }

        /*allocate the select descriptor*/
    if ((select_descriptor =

        sqlald (MAX_ITEMS, MAX_VNAME_LEN, MAX_INAME_LEN)) == (SQLDA *) 0)

    {

        MessageBox(NULL,"Cannot allocate memory for Select descriptor.","test Src",MB_OK);

        *rc = -1;
        return;

    }
    select_descriptor->N = MAX_ITEMS;

    /* Allocate the pointers to the indicator variables, and the

       actual data. */

    for (i = 0; i < MAX_ITEMS; i++) {

        bind_descriptor->I[i]   = (short *) malloc(sizeof (short));
        select_descriptor->I[i] = (short *) malloc(sizeof(short));
        bind_descriptor->V[i]   = (char *) malloc(1);
        select_descriptor->V[i] = (char *) malloc(1);
    }

    memset(sql_statement,0,sizeof(sql_statement));     memcpy(sql_statement,pSQL,strlen(pSQL));     MessageBox(NULL, sql_statement, "SQLSTMT", MB_OK);

    EXEC SQL PREPARE StmtName FROM :sql_statement;

    if(sqlca.sqlcode != 0) {

       char buf[100];
       /* ORACLE error handler */
       EXEC SQL WHENEVER SQLERROR CONTINUE;
       sprintf (buf,"%25.70s\n",sqlca.sqlerrm.sqlerrmc);
       MessageBox(NULL,buf,"Error",MB_OK);
       *rc = -1;
       sprintf
           (buf,"Parse error at character offset %25d in SQL
statement.\n",
           sqlca.sqlerrd[4]);
          MessageBox(NULL,buf,"Error",MB_OK);
       EXEC SQL ROLLBACK WORK;
	 return;
       }

    EXEC SQL DECLARE Cursor1 CURSOR FOR StmtName;

    bind_descriptor->N = MAX_ITEMS; /* Initialize count of array elements. */

    EXEC SQL DESCRIBE BIND VARIABLES FOR StmtName INTO bind_descriptor;

    	/*
	If F is negative, there were more bind variables
      than originally allocated by sqlald().
	*/

    if (bind_descriptor->F < 0)
    {

        MessageBox(NULL,"Too many bind variables","test Src",MB_OK);
        *rc = -1;
	  return;

    }

    /* Set the maximum number of array elements in the

       descriptor to the number found. */

    bind_descriptor->N = bind_descriptor->F;

    EXEC SQL OPEN Cursor1 USING DESCRIPTOR bind_descriptor; {

    select_descriptor->N = MAX_ITEMS;

    EXEC SQL DESCRIBE SELECT LIST FOR StmtName INTO select_descriptor;

    /* If F is negative, there were more select-list

       items than originally allocated by sqlald(). */     if (select_descriptor->F < 0)
    {

        MessageBox(NULL,"Too many bind variables","test Src",MB_OK);
        *rc = -1;
	  return;

    }
    	/*
	Set the maximum number of array elements in the
      descriptor to the number found.
	*/

    select_descriptor->N = select_descriptor->F;

    for (i = 0; i < select_descriptor->F; i++)     {

        /* Turn off high-order bit of datatype (in this example,
           it does not matter if the column is NOT NULL). */
        sqlnul (&(select_descriptor->T[i]), &(select_descriptor->T[i]),
&null_ok);
        /*
	  This currently supports CHAR/VARCHAR, NUMBER amd DATE
dataypes
	  */
        switch (select_descriptor->T[i])
        {
            case  1 : /* CHAR datatype: no change in length
                         needed, except possibly for TO_CHAR
                         conversions (not handled here). */
                break;
            case  2 : /* NUMBER datatype: use sqlprc() to
                         extract precision and scale. */
                sqlprc (&(select_descriptor->L[i]), &precision, &scale);
                      /* Allow for maximum size of NUMBER. */
                if (precision == 0) precision = 40;
                      /* Also allow for decimal point and
                         possible sign. */
                /* convert NUMBER datatype to FLOAT if scale > 0,
                   INT otherwise. */
                if (scale > 0)
                    select_descriptor->L[i] = sizeof(float);
                else
                    select_descriptor->L[i] = sizeof(int);
                break;

            case 12 : /* DATE datatype */
                select_descriptor->L[i] = 9;
                break;
        }

         if (select_descriptor->T[i] != 2) {
           select_descriptor->V[i] = (char *) realloc(select_descriptor-
>V[i],select_descriptor->L[i] + 1);
           select_descriptor->V[i] = memset(select_descriptor->V[i], 0,
sizeof(select_descriptor->L[i])+1);
           }
         else {
           select_descriptor->V[i] = (char *) realloc(select_descriptor-
>V[i],select_descriptor->L[i]);
           select_descriptor->V[i] = memset(select_descriptor->V[i], 0,
sizeof(select_descriptor->L[i]));
           }
            /*
		Print column headings, right-justifying number
            column headings.
		*/
		tbuf = malloc(select_descriptor->M[i] + 1);
		memset(tbuf,0,select_descriptor->M[i] + 1);
		strncpy(tbuf,select_descriptor->S[i],select_descriptor-
>M[i]);
            fprintf (fp,"%25s,", tbuf);
		free(tbuf);

      /*
	Coerce ALL datatypes except for LONG RAW and NUMBER to
      character.
	*/
        if (select_descriptor->T[i] != 24 && select_descriptor->T[i] !=
2)
            select_descriptor->T[i] = 1;

      /*
	Coerce the datatypes of NUMBERs to float or int depending on
      the scale.
	*/
        if (select_descriptor->T[i] == 2)
          if (scale > 0)
             select_descriptor->T[i] = 4;  /* float */
          else
             select_descriptor->T[i] = 3;  /* int */
    }
    fprintf (fp,"\n");

    MessageBox(NULL,"Fetch","Src",MB_OK);     EXEC SQL WHENEVER NOT FOUND GOTO end_select_loop;

    for (;;)
    {

        EXEC SQL FETCH Cursor1 USING DESCRIPTOR select_descriptor;

        for (i = 0; i < select_descriptor->F; i++)
        {
            int radix = 10;

            if (*select_descriptor->I[i] < 0){
                  fprintf (fp,",");
            }
            else {
				tbuf = malloc(select_descriptor->L[i] +
1);
				memset(tbuf,0,select_descriptor->L[i] +
1);
				if (select_descriptor->T[i] == 3)
{     /* int datatype */
                  fprintf (fp,"%25d,", *(int *)select_descriptor->V[i]);
                  }
                else if (select_descriptor->T[i] == 4) {    /* float
datatype */
                  fprintf (fp,"%25.2f,", *(float *)select_descriptor->V
[i]);
                  }
                else if (select_descriptor->T[i] == 12) {    /* date
data type */
                  fprintf (fp,"%25s,",  select_descriptor->V[i]);
                  }
                else {                         /* character string */
                int len;
                len = select_descriptor->L[i];
				strncpy(tbuf,select_descriptor->V
[i],len);
                RemoveSpace(tbuf);
                fprintf(fp,"%25s,", tbuf);
			free(tbuf);
                }
            }
        }
        fprintf (fp,"\n");

    }
end_select_loop:

     ;
}

        /* Tell user how many rows processed. */
        for (i = 0; i < 8; i++)
        {
               sprintf(buf,"%25d row%25c processed.\n", sqlca.sqlerrd
[2],
                       sqlca.sqlerrd[2] == 1 ? '\0' : 's');
               MessageBox(NULL,buf,"Oracle",MB_OK);
               *RecordSelected = sqlca.sqlerrd[2];
               break;
        }

    /* When done, free the memory allocated for
       pointers in the bind and select descriptors. */
    for (i = 0; i < MAX_ITEMS; i++)
    {
        if (bind_descriptor->V[i] != (char *) 0)
            free(bind_descriptor->V[i]);
        free(bind_descriptor->I[i]);   /* MAX_ITEMS were allocated. */
        if (select_descriptor->V[i] != (char *) 0)
            free(select_descriptor->V[i]);
        free(select_descriptor->I[i]); /* MAX_ITEMS were allocated. */
    }

    /* Free space used by the descriptors themselves. */     sqlclu(bind_descriptor);
    sqlclu(select_descriptor);

/* EXEC SQL WHENEVER SQLERROR CONTINUE; */     /* Close the cursor. */
    EXEC SQL CLOSE Cursor1;
    fclose(fp);
} /* end of Record to File */

/* remove trailing spaces */
void RemoveSpace(char *s)
{

   int len;

   len = strlen(s);
   len--;
   while (len >= 0) {

      if( *(s + len) == ' ' ){
         len--;
         }
         else {
            break;
         }

   }
   *(s + len + 1) = '\0';
}

/*

	params:
		username
		password
		connect string

*/
int main(int argc, char *argv[ ], char *envp[ ]) {
	int  rc;
	long RecordSelected;
	char TempFile[128];
	char stmt[256];
	char user[100];
	char pass[100];
	char dbms[100];

	memset(TempFile,0,128);
	memset(stmt,0,256);
	memset(user,0,100);
	memset(pass,0,100);
	memset(dbms,0,100);

	for(rc = 1;rc < argc;rc++)	{
		switch(rc)	{
		case 1:
			strcpy(user,argv[rc]);
			break;
		case 2:
			strcpy(pass,argv[rc]);
			break;
		case 3:
			strcpy(dbms,argv[rc]);
			break;
		}
	}
	if(strlen(user) == 0)
		strcpy(user,"scott");
	if(strlen(pass) == 0);
	    strcpy(pass,"tiger");
	if(strlen(dbms) == 0)
		strcpy(dbms,"orlnt5.world");
	/*
	This could be any arbitrary select statement...
	*/
	strcpy(stmt,"SELECT ENAME, EMPNO FROM EMP");
	strcpy(TempFile,"testme.txt");
	Connect(user,pass,dbms);
	RecordToFile(&rc,&RecordSelected,TempFile,stmt);
	Disconnect();
	return 0;

}
/*end DM4SAM.PC*/

--
-cheers
  DW



"It is a kind of good deed to say well; and yet words are not deeds.   -William Shakespeare"

Sent via Deja.com http://www.deja.com/
Before you buy. Received on Tue Mar 07 2000 - 12:27:27 CST

Original text of this message

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