/****************************************************************************/ // SQLSVR.CXX v1.0 - 15.11.1990 /****************************************************************************/ /* */ /* Copyright (c) 1989-1993 Bernhard Strassl */ /* Institute for Applied Computer Science and Information Systems */ /* University of Vienna, Austria */ /* */ /* See file COPYRIGHT in this directory for details. If this file is */ /* missing please mail to bernhard@ani.univie.ac.at */ /****************************************************************************/ // // OS/2 SQL Server version // #define SQL_API_FN far pascal #include #include "\sqllib\sqlca.h" #include "\sqllib\sqlenv.h" // #include "\sqllib\sqlda.h" #include "\muglib\upm.h" #include #include "sqlmisc.hxx" #include "sqlsvr.hxx" struct sqlca* sql_ca; /* OS/2 ca area */ unsigned char far * os2node; unsigned char far * os2database; unsigned char far * os2user; unsigned char far * os2password; static unsigned char sqla_program_id[40] = {111,65,65,66,65,67,66,67,66,83,32,32,32,32,32,32,67,66,32,32, 32,32,32,32,65,65,70,67,84,81,76,71,32,32,32,32,32,32,32,32}; extern sqlda* malloc(int); extern void free(sqlda*); void splitUID(char* ); void do_logout(); void nearcpy(char near *, char near *, int); void farcpy(char far*, char far *, int); void dumpLda(sqlda*); class ConvertInfo : SqlInfo // convert CM - types from / to OS2 types { friend class SqlSvr; friend class SysDescr; short type; void* pgmdata; void* os2data; ConvertInfo(short t, void* pd, short size = 0); ~ConvertInfo() { delete os2data; } void convert(bool); // bool gives direction public: void dump() { cerr << "ConvertInfo: type " << type << long(pgmdata) << " " << long(os2data) << "\n"; } }; ConvertInfo::ConvertInfo(short t, void* pd, short size) { pgmdata = pd; switch(type = t) { case CB_PUINT: case CB_PINT: os2data = (void* )new short; size = sizeof(short); break; case CB_PFLOAT: os2data = (void* )new double; size = sizeof(double); break; case CB_PLSTRING: size = strlen((char* )pgmdata); case CB_PBUFFER: os2data = new char[sizeof(short) + size]; *((short* )os2data) = size; break; case CB_PLSTREAM: size = OS2_LSTRSIZE; os2data = new char[sizeof(short) + size]; *((short* )os2data) = size; break; default: os2data = pgmdata; } } void ConvertInfo::convert(bool dir) // TRUE - input { short i; char* src, * dest, c; switch(type) { case CB_PUINT: case CB_PINT: if(dir == TRUE) *((short* )os2data) = *((int* )pgmdata); else *((int* )pgmdata) = *((short* )os2data); break; case CB_PFLOAT: if(dir == TRUE) *((double* )os2data) = *((float* )pgmdata); else *((float* )pgmdata) = *((double* )os2data); break; case CB_PBUFFER: case CB_PLSTRING: if(dir == TRUE) { src = (char* )pgmdata; dest = (char* )(long(os2data) + 2); } else { dest = (char* )pgmdata; src = (char* )(long(os2data) + 2); } for(i = 0; i < *((short* )os2data); i++) *(dest + i) = *(src + i); break; case CB_PLSTREAM: i = 0; if(dir == TRUE) { for( ; ; ) { ((istream* )pgmdata)->get(c); if(((istream* )pgmdata)->eof() || i > OS2_LSTRSIZE) break; *((char* )os2data + 2 + i) = c; i++; } } else { for( ; ; ) { if(((ostream* )pgmdata)->eof() || i > *((short* )os2data)) break; c = *((char* )os2data + 2 + i); ((ostream* )pgmdata)->put(c); i++; } } } } bool checkConvert(short t) { switch(t) { case CB_PUINT: case CB_PINT: case CB_PFLOAT: case CB_PLSTRING: case CB_PBUFFER: case CB_PLSTREAM: return(TRUE); } return(FALSE); } class SysDescr : SqlDescr { friend class SysCurParam; friend class SqlSvr; SysDescr() {} ~SysDescr() {} ConvertInfo* at(int i) { return((ConvertInfo* )infoAt(i)); } ConvertInfo* next(int& i) { return((ConvertInfo* )infoNext(i)); } void convert(bool); }; void SysDescr::convert(bool dir) { int i = 0; ConvertInfo* cvi; while((cvi = next(i)) != (ConvertInfo* )NULL) cvi->convert(dir); } class SysCurParam /* OS2 specific cursor parameters */ { friend class SqlSvr; unsigned short sectionNo; sqlda* inputLda; sqlda* outputLda; SysDescr* inConvert; SysDescr* outConvert; SysCurParam() { sectionNo = 0; inputLda = outputLda = (sqlda* )NULL; inConvert = outConvert = (SysDescr* )NULL; } ~SysCurParam() { if(inputLda) free(inputLda); if(outputLda) free(outputLda); if(inConvert) delete inConvert; if(outConvert) delete outConvert; }; void convertInput() { if(inConvert) inConvert->convert(TRUE); } void convertOutput() { if(outConvert) outConvert->convert(FALSE); } }; SqlSvr::SqlSvr() { init_data_tables(); allCursors = new CursorDescr; sql_ca = (sqlca* )NULL; } SqlSvr::~SqlSvr() { CursorInfo* ii; int i = 0; while((ii = allCursors->next(i)) != (CursorInfo* )NULL) { cerr << "checking cursor: " << ii->cndx << " active: " << ii->active << "\n"; if(ii->active == TRUE) { cerr << "disconnecting:\n"; ii->dump(); disconnect(ii); } if(sql_ca == (sqlca* )NULL) // logged out { cerr << "logged out, quiting.\n"; break; } } delete allCursors; } CursorInfo* SqlSvr::connect(char* uid, int, short, short) { unsigned short rtype; int rcode; SysCurParam* sc; char errmsg[200]; ostream msg(200, errmsg); CursorInfo* ci; cerr << "logging: " << (char near *)os2node << "-" << (char near *)os2database << "-" << (char near *)os2user << "-" << (char near *)os2password << "\n"; if(sql_ca == (sqlca* )NULL) { sql_ca = new sqlca; splitUID(uid); // set the globals node/database/user/password if(strlen((char near *)os2node)) rtype = UPM_DOMAIN; else rtype = UPM_LOCAL; cerr << "remote type: " << rtype << "\n"; if(rcode = upmelgn(os2user, os2password, os2node, rtype, (unsigned short )UPM_USER)) { msg << "Database logon failed, error code " << rcode; msg.put('\0'); cb_error(errmsg); return((CursorInfo* )NULL); } if(rcode = sqlestrd((char near * )os2database, 'S', sql_ca)) { msg << "Start using database failed, error code " << rcode; msg.put('\0'); cb_error(errmsg); return((CursorInfo* )NULL); } } ci = new CursorInfo; ci->sysinfo = (void* )(sc = new SysCurParam); sc->sectionNo = (unsigned short )ci->cndx + 1; ci->active = TRUE; return(ci); } bool SqlSvr::disconnect(CursorInfo* ci) { int i = 0; CursorInfo* ii; SysCurParam* sc; if(sql_ca == (sqlca* )NULL) return(FALSE); sc = (SysCurParam* )ci->sysinfo; if(sc->outputLda) // statement was a SELECT { cerr << "a select cursor....\n"; sqlastrt(sqla_program_id,0L,sql_ca); sqlacall((unsigned short)20,sc->sectionNo,0,0,0L); sqlastop(0L); if(ci->cstat = sql_ca->sqlcode) error(ci); // close failed else cerr << "close ok.\n"; } delete sc; ci->active = FALSE; ci->sysinfo = (void* )NULL; while((ii = allCursors->next(i)) != (CursorInfo* )NULL) { if(ii->active == TRUE) { cerr << "active cursor found: " << ii->cndx << "\n"; return(TRUE); } } cerr << "no more active cursors, logging out.\n"; do_logout(); return(TRUE); } bool SqlSvr::compile(CursorInfo* ci, char* stmt) { sqlastrt(sqla_program_id,0L,sql_ca); sqlasets(strlen(stmt),stmt,0L); sqlacall((unsigned short)27, ((SysCurParam* )ci->sysinfo)->sectionNo,0,0,0L); sqlastop(0L); if(ci->cstat = sql_ca->sqlcode) { error(ci); // compile failed return(FALSE); } return(TRUE); } bool SqlSvr::exec(CursorInfo* ci) { SysCurParam* sc; unsigned short inldaid = 0; sc = (SysCurParam* )ci->sysinfo; sc->convertInput(); sqlastrt(sqla_program_id,0L,sql_ca); if(sc->outputLda) // statement is a SELECT { cerr << "using output lda:\n"; dumpLda(sc->outputLda); if(sc->inputLda) // and has input parameters { cerr << "using input lda:\n"; dumpLda(sc->inputLda); sqlausda((inldaid = sc->sectionNo),sc->inputLda,0L); } sqlacall((unsigned short)26,sc->sectionNo, inldaid,0,0L); } else // other statement { if(sc->inputLda) // with input parameters { cerr << "using input lda:\n"; dumpLda(sc->inputLda); sqlausda((inldaid = sc->sectionNo),sc->inputLda,0L); } sqlacall((unsigned short)24,sc->sectionNo, inldaid,0,0L); } sqlastop(0L); if(ci->cstat = sql_ca->sqlcode) { error(ci); // execute failed return(FALSE); } return(TRUE); } bool SqlSvr::compexec(CursorInfo* ci, char* stmt) { sqlastrt(sqla_program_id,0L,sql_ca); sqlasets(strlen(stmt),stmt,0L); sqlacall((unsigned short)23,((SysCurParam* )ci->sysinfo)->sectionNo,0,0,0L); sqlastop(0L); if(ci->cstat = sql_ca->sqlcode) { error(ci); // execute failed return(FALSE); } return(TRUE); } bool SqlSvr::bindInput(CursorInfo* ci, BindDescr* bd) { BindInfo* bi; SysCurParam* sc; ConvertInfo* cvi; sqlda* da; long dasize; sc = (SysCurParam* )ci->sysinfo; da = malloc(dasize = (long )SQLDASIZE(bd->itemCount)); farcpy("SQLDA ", da->sqldaid, 8); da->sqldabc = dasize; da->sqln = bd->itemCount; da->sqld = bd->itemCount; int i = 0; while(bi = bd->next(i)) { (da->sqlvar[i - 1]).sqltype = (short)pdtype[bi->type]; (da->sqlvar[i - 1]).sqllen = (short )bi->length; if(checkConvert(bi->type) == TRUE) { if(!sc->inConvert) sc->inConvert = new SysDescr; cvi = new ConvertInfo(bi->type, bi->data, bi->length); (da->sqlvar[i - 1]).sqldata = (char* ) cvi->os2data; (sc->inConvert)->addInfo((SqlInfo* )cvi); } else (da->sqlvar[i - 1]).sqldata = (char* ) bi->data; (da->sqlvar[i - 1]).sqlind = NULL; } sc->inputLda = da; return(TRUE); } bool SqlSvr::bindOutput(CursorInfo* ci, BindDescr* bd) { BindInfo* bi; SysCurParam* sc; ConvertInfo* cvi; sqlda* da; long dasize; sc = (SysCurParam* )ci->sysinfo; da = malloc(dasize = (long )SQLDASIZE(bd->itemCount)); farcpy("SQLDA ", da->sqldaid, 8); da->sqldabc = dasize; da->sqln = bd->itemCount; da->sqld = bd->itemCount; int i = 0; while(bi = bd->next(i)) { (da->sqlvar[i - 1]).sqltype = (short)pdtype[bi->type]; (da->sqlvar[i - 1]).sqllen = (short )bi->length; if(checkConvert(bi->type) == TRUE) { if(!sc->outConvert) sc->outConvert = new SysDescr; cvi = new ConvertInfo(bi->type, bi->data, bi->length); (da->sqlvar[i - 1]).sqldata = (char* ) cvi->os2data; (sc->outConvert)->addInfo((SqlInfo* )cvi); } else (da->sqlvar[i - 1]).sqldata = (char* ) bi->data; (da->sqlvar[i - 1]).sqlind = (short* ) &(bi->retCode); } sc->outputLda = da; return(TRUE); } #define OS2_EOF 100 bool SqlSvr::descr(CursorInfo*, QryDescr&) { return(FALSE); } bool SqlSvr::fetch(CursorInfo* ci, short& fcode) { SysCurParam* sc; unsigned short outldaid; sc = (SysCurParam* )ci->sysinfo; sqlastrt(sqla_program_id,0L,sql_ca); sqlausda((outldaid = SS_MAXCURSORS + sc->sectionNo),sc->outputLda,0L); sqlacall((unsigned short)25,sc->sectionNo,0,outldaid,0L); sqlastop(0L); if(ci->cstat = sql_ca->sqlcode) { if((fcode = ci->cstat) != OS2_EOF) error(ci); // fetch failed else fcode = ci->cstat = CB_STATUS_EOF; return(FALSE); } sc->convertOutput(); return(TRUE); } bool SqlSvr::getStatus(CursorInfo* ci, int& rcode) { rcode = ci->cstat; return(TRUE); } bool SqlSvr::getRbFlag(CursorInfo* , bool& ) { cb_error("sorry, getRbFlag not implemented in this version"); return(FALSE); } bool SqlSvr::getRowCount(CursorInfo* , char* , long& ) { cb_error("sorry, getRowCount not implemented in this version"); return(FALSE); } bool SqlSvr::getCurRowCount(CursorInfo* , long& ) { cb_error("sorry, getCurRowCount not implemented in this version"); return(FALSE); } bool SqlSvr::commit(CursorInfo* ) { sqlastrt(sqla_program_id,0L,sql_ca); sqlacall((unsigned short)21,0,0,0,0L); sqlastop(0L); if(sql_ca->sqlcode) { cb_error("commit failed"); return(FALSE); } return(TRUE); } bool SqlSvr::rollback(CursorInfo* ci) { sqlastrt(sqla_program_id,0L,sql_ca); sqlacall((unsigned short)28,0,0,0,0L); sqlastop(0L); if(sql_ca->sqlcode) { cb_error("rollback failed"); return(FALSE); } return(TRUE); } void SqlSvr::error(CursorInfo* ci) { bool fatal; cb_error("class SqlSvr: error in server function", FALSE); allCursors->dump(); if(ci == (CursorInfo* )NULL) cb_error("class SqlSvr: invalid cursor handle", TRUE); char* errtxt = new char[CB_MAX_ERRTXTLEN]; fatal = !getErrorText(ci, errtxt); cb_error(errtxt, fatal); } bool SqlSvr::getErrorText(CursorInfo* ci, char* txt) { ostream msg(200, txt); msg << "OS/2 system error code: " << ci->cstat; msg.put('\0'); return(TRUE); } // additional OS/2 routines ////////////////////////// void splitUID(char* uidstr) { static char* dummy = ""; short curptr = 0, found = 1; char c, * foundptr[4]; foundptr[0] = uidstr; while((c = *(uidstr + curptr)) != '\0') { if(c == '/') { *(uidstr + curptr) = '\0'; foundptr[found++] = uidstr + curptr + 1; } curptr++; } switch(found) { case 1: os2user = foundptr[0]; os2node = os2database = os2password = dummy; break; case 2: os2user = foundptr[0]; os2password = foundptr[1]; os2node = os2database = dummy; break; case 3: os2database = foundptr[0]; os2user = foundptr[1]; os2password = foundptr[2]; os2node = dummy; break; default: os2node = foundptr[0]; os2database = foundptr[1]; os2user = foundptr[2]; os2password = foundptr[3]; } } void do_logout() { unsigned short rtype; int rcode; char errmsg[200]; ostream msg(200, errmsg); if(sqlestpd(sql_ca)) cb_error("Database disconnect failed"); if(strlen((char near *)os2node)) rtype = UPM_DOMAIN; else rtype = UPM_LOCAL; if(rcode = upmelgff(os2user, os2node, rtype) != UPM_NOT_LOGGED) { if(rcode > 0) msg << "Database logout return code: " << rcode; else msg << "Database logout failed, error code " << rcode; msg.put('\0'); cb_error(errmsg); } delete sql_ca; sql_ca = (sqlca* )NULL; } void nearcpy(char near * a, char near * b, int n) { int i = 0; while((*(b + i) = *(a + i)) != '\0') { if(i++ >= n) break; } } void farcpy(char far * a, char far * b, int n) { int i = 0; while((*(b + i) = *(a + i)) != '\0') { if(i++ >= n) break; } } void dumpLda(sqlda* da) { short cnt; cerr << da->sqldaid << " " << da->sqldabc << " " << da->sqln << " " << (cnt = da->sqld) << "\n"; for(int i = 0; i < cnt; i++) { cerr << "var: " << i << " " << (da->sqlvar[i]).sqltype << " " << (da->sqlvar[i]).sqllen << " " << long((da->sqlvar[i]).sqldata) << " " << long((da->sqlvar[i]).sqlind) << " \n"; if(i > 10) { cerr << "........?\n"; break; } } }