This one cleans the cursor problems ecpg had so far. It is now able
authorBruce Momjian <bruce@momjian.us>
Tue, 11 Aug 1998 18:33:37 +0000 (18:33 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 11 Aug 1998 18:33:37 +0000 (18:33 +0000)
to understand cursors with variables.

Michael

src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/TODO
src/interfaces/ecpg/include/ecpglib.h
src/interfaces/ecpg/lib/Makefile.in
src/interfaces/ecpg/lib/ecpglib.c
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/test/Makefile
src/interfaces/ecpg/test/test2.pgc

index 1907471a731cceb061ef6bc473a0383cfdbd26d5..6ac03ff234fd8356638df543294d7a2d6ce6a5c6 100644 (file)
@@ -270,3 +270,10 @@ Mon Aug  3 17:23:18 CEST 1998
    - Fixed cursor handling
    - Set version to 2.3.5
    - Set library version to 2.4
+
+Fri Aug  7 12:38:50 CEST 1998
+
+   - Fixed cursor handling once again
+   - Added support for variables in cursor
+   - Set version to 2.3.6
+   - Set library version to 2.5
index 5811cb767de7b102aa2ae4e9d082cafa23b5013e..908ec6192705f985005facf908bffd9fdf21992a 100644 (file)
@@ -1,9 +1,7 @@
-What happens to a cursor declaration with variables?
-
 The complete structure definition has to be listed inside the declare
 section of the structure variable for ecpg to be able to understand it.
 
-Variable type bool has to be checked. I never used it so far.
+Variable type bool has to be tested. I never used it so far.
 
 The error message for "no data" in an exec sql insert select from statement
 has to be 100.
index a81ca7e8b9cda3139ae9fc3955d4d3796f4bf4db..83f2e6efb86ee7b59cc1e7aeb0fd40f6a76e3eea 100644 (file)
@@ -13,9 +13,6 @@ bool      ECPGdisconnect(int, const char *);
 
 void       ECPGlog(const char *format,...);
 
-bool       ECPGdeclare(int, const char *, char *);
-bool       ECPGopen(int, const char *);
-
 #ifdef LIBPQ_FE_H
 bool       ECPGsetdb(PGconn *);
 
index 8fd6b7720302382cb873202c9da1017d264f6bda..e236487d6aaec05d351744292689d85f7e14712b 100644 (file)
@@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
 PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
 
 SO_MAJOR_VERSION=2
-SO_MINOR_VERSION=4
+SO_MINOR_VERSION=5
 
 PORTNAME=@PORTNAME@
 
index 86021d6ee461b381372910f04748ab32a7efb489..0d3d4fa0e6a471ca82607d4c8fb6cebf2657c467 100644 (file)
@@ -33,6 +33,29 @@ static struct connection
    struct connection *next;
 } *all_connections = NULL, *actual_connection = NULL;
 
+struct variable
+{
+   enum ECPGttype type;
+   void *value;
+   long varcharsize;
+   long arrsize;
+   long offset;
+   enum ECPGttype ind_type;
+   void *ind_value;
+   long ind_varcharsize;
+   long ind_arrsize;
+   long ind_offset;
+   struct variable *next;
+};
+
+struct statement
+{
+   int lineno;
+   char *command;
+   struct variable *inlist;
+   struct variable *outlist;
+};
+
 static int simple_debug = 0;
 static FILE *debugstream = NULL;
 static int committed = true;
@@ -116,27 +139,87 @@ ECPGfinish(struct connection *act)
        ECPGlog("ECPGfinish: called an extra time.\n");
 }
 
-bool
-ECPGdo(int lineno, char *query,...)
+/* create a list of variables */
+static bool
+create_statement(int lineno, struct statement **stmt, char *query, va_list ap)
+{
+   struct variable **list = &((*stmt)->inlist);
+   enum ECPGttype  type;
+   
+   *stmt = calloc(sizeof(struct statement), 1);
+   
+   if (!*stmt)
+   {
+          ECPGfinish(actual_connection);
+          ECPGlog("out of memory\n");
+          register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+          return false;
+   }
+   
+   (*stmt)->command = query;
+   (*stmt)->lineno = lineno;
+   
+   list = &((*stmt)->inlist);
+
+   type = va_arg(ap, enum ECPGttype);
+   
+   while (type != ECPGt_EORT)
+       {  
+          if (type == ECPGt_EOIT)
+          {
+           list = &((*stmt)->outlist);
+          }
+          else
+          {
+       struct variable *var, *ptr;
+                       
+       var = malloc(sizeof(struct variable));
+       if (!var)
+       {
+           ECPGfinish(actual_connection);
+           ECPGlog("out of memory\n");
+               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+           return false;
+       }
+       
+       var->type = type;
+       var->value = va_arg(ap, void *);
+       var->varcharsize = va_arg(ap, long);
+       var->arrsize = va_arg(ap, long);
+       var->offset = va_arg(ap, long);
+       var->ind_type = va_arg(ap, enum ECPGttype);
+       var->ind_value = va_arg(ap, void *);
+       var->ind_varcharsize = va_arg(ap, long);
+       var->ind_arrsize = va_arg(ap, long);
+       var->ind_offset = va_arg(ap, long);
+       var->next = NULL;
+       
+       for (ptr = *list; ptr && ptr->next; ptr=ptr->next);
+       
+       if (ptr == NULL)
+           *list = var;
+       else
+           ptr->next = var;
+      }
+      
+      type = va_arg(ap, enum ECPGttype);
+   }
+   
+   return(true);
+}
+
+static bool
+ECPGexecute(struct statement *stmt)
 {
-   va_list     ap;
    bool        status = false;
    char       *copiedquery;
    PGresult   *results;
    PGnotify   *notify;
-   enum ECPGttype type;
-   void       *value = NULL, *ind_value;
-   long        varcharsize, ind_varcharsize;
-   long        arrsize, ind_arrsize;
-   long        offset, ind_offset;
-   enum ECPGttype ind_type;
+   struct variable *var;
 
    memset((char *) &sqlca, 0, sizeof (sqlca));
-   va_start(ap, query);
 
-   copiedquery = strdup(query);
-
-   type = va_arg(ap, enum ECPGttype);
+   copiedquery = strdup(stmt->command);
 
    /*
     * Now, if the type is one of the fill in types then we take the
@@ -144,7 +227,8 @@ ECPGdo(int lineno, char *query,...)
     * Then if there are any more fill in types we fill in at the next and
     * so on.
     */
-   while (type != ECPGt_EOIT)
+   var = stmt->inlist;
+   while (var)
    {
        char       *newcopy;
        char       *mallocedval = NULL;
@@ -158,34 +242,24 @@ ECPGdo(int lineno, char *query,...)
         * think).
         */
 
-       value = va_arg(ap, void *);
-       varcharsize = va_arg(ap, long);
-       arrsize = va_arg(ap, long);
-       offset = va_arg(ap, long);
-       ind_type = va_arg(ap, enum ECPGttype);
-       ind_value = va_arg(ap, void *);
-       ind_varcharsize = va_arg(ap, long);
-       ind_arrsize = va_arg(ap, long);
-       ind_offset = va_arg(ap, long);
-
        buff[0] = '\0';
        
        /* check for null value and set input buffer accordingly */
-       switch (ind_type)
+       switch (var->ind_type)
        {
            case ECPGt_short:
            case ECPGt_unsigned_short:
-               if (*(short *) ind_value < 0)
+               if (*(short *) var->ind_value < 0)
                    strcpy(buff, "null");
                break;
            case ECPGt_int:
            case ECPGt_unsigned_int:
-               if (*(int *) ind_value < 0)
+               if (*(int *) var->ind_value < 0)
                    strcpy(buff, "null");
                break;
            case ECPGt_long:
            case ECPGt_unsigned_long:
-               if (*(long *) ind_value < 0L)
+               if (*(long *) var->ind_value < 0L)
                    strcpy(buff, "null");
                break;
            default:
@@ -194,42 +268,42 @@ ECPGdo(int lineno, char *query,...)
        
        if (*buff == '\0')
        {
-          switch (type)
+          switch (var->type)
           {
            case ECPGt_short:
            case ECPGt_int:
-               sprintf(buff, "%d", *(int *) value);
+               sprintf(buff, "%d", *(int *) var->value);
                tobeinserted = buff;
                break;
 
            case ECPGt_unsigned_short:
            case ECPGt_unsigned_int:
-               sprintf(buff, "%d", *(unsigned int *) value);
+               sprintf(buff, "%d", *(unsigned int *) var->value);
                tobeinserted = buff;
                break;
 
            case ECPGt_long:
-               sprintf(buff, "%ld", *(long *) value);
+               sprintf(buff, "%ld", *(long *) var->value);
                tobeinserted = buff;
                break;
 
            case ECPGt_unsigned_long:
-               sprintf(buff, "%ld", *(unsigned long *) value);
+               sprintf(buff, "%ld", *(unsigned long *) var->value);
                tobeinserted = buff;
                break;
 
            case ECPGt_float:
-               sprintf(buff, "%.14g", *(float *) value);
+               sprintf(buff, "%.14g", *(float *) var->value);
                tobeinserted = buff;
                break;
 
            case ECPGt_double:
-               sprintf(buff, "%.14g", *(double *) value);
+               sprintf(buff, "%.14g", *(double *) var->value);
                tobeinserted = buff;
                break;
 
            case ECPGt_bool:
-               sprintf(buff, "'%c'", (*(char *) value ? 't' : 'f'));
+               sprintf(buff, "'%c'", (*(char *) var->value ? 't' : 'f'));
                tobeinserted = buff;
                break;
 
@@ -237,7 +311,7 @@ ECPGdo(int lineno, char *query,...)
            case ECPGt_unsigned_char:
                {
                    /* set slen to string length if type is char * */
-                   int         slen = (varcharsize == 0) ? strlen((char *) value) : varcharsize;
+                   int         slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
                    char * tmp;
 
                    newcopy = (char *) malloc(slen + 1);
@@ -245,11 +319,11 @@ ECPGdo(int lineno, char *query,...)
                    {
                        ECPGfinish(actual_connection);
                        ECPGlog("out of memory\n");
-                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
                        return false;
                    }
                        
-                   strncpy(newcopy, (char *) value, slen);
+                   strncpy(newcopy, (char *) var->value, slen);
                    newcopy[slen] = '\0';
 
                    mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
@@ -257,7 +331,7 @@ ECPGdo(int lineno, char *query,...)
                    {
                        ECPGfinish(actual_connection);
                        ECPGlog("out of memory\n");
-                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
                        return false;
                    }
                        
@@ -267,7 +341,7 @@ ECPGdo(int lineno, char *query,...)
                    {
                        ECPGfinish(actual_connection);
                        ECPGlog("out of memory\n");
-                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
                        return false;
                    }
                        
@@ -282,28 +356,28 @@ ECPGdo(int lineno, char *query,...)
 
            case ECPGt_varchar:
                {
-                   struct ECPGgeneric_varchar *var =
-                   (struct ECPGgeneric_varchar *) value;
+                   struct ECPGgeneric_varchar *variable =
+                   (struct ECPGgeneric_varchar *) (var->value);
                    char *tmp;
 
-                   newcopy = (char *) malloc(var->len + 1);
+                   newcopy = (char *) malloc(variable->len + 1);
                    if (!newcopy)
                    {
                        ECPGfinish(actual_connection);
                        ECPGlog("out of memory\n");
-                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
                        return false;
                    }
                        
-                   strncpy(newcopy, var->arr, var->len);
-                   newcopy[var->len] = '\0';
+                   strncpy(newcopy, variable->arr, variable->len);
+                   newcopy[variable->len] = '\0';
 
                    mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
                    if (!mallocedval)
                    {
                        ECPGfinish(actual_connection);
                        ECPGlog("out of memory\n");
-                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
                        return false;
                    }
                    
@@ -313,7 +387,7 @@ ECPGdo(int lineno, char *query,...)
                    {
                        ECPGfinish(actual_connection);
                        ECPGlog("out of memory\n");
-                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+                               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
                        return false;
                    }
                                                                    
@@ -329,7 +403,7 @@ ECPGdo(int lineno, char *query,...)
            default:
                /* Not implemented yet */
                register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
-                              ECPGtype_name(type), lineno);
+                              ECPGtype_name(var->type), stmt->lineno);
                return false;
                break;
           }
@@ -348,7 +422,7 @@ ECPGdo(int lineno, char *query,...)
        {
            ECPGfinish(actual_connection);
            ECPGlog("out of memory\n");
-                   register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
+                   register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", stmt->lineno);
            return false;
        }
            
@@ -360,7 +434,7 @@ ECPGdo(int lineno, char *query,...)
             * We have an argument but we dont have the matched up string
             * in the string
             */
-           register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
+           register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
            return false;
        }
        else
@@ -379,7 +453,7 @@ ECPGdo(int lineno, char *query,...)
 
        /*
         * Now everything is safely copied to the newcopy. Lets free the
-        * oldcopy and let the copiedquery get the value from the newcopy.
+        * oldcopy and let the copiedquery get the var->value from the newcopy.
         */
        if (mallocedval != NULL)
        {
@@ -390,13 +464,13 @@ ECPGdo(int lineno, char *query,...)
        free(copiedquery);
        copiedquery = newcopy;
 
-       type = va_arg(ap, enum ECPGttype);
+       var = var->next;
    }
 
    /* Check if there are unmatched things left. */
    if (strstr(copiedquery, ";;") != NULL)
    {
-       register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
+       register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
        return false;
    }
 
@@ -406,27 +480,28 @@ ECPGdo(int lineno, char *query,...)
    {
        if ((results = PQexec(actual_connection->connection, "begin transaction")) == NULL)
        {
-           register_error(ECPG_TRANS, "Error starting transaction line %d.", lineno);
+           register_error(ECPG_TRANS, "Error starting transaction line %d.", stmt->lineno);
            return false;
        }
        PQclear(results);
        committed = 0;
    }
 
-   ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery);
+   ECPGlog("ECPGexecute line %d: QUERY: %s\n", stmt->lineno, copiedquery);
    results = PQexec(actual_connection->connection, copiedquery);
    free(copiedquery);
 
    if (results == NULL)
    {
-       ECPGlog("ECPGdo line %d: error: %s", lineno,
+       ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
                PQerrorMessage(actual_connection->connection));
        register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
-                      PQerrorMessage(actual_connection->connection), lineno);
+                      PQerrorMessage(actual_connection->connection), stmt->lineno);
    }
    else
    {
        sqlca.sqlerrd[2] = 0;
+       var = stmt->outlist;
        switch (PQresultStatus(results))
        {
                int         nfields, ntuples, act_tuple, act_field;
@@ -445,9 +520,9 @@ ECPGdo(int lineno, char *query,...)
                
                if (ntuples < 1)
                {
-                   ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
-                           lineno, ntuples);
-                   register_error(ECPG_NOT_FOUND, "Data not found line %d.", lineno);
+                   ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
+                           stmt->lineno, ntuples);
+                   register_error(ECPG_NOT_FOUND, "Data not found line %d.", stmt->lineno);
                    status = false;
                    break;
                }
@@ -457,23 +532,19 @@ ECPGdo(int lineno, char *query,...)
                                      char     *pval;
                                      char     *scan_length;
                                              
-                                     type = va_arg(ap, enum ECPGttype);
-                                     value = va_arg(ap, void *);
-                                     varcharsize = va_arg(ap, long);
-                                     arrsize = va_arg(ap, long);
-                                     offset = va_arg(ap, long);
-                                     ind_type = va_arg(ap, enum ECPGttype);
-                                     ind_value = va_arg(ap, void *);
-                                     ind_varcharsize = va_arg(ap, long);
-                                     ind_arrsize = va_arg(ap, long);
-                                     ind_offset = va_arg(ap, long);
-
+                                     if (var == NULL)
+                                     {
+                                             ECPGlog("ECPGexecute line %d: Too few arguments.\n", stmt->lineno);
+                                             register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
+                                             return(false);
+                                     }
+                                     
                                      /* if we don't have enough space, we cannot read all tuples */
-                                     if ((arrsize > 0 && ntuples > arrsize) || (ind_arrsize > 0 && ntuples > ind_arrsize))
+                                     if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
                                      {
-                                             ECPGlog("ECPGdo line %d: Incorrect number of matches: %d don't fit into array of %d\n",
-                                                             lineno, ntuples, arrsize);
-                                             register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", lineno);
+                                             ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
+                                                             stmt->lineno, ntuples, var->arrsize);
+                                             register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", stmt->lineno);
                                              status = false;
                                              break;
                                      }
@@ -481,31 +552,31 @@ ECPGdo(int lineno, char *query,...)
                                      {
                                          pval = PQgetvalue(results, act_tuple, act_field);
 
-                                         ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
+                                         ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
 
-                                         /* Now the pval is a pointer to the value. */
-                                         /* We will have to decode the value */
+                                         /* Now the pval is a pointer to the var->value. */
+                                         /* We will have to decode the var->value */
                                      
-                                         /* check for null value and set indicator accordingly */
-                                         switch (ind_type)
+                                         /* check for null var->value and set indicator accordingly */
+                                         switch (var->ind_type)
                                          {
                                                  case ECPGt_short:
                                                  case ECPGt_unsigned_short:
-                                                         ((short *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+                                                         ((short *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
                                                          break;
                                                  case ECPGt_int:
                                                  case ECPGt_unsigned_int:
-                                                         ((int *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+                                                         ((int *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
                                                          break;
                                                  case ECPGt_long:
                                                  case ECPGt_unsigned_long:
-                                                         ((long *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+                                                         ((long *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
                                                          break;
                                                  default:
                                                          break;
                                          }
                                                                                  
-                                         switch (type)
+                                         switch (var->type)
                                          {
                                                          long      res;
                                                          unsigned long ures;
@@ -520,7 +591,7 @@ ECPGdo(int lineno, char *query,...)
                                                                  if (*scan_length != '\0')     /* Garbage left */
                                                                  {
                                                                          register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
-                                                                                                    pval, lineno);
+                                                                                                    pval, stmt->lineno);
                                                                          status = false;
                                                                          res = 0L;
                                                                  }
@@ -529,16 +600,16 @@ ECPGdo(int lineno, char *query,...)
                                                                  res = 0L;
     
                                                          /* Again?! Yes */
-                                                         switch (type)
+                                                         switch (var->type)
                                                          {
                                                                  case ECPGt_short:
-                                                                         ((short *) value)[act_tuple] = (short) res;
+                                                                         ((short *) var->value)[act_tuple] = (short) res;
                                                                          break;
                                                                  case ECPGt_int:
-                                                                         ((int *) value)[act_tuple] = (int) res;
+                                                                         ((int *) var->value)[act_tuple] = (int) res;
                                                                          break;
                                                                  case ECPGt_long:
-                                                                         ((long *) value)[act_tuple] = res;
+                                                                         ((long *) var->value)[act_tuple] = res;
                                                                          break;
                                                                  default:
                                                                          /* Cannot happen */
@@ -555,7 +626,7 @@ ECPGdo(int lineno, char *query,...)
                                                                  if (*scan_length != '\0')     /* Garbage left */
                                                                  {
                                                                          register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
-                                                                                                    pval, lineno);
+                                                                                                    pval, stmt->lineno);
                                                                          status = false;
                                                                          ures = 0L;
                                                                  }
@@ -564,16 +635,16 @@ ECPGdo(int lineno, char *query,...)
                                                                  ures = 0L;
     
                                                          /* Again?! Yes */
-                                                         switch (type)
+                                                         switch (var->type)
                                                          {
                                                                  case ECPGt_unsigned_short:
-                                                                         ((unsigned short *) value)[act_tuple] = (unsigned short) ures;
+                                                                         ((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
                                                                          break;
                                                                  case ECPGt_unsigned_int:
-                                                                         ((unsigned int *) value)[act_tuple] = (unsigned int) ures;
+                                                                         ((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
                                                                          break;
                                                                  case ECPGt_unsigned_long:
-                                                                         ((unsigned long *) value)[act_tuple] = ures;
+                                                                         ((unsigned long *) var->value)[act_tuple] = ures;
                                                                          break;
                                                                  default:
                                                                          /* Cannot happen */
@@ -590,7 +661,7 @@ ECPGdo(int lineno, char *query,...)
                                                                  if (*scan_length != '\0')     /* Garbage left */
                                                                  {
                                                                          register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
-                                                                                                    pval, lineno);
+                                                                                                    pval, stmt->lineno);
                                                                          status = false;
                                                                          dres = 0.0;
                                                                  }
@@ -599,13 +670,13 @@ ECPGdo(int lineno, char *query,...)
                                                                  dres = 0.0;
     
                                                          /* Again?! Yes */
-                                                         switch (type)
+                                                         switch (var->type)
                                                          {
                                                                  case ECPGt_float:
-                                                                         ((float *) value)[act_tuple] = dres;
+                                                                         ((float *) var->value)[act_tuple] = dres;
                                                                          break;
                                                                  case ECPGt_double:
-                                                                         ((double *) value)[act_tuple] = dres;
+                                                                         ((double *) var->value)[act_tuple] = dres;
                                                                          break;
                                                                  default:
                                                                          /* Cannot happen */
@@ -618,50 +689,50 @@ ECPGdo(int lineno, char *query,...)
                                                          {
                                                                  if (pval[0] == 'f' && pval[1] == '\0')
                                                                  {
-                                                                         ((char *) value)[act_tuple] = false;
+                                                                         ((char *) var->value)[act_tuple] = false;
                                                                          break;
                                                                  }
                                                                  else if (pval[0] == 't' && pval[1] == '\0')
                                                                  {
-                                                                         ((char *) value)[act_tuple] = true;
+                                                                         ((char *) var->value)[act_tuple] = true;
                                                                          break;
                                                                  }
                                                          }
     
                                                          register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
                                                                                     (pval ? pval : "NULL"),
-                                                                                    lineno);
+                                                                                    stmt->lineno);
                                                          status = false;
                                                          break;
     
                                                  case ECPGt_char:
                                                  case ECPGt_unsigned_char:
                                                          {
-                                                                 if (varcharsize == 0)
+                                                                 if (var->varcharsize == 0)
                                                                  {
                                                                          /* char* */
-                                                                         strncpy(((char **) value)[act_tuple], pval, strlen(pval));
-                                                                         (((char **) value)[act_tuple])[strlen(pval)] = '\0';
+                                                                         strncpy(((char **) var->value)[act_tuple], pval, strlen(pval));
+                                                                         (((char **) var->value)[act_tuple])[strlen(pval)] = '\0';
                                                                  }
                                                                  else
                                                                  {
-                                                                         strncpy((char *) (value + offset * act_tuple), pval, varcharsize);
-                                                                         if (varcharsize < strlen(pval))
+                                                                         strncpy((char *) (var->value + var->offset * act_tuple), pval, var->varcharsize);
+                                                                         if (var->varcharsize < strlen(pval))
                                                                          {
                                                                                  /* truncation */
-                                                                                 switch (ind_type)
+                                                                                 switch (var->ind_type)
                                                                                  {
                                                                                          case ECPGt_short:
                                                                                          case ECPGt_unsigned_short:
-                                                                                                 ((short *) ind_value)[act_tuple] = varcharsize;
+                                                                                                 ((short *) var->ind_value)[act_tuple] = var->varcharsize;
                                                                                                  break;
                                                                                          case ECPGt_int:
                                                                                          case ECPGt_unsigned_int:
-                                                                                                 ((int *) ind_value)[act_tuple] = varcharsize;
+                                                                                                 ((int *) var->ind_value)[act_tuple] = var->varcharsize;
                                                                                                  break;
                                                                                          case ECPGt_long:
                                                                                          case ECPGt_unsigned_long:
-                                                                                                 ((long *) ind_value)[act_tuple] = varcharsize;
+                                                                                                 ((long *) var->ind_value)[act_tuple] = var->varcharsize;
                                                                                                  break;
                                                                                          default:
                                                                                                  break;
@@ -674,62 +745,55 @@ ECPGdo(int lineno, char *query,...)
     
                                                  case ECPGt_varchar:
                                                          {
-                                                                 struct ECPGgeneric_varchar *var =
-                                (struct ECPGgeneric_varchar *) (value + offset * act_tuple);
+                                                                 struct ECPGgeneric_varchar *variable =
+                                (struct ECPGgeneric_varchar *) (var->value + var->offset * act_tuple);
     
-                                if (varcharsize == 0)
-                                  strncpy(var->arr, pval, strlen(pval));
+                                if (var->varcharsize == 0)
+                                  strncpy(variable->arr, pval, strlen(pval));
                                 else
-                                  strncpy(var->arr, pval, varcharsize);
+                                  strncpy(variable->arr, pval, var->varcharsize);
 
-                                                                 var->len = strlen(pval);
-                                                                 if (varcharsize > 0 && var->len > varcharsize)
+                                                                 variable->len = strlen(pval);
+                                                                 if (var->varcharsize > 0 && variable->len > var->varcharsize)
                                                                  {
                                                                          /* truncation */
-                                                                         switch (ind_type)
+                                                                         switch (var->ind_type)
                                                                          {
                                                                                  case ECPGt_short:
                                                                                  case ECPGt_unsigned_short:
-                                                                                         ((short *) ind_value)[act_tuple] = varcharsize;
+                                                                                         ((short *) var->ind_value)[act_tuple] = var->varcharsize;
                                                                                          break;
                                                                                  case ECPGt_int:
                                                                                  case ECPGt_unsigned_int:
-                                                                                         ((int *) ind_value)[act_tuple] = varcharsize;
+                                                                                         ((int *) var->ind_value)[act_tuple] = var->varcharsize;
                                                                                          break;
                                                                                  case ECPGt_long:
                                                                                  case ECPGt_unsigned_long:
-                                                                                         ((long *) ind_value)[act_tuple] = varcharsize;
+                                                                                         ((long *) var->ind_value)[act_tuple] = var->varcharsize;
                                                                                          break;
                                                                                  default:
                                                                                          break;
                                                                          }
                                                                          sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
     
-                                                                         var->len = varcharsize;
+                                                                         variable->len = var->varcharsize;
                                                                  }
                                                          }
                                                          break;
     
-                                                 case ECPGt_EORT:
-                                                         ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
-                                                         register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
-                                                         status = false;
-                                                         break;
-    
                                                  default:
                                                          register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
-                                                                                    ECPGtype_name(type), lineno);
+                                                                                    ECPGtype_name(var->type), stmt->lineno);
                                                          status = false;
                                                          break;
                                          }
                                      }
+                    var = var->next;
                }
 
-               type = va_arg(ap, enum ECPGttype);
-
-               if (status && type != ECPGt_EORT)
+               if (status && var != NULL)
                {
-                   register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
+                   register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
                    status = false;
                }
 
@@ -737,35 +801,34 @@ ECPGdo(int lineno, char *query,...)
                break;
            case PGRES_EMPTY_QUERY:
                /* do nothing */
-               register_error(ECPG_EMPTY, "Empty query line %d.", lineno);
+               register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
                break;
            case PGRES_COMMAND_OK:
                status = true;
                sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
-               ECPGlog("TEST: %s\n", PQcmdTuples(results));
-               ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
+               ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, PQcmdStatus(results));
                break;
            case PGRES_NONFATAL_ERROR:
            case PGRES_FATAL_ERROR:
            case PGRES_BAD_RESPONSE:
-               ECPGlog("ECPGdo line %d: Error: %s",
-                       lineno, PQerrorMessage(actual_connection->connection));
+               ECPGlog("ECPGexecute line %d: Error: %s",
+                       stmt->lineno, PQerrorMessage(actual_connection->connection));
                register_error(ECPG_PGSQL, "Error: %s line %d.",
-                              PQerrorMessage(actual_connection->connection), lineno);
+                              PQerrorMessage(actual_connection->connection), stmt->lineno);
                status = false;
                break;
            case PGRES_COPY_OUT:
-               ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
+               ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
                PQendcopy(results->conn);
                break;
            case PGRES_COPY_IN:
-               ECPGlog("ECPGdo line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
+               ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
                PQendcopy(results->conn);
                break;
            default:
-               ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
-                       lineno);
-               register_error(ECPG_PGSQL, "Postgres error line %d.", lineno);
+               ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
+                       stmt->lineno);
+               register_error(ECPG_PGSQL, "Postgres error line %d.", stmt->lineno);
                status = false;
                break;
        }
@@ -775,8 +838,8 @@ ECPGdo(int lineno, char *query,...)
    notify = PQnotifies(actual_connection->connection);
    if (notify)
    {
-       ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
-               lineno, notify->relname, notify->be_pid);
+       ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
+               stmt->lineno, notify->relname, notify->be_pid);
        free(notify);
    }
 
@@ -784,6 +847,20 @@ ECPGdo(int lineno, char *query,...)
    return status;
 }
 
+bool
+ECPGdo(int lineno, char *query, ...)
+{
+   va_list         args;
+   struct statement    *stmt;
+                                                                                                                                                        
+   va_start(args, query);
+   if (create_statement(lineno, &stmt, query, args) == false)
+       return(false);
+   va_end(args);
+   
+   return(ECPGexecute(stmt));
+}
+
 
 bool
 ECPGtrans(int lineno, const char * transaction)
@@ -940,56 +1017,3 @@ sqlprint(void)
    sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
    printf("sql error %s\n", sqlca.sqlerrm.sqlerrmc);
 }
-
-/* keep a list of cursors */
-struct cursor *cur = NULL;
-
-bool ECPGdeclare(int lineno, const char *name, char *command)
-{
-   struct cursor *ptr;
-   
-   for (ptr = cur; ptr != NULL; ptr = ptr->next)
-   {
-       if (strcmp(name, ptr->name) == 0)
-       {
-               /* re-definition */
-                   free(ptr->command);
-                        ptr->command = command;
-                        break;
-                }
-        }
-                        
-        if (ptr == NULL)
-        {
-           struct cursor *this = (struct cursor *) malloc(sizeof(struct cursor));
-
-       if (!this)
-       {
-               ECPGlog("out of memory\n");
-               register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
-                   return false;
-                }
-           /* initial definition */
-           this->next = cur;
-           this->name = name;
-           this->command = command;
-           cur = this;
-   }
-   
-   return(true);
-}
-
-bool ECPGopen(int lineno, const char *name)
-{
-   struct cursor *ptr;
-
-        for (ptr = cur; ptr != NULL; ptr=ptr->next)
-        {
-               if (strcmp(ptr->name, name) == 0)
-                    return(ECPGdo(lineno, ptr->command, ECPGt_EOIT, ECPGt_EORT));
-        }
-
-   ECPGlog("trying to open undeclared cursor %s\n", name);
-   register_error(ECPG_UNDECLARED_CURSOR, "trying to open undeclared cursor %s in line %d", name, lineno);        
-        return(false);
-}
index f12b799850c035c9464d25631f65144beb2b4fd9..1fe777845b7ad3979130c06bbd75347a669da60a 100644 (file)
@@ -23,6 +23,7 @@ extern char *optarg;
 
 struct _include_path *include_paths;
 static int no_auto_trans = 0;
+struct cursor *cur = NULL;
 
 static void
 usage(char *progname)
@@ -138,6 +139,24 @@ main(int argc, char *const argv[])
            {
                struct cursor *ptr;
                
+               /* remove old cursor definitions if any are still there */
+               for (ptr = cur; ptr != NULL; ptr=ptr->next)
+               {
+                   struct arguments *l1, *l2;
+                   
+                   free(ptr->command);
+                   free(ptr->name);
+                   for (l1 = argsinsert; l1; l1 = l2)
+                   {
+                       l2 = l1->next;
+                       free(l1);
+                   }
+                   for (l1 = argsresult; l1; l1 = l2)
+                   {
+                       l2 = l1->next;
+                       free(l1);
+                   }
+               }
                /* initialize lex */
                lex_init();
                
index d2eec0c097807d426c0c12e81005f8b20ca32b33..43a15394af3d86c92f548255e471c6778c7c1b67 100644 (file)
@@ -16,6 +16,15 @@ struct _include_path {  char * path;
 
 extern struct _include_path *include_paths;
 
+struct cursor { char *name;
+                char *command;
+                struct arguments * argsinsert;
+                struct arguments * argsresult;
+                struct cursor *next;
+              };
+                                           
+extern struct cursor *cur;
+
 /* This is a linked list of the variable names and types. */
 struct variable
 {
@@ -28,6 +37,15 @@ struct variable
 extern struct ECPGtype ecpg_no_indicator;
 extern struct variable no_indicator;
 
+struct arguments {
+    struct variable * variable;
+    struct variable * indicator;
+    struct arguments * next;
+};
+
+extern struct arguments * argsinsert;
+extern struct arguments * argsresult;
+
 /* functions */
 
 extern void lex_init(void);
index 290440a39f5c2517f8688df38118c91e1ea7b43c..4d6960e406bd3d526c6f0cc3959b9499b5ce10e4 100644 (file)
@@ -245,14 +245,9 @@ remove_variables(int brace_level)
  * These are of two kinds: input and output.
  * I will make two lists for them.
  */
-struct arguments {
-    struct variable * variable;
-    struct variable * indicator;
-    struct arguments * next;
-};
 
-static struct arguments * argsinsert = NULL;
-static struct arguments * argsresult = NULL;
+struct arguments * argsinsert = NULL;
+struct arguments * argsresult = NULL;
 
 static void
 reset_variables(void)
@@ -279,7 +274,7 @@ add_variable(struct arguments ** list, struct variable * var, struct variable *
    deletes the list as we go on.
  */
 static void
-dump_variables(struct arguments * list)
+dump_variables(struct arguments * list, int mode)
 {
     if (list == NULL)
     {
@@ -290,7 +285,7 @@ dump_variables(struct arguments * list)
        end of the list:
      */
 
-    dump_variables(list->next);
+    dump_variables(list->next, mode);
 
     /* Then the current element and its indicator */
     ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
@@ -298,7 +293,8 @@ dump_variables(struct arguments * list)
    (list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
 
     /* Then release the list element. */
-    free(list);
+    if (mode != 0)
+       free(list);
 }
 
 static void
@@ -494,9 +490,9 @@ output_statement(char * stmt, int mode)
    fputs("\", ", yyout);
 
    /* dump variables to C file*/
-   dump_variables(argsinsert);
+   dump_variables(argsinsert, 1);
    fputs("ECPGt_EOIT, ", yyout);
-   dump_variables(argsresult);
+   dump_variables(argsresult, 1);
    fputs("ECPGt_EORT);", yyout);
    whenever_action(mode);
    free(stmt);
@@ -737,10 +733,9 @@ stmt:  AddAttrStmt         { output_statement($1, 0); }
        | RenameStmt        { output_statement($1, 0); }
        | RevokeStmt        { output_statement($1, 0); }
                 | OptimizableStmt  {
-                       if (strncmp($1, "ECPGdeclare" , sizeof("ECPGdeclare")-1) == 0)
+                       if (strncmp($1, "/* " , sizeof("/* ")-1) == 0)
                        {
                            fputs($1, yyout);
-                           whenever_action(0);
                            free($1);
                        }
                        else
@@ -775,7 +770,27 @@ stmt:  AddAttrStmt         { output_statement($1, 0); }
                        whenever_action(0);
                        free($1);
                    }
-       | ECPGOpen      {   fprintf(yyout, "ECPGopen(__LINE__, %s);", $1);
+       | ECPGOpen      {   
+                       struct cursor *ptr;
+                        
+                       for (ptr = cur; ptr != NULL; ptr=ptr->next)
+                       {
+                                  if (strcmp(ptr->name, $1) == 0)
+                                   break;
+                       }
+                       
+                       if (ptr == NULL)
+                       {
+                           sprintf(errortext, "trying to open undeclared cursor %s\n", $1);
+                           yyerror(errortext);
+                       }
+                  
+                       fprintf(yyout, "ECPGdo(__LINE__, \"%s\",", ptr->command);
+                       /* dump variables to C file*/
+                       dump_variables(ptr->argsinsert, 0);
+                       fputs("ECPGt_EOIT, ", yyout);
+                       dump_variables(ptr->argsresult, 0);
+                       fputs("ECPGt_EORT);", yyout);
                        whenever_action(0);
                        free($1);
                    }
@@ -2359,7 +2374,31 @@ CursorStmt:  DECLARE name opt_binary CURSOR FOR
             group_clause having_clause
             union_clause sort_clause
                {
-                   $$ = make5_str(make1_str("ECPGdeclare(__LINE__, \""), $2, make1_str("\", \""), cat4_str(cat5_str(cat5_str(make1_str("declare"), strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14), make1_str("\");"));
+                   struct cursor *ptr, *this;
+   
+                   for (ptr = cur; ptr != NULL; ptr = ptr->next)
+                   {
+                       if (strcmp($2, ptr->name) == 0)
+                       {
+                               /* re-definition is a bug*/
+                           sprintf(errortext, "cursor %s already defined", $2);
+                           yyerror(errortext);
+                               }
+                       }
+                        
+                       this = (struct cursor *) mm_alloc(sizeof(struct cursor));
+
+                       /* initial definition */
+                       this->next = cur;
+                       this->name = $2;
+                       this->command = cat4_str(cat5_str(cat5_str(make1_str("declare"), strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14);
+                   this->argsinsert = argsinsert;
+                   this->argsresult = argsresult;
+                   argsinsert = argsresult = NULL;
+                                           
+                       cur = this;
+                   
+                   $$ = cat3_str(make1_str("/*"), strdup(this->command), make1_str("*/"));
                }
        ;
 
@@ -4221,7 +4260,7 @@ execstring: cvariable |
  * open is an open cursor, at the moment this has to be removed
  */
 ECPGOpen: SQL_OPEN name open_opts {
-       $$ = make3_str(make1_str("\""), $2, make1_str("\""));
+       $$ = $2;
 };
 
 open_opts: /* empty */     { $$ = make1_str(""); }
index 8a7f1f69df49273fdbfca3c0a6a076c224422ea2..4e19502fca9705f9b125fa2948968a8489bc26ac 100644 (file)
@@ -1,6 +1,6 @@
 all: test1 test2 perftest
 
-LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt --static
+LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt
 
 test1: test1.c
 test1.c: test1.pgc
index 1506dd7bfa9b1fda9d323ca0878ab6b0eddde28b..89d938730b801b6fece3a79dd5b0d11731e198f5 100644 (file)
@@ -19,6 +19,10 @@ exec sql begin declare section;
    long ind_married;
    char married[9];
 exec sql end declare section;
+
+exec sql declare cur cursor for
+       select name, born, age, married from meskes;
+
    char msg[128], command[128];
    FILE *dbgs;
 
@@ -26,7 +30,7 @@ exec sql end declare section;
                 ECPGdebug(1, dbgs);
 
    strcpy(msg, "connect");
-   exec sql connect to tcp:postgresql://localhost:5432/mm;
+   exec sql connect to tcp:postgresql://localhost:5432/mm; 
 
    strcpy(msg, "create");
    exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
@@ -41,10 +45,6 @@ exec sql end declare section;
    strcpy(msg, "commit");
    exec sql commit;
 
-   strcpy(msg, "declare");
-   exec sql declare cur cursor for
-                select name, born, age, married from meskes;
-
    strcpy(msg, "open");
    exec sql open cur;