BUG #15176: ecpg generation error - Mailing list pgsql-bugs

From PG Bug reporting form
Subject BUG #15176: ecpg generation error
Date
Msg-id 152468741102.19805.13932148777494153815@wrigleys.postgresql.org
Whole thread Raw
Responses Re: BUG #15176: ecpg generation error
List pgsql-bugs
The following bug has been logged on the website:

Bug reference:      15176
Logged by:          Uwe Höppner
Email address:      uhoeppner@psi.de
PostgreSQL version: 10.3
Operating system:   PostgreSQL 10.3, compiled by Visual C++ build 180
Description:

Hello,
we are very happy, that PostgreSQL exists as an alternative and we want to
migrate to postgresql and try to use ecpg to precompile our existing code to
produce c-Code to access our pg-database. But the generated code does not
compile. We tested with Microsoft Visual Studio Professional 2015, Version
14.

Our C++ applications have a lot of embedded SQL, so it is not possible to
change fast to other frameworks.

The main problem arises, when we use structs with VARCHAR elements.

an example-table:
CREATE TABLE public.test_ta
(
    bb double precision,
    ii integer,
    nname character varying(80)
)
WITH (
    OIDS = FALSE
);

ALTER TABLE public.test_ta
    OWNER to postgres;

----------------------------------------------------------------------------------------------------------
pgc-Code snippet start:
int fkt1()
{

 EXEC SQL BEGIN DECLARE SECTION;
  struct a_t
  {
    double b;
    int i;
    VARCHAR name[180];
  };
  struct a_ind_t
  {
    short b;
    short i;
    short name;
  };
  struct a_t a_var;
  struct a_ind_t a_ind_var;

  EXEC SQL END DECLARE SECTION;
  EXEC SQL SELECT bb,ii, nname INTO :a_var:a_ind_var FROM test_ta;
pgc-code snippet stop

--------------------------------------------------------------------------------------------------------------------------
ecpg generates the following output:
int fkt1()
{
  /* exec sql begin declare section */
   
  
     
     
(yes, these empty lines are produced    by ecpg :-) )
  

   
  
     
     
     
  

    
    

  struct a_t { 
#line 37 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
 double b ;
 
#line 38 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
 int i ;
 
#line 39 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
  struct varchar_1  { int len; char arr[ 180 ]; }  name ;
 } ; struct a_ind_t { 
#line 44 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
 short b ;
 
#line 45 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
 short i ;
 
#line 46 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
 short name ;
 } ; 
#line 49 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
 struct a_t a_var ;
 
#line 50 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"
 struct a_ind_t a_ind_var ;
/* exec sql end declare section */
#line 52 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"


  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select bb , ii , nname
from test_ta", ECPGt_EOIT, 
    ECPGt_double,&(a_var.b),(long)1,(long)1,sizeof( struct a_t ), 
    ECPGt_short,&(a_ind_var.b),(long)1,(long)1,sizeof( struct a_ind_t ), 
    ECPGt_int,&(a_var.i),(long)1,(long)1,sizeof( struct a_t ), 
    ECPGt_short,&(a_ind_var.i),(long)1,(long)1,sizeof( struct a_ind_t ), 
    ECPGt_varchar,&(a_var.name),(long)180,(long)1,sizeof( struct a_t ), 
    ECPGt_short,&(a_ind_var.name),(long)1,(long)1,sizeof( struct a_ind_t ),
ECPGt_EORT);}
#line 54 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"

--------------------------------------------------------------------------------------------------------------------------
For select statements the generated code compiles, but IMO, the parameters
of all sizeof() calls are wrong. I would expect code like this:

  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select bb , ii , nname
from test_ta", ECPGt_EOIT, 
    ECPGt_double,&(a_var.b),(long)1,(long)1,sizeof(a_var.b),
    ECPGt_short,&(a_ind_var.b),(long)1,(long)1,sizeof(a_ind_var.b),
    ECPGt_int,&(a_var.i),(long)1,(long)1,sizeof(a_var.i),
    ECPGt_short,&(a_ind_var.i),(long)1,(long)1,sizeof(a_ind_var.i),
    ECPGt_varchar,&(a_var.name),(long)180,(long)1,sizeof(a_var.name),
    ECPGt_short,&(a_ind_var.name),(long)1,(long)1,sizeof(a_ind_var.name),
ECPGt_EORT);}

--------------------------------------------------------------------------------------------------------------------------

The result is even worse, if you try to insert into the database.
the pgc-code:
  a_var.b = 1.0;
  a_var.i = 2;
  //a_var.name is empty

  EXEC SQL INSERT INTO test_ta(bb,ii,nname) VALUES(:a_var.b, :a_var.i,
:a_var.name);

pgc-code stop

--------------------------------------------------------------------------------------------------------------------------
ecpg generates the following output:
  a_var.b = 1.0;
  a_var.i = 2;
  //a_var.name is empty

  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into test_ta ( bb
, ii , nname ) values ( $1  , $2  , $3  )", 
    ECPGt_double,&(a_var.b),(long)1,(long)1,sizeof(double), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
    ECPGt_int,&(a_var.i),(long)1,(long)1,sizeof(int), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
    ECPGt_varchar,&(a_var.name),(long)180,(long)1,sizeof(struct varchar_1), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 62 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"

--------------------------------------------------------------------------------------------------------------------------
This code does not compile!

If you look to #line 39 you can see the definition of struct varchar_1
inside of struct a_t in function fkt1. So this results in the following
error message:

1>d:\dev\ems\master\src\db\bdp\app\pgtest\ctestapp.pc(67): error C2027:
Verwendung des undefinierten Typs "fkt1::varchar_1"
varchar_1 is unknown.

After manual correction it compiles:
  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into test_ta ( bb
, ii , nname ) values ( $1  , $2  , $3  )", 
    ECPGt_double,&(a_var.b),(long)1,(long)1,sizeof(double), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
    ECPGt_int,&(a_var.i),(long)1,(long)1,sizeof(int), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
/*    ECPGt_varchar,&(a_var.name),(long)180,(long)1,sizeof(struct varchar_1),
wrong generated */
/*    ECPGt_varchar,&(a_var.name),(long)180,(long)1,sizeof(struct
a_t::varchar_1), also okay */
    ECPGt_varchar, &(a_var.name), (long)180, (long)1, sizeof(a_var.name), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 62 "D:/dev/ems/master/src/db/bdp/app/pgtest/CTestApp.pc"

I would prefer the variant with use of the variable over the variant with
the type. Both seem ok.

Could you please repair ecpg, so it generates code, that compiles. :-)

Cheers, 
Uwe


pgsql-bugs by date:

Previous
From: PG Bug reporting form
Date:
Subject: BUG #15175: Stack Builder no descarga postgis 2.4
Next
From: jake
Date:
Subject: Re: BUG #15168: "pg_isready -d" effectively ignores given databasename