BUG #15176: ecpg generation error

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: uhoeppner(at)psi(dot)de
Subject: BUG #15176: ecpg generation error
Date: 2018-04-25 20:16:51
Message-ID: 152468741102.19805.13932148777494153815@wrigleys.postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 15176
Logged by: Uwe Höppner
Email address: uhoeppner(at)psi(dot)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

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message jake 2018-04-25 21:56:00 Re: BUG #15168: "pg_isready -d" effectively ignores given database name
Previous Message PG Bug reporting form 2018-04-25 19:01:27 BUG #15175: Stack Builder no descarga postgis 2.4