home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
dbutil.zip
/
BUFOP.ZIP
/
HOSTVARS.CPP
< prev
next >
Wrap
Text File
|
1993-11-01
|
11KB
|
375 lines
// Precompiler support files
#include "compsql.hpp"
#include "pctypes.hpp" // precompiler types
#include "hostvars.hpp"
#include <fstream.h>
#include <IEqseq.h>
#include <Ikeyset.h>
#include <iglobals.h>
typedef IEqualitySequence <Variable> VarListType; // collection of variables
typedef IKeySet<Vtype,IString> ValidSQLTypes; // collection of sql types
VarListType VarList;
ValidSQLTypes ValidTypes;
extern sqlca mysqlca;
extern ofstream monitor; // monitor output file name from compsql.h
static Boolean InDeclareSection;
Boolean InDeclare()
{ return InDeclareSection;}
void setDeclare(Boolean B)
{ InDeclareSection = B;}
VarListType::Cursor VarCursor(VarList); //used to locate by name
/**********************************************************************
* Variable class implementation
* this is made into a class to store the information into a
* sequence container for SQL Processing
*
**********************************************************************/
unsigned long Variable::nxtID=0;
Variable:: Variable(){
name = "";
type = 0;
len = 0;
Obj = false;
aPointer = false;
ID = 0;}
Variable:: Variable(IString & theName, int thelen, int theType, Boolean anObj)
{ name = theName;
len = thelen;
type = theType;
Obj = anObj;
aPointer = false;
ID = 0;
// setID();
}
ostream& operator<<(ostream & os, Variable & V)
{
os << "Name: " << V.name << " Len: " << V.len
<< " Type: " << V.type << " " << V.vTypeTxt << " ID: " << V.ID << "\n";
return os;
}
void Variable::setName(const IString & thename)
{
name = thename;
name.strip(' ');
name.strip(';');
}
void Variable::registerHV() // register the hostvar
{
setID(); // assign an ID
unsigned short namelen = name.length();
unsigned short location;
if (InDeclare()) {
location = SQLA_DECLARE_SECT;
int rc = sqlaahvr(&namelen,name,&type,&len,&ID,
&location,NULL,&mysqlca);
} else {
location = SQLA_SQL_STMT;
int rc = sqlaahvr(&namelen,name,&type,&len,&ID,
&location,NULL,&mysqlca);
} /* endif */
if (! mysqlca.sqlcode==0 ) {
MSQLError(ID);
} /* endif */
}
Variable & Variable::operator=(Variable const & v)
{ if (this == & v)
return *this;
name = v.name;
len = v.len;
type = v.type;
ID = v.ID;
aPointer = v.aPointer;
prefix = v.prefix;
}
Variable:: Variable(IString & theName)
{ name = theName;
len = 0;
type = 0;
Obj = false;
aPointer = false;
ID = 0;
}
void Variable::setDefaults(Vtype const & V )
{
len = V.getLen();
type = V.getType();
vTypeTxt = V.getName();
IsObject = V.isObj();
aPointer = false;
}
void Variable::setV(unsigned short sqlaID, unsigned short idx,ofstream & fout)
/************************************
* Generate a call to SETV in the form
* sqlsetv(sqlaid,idx,type,len,&name,NULL,NULL);
**************************************/
{ int tmplen = len;
if ((type == SQL_TYP_CHAR) && len > 1) {
tmplen--;
} /* endif */
fout << " sqlasetv("
<< sqlaID << ","
<< idx << " ,"
<< type << ","
<< len << ","
<< getFullName()
<< ",NULL,NULL); // set host variable with no null indicator \n";
}
void Variable:: setVNull(unsigned short sqlaID, unsigned short idx,ofstream & fout,
int nullID)
/************************************
* Generate a call to SETV in the form
* sqlsetv(sqlaid,idx,type+1,len,&name,&nullInd,NULL);
**************************************/
{
Variable V;
V = getVarByID(nullID);
fout << " sqlasetv("
<< sqlaID << ","
<< idx << " ,"
<< type+1 << ","
<< len << ","
<< getFullName() << ","
<< V.getFullName()
<< ",NULL); // set host variable with a null indicator \n";
}
IString Variable:: getFullName()
/***********************************************************
* return prefix and name for use in setV
* if the variable is not an address (isAddress = false)
* then prefix the name with the "&"
**************************************************************/
{
IString tmp = prefix+name;
if (!aPointer)
tmp.insert("&");
return tmp;
}
void Variable:: setUnknown()
{
len = 0;
type = 0;
vTypeTxt = "Unknown variable - should be SQLDA";
IsObject = false;
aPointer = false;
}
Variable:: ~Variable(){}
void initSQLTypes(){
/*********************************************************************
* Took some liberties here in defining sql types.
* In support of IString, I defined a new type which is derived from
* IString.
*
* each of the types are defined and added to the keyset
*
* N O T E I do not support structures in this implementation
* planned for release 2 ha ha!
**********************************************************************/
initSQLStuff();
Vtype aVtype;
aVtype.setParams("fchar",SQL_TYP_CHAR,1); // fixed char
ValidTypes.add(aVtype);
aVtype.setParams("char",SQL_TYP_CSTR,1); // var length null term
ValidTypes.add(aVtype);
aVtype.setParams("ZString",SQL_TYP_CHAR,1,true);// IString, with length (C++ tools)
ValidTypes.add(aVtype);
aVtype.setParams("NString",SQL_TYP_CHAR,1);// same as Istring but null term
ValidTypes.add(aVtype);
aVtype.setParams("IDate",SQL_TYP_DATE,SQL_DATE_STRLEN,true); // IDate from C++ Tools
ValidTypes.add(aVtype);
aVtype.setParams("ITime",SQL_TYP_TIME,SQL_TIME_STRLEN,true);// same as Istring but null term
ValidTypes.add(aVtype);
aVtype.setParams("float",SQL_TYP_FLOAT,SQL_FLOAT_LENGTH); // 8-byte floating point IEEE
ValidTypes.add(aVtype);
aVtype.setParams("int",SQL_TYP_INTEGER,SQL_INT_LENGTH); // long int (4 byte)
ValidTypes.add(aVtype);
aVtype.setParams("short",SQL_TYP_SMALL,SQL_SMALL_LENGTH); // short int 16 bit
ValidTypes.add(aVtype);
aVtype.setParams("Boolean",SQL_TYP_CHAR,1); // translate to "T" or "F"
ValidTypes.add(aVtype); // on the database
return;
}
void processDeclare(IString & theStr)
/****************************************************************************
* P R O C E S S D E C L A R E
* This routine is entered with a string from the source program and is
* evaluated for a valid variable. If one is found it is added to the
* variable list
*
* N O T E -
* for the host variables I'm not sure what type of collection structure
* to use I have a collection that must be accessed by two different methods.
* The name (which I defined as a key)
* and an integer ID (defined as a sequence number).
* the host program refers to the variable by name, while the precompiler
* services uses the variable ID. I chose the sequence
* because while the order of entry is not important, once a variable is
* added, I use its position as the precompiler services ID.
****************************************************************************/
{Vtype theType;
if (theStr.length() == 0) {
return;
} /* endif */
if (theStr.includes("const")) { // no can do
return;
} /* endif */
theStr.change("unsigned",""); // these words have not meaning in the database types
theStr.change("signed","");
theStr = theStr.change("short int","short"); // get rid of long / short qualifiers
theStr = theStr.change("long int","int");
theStr = theStr.change("double","float"); // DB2 will use auto converting
if (theStr.numWords() == 1) {
theStr.insert("int ");
} /* endif */
IString theSType = theStr.word(1); // get first word for possible type
// ValidSQLTypes::Cursor c(ValidTypes); // create cursor for valid types
// Vtype x;
if (ValidTypes.containsElementWithKey(theSType)) {
// have a valid SQL type
// parse the rest of the stament
theType=ValidTypes.elementWithKey(theSType); // get the type
Variable myVar; // put here - so it doesn't get init
myVar.setDefaults(theType); // unless needed
if (theStr.includes("*")) {
myVar.setPointer();
theStr = theStr.remove("*",1);
} /* endif */
if (theStr.includes("[")) { // has associated length
int start = theStr.indexOf('['); // get the length
int end = theStr.indexOf(']'); // what's between should be length
IString tmp = theStr.subString(start+1,end-start-1);
myVar.setLen(tmp.asUnsigned());
theStr.remove(start,end);
} /* endif */
myVar.setName(theStr.word(2));
myVar.registerHV(); // register the hostvar
VarList.add(myVar); // add to host variable list
} else { // not a host variable
return;
} /* endif */
} // end process declare
/***********************************************************************
* FUNCTION GetVarByName
* Host variables are stored in the sequence collection - VarList
* Pass the variable name
* return the variable
* If the variable is not found, assume it is a dynamic SQLDA or
* A nul indicator
************************************************************************/
Variable * getVarByName(IString const& theName)
{ Variable aVar;
aVar.setName(theName);
VarCursor.setToFirst();
if (VarList.locate(aVar,VarCursor))
return &VarList.elementAt(VarCursor); // item was found return it
aVar.setUnknown(); // don't know but keep it
aVar.registerHV();
VarList.add(aVar);
VarCursor.invalidate();
VarCursor.setToLast();
return &VarList.elementAt(VarCursor);
}
// given an ID, get the variable
Variable & getVarByID(long theID)
{ Boolean B;
VarCursor.setToFirst();
for (int j=1;j<theID ;j++) {
VarCursor.setToNext();
} /* endfor */
if (VarCursor.isValid()) {
return VarList.elementAt(VarCursor);
} else {
monitor << "Internal error in program; Variable ID "
<< theID
<< "Does not exist \n";
dumpVars();
monitor.flush();
Variable aVar;
aVar.changeID(theID);
aVar.setName("Unknown - error");
VarList.add(aVar);
VarCursor.setToLast();
} /* endif */
return VarList.elementAt(VarCursor);
}
void dumpVars()
{
Variable AVar;
VarCursor.setToFirst();
monitor << "All registered host variables \n ";
forCursor(VarCursor)
{
monitor << VarList.elementAt(VarCursor);
}
}