Segmentation fault when using static SQL
-
I'm going to convert a GUI program using IBM's DB2 with static SQL
from IBM's VisualAge to Qt. Depending on whether I compile the static
SQL program along with the test routine or not I receive a segmentation
fault when calling sqlestar() (the DB2 routine to start the database
manager). Does anybody know what's going wrong?==== main.cpp ========================================================
@
#include <Q..>
#include <sqlenv.h>
#include <qistring.h>
#include "testdb.hpp"int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);int rc = sqlestar(); // <== point of error
QIString txt("0");
short key = 1 ,seq = 1;if ( rc != 0 && rc != -1026 )
txt = QIString::number(rc);
else
{
//new TestDB("TESTDB");
//psDB->getText(key ,seq ,txt);
}QFile file;
if ( file.open(stdout ,QIODevice::WriteOnly | QIODevice::Text) )
{
QTextStream out(&file);
out << "txt: " << txt.toAscii().data() << "\n";
file.close();
}
return 0;
}
@QtCreator profiles...
@
no segmentation fault |segmentation fault
---------------------------------------+-----------------------------
TARGET = testdbstr |TARGET = testdbnp
SOURCES += main.cpp |SOURCES += main.cpp
| testdb.cxx
|
QT += core |do.
QT -= gui |do.
CONFIG += console |do.
CONFIG -= app_bundle |do.
TEMPLATE = app |do.
HEADERS += testdb.hpp |do.
INCLUDEPATH += d:\sqllib\include \ |do.
f:\qtExt\include |do.
LIBS += -L"D:\SQLLIB\lib" \ |do.
-ldb2api \ |do.
-L"F:\QtExt\lib" \ |do.
-lqistring |do.
@=== testdb.hpp ===
@
#include <sqlca.h>
#include <QDate>
#include <qistring.h>#define psDB TestDB::psCurrent
class TestDB
{
public:
TestDB (const QIString &dbname);
~TestDB();
QIString& name()
{ return ivDBName; }
long getText(short key ,short seq ,QIString &text);
static TestDB *psCurrent;
private:
void throwExc(const QIString &errPos = "" );
int chkSQL(struct sqlca *pSQLCA ,const QIString &errPos);
QIString ivDBName;
char dbDBName[9];
short dbTextKey;
short dbTextSeq;
char dbTextText[81];
#endif
};
@=== testdb.cxx =========================================================
@
static char sqla_program_id[162] =
{
42,...
};#include "sqladef.h"
static struct sqla_runtime_info sqla_rtinfo =
{{'S','Q','L','A','R','T','I','N'}, sizeof(wchar_t), 0, {' ',' ',' ',' '}};
static const short sqlIsLiteral = SQL_IS_LITERAL;
static const short sqlIsInputHvar = SQL_IS_INPUT_HVAR;#line 1
#ifdef SQL_PRE_PROCESSING // do not define it!
/* EXEC SQL BEGIN DECLARE SECTION; /
#line 2 "..."
//EXEC SQL INCLUDE '..\testdb.hv';
char dbDBName[9];
short dbTextKey;
short dbTextSeq;
char dbTextText[81];
/ EXEC SQL END DECLARE SECTION; */
#line 10 "..."
#endif#include <QByteArray>
#include <QtCore>
#include <sql.h>
#include <sqlenv.h>
#include <sqlda.h>
#include <sqlca.h>#define CHKSQL(ACTION ,POS)
if ( 0 != this->chkSQL(&sqlca ,POS) )
{ ACTION; }#define TESTDB_HV
#include "testdb.hpp"
/* EXEC SQL INCLUDE SQLCA; */
#include "sqlca.h"
struct sqlca sqlca;
#line 30 "..."
TestDB *TestDB::psCurrent = 0;TestDB::TestDB (const QIString &dbname)
:ivDBName(dbname)
{
int rc = sqlestar();
if ( SQL_RC_OK == rc )
psDB = this;
else if ( SQLE_RC_INVSTRT == rc ) // -1026 (already started)
psDB = this;
else
this->throwExc("DB2START RC=" + QIString(rc));
QByteArray tmp = dbname.toAscii();
strncpy(&dbDBName[0] ,tmp ,sizeof(dbDBName));
/* EXEC SQL CONNECT TO :dbDBName; */
{
#line 54 "..."
sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca);
sqlaaloc(2,1,1,0L);
{
struct sqla_setdata_list sql_setdlist[1];
...
sqlasetdata(2,0,1,sql_setdlist,NULL,0L);
}
sqlacall((unsigned short)29,4,2,0,0L);
sqlastop(0L);
}
CHKSQL(rc = -1 ,"Ctor CONNECT TO " + dbname);
if ( -1 == rc )
this->throwExc();
psCurrent = this;
}TestDB::~TestDB()
{
/* EXEC SQL CONNECT RESET; */
{
#line 71 "..."
sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca);
sqlacall((unsigned short)29,3,0,0,0L);
sqlastop(0L);
}
CHKSQL(psCurrent = 0 ,"Dtor DISCONNECT");
psCurrent = 0;
}void TestDB::throwExc(const QIString &txt)
{
...
}int TestDB::chkSQL(struct sqlca *pSQLCA ,const QIString &errPos)
{
...
}long TestDB::getText(short key ,short seq ,QIString &text)
{
const QIString method = "getText";
dbTextKey = key;
dbTextSeq = seq;
/*
EXEC SQL DECLARE c32 CURSOR FOR SELECT text FROM np.npgttext
WHERE key = :dbTextKey AND seq = :dbTextSeq;
/
#line 169 "..."
long rc = 0;
/ EXEC SQL OPEN c32; /
{
#line 173 "..."
sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca);
sqlaaloc(2,2,2,0L);
{
struct sqla_setdata_list sql_setdlist[2];
...
sqlasetdata(2,0,2,sql_setdlist,NULL,0L);
}
sqlacall((unsigned short)26,1,2,0,0L);
sqlastop(0L);
}
CHKSQL(return -1 ,method + " OPEN");
/ EXEC SQL FETCH c32 INTO :dbTextText; /
{
#line 179 "..."
sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca);
sqlaaloc(3,1,3,0L);
{
struct sqla_setdata_list sql_setdlist[1];
...
sqlasetdata(3,0,1,sql_setdlist,NULL,0L);
}
sqlacall((unsigned short)25,1,0,3,0L);
sqlastop(0L);
}
switch ( SQLCODE )
{
case 0:
text = QIString(dbTextText);
break;
case 100:
text = "";
break;
default:
CHKSQL(rc = -1 ,method + " FETCH");
break;
} // switch
/ EXEC SQL CLOSE c32; */
{
#line 199 "..."
sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca);
sqlacall((unsigned short)20,1,0,0,0L);
sqlastop(0L);
}
CHKSQL(rc = -1 ,method + " CLOSE");
return rc;
}
@ -
I just hit exactly the same problem: Calling sqlastrt in embedded SQL segfaults.
Environment: WinXP 32bit, compiler is mingw32, DB2 is v7.2But: On the same platform, compiling and linking my code against the libs in BD2 v 9.1 works fine!
So my current thinking is that mingw+DB2 v7 libs somehow don't match. Also, I don't think that it's a simple stipped/non-stripped issue (which apparently could be solved by reimp) because the DB2 libs appear to be stripped already.
I'm going to try to build with MSVC 2008 Express next.
-
Meanwhile I converted the static SQL to CLI and I'm happy with QSqlDatabase and QSqlQuery. To make the connection to a local DB2 database easier, that is just specifying the database name, I changed the QDB2Driver code (qsql_db2.cpp):
@bool QDB2Driver::open(const QString& db,....
:
QString connQStr;
// connQStr = protocol + QLatin1String(";DSN=") + db + QLatin1String(";HOSTNAME=") + host
// + QLatin1String(";PORT=") + QString::number(port) + QLatin1String(";UID=") + user
// + QLatin1String(";PWD=") + password;
connQStr = QLatin1String("UID=") + user
+ QLatin1String(";PWD=") + password;
if ( host.length() == 0 )
connQStr += QLatin1String(";DSN=") + db; // local DB name
else
connQStr += QLatin1String(";DATABASE=") + db // remote DB name
+ QLatin1String(";") + protocol
+ QLatin1String(";HOSTNAME=") + host
+ QLatin1String(";PORT=") + QString::number(port);SQLTCHAR connOut[SQL_MAX_OPTION_STRING_LENGTH]; SQLSMALLINT cb; r = SQLDriverConnect(d->hDbc,...
:
@ -
For what it's worth, my code compiles and runs with MSVC 2008 and DB2 v7.
Unfortunately I cannot switch to CLI, I'm using 3rd/4th-level dynamic SQL, and something like
@EXEC SQL PREPARE stat1 FROM :stmt; @
will get expanded to
@sqlastrt(sqla_program_id, &sqla_rtinfo, &sqlca); @
which in turn crashes.To summarize:
- DB2 v9 + mingw works fine
- DB2 v7 + mingw crashes
- DB2 v7 + MSVC works