- Issue a warning if a cursor is declared but not opened.
authorMichael Meskes
Wed, 28 Jan 2004 09:52:14 +0000 (09:52 +0000)
committerMichael Meskes
Wed, 28 Jan 2004 09:52:14 +0000 (09:52 +0000)
- Fixed prototype for ECPGprepared_statement to not moan about "const char"
- Fixed parsing of nested structures.
- Added option to parse header files.

src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/ecpglib/execute.c
src/interfaces/ecpg/ecpglib/prepare.c
src/interfaces/ecpg/include/ecpglib.h
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/preproc/type.c
src/interfaces/ecpg/preproc/type.h
src/interfaces/ecpg/preproc/variable.c

index df608d25cf7311764bc7620f2b80a1dae5ae1304..576e6ee03a53e7fdff129bcfd19e7aee8e05ec6f 100644 (file)
@@ -1728,3 +1728,11 @@ Wed Dec 17 16:11:16 CET 2003
    - Set pgtypes library to 1.1.0
    - Set compat library to 1.1.0
 
+Mon Jan 26 21:57:14 CET 2004
+
+   - Issue a warning if a cursor is declared but not opened.
+   - Fixed prototype for ECPGprepared_statement to not moan about "const
+     char"
+   - Fixed parsing of nested structures.
+   - Added option to parse header files.
+
index e540f99e83f31bec5667388e107fb201584bcee4..758f878ff89a7e5861fefd487a66cf7549c1edd8 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.31 2004/01/07 18:56:29 neilc Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.32 2004/01/28 09:52:14 meskes Exp $ */
 
 /*
  * The aim is to get a simpler inteface to the database routines.
@@ -333,7 +333,7 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia
    }
    PQclear(query);
    ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
-   ECPGlog("ECPGexecute line %d: TYPE database: %d C: %d array: %d\n", stmt->lineno, type, var->type, isarray);
+   ECPGlog("ECPGis_type_an_array line %d: TYPE database: %d C: %d array: %d\n", stmt->lineno, type, var->type, isarray);
    return isarray;
 }
 
@@ -356,7 +356,7 @@ ECPGstore_result(const PGresult *results, int act_field,
         */
        if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
        {
-           ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
+           ECPGlog("ECPGstore_result line %d: Incorrect number of matches: %d don't fit into array of %d\n",
                    stmt->lineno, ntuples, var->arrsize);
            ECPGraise(stmt->lineno, INFORMIX_MODE(stmt->compat)?ECPG_INFORMIX_SUBSELECT_NOT_ONE:ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
            return false;
index b391327e090858bc3e991b09ccdac4dec0f004f7..9de1b9bfd8bcceec5e3b33701744e77959fc95f4 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.10 2003/11/29 19:52:08 pgsql Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.11 2004/01/28 09:52:14 meskes Exp $ */
 
 #define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
@@ -169,7 +169,7 @@ ECPGdeallocate_all(int lineno)
 
 /* return the prepared statement */
 char *
-ECPGprepared_statement(char *name)
+ECPGprepared_statement(const char *name)
 {
    struct prepared_statement *this;
 
index 317d35e329485eabb28a0baf6e6b997365a28e56..6f9938aaf0d1d14d1a5d83d8f6c3559570538a5d 100644 (file)
@@ -54,7 +54,7 @@ bool      ECPGprepare(int, char *, char *);
 bool       ECPGdeallocate(int, int, char *);
 bool       ECPGdeallocate_one(int, char *);
 bool       ECPGdeallocate_all(int);
-char      *ECPGprepared_statement(char *);
+char      *ECPGprepared_statement(const char *);
 
 void       ECPGlog(const char *format,...);
 char      *ECPGerrmsg(void);
index 3c6e1c31b3bcfec9b852e128450ed301f13e2f8a..e1c99de8d70bdee4a2387fe175c574850361a9c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.83 2003/12/18 18:55:09 petere Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.84 2004/01/28 09:52:14 meskes Exp $ */
 
 /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
 /* (C) Michael Meskes  Feb 5th, 1998 */
@@ -22,6 +22,7 @@ int           ret_value = 0,
            auto_create_c = false,
            system_includes = false,
            force_indicator = true;
+           header_mode = false;
 
 enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL;
 
@@ -47,6 +48,7 @@ help(const char *progname)
    printf("  -d             generate parser debug output\n");
 #endif
    printf("  -D SYMBOL      define SYMBOL\n");
+   printf("  -h             parse a header file, this option includes option \"-c\"\n");
    printf("  -i             parse system include files as well\n");
    printf("  -I DIRECTORY   search DIRECTORY for include files\n");
    printf("  -o OUTFILE     write result to OUTFILE\n");
@@ -136,7 +138,7 @@ main(int argc, char *const argv[])
        }
    }
 
-   while ((c = getopt(argc, argv, "vcio:I:tD:dC:r:")) != -1)
+   while ((c = getopt(argc, argv, "vcio:I:tD:dC:r:h")) != -1)
    {
        switch (c)
        {
@@ -160,6 +162,10 @@ main(int argc, char *const argv[])
            case 'v':
                verbose = true;
                break;
+           case 'h':
+               header_mode = true;
+               /* this must include "-c" to make sense */
+               /* so do not place a break; here */
            case 'c':
                auto_create_c = true;
                break;
@@ -259,11 +265,11 @@ main(int argc, char *const argv[])
                {
                    ptr2ext = input_filename + strlen(input_filename);
 
-                   /* no extension => add .pgc */
+                   /* no extension => add .pgc or .pgh */
                    ptr2ext[0] = '.';
                    ptr2ext[1] = 'p';
                    ptr2ext[2] = 'g';
-                   ptr2ext[3] = 'c';
+                   ptr2ext[3] = (header_mode == true)? 'h' : 'c';
                    ptr2ext[4] = '\0';
                }
 
@@ -279,8 +285,8 @@ main(int argc, char *const argv[])
                    output_filename = strdup(input_filename);
 
                    ptr2ext = strrchr(output_filename, '.');
-                   /* make extension = .c */
-                   ptr2ext[1] = 'c';
+                   /* make extension = .c resp. .h */
+                   ptr2ext[1] = (header_mode == true)? 'h' : 'c';
                    ptr2ext[2] = '\0';
 
                    yyout = fopen(output_filename, PG_BINARY_W);
@@ -383,17 +389,39 @@ main(int argc, char *const argv[])
                lex_init();
 
                /* we need several includes */
-               fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/* These include files are added by the preprocessor */\n#include \n#include \n#include \n#include \n#line 1 \"%s\"\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL, input_filename);
+               /* but not if we are in header mode */
+               fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
+               
+               if (header_mode == false)
+               {
+                   fprintf(yyout, "/* These include files are added by the preprocessor */\n#include \n#include \n#include \n#include \n");
 
-               /* add some compatibility headers */
-               if (INFORMIX_MODE)
-                   fprintf(yyout, "/* Needed for informix compatibility */\n#include \n");
+                   /* add some compatibility headers */
+                   if (INFORMIX_MODE)
+                       fprintf(yyout, "/* Needed for informix compatibility */\n#include \n");
 
-               fprintf(yyout, "/* End of automatic include section */\n");
+                   fprintf(yyout, "/* End of automatic include section */\n");
+               }
 
+               fprintf(yyout, "#line 1 \"%s\"\n", input_filename);
+               
                /* and parse the source */
                yyparse();
 
+               /* check if all cursors were indeed opened */
+               for (ptr = cur; ptr != NULL;)
+               {
+                   char errortext[128];
+                   
+                   if (!(ptr->opened))
+                   {
+                       /* Does not really make sense to declare a cursor but not open it */
+                       snprintf(errortext, sizeof(errortext), "cursor `%s´ has been declared but ot opened\n", ptr->name);
+                       mmerror(PARSE_ERROR, ET_WARNING, errortext);
+                   }
+                   ptr = ptr->next;
+               }
+               
                if (yyin != NULL && yyin != stdin)
                    fclose(yyin);
                if (out_option == 0 && yyout != stdout)
index 4d8e3b172636460a32faf8b784ae57114732e4d1..267950acf9002589af1bbbf8677b7b45b03d94a6 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.270 2004/01/21 14:09:34 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.271 2004/01/28 09:52:14 meskes Exp $ */
 
 /* Copyright comment */
 %{
@@ -778,6 +778,7 @@ stmt:  AlterDatabaseSetStmt     { output_statement($1, 0, connection); }
 
            if ((ptr = add_additional_variables($1, true)) != NULL)
                output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL);
+           ptr->opened = true;
        }
        | ECPGPrepare
        {
@@ -2780,6 +2781,7 @@ DeclareCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
            this->next = cur;
            this->name = $2;
            this->connection = connection;
+           this->opened = false;
            this->command =  cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7);
            this->argsinsert = argsinsert;
            this->argsresult = argsresult;
index e14321d54f93ef6aba3182816060aa85b3ec33a5..cb0eb2756673ebd1cf5ee57e0219c53b8dcc2bf7 100644 (file)
@@ -47,7 +47,11 @@ ECPGstruct_member_dup(struct ECPGstruct_member * rm)
                type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->struct_sizeof);
                break;
            case ECPGt_array:
-               type = ECPGmake_array_type(ECPGmake_simple_type(rm->type->u.element->type, rm->type->u.element->size), rm->type->size);
+               /* if this array does contain a struct again, we have to create the struct too */
+               if (rm->type->u.element->type == ECPGt_struct)
+                   type = ECPGmake_struct_type(rm->type->u.element->u.members, rm->type->u.element->type, rm->type->u.element->struct_sizeof);
+               else
+                   type = ECPGmake_array_type(ECPGmake_simple_type(rm->type->u.element->type, rm->type->u.element->size), rm->type->size);
                break;
            default:
                type = ECPGmake_simple_type(rm->type->type, rm->type->size);
index 2dd511ff854f284399082fc024e5f1b042e68382..a528b11040acfebd93916600e055ddec808cc918 100644 (file)
@@ -115,6 +115,7 @@ struct cursor
    char       *name;
    char       *command;
    char       *connection;
+   bool        opened;
    struct arguments *argsinsert;
    struct arguments *argsresult;
    struct cursor *next;
index be1cb5f0b74e960b75a27ef2d098e6d7ca23c4c3..2b98828c79c3d8157bbdb1c7be0942d1799ac4f9 100644 (file)
@@ -31,9 +31,11 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in
        c = *next;
        *next = '\0';
    }
+   printf("MM: Need to search for %s\n", str);
 
    for (; members; members = members->next)
    {
+       printf("MM: comparing %s\n§", members->name);
        if (strcmp(members->name, str) == 0)
        {
            if (next == NULL)
@@ -104,10 +106,11 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in
                        return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
                        break;
                    case '.':
-                       if (members->type->type != ECPGt_array)
+                       printf("MM: Now searching for %s \n", end);
+                       if (members->type->type == ECPGt_array)
                            return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
                        else
-                           return (find_struct_member(name, next, members->type->u.members, brace_level));
+                           return (find_struct_member(name, end, members->type->u.members, brace_level));
                        break;
                    default:
                        snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name);