Re: DECLARE doesn't set/reset sqlca after DECLARE cursor - Mailing list pgsql-hackers

From Boszormenyi Zoltan
Subject Re: DECLARE doesn't set/reset sqlca after DECLARE cursor
Date
Msg-id 4A843789.2050202@cybertec.at
Whole thread Raw
In response to Re: DECLARE doesn't set/reset sqlca after DECLARE cursor  (Michael Meskes <meskes@postgresql.org>)
Responses Re: DECLARE doesn't set/reset sqlca after DECLARE cursor  (Michael Meskes <meskes@postgresql.org>)
List pgsql-hackers
Michael Meskes írta:
> On Wed, Aug 12, 2009 at 07:13:44PM +0200, Boszormenyi Zoltan wrote:
>
>> a customer of us complained a behavioural difference
>> ...
>> The attached patch implements this. The only downside
>> is that now DECLARE CURSOR cannot appear outside
>> of a function, a change in test/preproc/variable.pgc reflects
>>
>
> DECLARE by definition is a declarative command and as such should be able to
> live outside a function.
>

Okay, so it's a declarative command. But if we're in a function,
we should still emit a call to ecpg_init, to be able to follow
the Informix behaviour. We can limit it it compat mode, though.
The attached patch does this, and detects being inside of a function
by braces_open > 0. Short of rewriting ECPG into a flull-fledged
C/C++ preprocessor, we can't do better currently.

In compat mode, you cannot do
    DECLARE mycur CURSOR FOR SELECT ... INTO :var, ...
or
    DECLARE mycur CURSOR FOR SELECT ... WHERE field = ?
in the global scope because adjust_informix() emits function calls
outside of a function. Or is this declaration illegal?
At least it should be documented in PostgreSQL.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/

diff -dcrpN pgsql.describe/src/interfaces/ecpg/ecpglib/exports.txt
pgsql.declare-reset-sqlca/src/interfaces/ecpg/ecpglib/exports.txt
*** pgsql.describe/src/interfaces/ecpg/ecpglib/exports.txt    2008-03-25 13:58:49.000000000 +0100
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/ecpglib/exports.txt    2009-08-12 18:13:11.000000000 +0200
*************** ECPGstatus                       23
*** 26,28 ****
--- 26,29 ----
  ECPGtrans                        24
  sqlprint                         25
  ECPGget_PGconn             26
+ ECPGreset_sqlca             27
diff -dcrpN pgsql.describe/src/interfaces/ecpg/ecpglib/misc.c
pgsql.declare-reset-sqlca/src/interfaces/ecpg/ecpglib/misc.c
*** pgsql.describe/src/interfaces/ecpg/ecpglib/misc.c    2009-08-07 13:06:28.000000000 +0200
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/ecpglib/misc.c    2009-08-12 18:22:35.000000000 +0200
*************** ecpg_gettext(const char *msgid)
*** 489,491 ****
--- 489,499 ----
  }

  #endif   /* ENABLE_NLS */
+
+ bool
+ ECPGreset_sqlca(int lineno, const char *connection_name)
+ {
+     struct connection *con = ecpg_get_connection(connection_name);
+
+     return ecpg_init(con, connection_name, lineno);
+ }
diff -dcrpN pgsql.describe/src/interfaces/ecpg/include/ecpglib.h
pgsql.declare-reset-sqlca/src/interfaces/ecpg/include/ecpglib.h
*** pgsql.describe/src/interfaces/ecpg/include/ecpglib.h    2009-08-11 14:34:03.000000000 +0200
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/include/ecpglib.h    2009-08-12 18:21:06.000000000 +0200
*************** bool        ECPGset_desc(int, const char *, in
*** 84,89 ****
--- 84,90 ----
  void        ECPGset_noind_null(enum ECPGttype, void *);
  bool        ECPGis_noind_null(enum ECPGttype, void *);
  bool        ECPGdescribe(int, bool, const char *, const char *, ...);
+ bool        ECPGreset_sqlca(int, const char *);

  /* dynamic result allocation */
  void        ECPGfree_auto_mem(void);
diff -dcrpN pgsql.describe/src/interfaces/ecpg/preproc/ecpg.addons
pgsql.declare-reset-sqlca/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.describe/src/interfaces/ecpg/preproc/ecpg.addons    2009-08-11 14:34:03.000000000 +0200
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/preproc/ecpg.addons    2009-08-13 17:40:41.000000000 +0200
*************** ECPG: DeclareCursorStmtDECLAREcursor_nam
*** 318,324 ****
          cur = this;

          if (INFORMIX_MODE)
!             $$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"),
mm_strdup(this->command),make_str("*/")); 
          else
              $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
      }
--- 318,338 ----
          cur = this;

          if (INFORMIX_MODE)
!         {
!             char *comment;
!             const char *con = connection ? connection : "NULL";
!
!             comment = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
!
!             if (braces_open > 0) /* we're in a function */
!             {
!                 char *command = (char *)mm_alloc(sizeof("ECPGreset_sqlca(__LINE__, );") + strlen(con));
!                 sprintf(command, "ECPGreset_sqlca(__LINE__, %s);", con);
!                 $$ = cat_str(4, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), command,
comment);
!             }
!             else
!                 $$ = cat_str(3, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), comment);
!         }
          else
              $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
      }
diff -dcrpN pgsql.describe/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql.declare-reset-sqlca/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql.describe/src/interfaces/ecpg/preproc/ecpg.trailer    2009-08-11 17:18:31.000000000 +0200
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/preproc/ecpg.trailer    2009-08-13 17:48:27.000000000 +0200
*************** ECPGCursorStmt:  DECLARE cursor_name cur
*** 356,362 ****
              add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
              cur = this;

!             $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
          }
          ;

--- 356,374 ----
              add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
              cur = this;

!             if (INFORMIX_MODE)
!             {
!                 if (braces_open > 0) /* we're in a function */
!                 {
!                     char *command = (char *)mm_alloc(sizeof("ECPGreset_sqlca(__LINE__, );") + strlen(con));
!                     sprintf(command, "ECPGreset_sqlca(__LINE__, %s);", con);
!                     $$ = cat_str(4, command, make_str("/*"), mm_strdup(this->command), make_str("*/"));
!                 }
!                 else
!                     $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
!             }
!             else
!                 $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
          }
          ;

diff -dcrpN pgsql.describe/src/interfaces/ecpg/test/expected/compat_informix-cursor.c
pgsql.declare-reset-sqlca/src/interfaces/ecpg/test/expected/compat_informix-cursor.c
*** pgsql.describe/src/interfaces/ecpg/test/expected/compat_informix-cursor.c    2009-08-10 18:06:56.000000000 +0200
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/test/expected/compat_informix-cursor.c    2009-08-13
17:00:25.000000000+0200 
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 156,162 ****

      strcpy(msg, "declare");
      ECPG_informix_set_var( 0, &( curname1 ), __LINE__);\
!  /* declare $0 cursor for select id , t from t1 */
  #line 59 "cursor.pgc"


--- 156,162 ----

      strcpy(msg, "declare");
      ECPG_informix_set_var( 0, &( curname1 ), __LINE__);\
!  ECPGreset_sqlca(__LINE__, NULL); /* declare $0 cursor for select id , t from t1 */
  #line 59 "cursor.pgc"


*************** if (sqlca.sqlcode < 0) exit (1);}
*** 292,298 ****
      ECPG_informix_set_var( 3, &( curname2 ), __LINE__);\
   ECPG_informix_set_var( 1, ( t ), __LINE__);\
   ECPG_informix_set_var( 2, &( id ), __LINE__);\
!  /* declare $0 cursor for select id , t from t1 */
  #line 100 "cursor.pgc"


--- 292,298 ----
      ECPG_informix_set_var( 3, &( curname2 ), __LINE__);\
   ECPG_informix_set_var( 1, ( t ), __LINE__);\
   ECPG_informix_set_var( 2, &( id ), __LINE__);\
!  ECPGreset_sqlca(__LINE__, NULL); /* declare $0 cursor for select id , t from t1 */
  #line 100 "cursor.pgc"


*************** if (sqlca.sqlcode < 0) exit (1);}
*** 441,447 ****


      strcpy(msg, "declare");
!     /* declare $0 cursor for $1 */
  #line 143 "cursor.pgc"


--- 441,447 ----


      strcpy(msg, "declare");
!     ECPGreset_sqlca(__LINE__, NULL); /* declare $0 cursor for $1 */
  #line 143 "cursor.pgc"


*************** if (sqlca.sqlcode < 0) exit (1);}
*** 596,602 ****


      strcpy(msg, "declare");
!     /* declare $0 cursor for $1 */
  #line 193 "cursor.pgc"


--- 596,602 ----


      strcpy(msg, "declare");
!     ECPGreset_sqlca(__LINE__, NULL); /* declare $0 cursor for $1 */
  #line 193 "cursor.pgc"


diff -dcrpN pgsql.describe/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
pgsql.declare-reset-sqlca/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
*** pgsql.describe/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c    2009-08-11 14:24:20.000000000 +0200
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c    2009-08-13
17:00:25.000000000+0200 
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 291,297 ****


      strcpy(msg, "declare");
!     /* declare mycur1 cursor for $1 */
  #line 100 "sqlda.pgc"


--- 291,297 ----


      strcpy(msg, "declare");
!     ECPGreset_sqlca(__LINE__, NULL); /* declare mycur1 cursor for $1 */
  #line 100 "sqlda.pgc"


*************** if (sqlca.sqlcode < 0) exit (1);}
*** 366,372 ****


      strcpy(msg, "declare");
!     /* declare mycur2 cursor for $1 */
  #line 137 "sqlda.pgc"


--- 366,372 ----


      strcpy(msg, "declare");
!     ECPGreset_sqlca(__LINE__, NULL); /* declare mycur2 cursor for $1 */
  #line 137 "sqlda.pgc"


diff -dcrpN pgsql.describe/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c
pgsql.declare-reset-sqlca/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c
*** pgsql.describe/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c    2009-08-09 22:00:45.000000000
+0200
--- pgsql.declare-reset-sqlca/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c    2009-08-13
17:00:26.000000000+0200 
*************** if (sqlca.sqlcode < 0) dosqlprint ( );}
*** 147,153 ****


      ECPG_informix_set_var( 0, &( i ), __LINE__);\
!  /* declare c cursor for select * from test where i <= $1  */
  #line 48 "test_informix.pgc"

      openit();
--- 147,153 ----


      ECPG_informix_set_var( 0, &( i ), __LINE__);\
!  ECPGreset_sqlca(__LINE__, NULL); /* declare c cursor for select * from test where i <= $1  */
  #line 48 "test_informix.pgc"

      openit();

pgsql-hackers by date:

Previous
From: "Kevin Grittner"
Date:
Subject: Re: Hot standby and synchronous replication status
Next
From: Hitoshi Harada
Date:
Subject: Re: Implementation of GROUPING SETS (T431: Extended grouping capabilities)