- Fixed indicator in SET DESCRIPTOR.
authorMichael Meskes <meskes@postgresql.org>
Mon, 5 Jul 2004 09:45:54 +0000 (09:45 +0000)
committerMichael Meskes <meskes@postgresql.org>
Mon, 5 Jul 2004 09:45:54 +0000 (09:45 +0000)
- Added special handling of descriptor header information.
- Some code cleanup.

src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/ecpglib/descriptor.c
src/interfaces/ecpg/ecpglib/execute.c
src/interfaces/ecpg/include/ecpglib.h
src/interfaces/ecpg/preproc/descriptor.c
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/test/test_desc.pgc

index 888dd73bc841bdba55ecfd3e0265b048d549bab9..e6d8a0098e0e286fe97bb96e7c992cde0de4a257 100644 (file)
@@ -1834,6 +1834,13 @@ Wed Jun 30 16:56:32 CEST 2004
 Sun Jul  4 16:53:53 CEST 2004
 
    - Made sure SET DESCRIPTOR accepts all data types including constants.
+   - Some code cleanup.
+   
+Mon,  5 Jul 2004 10:41:54 +0200
+
+   - Fixed indicator in SET DESCRIPTOR.
+   - Added special handling of descriptor header information.
+   - More code cleanup.
    - Set pgtypes library version to 1.2.
    - Set ecpg version to 3.2.0.
    - Set compat library version to 1.2.
index e653203f89b39dcd9546c17cff7a333923d3bd0e..bc56b0222bc47e730e00934d74a3efe7d9209a16 100644 (file)
@@ -1,6 +1,6 @@
 /* dynamic SQL support routines
  *
- * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.10 2004/07/04 15:02:22 meskes Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.11 2004/07/05 09:45:53 meskes Exp $
  */
 
 #define POSTGRES_ECPG_INTERNAL
@@ -430,6 +430,27 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
    return (true);
 }
 
+bool
+ECPGset_desc_header(int lineno, char *desc_name, int count)
+{
+   struct descriptor *desc;
+   
+   for (desc = all_descriptors; desc; desc = desc->next)
+   {
+       if (strcmp(desc_name, desc->name)==0)
+           break;
+   }
+
+   if (desc == NULL)
+   {
+       ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
+       return false;
+   }
+
+   desc->count = count;
+   return true;
+}
+
 bool
 ECPGset_desc(int lineno, char *desc_name, int index,...)
 {
@@ -581,6 +602,7 @@ ECPGallocate_desc(int line, const char *name)
        ECPGfree(new);
        return false;
    }
+   new->count = -1;
    new->items = NULL;
    new->result = PQmakeEmptyPGresult(NULL, 0);
    if (!new->result)
index 6464ecb4b322a7270d7896daf1d26bd572f21059..a3a601aed52b1d936b806f292a10811ec40e2177 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.36 2004/07/04 15:02:22 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.37 2004/07/05 09:45:53 meskes Exp $ */
 
 /*
  * The aim is to get a simpler inteface to the database routines.
@@ -1080,6 +1080,7 @@ ECPGexecute(struct statement * stmt)
        int    hostvarl = 0;
 
        tobeinserted = NULL;
+       
        /* A descriptor is a special case since it contains many variables but is listed only once. */
        if (var->type == ECPGt_descriptor)
        {
@@ -1100,28 +1101,43 @@ ECPGexecute(struct statement * stmt)
            }
            
            desc_counter++;
-           for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
+           if (desc->count < 0 || desc->count >= desc_counter)
            {
-               if (desc_item->num == desc_counter)
+               for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
                {
-                   desc_inlist.type = ECPGt_char;
-                   desc_inlist.value = desc_item->data;
-                   desc_inlist.pointer = &(desc_item->data);
-                   desc_inlist.varcharsize = strlen(desc_item->data);
-                   desc_inlist.arrsize = 1;
-                   desc_inlist.offset = 0;
-                   desc_inlist.ind_type = ECPGt_NO_INDICATOR;
-                   desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
-                   desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
-
-                   if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, &malloced))
-                       return false;
-                   
-                   break;
+                   if (desc_item->num == desc_counter)
+                   {
+                       desc_inlist.type = ECPGt_char;
+                       desc_inlist.value = desc_item->data;
+                       desc_inlist.pointer = &(desc_item->data);
+                       desc_inlist.varcharsize = strlen(desc_item->data);
+                       desc_inlist.arrsize = 1;
+                       desc_inlist.offset = 0;
+                       if (!desc_item->indicator)
+                       {
+                           desc_inlist.ind_type = ECPGt_NO_INDICATOR;
+                           desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
+                           desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
+                       }
+                       else
+                       {
+                           desc_inlist.ind_type = ECPGt_int;
+                           desc_inlist.ind_value = &(desc_item->indicator);
+                           desc_inlist.ind_pointer = &(desc_inlist.ind_value);
+                           desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
+                           desc_inlist.ind_offset = 0;
+                       }
+                       if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, &malloced))
+                           return false;
+                       
+                       break;
+                   }
                }
-           }
 
-           if (!desc_item) /* no more entries found in descriptor */
+               if (!desc_item) /* no more entries found in descriptor */
+                   desc_counter = 0;
+           }
+           else
                desc_counter = 0;
        }
        else
@@ -1129,6 +1145,7 @@ ECPGexecute(struct statement * stmt)
            if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, &malloced))
                return false;
        }
+       
        if (tobeinserted)
        {
            /*
index 778104a27b22e39ab905cda1199b5d021d48dbac..6145e79cb4df05910ed0cd711a3335ff85e5d83f 100644 (file)
@@ -77,7 +77,7 @@ void      ECPGraise(int line, int code, const char *sqlstate, const char *str);
 void       ECPGraise_backend(int line, PGresult *result, PGconn *conn, int compat);
 bool       ECPGget_desc_header(int, char *, int *);
 bool       ECPGget_desc(int, char *, int,...);
-bool       ECPGset_desc_header(int, char *, int *);
+bool       ECPGset_desc_header(int, char *, int);
 bool       ECPGset_desc(int, char *, int,...);
 
 void       ECPGset_noind_null(enum ECPGttype, void *);
index 6861a91dc7fb8fc0443c65983b8503172f74c582..43193364b474250d70d025d514c9740cdfc207aa 100644 (file)
@@ -55,6 +55,7 @@ ECPGnumeric_lvalue(FILE *f, char *name)
        case ECPGt_unsigned_int:
        case ECPGt_unsigned_long:
        case ECPGt_unsigned_long_long:
+       case ECPGt_const:
            fputs(name, yyout);
            break;
        default:
@@ -198,7 +199,7 @@ output_set_descr_header(char *desc_name)
 {
    struct assignment *results;
 
-   fprintf(yyout, "{ ECPGset_desc_header(__LINE__, %s, &(", desc_name);
+   fprintf(yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
    for (results = assignments; results != NULL; results = results->next)
    {
        if (results->value == ECPGd_count)
index e1dab2b72e8a0b8e3e069ee74afba20a5c723af0..3c10072f6860fd790b4a0b54f937927068e6c036 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.291 2004/07/04 15:02:23 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.292 2004/07/05 09:45:53 meskes Exp $ */
 
 /* Copyright comment */
 %{
@@ -522,7 +522,7 @@ add_additional_variables(char *name, bool insert)
 %type  <str>   select_limit opt_for_update_clause CheckPointStmt
 %type  <str>   OptSchemaName OptSchemaEltList schema_stmt opt_drop_behavior
 %type  <str>   handler_name any_name_list any_name opt_as insert_column_list
-%type  <str>   columnref function_name insert_target_el
+%type  <str>   columnref function_name insert_target_el AllConstVar
 %type  <str>   insert_target_list insert_column_item DropRuleStmt
 %type  <str>   createfunc_opt_item set_rest var_list_or_default
 %type  <str>   CreateFunctionStmt createfunc_opt_list func_table
@@ -4207,7 +4207,7 @@ IntConst: PosIntConst     { $$ = $1; }
 IntConstVar:   Iconst  
        {
                char *length = mm_alloc(32);
-           
+
            sprintf(length, "%d", (int) strlen($1));
            new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0);
            $$ = $1;
@@ -4215,6 +4215,45 @@ IntConstVar: Iconst
        | cvariable { $$ = $1; }
        ;
 
+AllConstVar:   Fconst
+       {
+               char *length = mm_alloc(32);
+           
+           sprintf(length, "%d", (int) strlen($1));
+           new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0);
+           $$ = $1;
+       }
+       | IntConstVar       { $$ = $1; }
+       | '-' Fconst
+       {
+               char *length = mm_alloc(32);
+           char *var = cat2_str(make_str("-"), $2);
+           
+           sprintf(length, "%d", (int) strlen(var));
+           new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
+           $$ = var;
+       }
+       | '-' Iconst
+       {
+               char *length = mm_alloc(32);
+           char *var = cat2_str(make_str("-"), $2);
+           
+           sprintf(length, "%d", (int) strlen(var));
+           new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
+           $$ = var;
+       }
+       | Sconst        
+       {
+               char *length = mm_alloc(32);
+           char *var = $1 + 1;
+           
+           var[strlen(var) - 1] = '\0';
+           sprintf(length, "%d", (int) strlen(var));
+           new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
+           $$ = var;
+       }
+       ;
+
 StringConst:   Sconst      { $$ = $1; }
        | civar     { $$ = $1; }
        ;
@@ -5375,7 +5414,7 @@ ECPGSetDescItems: ECPGSetDescItem
        | ECPGSetDescItems ',' ECPGSetDescItem
        ;
 
-ECPGSetDescItem: descriptor_item '=' IntConstVar
+ECPGSetDescItem: descriptor_item '=' AllConstVar
        {
            push_assignment($3, $1);
        }
index aee30bc59f344cf1b717104176d9240cb2d22faa..7d4854cfdf2ad04e60fa05d397851b8e9559c9f6 100644 (file)
@@ -6,11 +6,12 @@ main()
    EXEC SQL BEGIN DECLARE SECTION;
    char *stmt1 = "INSERT INTO test1 VALUES (?, ?)";
    char *stmt2 = "SELECT * from test1 where a = ? and b = ?";
+   char *stmt3 = "SELECT * from test1 where a = ?";
 
    int val1 = 1;
    char val2[] = "one", val2output[] = "AAA";
    int val1output = 2, val2i = 0;
-   int val2null = 1;
+   int val2null = -1;
    EXEC SQL END DECLARE SECTION;
    FILE *dbgs;
 
@@ -28,6 +29,7 @@ main()
    EXEC SQL CREATE TABLE test1 (a int, b text);
    EXEC SQL PREPARE foo1 FROM :stmt1;
    EXEC SQL PREPARE foo2 FROM :stmt2;
+   EXEC SQL PREPARE foo3 FROM :stmt3;
 
    EXEC SQL EXECUTE foo1 USING DESCRIPTOR indesc;
 
@@ -44,16 +46,27 @@ main()
    EXEC SQL GET DESCRIPTOR outdesc VALUE 1 :val2output = DATA;
    printf("output = %s\n", val2output);
    
-   EXEC SQL DECLARE c CURSOR FOR foo2;
-   EXEC SQL OPEN c USING DESCRIPTOR indesc;
+   EXEC SQL DECLARE c1 CURSOR FOR foo2;
+   EXEC SQL OPEN c1 USING DESCRIPTOR indesc;
 
-   EXEC SQL FETCH next FROM c INTO :val1output, :val2output;
+   EXEC SQL FETCH next FROM c1 INTO :val1output, :val2output;
    printf("val1=%d val2=%s\n", val1output, val2output);
 
-   EXEC SQL CLOSE c;
+   EXEC SQL CLOSE c1;
+
+   EXEC SQL SET DESCRIPTOR indesc COUNT = 1;
+   EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2;
    
-   EXEC SQL SELECT * INTO :val1output, :val2output FROM test1 where a = 2;
-   printf("val1=%d val2=%s\n", val1output, val2output);
+   EXEC SQL DECLARE c2 CURSOR FOR foo3;
+   EXEC SQL OPEN c2 USING DESCRIPTOR indesc;
+
+   EXEC SQL FETCH next FROM c2 INTO :val1output, :val2output :val2i;
+   printf("val1=%d val2=%s\n", val1output, val2i ? "null" : val2output);
+
+   EXEC SQL CLOSE c2;
+   
+   EXEC SQL SELECT * INTO :val1output, :val2output :val2i FROM test1 where a = 2;
+   printf("val1=%d val2=%s\n", val1output, val2i ? "null" : val2output);
    
    EXEC SQL DROP TABLE test1;
    EXEC SQL DISCONNECT;