By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,686 Members | 2,708 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,686 IT Pros & Developers. It's quick & easy.

I cannot compile embedded SQL in C++ programs with RHEL 3 ES.

P: n/a
I have some programs running on Red Hat Linux 7.3 working with IBM DB2
V6.1 (with all the FixPacks) on my old machine.

I have just installed IBM DB2 V8.1 on this (new) machine running Red Hat
Enterplise Linux 3 ES, and applied FixPack fp5_mi00069.tar to it. After
creating an instance, starting the database, creating a database, and
entering the table definitions, all of which seems to work OK, I entered a
tiny 8-row table and can do queries on it. So the server seems to be
working OK. BTW, I am running Personal Developers' Edition.

However, to go further I must be able to build my client programs to
populate the rest of the database and this requires I recompile my old RHL
7.3 programs that work with DB2 V6.1 to run on this RHEL 3 ES machine with
V8.1.5, and the C++ programs with embedded SQL in them do not compile. A
few of the statements compile, but the important ones do not.

E.g., here is the beginning of a constructor, for example:

dbBase:: // Custom constructor
dbBase(const string& db_name)
{
EXEC SQL BEGIN DECLARE SECTION; <---<<<
char dbName[DB_DB2N_SIZE + 1]; | "A"
EXEC SQL END DECLARE SECTION; <---<<<

_connected = false;
_dbName = "";

if(db_name.empty()) {
cerr << "dbBase(" << db_name << "): db_name missing." << endl;
exit(EXIT_FAILURE);
}
if(db_name.size() > DB_DB2N_SIZE) {
cerr << "dbBase(" << db_name << "): db_name too long." << endl;
exit(EXIT_FAILURE);
}
(void) strncpy(dbName, db_name.c_str(), DB_DB2N_SIZE);
dbName[DB_DB2N_SIZE] = EOS;

// Connect to database.
EXEC SQL CONNECT TO :dbName; <---<<< "B"

The stuff marked "A" goes right through the preprocessor and compiler,
but the line marked "B" chokes as follows:

dbBase.i: In constructor `dbBase::dbBase(const string&)':
dbBase.i:9122: `NULL' undeclared (first use this function)
dbBase.i:9122: (Each undeclared identifier is reported only once for each
function it appears in.)
make: *** [dbBase.o] Error 1

Here is dbBase.i line 9122"

EXEC SQL CONNECT TO :dbName;

I cannot go on until I fix this problem (that appears in almost every
function of this class, and I assume for all other classes as well.

In addition to this fatal error, I am getting lots of warning messages I
am not used to, such as:

/usr/bin/g++ -c -g -Wno-deprecated -mcpu=i686 -march=i686 -O2
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include
dbBase.CdbBase.C:4011: warning: `typename
__default_alloc_template<threads, inst>::_Obj
' is implicitly a typename
dbBase.C:5433: warning: `typename basic_string<charT, traits, Allocator>::Rep'
is implicitly a typename
dbBase.C:5607: warning: `typename basic_string<charT, traits,
Allocator>::size_type' is implicitly a typename

even though I include _-Wno-deprecated_ in the compiler command line. I
prefer not to include that, and would like that fixed too.

Since DB2 V8.1.5 is supposedly supported on RHEL 3, I would like to know
how to deal with this. If I need to include some new header flags, use
different flags for the compiler or something, I would be glad to do so
(easy in my makefiles).

I am annoyed that installing fp5_mi00069.tar deleted all the html
documentation from the system, but I put it back.

--
.~. Jean-David Beyer Registered Linux User 85642.
/V\ Registered Machine 241939.
/( )\ Shrewsbury, New Jersey http://counter.li.org
^^-^^ 21:05:00 up 9 days, 21:47, 7 users, load average: 4.08, 4.13, 4.10

Nov 12 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Jean-David Beyer wrote:
I have some programs running on Red Hat Linux 7.3 working with IBM DB2
V6.1 (with all the FixPacks) on my old machine.

I have just installed IBM DB2 V8.1 on this (new) machine running Red Hat
Enterplise Linux 3 ES, and applied FixPack fp5_mi00069.tar to it. After
creating an instance, starting the database, creating a database, and
entering the table definitions, all of which seems to work OK, I entered a
tiny 8-row table and can do queries on it. So the server seems to be
working OK. BTW, I am running Personal Developers' Edition.

However, to go further I must be able to build my client programs to
populate the rest of the database and this requires I recompile my old RHL
7.3 programs that work with DB2 V6.1 to run on this RHEL 3 ES machine with
V8.1.5, and the C++ programs with embedded SQL in them do not compile. A
few of the statements compile, but the important ones do not.

E.g., here is the beginning of a constructor, for example:

dbBase:: // Custom constructor
dbBase(const string& db_name)
{
You might want to include this:

EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION; <---<<<
char dbName[DB_DB2N_SIZE + 1]; | "A"
EXEC SQL END DECLARE SECTION; <---<<<

_connected = false;
_dbName = "";

if(db_name.empty()) {
cerr << "dbBase(" << db_name << "): db_name missing." << endl;
exit(EXIT_FAILURE);
}
if(db_name.size() > DB_DB2N_SIZE) {
cerr << "dbBase(" << db_name << "): db_name too long." << endl;
exit(EXIT_FAILURE);
}
(void) strncpy(dbName, db_name.c_str(), DB_DB2N_SIZE);
dbName[DB_DB2N_SIZE] = EOS;

// Connect to database.
EXEC SQL CONNECT TO :dbName; <---<<< "B"

The stuff marked "A" goes right through the preprocessor and compiler,
but the line marked "B" chokes as follows:

dbBase.i: In constructor `dbBase::dbBase(const string&)':
dbBase.i:9122: `NULL' undeclared (first use this function)
dbBase.i:9122: (Each undeclared identifier is reported only once for each
function it appears in.)
make: *** [dbBase.o] Error 1

Here is dbBase.i line 9122"

EXEC SQL CONNECT TO :dbName;

I cannot go on until I fix this problem (that appears in almost every
function of this class, and I assume for all other classes as well.
How exactly do you do the "precompile"?

I saw the same error once when I used the compiler's precompiler to resolve
macros in host variable definitions as you have. The precompiler will then
include <stdlib.h> and expand all macros, including the #define for NULL.
Later, the DB2 precompiler pastes some function calls into the generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.

It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).

Either way, I wouldn't use the compiler's precompiler because it garbles all
the line numbers (at the latest after the DB2 prep was ran) and debugging
this stuff will be a mess because the debugger has the incorrect line
information and just shows the wrong things when you step through the code.

For all my things, I wrote a small Perl script that replaces the macros in
the host variable definitions in a file with the extension .SQX, generates
a .SQC and that is given to DB2 prep to do its job.
In addition to this fatal error, I am getting lots of warning messages I
am not used to, such as:

/usr/bin/g++ -c -g -Wno-deprecated -mcpu=i686 -march=i686 -O2
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include
dbBase.CdbBase.C:4011: warning: `typename
__default_alloc_template<threads, inst>::_Obj
' is implicitly a typename
dbBase.C:5433: warning: `typename basic_string<charT, traits,
Allocator>::Rep'
is implicitly a typename
dbBase.C:5607: warning: `typename basic_string<charT, traits,
Allocator>::size_type' is implicitly a typename

even though I include _-Wno-deprecated_ in the compiler command line. I
prefer not to include that, and would like that fixed too.


I don't see why the warnings to show deprecated uses of functions would be
relevant to the warnings shown above. What's the code in line 5433 or 5607
where the compiler complains?

p.s: My experience is that newer compilers often raise new warnings/errors
because the old code is not as clean as it should have been.

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #2

P: n/a
Jean-David Beyer wrote:
I have some programs running on Red Hat Linux 7.3 working with IBM DB2
V6.1 (with all the FixPacks) on my old machine.

I have just installed IBM DB2 V8.1 on this (new) machine running Red Hat
Enterplise Linux 3 ES, and applied FixPack fp5_mi00069.tar to it. After
creating an instance, starting the database, creating a database, and
entering the table definitions, all of which seems to work OK, I entered a
tiny 8-row table and can do queries on it. So the server seems to be
working OK. BTW, I am running Personal Developers' Edition.

However, to go further I must be able to build my client programs to
populate the rest of the database and this requires I recompile my old RHL
7.3 programs that work with DB2 V6.1 to run on this RHEL 3 ES machine with
V8.1.5, and the C++ programs with embedded SQL in them do not compile. A
few of the statements compile, but the important ones do not.

E.g., here is the beginning of a constructor, for example:

dbBase:: // Custom constructor
dbBase(const string& db_name)
{
You might want to include this:

EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION; <---<<<
char dbName[DB_DB2N_SIZE + 1]; | "A"
EXEC SQL END DECLARE SECTION; <---<<<

_connected = false;
_dbName = "";

if(db_name.empty()) {
cerr << "dbBase(" << db_name << "): db_name missing." << endl;
exit(EXIT_FAILURE);
}
if(db_name.size() > DB_DB2N_SIZE) {
cerr << "dbBase(" << db_name << "): db_name too long." << endl;
exit(EXIT_FAILURE);
}
(void) strncpy(dbName, db_name.c_str(), DB_DB2N_SIZE);
dbName[DB_DB2N_SIZE] = EOS;

// Connect to database.
EXEC SQL CONNECT TO :dbName; <---<<< "B"

The stuff marked "A" goes right through the preprocessor and compiler,
but the line marked "B" chokes as follows:

dbBase.i: In constructor `dbBase::dbBase(const string&)':
dbBase.i:9122: `NULL' undeclared (first use this function)
dbBase.i:9122: (Each undeclared identifier is reported only once for each
function it appears in.)
make: *** [dbBase.o] Error 1

Here is dbBase.i line 9122"

EXEC SQL CONNECT TO :dbName;

I cannot go on until I fix this problem (that appears in almost every
function of this class, and I assume for all other classes as well.
How exactly do you do the "precompile"?

I saw the same error once when I used the compiler's precompiler to resolve
macros in host variable definitions as you have. The precompiler will then
include <stdlib.h> and expand all macros, including the #define for NULL.
Later, the DB2 precompiler pastes some function calls into the generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.

It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).

Either way, I wouldn't use the compiler's precompiler because it garbles all
the line numbers (at the latest after the DB2 prep was ran) and debugging
this stuff will be a mess because the debugger has the incorrect line
information and just shows the wrong things when you step through the code.

For all my things, I wrote a small Perl script that replaces the macros in
the host variable definitions in a file with the extension .SQX, generates
a .SQC and that is given to DB2 prep to do its job.
In addition to this fatal error, I am getting lots of warning messages I
am not used to, such as:

/usr/bin/g++ -c -g -Wno-deprecated -mcpu=i686 -march=i686 -O2
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include
dbBase.CdbBase.C:4011: warning: `typename
__default_alloc_template<threads, inst>::_Obj
' is implicitly a typename
dbBase.C:5433: warning: `typename basic_string<charT, traits,
Allocator>::Rep'
is implicitly a typename
dbBase.C:5607: warning: `typename basic_string<charT, traits,
Allocator>::size_type' is implicitly a typename

even though I include _-Wno-deprecated_ in the compiler command line. I
prefer not to include that, and would like that fixed too.


I don't see why the warnings to show deprecated uses of functions would be
relevant to the warnings shown above. What's the code in line 5433 or 5607
where the compiler complains?

p.s: My experience is that newer compilers often raise new warnings/errors
because the old code is not as clean as it should have been.

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #3

P: n/a
Knut Stolze wrote:
Jean-David Beyer wrote:
E.g., here is the beginning of a constructor, for example:

dbBase:: // Custom constructor
dbBase(const string& db_name)
{

You might want to include this:

EXEC SQL INCLUDE SQLCA;


Trouble is, that is already in the file.
EXEC SQL BEGIN DECLARE SECTION; <---<<<
char dbName[DB_DB2N_SIZE + 1]; | "A"
EXEC SQL END DECLARE SECTION; <---<<<

_connected = false;
_dbName = "";

if(db_name.empty()) {
cerr << "dbBase(" << db_name << "): db_name missing." << endl;
exit(EXIT_FAILURE);
}
if(db_name.size() > DB_DB2N_SIZE) {
cerr << "dbBase(" << db_name << "): db_name too long." << endl;
exit(EXIT_FAILURE);
}
(void) strncpy(dbName, db_name.c_str(), DB_DB2N_SIZE);
dbName[DB_DB2N_SIZE] = EOS;

// Connect to database.
EXEC SQL CONNECT TO :dbName; <---<<< "B"

The stuff marked "A" goes right through the preprocessor and compiler,
but the line marked "B" chokes as follows:

dbBase.i: In constructor `dbBase::dbBase(const string&)':
dbBase.i:9122: `NULL' undeclared (first use this function)
dbBase.i:9122: (Each undeclared identifier is reported only once for each
function it appears in.)
make: *** [dbBase.o] Error 1

Here is dbBase.i line 9122"

EXEC SQL CONNECT TO :dbName;

I cannot go on until I fix this problem (that appears in almost every
function of this class, and I assume for all other classes as well.

How exactly do you do the "precompile"?


Like this:

trillian:jdbeyer[~/stocks/src]$ make dbBase.o
/opt/IBM/db2/V8.1/bin/db2 CONNECT TO stock

Database Connection Information

Database server = DB2/LINUX 8.1.5
SQL authorization ID = JDBEYER
Local database alias = STOCK

/opt/IBM/db2/V8.1/bin/db2 PREP dbBase.sqC DEGREE 1 ISOLATION RS QUERYOPT 2
EXPLAIN NO EXPLSNAP NO PREPROCESSOR \"g++296 -x c++ -o dbBase.i -E -P
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include \" bindfile

LINE MESSAGES FOR dbBase.sqC
------ --------------------------------------------------------------------
SQL0060W The "C++" precompiler is in progress.
SQL4017W Preprocessing has completed successfully.
SQL4018W Starting to process the preprocessed file
"/home/jdbeyer/stocks/src/dbBase.i".
SQL4019W Completed processing the preprocessed file
"dbBase.i".
SQL0091W Precompilation or binding was ended with "0"
errors and "0" warnings.
/opt/IBM/db2/V8.1/bin/db2 BIND dbBase.bnd

LINE MESSAGES FOR dbBase.bnd
------ --------------------------------------------------------------------
SQL0061W The binder is in progress.
SQL0091N Binding was ended with "0" errors and "0" warnings.
/opt/IBM/db2/V8.1/bin/db2 DISCONNECT stock
DB20000I The SQL DISCONNECT command completed successfully.
/opt/IBM/db2/V8.1/bin/db2 TERMINATE
DB20000I The TERMINATE command completed successfully.
/usr/bin/g++296 -c -g -mcpu=i686 -march=i686 -O2 -DNULL=0 <---<<<
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include dbBase.C

I saw the same error once when I used the compiler's precompiler to resolve
macros in host variable definitions as you have. The precompiler will then
include <stdlib.h> and expand all macros, including the #define for NULL.
Later, the DB2 precompiler pastes some function calls into the generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.
Exactly what is happening. Since the the pre-compiler (the one that
expands all the Embedded SQL) generates .C files with no #include
statements in it, but with NULL strings in it, there is no way the g++
compiler can deal with it. Yet if it is a bug in the pre-compiler, surely
I would not be the first person to try to compile C++ with Embedded SQL in it.

The <---<<< above, where I force a definition of NULL into the g++296
compiler makes the error message go away and makes instances of

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

turn into

sqlasetdata(2,0,1,sql_setdlist,0,0L);

but it scares me because I have no idea what sqlasetdata is supposed to do
with that argument. In V6.1, the same code generates

sqlasetd(2,0,1,sql_setdlist,0L);
It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).
Trouble is, the NULL s are inserted after all macro expansion is done by
the pre-compiler. So it is too late. I would call this a bug, but it
cannot be as it implies that I am the first person to try to compile C++
with Embedded SQL, and I am not vain enough to believe that.
Either way, I wouldn't use the compiler's precompiler because it garbles all
the line numbers (at the latest after the DB2 prep was ran) and debugging
this stuff will be a mess because the debugger has the incorrect line
information and just shows the wrong things when you step through the code.
Are you implying I should write my own precompiler to convert C++ with
embedded SQL into the transmografied code ultimately delivered to the g++
compiler? I cannot believe you are serious. I would need to know the API
interface for these functions and I cannot find them documented anywhere.
For all my things, I wrote a small Perl script that replaces the macros in
the host variable definitions in a file with the extension .SQX, generates
a .SQC and that is given to DB2 prep to do its job.

In addition to this fatal error, I am getting lots of warning messages I
am not used to, such as:
[snip]
I don't see why the warnings to show deprecated uses of functions would be
relevant to the warnings shown above. What's the code in line 5433 or 5607
where the compiler complains?

p.s: My experience is that newer compilers often raise new warnings/errors
because the old code is not as clean as it should have been.

Yes: I got rid of the warnings by using the 2.96 compiler instead of the
3.2.3 compiler that is default on this machine. They have what seems to be
a totally undocumented alternate compiler, gcc296 and g++296 that are
equivalent to the Red Hat Linux 7.3 compiler, and diddling the makefile to
use it gets rid of all those warnings.

--
.~. Jean-David Beyer Registered Linux User 85642.
/V\ Registered Machine 241939.
/( )\ Shrewsbury, New Jersey http://counter.li.org
^^-^^ 14:40:00 up 10 days, 15:22, 7 users, load average: 4.26, 4.16, 3.99

Nov 12 '05 #4

P: n/a
Knut Stolze wrote:
Jean-David Beyer wrote:
E.g., here is the beginning of a constructor, for example:

dbBase:: // Custom constructor
dbBase(const string& db_name)
{

You might want to include this:

EXEC SQL INCLUDE SQLCA;


Trouble is, that is already in the file.
EXEC SQL BEGIN DECLARE SECTION; <---<<<
char dbName[DB_DB2N_SIZE + 1]; | "A"
EXEC SQL END DECLARE SECTION; <---<<<

_connected = false;
_dbName = "";

if(db_name.empty()) {
cerr << "dbBase(" << db_name << "): db_name missing." << endl;
exit(EXIT_FAILURE);
}
if(db_name.size() > DB_DB2N_SIZE) {
cerr << "dbBase(" << db_name << "): db_name too long." << endl;
exit(EXIT_FAILURE);
}
(void) strncpy(dbName, db_name.c_str(), DB_DB2N_SIZE);
dbName[DB_DB2N_SIZE] = EOS;

// Connect to database.
EXEC SQL CONNECT TO :dbName; <---<<< "B"

The stuff marked "A" goes right through the preprocessor and compiler,
but the line marked "B" chokes as follows:

dbBase.i: In constructor `dbBase::dbBase(const string&)':
dbBase.i:9122: `NULL' undeclared (first use this function)
dbBase.i:9122: (Each undeclared identifier is reported only once for each
function it appears in.)
make: *** [dbBase.o] Error 1

Here is dbBase.i line 9122"

EXEC SQL CONNECT TO :dbName;

I cannot go on until I fix this problem (that appears in almost every
function of this class, and I assume for all other classes as well.

How exactly do you do the "precompile"?


Like this:

trillian:jdbeyer[~/stocks/src]$ make dbBase.o
/opt/IBM/db2/V8.1/bin/db2 CONNECT TO stock

Database Connection Information

Database server = DB2/LINUX 8.1.5
SQL authorization ID = JDBEYER
Local database alias = STOCK

/opt/IBM/db2/V8.1/bin/db2 PREP dbBase.sqC DEGREE 1 ISOLATION RS QUERYOPT 2
EXPLAIN NO EXPLSNAP NO PREPROCESSOR \"g++296 -x c++ -o dbBase.i -E -P
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include \" bindfile

LINE MESSAGES FOR dbBase.sqC
------ --------------------------------------------------------------------
SQL0060W The "C++" precompiler is in progress.
SQL4017W Preprocessing has completed successfully.
SQL4018W Starting to process the preprocessed file
"/home/jdbeyer/stocks/src/dbBase.i".
SQL4019W Completed processing the preprocessed file
"dbBase.i".
SQL0091W Precompilation or binding was ended with "0"
errors and "0" warnings.
/opt/IBM/db2/V8.1/bin/db2 BIND dbBase.bnd

LINE MESSAGES FOR dbBase.bnd
------ --------------------------------------------------------------------
SQL0061W The binder is in progress.
SQL0091N Binding was ended with "0" errors and "0" warnings.
/opt/IBM/db2/V8.1/bin/db2 DISCONNECT stock
DB20000I The SQL DISCONNECT command completed successfully.
/opt/IBM/db2/V8.1/bin/db2 TERMINATE
DB20000I The TERMINATE command completed successfully.
/usr/bin/g++296 -c -g -mcpu=i686 -march=i686 -O2 -DNULL=0 <---<<<
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include dbBase.C

I saw the same error once when I used the compiler's precompiler to resolve
macros in host variable definitions as you have. The precompiler will then
include <stdlib.h> and expand all macros, including the #define for NULL.
Later, the DB2 precompiler pastes some function calls into the generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.
Exactly what is happening. Since the the pre-compiler (the one that
expands all the Embedded SQL) generates .C files with no #include
statements in it, but with NULL strings in it, there is no way the g++
compiler can deal with it. Yet if it is a bug in the pre-compiler, surely
I would not be the first person to try to compile C++ with Embedded SQL in it.

The <---<<< above, where I force a definition of NULL into the g++296
compiler makes the error message go away and makes instances of

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

turn into

sqlasetdata(2,0,1,sql_setdlist,0,0L);

but it scares me because I have no idea what sqlasetdata is supposed to do
with that argument. In V6.1, the same code generates

sqlasetd(2,0,1,sql_setdlist,0L);
It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).
Trouble is, the NULL s are inserted after all macro expansion is done by
the pre-compiler. So it is too late. I would call this a bug, but it
cannot be as it implies that I am the first person to try to compile C++
with Embedded SQL, and I am not vain enough to believe that.
Either way, I wouldn't use the compiler's precompiler because it garbles all
the line numbers (at the latest after the DB2 prep was ran) and debugging
this stuff will be a mess because the debugger has the incorrect line
information and just shows the wrong things when you step through the code.
Are you implying I should write my own precompiler to convert C++ with
embedded SQL into the transmografied code ultimately delivered to the g++
compiler? I cannot believe you are serious. I would need to know the API
interface for these functions and I cannot find them documented anywhere.
For all my things, I wrote a small Perl script that replaces the macros in
the host variable definitions in a file with the extension .SQX, generates
a .SQC and that is given to DB2 prep to do its job.

In addition to this fatal error, I am getting lots of warning messages I
am not used to, such as:
[snip]
I don't see why the warnings to show deprecated uses of functions would be
relevant to the warnings shown above. What's the code in line 5433 or 5607
where the compiler complains?

p.s: My experience is that newer compilers often raise new warnings/errors
because the old code is not as clean as it should have been.

Yes: I got rid of the warnings by using the 2.96 compiler instead of the
3.2.3 compiler that is default on this machine. They have what seems to be
a totally undocumented alternate compiler, gcc296 and g++296 that are
equivalent to the Red Hat Linux 7.3 compiler, and diddling the makefile to
use it gets rid of all those warnings.

--
.~. Jean-David Beyer Registered Linux User 85642.
/V\ Registered Machine 241939.
/( )\ Shrewsbury, New Jersey http://counter.li.org
^^-^^ 14:40:00 up 10 days, 15:22, 7 users, load average: 4.26, 4.16, 3.99

Nov 12 '05 #5

P: n/a
Jean-David Beyer wrote:
Knut Stolze wrote:
Jean-David Beyer wrote:
E.g., here is the beginning of a constructor, for example:

dbBase:: // Custom constructor
dbBase(const string& db_name)
{

You might want to include this:

EXEC SQL INCLUDE SQLCA;


Trouble is, that is already in the file.


I would add this in each and every function/method that uses embedded SQL.
It avoids global variables and can be especially problematic in threaded
applications.
How exactly do you do the "precompile"?


Like this:

trillian:jdbeyer[~/stocks/src]$ make dbBase.o
/opt/IBM/db2/V8.1/bin/db2 CONNECT TO stock

Database Connection Information

Database server = DB2/LINUX 8.1.5
SQL authorization ID = JDBEYER
Local database alias = STOCK

/opt/IBM/db2/V8.1/bin/db2 PREP dbBase.sqC DEGREE 1 ISOLATION RS QUERYOPT 2
EXPLAIN NO EXPLSNAP NO PREPROCESSOR \"g++296 -x c++ -o dbBase.i -E -P
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include \" bindfile

I saw the same error once when I used the compiler's precompiler to
resolve
macros in host variable definitions as you have. The precompiler will
then include <stdlib.h> and expand all macros, including the #define for
NULL. Later, the DB2 precompiler pastes some function calls into the
generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.


Exactly what is happening. Since the the pre-compiler (the one that
expands all the Embedded SQL) generates .C files with no #include
statements in it, but with NULL strings in it, there is no way the g++
compiler can deal with it. Yet if it is a bug in the pre-compiler, surely
I would not be the first person to try to compile C++ with Embedded SQL in
it.

The <---<<< above, where I force a definition of NULL into the g++296
compiler makes the error message go away and makes instances of

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

turn into

sqlasetdata(2,0,1,sql_setdlist,0,0L);

but it scares me because I have no idea what sqlasetdata is supposed to do
with that argument. In V6.1, the same code generates

sqlasetd(2,0,1,sql_setdlist,0L);

It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).


Trouble is, the NULL s are inserted after all macro expansion is done by
the pre-compiler. So it is too late.


That is, strictly spoken, not correct. Using the C++ precompiler in the way
you are doing it causes the "#include" directives to be processed and after
that, they are gone.

Here are the options I see:

(a) Make sure that a macro "#define NULL ((void *)0)" is inserted into the
file so that the subsequent pre-compile/compile phase can resolve the
"NULL"s - that's what you already did.
(b) Replace the macros before the db2 prep starts (see my explanation below)
(c) write the "#include <stdlib.h> in such a way that it will NOT be
expanded by the DB2 precompiler during the precompile phase done with gcc.
This could be done so, I think:

source file:
-----------------
INCLUDE <stdlib.h>
-----------------

db2 prep ... PRECOMPILE "g++296... -DINCLUDE="#include" ..."

Note that (C) only works as described if your precompiler is not working
recursively.
I would call this a bug, but it
cannot be as it implies that I am the first person to try to compile C++
with Embedded SQL, and I am not vain enough to believe that.


If you want to get this behavior changed, then you should contact IBM
support and open a PMR. Here we can give you suggestions how to work
around the issue...
Either way, I wouldn't use the compiler's precompiler because it garbles
all the line numbers (at the latest after the DB2 prep was ran) and
debugging this stuff will be a mess because the debugger has the
incorrect line information and just shows the wrong things when you step
through the code.


Are you implying I should write my own precompiler to convert C++ with
embedded SQL into the transmografied code ultimately delivered to the g++
compiler? I cannot believe you are serious. I would need to know the API
interface for these functions and I cannot find them documented anywhere.


What APIs do you mean? I don't quite follow you there.

The script I use parses a given header file (that has to adhere to some
restrictions), finds all "#define" directives and their replacement, and
then it goes through the .SQX files, replaces the macros with their values
and writes the results to a .SQC file which is then given to "db2 prep" and
no further PRECOMPILE option is used. The advantage to get the correct
line numbers in the debug output of the compiled file was the most
important factor in using that approach. The script is just 100 lines
long.

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #6

P: n/a
Jean-David Beyer wrote:
Knut Stolze wrote:
Jean-David Beyer wrote:
E.g., here is the beginning of a constructor, for example:

dbBase:: // Custom constructor
dbBase(const string& db_name)
{

You might want to include this:

EXEC SQL INCLUDE SQLCA;


Trouble is, that is already in the file.


I would add this in each and every function/method that uses embedded SQL.
It avoids global variables and can be especially problematic in threaded
applications.
How exactly do you do the "precompile"?


Like this:

trillian:jdbeyer[~/stocks/src]$ make dbBase.o
/opt/IBM/db2/V8.1/bin/db2 CONNECT TO stock

Database Connection Information

Database server = DB2/LINUX 8.1.5
SQL authorization ID = JDBEYER
Local database alias = STOCK

/opt/IBM/db2/V8.1/bin/db2 PREP dbBase.sqC DEGREE 1 ISOLATION RS QUERYOPT 2
EXPLAIN NO EXPLSNAP NO PREPROCESSOR \"g++296 -x c++ -o dbBase.i -E -P
-I/home/jdbeyer/include -I/home/jdbeyer/stocks/include
-I/usr/include/g++-3 -I/dataA/db2inst1/sqllib/include \" bindfile

I saw the same error once when I used the compiler's precompiler to
resolve
macros in host variable definitions as you have. The precompiler will
then include <stdlib.h> and expand all macros, including the #define for
NULL. Later, the DB2 precompiler pastes some function calls into the
generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.


Exactly what is happening. Since the the pre-compiler (the one that
expands all the Embedded SQL) generates .C files with no #include
statements in it, but with NULL strings in it, there is no way the g++
compiler can deal with it. Yet if it is a bug in the pre-compiler, surely
I would not be the first person to try to compile C++ with Embedded SQL in
it.

The <---<<< above, where I force a definition of NULL into the g++296
compiler makes the error message go away and makes instances of

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

turn into

sqlasetdata(2,0,1,sql_setdlist,0,0L);

but it scares me because I have no idea what sqlasetdata is supposed to do
with that argument. In V6.1, the same code generates

sqlasetd(2,0,1,sql_setdlist,0L);

It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).


Trouble is, the NULL s are inserted after all macro expansion is done by
the pre-compiler. So it is too late.


That is, strictly spoken, not correct. Using the C++ precompiler in the way
you are doing it causes the "#include" directives to be processed and after
that, they are gone.

Here are the options I see:

(a) Make sure that a macro "#define NULL ((void *)0)" is inserted into the
file so that the subsequent pre-compile/compile phase can resolve the
"NULL"s - that's what you already did.
(b) Replace the macros before the db2 prep starts (see my explanation below)
(c) write the "#include <stdlib.h> in such a way that it will NOT be
expanded by the DB2 precompiler during the precompile phase done with gcc.
This could be done so, I think:

source file:
-----------------
INCLUDE <stdlib.h>
-----------------

db2 prep ... PRECOMPILE "g++296... -DINCLUDE="#include" ..."

Note that (C) only works as described if your precompiler is not working
recursively.
I would call this a bug, but it
cannot be as it implies that I am the first person to try to compile C++
with Embedded SQL, and I am not vain enough to believe that.


If you want to get this behavior changed, then you should contact IBM
support and open a PMR. Here we can give you suggestions how to work
around the issue...
Either way, I wouldn't use the compiler's precompiler because it garbles
all the line numbers (at the latest after the DB2 prep was ran) and
debugging this stuff will be a mess because the debugger has the
incorrect line information and just shows the wrong things when you step
through the code.


Are you implying I should write my own precompiler to convert C++ with
embedded SQL into the transmografied code ultimately delivered to the g++
compiler? I cannot believe you are serious. I would need to know the API
interface for these functions and I cannot find them documented anywhere.


What APIs do you mean? I don't quite follow you there.

The script I use parses a given header file (that has to adhere to some
restrictions), finds all "#define" directives and their replacement, and
then it goes through the .SQX files, replaces the macros with their values
and writes the results to a .SQC file which is then given to "db2 prep" and
no further PRECOMPILE option is used. The advantage to get the correct
line numbers in the debug output of the compiled file was the most
important factor in using that approach. The script is just 100 lines
long.

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #7

P: n/a
Knut Stolze wrote:
Jean-David Beyer wrote: [snip]
You might want to include this:

EXEC SQL INCLUDE SQLCA;


Trouble is, that is already in the file.

I would add this in each and every function/method that uses embedded SQL.
It avoids global variables and can be especially problematic in threaded
applications.

At the time I wrote the programs (for DB2 V6.1 for Red Hat Linux 6.0,
IIRC), once was enough. My programs are not threaded. I have found that
Linux process creation and destruction are efficient enough to use
separate processes instead of threading (recall that memory can be shared
if it is read-only as text segments are), so the total cost is low. As I
understand it, the main _benefit_ to running threaded applications is so
that the different threads can share memory without explicitly setting up
a shared memory segment. And for me, this shared memory is normaly quite
the opposite of a _benefit_, though I can imagine occassions where it
might be useful. [snip]
I saw the same error once when I used the compiler's precompiler to
resolve
macros in host variable definitions as you have. The precompiler will
then include <stdlib.h> and expand all macros, including the #define for
NULL. Later, the DB2 precompiler pastes some function calls into the
generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.


Exactly what is happening. Since the the pre-compiler (the one that
expands all the Embedded SQL) generates .C files with no #include
statements in it, but with NULL strings in it, there is no way the g++
compiler can deal with it. Yet if it is a bug in the pre-compiler, surely
I would not be the first person to try to compile C++ with Embedded SQL in
it.

The <---<<< above, where I force a definition of NULL into the g++296
compiler makes the error message go away and makes instances of

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

turn into

sqlasetdata(2,0,1,sql_setdlist,0,0L);

but it scares me because I have no idea what sqlasetdata is supposed to do
with that argument. In V6.1, the same code generates

sqlasetd(2,0,1,sql_setdlist,0L);
It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).


Trouble is, the NULL s are inserted _after_ all macro expansion is done by
the pre-compiler. So it is too late.

That is, strictly spoken, not correct. Using the C++ precompiler in the way
you are doing it causes the "#include" directives to be processed and after
that, they are gone.


The way I am doing is right out of the V6.1 books (that I have only on
CD-ROM for V8.1) that have worked for years. I cannot find this in the
V8.1 stuff (though it may well be there: I am just not familiar with the
documentation which has been reorganized and I find it hard to find
things). In any case, I cannot compile the example programs they have
supplied because of the same problem.

And it _should be OK_ that they are gone. It the precompiler chooses to
add NULLs into the program, it better find a way to get them defined, as
it used to do in V6.1.

It seems to me that someone changed the precompiler to invoke sqlasetdata
in V8.1 instead of sqlasetd that was used in V6.1., and the change to the
precompiler was hastily done and no provision was made to get the NULL
expanded. All the precompiler needed to do was put out a 0 instead of a
NULL. There are no other macros in the *.C files produced.
Here are the options I see:

(a) Make sure that a macro "#define NULL ((void *)0)" is inserted into the
file so that the subsequent pre-compile/compile phase can resolve the
"NULL"s - that's what you already did.
This will not work any better than including a #include (file with NULL
defined in it), since that has all been expanded long since.
(b) Replace the macros before the db2 prep starts (see my explanation below)
I do not see how, other than in (C), to replace the macros since they are
not there in the code I write; they are introduced by the DB2 precompiler.
(c) write the "#include <stdlib.h> in such a way that it will NOT be
expanded by the DB2 precompiler during the precompile phase done with gcc.
This could be done so, I think:

source file:
-----------------
INCLUDE <stdlib.h>
-----------------

db2 prep ... PRECOMPILE "g++296... -DINCLUDE="#include" ..."
Why is that any better than

... -D'NULL=0' ...

that I already guessed? What I do not know, since I cannot find any
documentation for the

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

function is what the fifth argument is for. I do not know what the other
arguments are for either, but those are the same as V6.1 that works.

Note in the IBM sample programs, they have no -D in the command line for
the g++ compiler after the precompiler has run and the NULLs put in.
Note that (C) only works as described if your precompiler is not working
recursively.

I would call this a bug, but it
cannot be as it implies that I am the first person to try to compile C++
with Embedded SQL, and I am not vain enough to believe that.

If you want to get this behavior changed, then you should contact IBM
support and open a PMR. Here we can give you suggestions how to work
around the issue...

I do not know if I want the behavior changed or not, though I think I do.
I would settle for having it documented that you must have a -D'NULL=0" in
the command to the compile step. I have since built all libraries and most
client programs, and they all work. So I infer defining NULL to be 0 is
correct.

It is gratifying that V8.1.5 on this machine is so very fast. Partly,
because the hardware is so fast, partly because with RHEL 3 ES I can run
DMS instead of SMS mode, partly because I have four hard drive spindles
and can organize things better than with SMS on two spindles. A 10-hour
job (major part of the initial populating of the database now takes 57
minutes 43 seconds.
Either way, I wouldn't use the compiler's precompiler because it garbles
all the line numbers (at the latest after the DB2 prep was ran) and
debugging this stuff will be a mess because the debugger has the
incorrect line information and just shows the wrong things when you step
through the code.
Are you implying I should write my own precompiler to convert C++ with
embedded SQL into the transmografied code ultimately delivered to the g++
compiler? I cannot believe you are serious. I would need to know the API
interface for these functions and I cannot find them documented anywhere.

What APIs do you mean? I don't quite follow you there.


The functions that really get invoked to get SQL done. Below, the ones
called sqlastrt, sqlaaloc, sqlasetdata, sqlacall, and sqlastop, as well as
the definition of the structure built up in qla_setdata_list sql_setdlist.
Now, of course, I should never need to know any of this, but I do need to
know it if I can intelligently pick a value for the NULL that I should not
have to define myself.

When you write embedded SQL in a C++ (or a C, I believe) program, it looks
like this:

EXEC SQL BEGIN DECLARE SECTION;
char db_name[DB_NAME_SIZE+1];
EXEC SQL END DECLARE SECTION;

This is just so that, in this case, db_name can be used as a variable
inside embedded SQL code later in a function. Like this:

EXEC SQL DISCONNECT :db_name;

The colon warns the precompiler that db_name is a variable inside a C++
program and not a literal field name in a tuple.

Now the rest of the program may have #define and #include in it (highly
likely, of course).

When building such a program, the first thing that happens is that the C++
preprocessor is invoked to expand all the #include, #define, #ifdef, and
so on. This must be done so that the C++ precompiler that converts the
Embedded SQL need not include the C++ preprocessor functionality inside
itself. And the preprocessing cannot be deferred because then the
precompiler would not know what code is included and what code is not, nor
would it know the size of arrays, and a lot else. A consequence of this,
however, is that all C++ preprocessing is done, so all source text related
to it is removed. When the C++ preprocessor is complete, there is a .i
file that is equivalent to the .sqC file I originally wrote, but with all
the preprocessing done.

The second thing that happens is that the SQL Precompiler runs and it
replaces all the Embedded SQL stuff (the stuff related to the EXEC SQL
lines) in the .i file with equivalent code to produce a .C file. So the

EXEC SQL DISCONNECT :db_name;

line is replaced by:
/*
EXEC SQL DISCONNECT :db_name;
*/

{
#line 4433 "dbBase.i"
sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca);
#line 4433 "dbBase.i"
sqlaaloc(2,1,2,0L);
{
struct sqla_setdata_list sql_setdlist[1];
#line 4433 "dbBase.i"
sql_setdlist[0].sqltype = 460; sql_setdlist[0].sqllen = 41;
#line 4433 "dbBase.i"
sql_setdlist[0].sqldata = (void*)db_name;
#line 4433 "dbBase.i"
sql_setdlist[0].sqlind = 0L;
#line 4433 "dbBase.i"
sqlasetdata(2,0,1,sql_setdlist,NULL,0L);
}
#line 4433 "dbBase.i"
sqlacall((unsigned short)40,23,2,0,0L);
#line 4433 "dbBase.i"
sqlastop(0L);
}

The third thing that happens is that the g++ compiler is called to compile
the .C file into a .o file. And it is here that the problem exists, since
there are _no_ C++ preprocessor statements in the .C file. The SQL
precompiler should not have put the NULLs in there, since there is no
mechanism to get them expanded.

The script I use parses a given header file (that has to adhere to some
restrictions), finds all "#define" directives and their replacement, and
then it goes through the .SQX files, replaces the macros with their values
and writes the results to a .SQC file which is then given to "db2 prep" and
no further PRECOMPILE option is used. The advantage to get the correct
line numbers in the debug output of the compiled file was the most
important factor in using that approach. The script is just 100 lines
long.

But db2 prep removes all the macros and replaces them with their values.
And then IT IS TOO LATE because the precompiler sticks NULLs into the file
and the final g++ step cannot expand them!

--
.~. Jean-David Beyer Registered Linux User 85642.
/V\ Registered Machine 241939.
/( )\ Shrewsbury, New Jersey http://counter.li.org
^^-^^ 07:35:00 up 12 days, 8:18, 5 users, load average: 4.10, 4.15, 4.07

Nov 12 '05 #8

P: n/a
Knut Stolze wrote:
Jean-David Beyer wrote: [snip]
You might want to include this:

EXEC SQL INCLUDE SQLCA;


Trouble is, that is already in the file.

I would add this in each and every function/method that uses embedded SQL.
It avoids global variables and can be especially problematic in threaded
applications.

At the time I wrote the programs (for DB2 V6.1 for Red Hat Linux 6.0,
IIRC), once was enough. My programs are not threaded. I have found that
Linux process creation and destruction are efficient enough to use
separate processes instead of threading (recall that memory can be shared
if it is read-only as text segments are), so the total cost is low. As I
understand it, the main _benefit_ to running threaded applications is so
that the different threads can share memory without explicitly setting up
a shared memory segment. And for me, this shared memory is normaly quite
the opposite of a _benefit_, though I can imagine occassions where it
might be useful. [snip]
I saw the same error once when I used the compiler's precompiler to
resolve
macros in host variable definitions as you have. The precompiler will
then include <stdlib.h> and expand all macros, including the #define for
NULL. Later, the DB2 precompiler pastes some function calls into the
generated C
code where "NULL" is used to pass a NULL pointer. That NULL can't be
expanded anymore because <stdlib.h> is not included again.


Exactly what is happening. Since the the pre-compiler (the one that
expands all the Embedded SQL) generates .C files with no #include
statements in it, but with NULL strings in it, there is no way the g++
compiler can deal with it. Yet if it is a bug in the pre-compiler, surely
I would not be the first person to try to compile C++ with Embedded SQL in
it.

The <---<<< above, where I force a definition of NULL into the g++296
compiler makes the error message go away and makes instances of

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

turn into

sqlasetdata(2,0,1,sql_setdlist,0,0L);

but it scares me because I have no idea what sqlasetdata is supposed to do
with that argument. In V6.1, the same code generates

sqlasetd(2,0,1,sql_setdlist,0L);
It might be that the above shown "EXEC SQL INCLUDE SQLCA" already solves
your problem. If not, then you should provide some sort if directive to
the DB2 precompiler in such a way that NULL will be resolved (or that
<stdlib.h> is included again).


Trouble is, the NULL s are inserted _after_ all macro expansion is done by
the pre-compiler. So it is too late.

That is, strictly spoken, not correct. Using the C++ precompiler in the way
you are doing it causes the "#include" directives to be processed and after
that, they are gone.


The way I am doing is right out of the V6.1 books (that I have only on
CD-ROM for V8.1) that have worked for years. I cannot find this in the
V8.1 stuff (though it may well be there: I am just not familiar with the
documentation which has been reorganized and I find it hard to find
things). In any case, I cannot compile the example programs they have
supplied because of the same problem.

And it _should be OK_ that they are gone. It the precompiler chooses to
add NULLs into the program, it better find a way to get them defined, as
it used to do in V6.1.

It seems to me that someone changed the precompiler to invoke sqlasetdata
in V8.1 instead of sqlasetd that was used in V6.1., and the change to the
precompiler was hastily done and no provision was made to get the NULL
expanded. All the precompiler needed to do was put out a 0 instead of a
NULL. There are no other macros in the *.C files produced.
Here are the options I see:

(a) Make sure that a macro "#define NULL ((void *)0)" is inserted into the
file so that the subsequent pre-compile/compile phase can resolve the
"NULL"s - that's what you already did.
This will not work any better than including a #include (file with NULL
defined in it), since that has all been expanded long since.
(b) Replace the macros before the db2 prep starts (see my explanation below)
I do not see how, other than in (C), to replace the macros since they are
not there in the code I write; they are introduced by the DB2 precompiler.
(c) write the "#include <stdlib.h> in such a way that it will NOT be
expanded by the DB2 precompiler during the precompile phase done with gcc.
This could be done so, I think:

source file:
-----------------
INCLUDE <stdlib.h>
-----------------

db2 prep ... PRECOMPILE "g++296... -DINCLUDE="#include" ..."
Why is that any better than

... -D'NULL=0' ...

that I already guessed? What I do not know, since I cannot find any
documentation for the

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

function is what the fifth argument is for. I do not know what the other
arguments are for either, but those are the same as V6.1 that works.

Note in the IBM sample programs, they have no -D in the command line for
the g++ compiler after the precompiler has run and the NULLs put in.
Note that (C) only works as described if your precompiler is not working
recursively.

I would call this a bug, but it
cannot be as it implies that I am the first person to try to compile C++
with Embedded SQL, and I am not vain enough to believe that.

If you want to get this behavior changed, then you should contact IBM
support and open a PMR. Here we can give you suggestions how to work
around the issue...

I do not know if I want the behavior changed or not, though I think I do.
I would settle for having it documented that you must have a -D'NULL=0" in
the command to the compile step. I have since built all libraries and most
client programs, and they all work. So I infer defining NULL to be 0 is
correct.

It is gratifying that V8.1.5 on this machine is so very fast. Partly,
because the hardware is so fast, partly because with RHEL 3 ES I can run
DMS instead of SMS mode, partly because I have four hard drive spindles
and can organize things better than with SMS on two spindles. A 10-hour
job (major part of the initial populating of the database now takes 57
minutes 43 seconds.
Either way, I wouldn't use the compiler's precompiler because it garbles
all the line numbers (at the latest after the DB2 prep was ran) and
debugging this stuff will be a mess because the debugger has the
incorrect line information and just shows the wrong things when you step
through the code.
Are you implying I should write my own precompiler to convert C++ with
embedded SQL into the transmografied code ultimately delivered to the g++
compiler? I cannot believe you are serious. I would need to know the API
interface for these functions and I cannot find them documented anywhere.

What APIs do you mean? I don't quite follow you there.


The functions that really get invoked to get SQL done. Below, the ones
called sqlastrt, sqlaaloc, sqlasetdata, sqlacall, and sqlastop, as well as
the definition of the structure built up in qla_setdata_list sql_setdlist.
Now, of course, I should never need to know any of this, but I do need to
know it if I can intelligently pick a value for the NULL that I should not
have to define myself.

When you write embedded SQL in a C++ (or a C, I believe) program, it looks
like this:

EXEC SQL BEGIN DECLARE SECTION;
char db_name[DB_NAME_SIZE+1];
EXEC SQL END DECLARE SECTION;

This is just so that, in this case, db_name can be used as a variable
inside embedded SQL code later in a function. Like this:

EXEC SQL DISCONNECT :db_name;

The colon warns the precompiler that db_name is a variable inside a C++
program and not a literal field name in a tuple.

Now the rest of the program may have #define and #include in it (highly
likely, of course).

When building such a program, the first thing that happens is that the C++
preprocessor is invoked to expand all the #include, #define, #ifdef, and
so on. This must be done so that the C++ precompiler that converts the
Embedded SQL need not include the C++ preprocessor functionality inside
itself. And the preprocessing cannot be deferred because then the
precompiler would not know what code is included and what code is not, nor
would it know the size of arrays, and a lot else. A consequence of this,
however, is that all C++ preprocessing is done, so all source text related
to it is removed. When the C++ preprocessor is complete, there is a .i
file that is equivalent to the .sqC file I originally wrote, but with all
the preprocessing done.

The second thing that happens is that the SQL Precompiler runs and it
replaces all the Embedded SQL stuff (the stuff related to the EXEC SQL
lines) in the .i file with equivalent code to produce a .C file. So the

EXEC SQL DISCONNECT :db_name;

line is replaced by:
/*
EXEC SQL DISCONNECT :db_name;
*/

{
#line 4433 "dbBase.i"
sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca);
#line 4433 "dbBase.i"
sqlaaloc(2,1,2,0L);
{
struct sqla_setdata_list sql_setdlist[1];
#line 4433 "dbBase.i"
sql_setdlist[0].sqltype = 460; sql_setdlist[0].sqllen = 41;
#line 4433 "dbBase.i"
sql_setdlist[0].sqldata = (void*)db_name;
#line 4433 "dbBase.i"
sql_setdlist[0].sqlind = 0L;
#line 4433 "dbBase.i"
sqlasetdata(2,0,1,sql_setdlist,NULL,0L);
}
#line 4433 "dbBase.i"
sqlacall((unsigned short)40,23,2,0,0L);
#line 4433 "dbBase.i"
sqlastop(0L);
}

The third thing that happens is that the g++ compiler is called to compile
the .C file into a .o file. And it is here that the problem exists, since
there are _no_ C++ preprocessor statements in the .C file. The SQL
precompiler should not have put the NULLs in there, since there is no
mechanism to get them expanded.

The script I use parses a given header file (that has to adhere to some
restrictions), finds all "#define" directives and their replacement, and
then it goes through the .SQX files, replaces the macros with their values
and writes the results to a .SQC file which is then given to "db2 prep" and
no further PRECOMPILE option is used. The advantage to get the correct
line numbers in the debug output of the compiled file was the most
important factor in using that approach. The script is just 100 lines
long.

But db2 prep removes all the macros and replaces them with their values.
And then IT IS TOO LATE because the precompiler sticks NULLs into the file
and the final g++ step cannot expand them!

--
.~. Jean-David Beyer Registered Linux User 85642.
/V\ Registered Machine 241939.
/( )\ Shrewsbury, New Jersey http://counter.li.org
^^-^^ 07:35:00 up 12 days, 8:18, 5 users, load average: 4.10, 4.15, 4.07

Nov 12 '05 #9

P: n/a
Jean-David Beyer wrote:
Here are the options I see:

(a) Make sure that a macro "#define NULL ((void *)0)" is inserted into
the file so that the subsequent pre-compile/compile phase can resolve the
"NULL"s - that's what you already did.
This will not work any better than including a #include (file with NULL
defined in it), since that has all been expanded long since.


I meant that this macro is inserted into the file by the precompiler used in
the PRECOMPILE option.
(b) Replace the macros before the db2 prep starts (see my explanation
below)


I do not see how, other than in (C), to replace the macros since they are
not there in the code I write; they are introduced by the DB2 precompiler.


I was referring to your macros that you used in the host variables. If you
replace them before the "db2 prep" is done, then you don't need the
PRECOMPILE option in the first place and the whole issue vanishes.
(c) write the "#include <stdlib.h> in such a way that it will NOT be
expanded by the DB2 precompiler during the precompile phase done with
gcc. This could be done so, I think:

source file:
-----------------
INCLUDE <stdlib.h>
-----------------

db2 prep ... PRECOMPILE "g++296... -DINCLUDE="#include" ..."


Why is that any better than

... -D'NULL=0' ...

that I already guessed?


Your "NULL=0" (I would rather use -DNULL="((void *)0)" ) is the option (A) I
outlined above.
What I do not know, since I cannot find any
documentation for the

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

function is what the fifth argument is for. I do not know what the other
arguments are for either, but those are the same as V6.1 that works.
That is an internal function and you do not need to worry about it. Hence,
it is not documented. You should never be in the situation to call the
function yourself.
What APIs do you mean? I don't quite follow you there.


The functions that really get invoked to get SQL done. Below, the ones
called sqlastrt, sqlaaloc, sqlasetdata, sqlacall, and sqlastop, as well as
the definition of the structure built up in qla_setdata_list sql_setdlist.
Now, of course, I should never need to know any of this, but I do need to
know it if I can intelligently pick a value for the NULL that I should not
have to define myself.


NULL is a null pointer, and it is even defined by the C standard (if I
remember correctly) as "(void *)0". So there is not much more you need to
know about it, is there?
When you write embedded SQL in a C++ (or a C, I believe) program, it looks
like this:

EXEC SQL BEGIN DECLARE SECTION;
char db_name[DB_NAME_SIZE+1];
EXEC SQL END DECLARE SECTION;

This is just so that, in this case, db_name can be used as a variable
inside embedded SQL code later in a function. Like this:

EXEC SQL DISCONNECT :db_name;

The colon warns the precompiler that db_name is a variable inside a C++
program and not a literal field name in a tuple.

Now the rest of the program may have #define and #include in it (highly
likely, of course).

When building such a program, the first thing that happens is that the C++
preprocessor is invoked to expand all the #include, #define, #ifdef, and
so on. [...] The second thing that happens is that the SQL Precompiler runs and it
replaces all the Embedded SQL stuff (the stuff related to the EXEC SQL
lines) in the .i file with equivalent code to produce a .C file. So the [...] The third thing that happens is that the g++ compiler is called to compile
the .C file into a .o file.


That depends on your specific build process. For your approach, the
description is correct. In my cases, I do use the Perl script to replace
only a certain, well-defined set of macros and I do not the full C/C++
preprocessing. So the resulting file is C including preprocesser
directives. (Note that your third step includes a C preprocessing - it is
just that there is nothing left to do.)
The script I use parses a given header file (that has to adhere to some
restrictions), finds all "#define" directives and their replacement, and
then it goes through the .SQX files, replaces the macros with their
values and writes the results to a .SQC file which is then given to "db2
prep" and
no further PRECOMPILE option is used. The advantage to get the correct
line numbers in the debug output of the compiled file was the most
important factor in using that approach. The script is just 100 lines
long.

But db2 prep removes all the macros and replaces them with their values.
And then IT IS TOO LATE because the precompiler sticks NULLs into the file
and the final g++ step cannot expand them!


I think there is a misunderstanding. In my approach, I have:

(1) replace some macros but do not do a full C/C++ preprocessing step; the
#include directives remain in the .sqc file (along with other macros)!
(2) run db2 prep to convert the SQL statements to C function calls
(3) compile the .c file (involving the actual C/C++ preprocessing step) and
compile everything to an .o file.

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #10

P: n/a
Jean-David Beyer wrote:
Here are the options I see:

(a) Make sure that a macro "#define NULL ((void *)0)" is inserted into
the file so that the subsequent pre-compile/compile phase can resolve the
"NULL"s - that's what you already did.
This will not work any better than including a #include (file with NULL
defined in it), since that has all been expanded long since.


I meant that this macro is inserted into the file by the precompiler used in
the PRECOMPILE option.
(b) Replace the macros before the db2 prep starts (see my explanation
below)


I do not see how, other than in (C), to replace the macros since they are
not there in the code I write; they are introduced by the DB2 precompiler.


I was referring to your macros that you used in the host variables. If you
replace them before the "db2 prep" is done, then you don't need the
PRECOMPILE option in the first place and the whole issue vanishes.
(c) write the "#include <stdlib.h> in such a way that it will NOT be
expanded by the DB2 precompiler during the precompile phase done with
gcc. This could be done so, I think:

source file:
-----------------
INCLUDE <stdlib.h>
-----------------

db2 prep ... PRECOMPILE "g++296... -DINCLUDE="#include" ..."


Why is that any better than

... -D'NULL=0' ...

that I already guessed?


Your "NULL=0" (I would rather use -DNULL="((void *)0)" ) is the option (A) I
outlined above.
What I do not know, since I cannot find any
documentation for the

sqlasetdata(2,0,1,sql_setdlist,NULL,0L);

function is what the fifth argument is for. I do not know what the other
arguments are for either, but those are the same as V6.1 that works.
That is an internal function and you do not need to worry about it. Hence,
it is not documented. You should never be in the situation to call the
function yourself.
What APIs do you mean? I don't quite follow you there.


The functions that really get invoked to get SQL done. Below, the ones
called sqlastrt, sqlaaloc, sqlasetdata, sqlacall, and sqlastop, as well as
the definition of the structure built up in qla_setdata_list sql_setdlist.
Now, of course, I should never need to know any of this, but I do need to
know it if I can intelligently pick a value for the NULL that I should not
have to define myself.


NULL is a null pointer, and it is even defined by the C standard (if I
remember correctly) as "(void *)0". So there is not much more you need to
know about it, is there?
When you write embedded SQL in a C++ (or a C, I believe) program, it looks
like this:

EXEC SQL BEGIN DECLARE SECTION;
char db_name[DB_NAME_SIZE+1];
EXEC SQL END DECLARE SECTION;

This is just so that, in this case, db_name can be used as a variable
inside embedded SQL code later in a function. Like this:

EXEC SQL DISCONNECT :db_name;

The colon warns the precompiler that db_name is a variable inside a C++
program and not a literal field name in a tuple.

Now the rest of the program may have #define and #include in it (highly
likely, of course).

When building such a program, the first thing that happens is that the C++
preprocessor is invoked to expand all the #include, #define, #ifdef, and
so on. [...] The second thing that happens is that the SQL Precompiler runs and it
replaces all the Embedded SQL stuff (the stuff related to the EXEC SQL
lines) in the .i file with equivalent code to produce a .C file. So the [...] The third thing that happens is that the g++ compiler is called to compile
the .C file into a .o file.


That depends on your specific build process. For your approach, the
description is correct. In my cases, I do use the Perl script to replace
only a certain, well-defined set of macros and I do not the full C/C++
preprocessing. So the resulting file is C including preprocesser
directives. (Note that your third step includes a C preprocessing - it is
just that there is nothing left to do.)
The script I use parses a given header file (that has to adhere to some
restrictions), finds all "#define" directives and their replacement, and
then it goes through the .SQX files, replaces the macros with their
values and writes the results to a .SQC file which is then given to "db2
prep" and
no further PRECOMPILE option is used. The advantage to get the correct
line numbers in the debug output of the compiled file was the most
important factor in using that approach. The script is just 100 lines
long.

But db2 prep removes all the macros and replaces them with their values.
And then IT IS TOO LATE because the precompiler sticks NULLs into the file
and the final g++ step cannot expand them!


I think there is a misunderstanding. In my approach, I have:

(1) replace some macros but do not do a full C/C++ preprocessing step; the
#include directives remain in the .sqc file (along with other macros)!
(2) run db2 prep to convert the SQL statements to C function calls
(3) compile the .c file (involving the actual C/C++ preprocessing step) and
compile everything to an .o file.

--
Knut Stolze
Information Integration
IBM Germany / University of Jena
Nov 12 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.