home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
rxsql.zip
/
RXSQL.C
next >
Wrap
C/C++ Source or Header
|
1993-02-19
|
13KB
|
645 lines
/****************************************************************************
REXX SQL ACCESS MODULE
- RXSQLQUERY
- RXSQLCLOSE
****************************************************************************/
#define DBMSOS2
#define INCL_DOS
#define INCL_RXSHV
#include <os2.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <sqlfront.h>
#include <sqldb.h>
#include <rexxsaa.h>
#define DLL far pascal
/****************************************************************************
SQL: DECLARATIONS/GLOBAL VARIABLES
****************************************************************************/
typedef DBPROCESS far * PDBPROCESS;
typedef LOGINREC far * PLOGINREC;
#define DATALEN 255
char szSQLBuf[DATALEN + 1]; /* common buffer */
/****************************************************************************
SQL: CONNECT TO A SERVER
- returns a non-NULL PDBPROCESS on success
****************************************************************************/
PDBPROCESS
SQL_Connect
(
PSZ pszServer,
PSZ pszUser,
PSZ pszPasswd,
PSZ pszAppname,
)
{
PDBPROCESS pdbp;
PLOGINREC plogin;
pdbp = NULL;
if (plogin = dblogin())
{
DBSETLUSER(plogin, pszUser);
DBSETLPWD(plogin, pszPasswd);
DBSETLAPP(plogin, pszAppname);
pdbp = dbopen(plogin, pszServer);
}
return pdbp;
}
/****************************************************************************
SQL: MESSAGE STORE
****************************************************************************/
SHORT sSQLError = 0;
char szSQLMessage[DATALEN + 1];
BOOL fMsgHandlerAdded = FALSE;
/****************************************************************************
SQL: MESSAGE HANDLER
****************************************************************************/
SHORT _loadds RxsqlMsgHandler
(
PDBPROCESS pdbp,
DBINT lMsgNo,
DBSMALLINT sMsgState,
DBSMALLINT sSeverity,
PSZ pszMsgText
)
{
if (sSeverity > 0)
{
sSQLError = sSeverity;
strcpy(szSQLMessage, pszMsgText);
}
return 0;
}
/****************************************************************************
SQL: EXECUTE A COMMAND
- returns SUCCEED or FAIL
****************************************************************************/
RETCODE SQL_Execute(PDBPROCESS pdbp, PSZ pszCommand)
{
RETCODE retcode;
sSQLError = 0;
if (((retcode = dbcmd(pdbp, pszCommand)) == SUCCEED) && (sSQLError == 0))
{
if (((retcode = dbsqlexec(pdbp)) == SUCCEED) && (sSQLError == 0))
{
return SUCCEED;
}
}
return FAIL;
}
/****************************************************************************
SQL: DISCONNECT FROM A SERVER
****************************************************************************/
void SQL_Disconnect(PDBPROCESS pdbp)
{
dbclose(pdbp);
}
/***************************************************************************
SET REX VARIABLE
***************************************************************************/
SHORT SetRexVar
(
PSZ pszVar, /* Variable name */
PVOID pValue, /* Ptr to value */
ULONG ulLen /* Value length */
)
{
SHVBLOCK RxVarBlock;
SHORT retc;
/* Initialize RxVarBlock */
RxVarBlock.shvnext = NULL;
RxVarBlock.shvname.strptr = pszVar;
RxVarBlock.shvname.strlength = (ULONG) strlen (pszVar);
RxVarBlock.shvnamelen = RxVarBlock.shvname.strlength;
RxVarBlock.shvvalue.strptr = pValue;
RxVarBlock.shvvalue.strlength = ulLen;
RxVarBlock.shvvaluelen = ulLen;
RxVarBlock.shvcode = RXSHV_SYSET;
RxVarBlock.shvret = RXSHV_OK;
/* set variable in pool */
retc = RxVar (&RxVarBlock);
/* test return codes */
if (retc == RXSHV_NEWV)
{
return (RXSHV_OK);
}
return (retc);
}
/***************************************************************************
MAKE AN INDEXED VARIABLE NAME
***************************************************************************/
SHORT RxsqlSetVar(PSZ pszVar, SHORT sRow, SHORT sColumn, PSZ pszValue)
{
char szName[250];
sprintf(szName, "%s.%d.%d", pszVar, sRow, sColumn);
return SetRexVar(szName, pszValue, (ULONG)strlen(pszValue));
}
/***************************************************************************
REXX QUERY
var.0.0 = status
var.1.0 = rows (N)
var.2.0 = columns (M)
var.0.1, ..., var.0.M = column names
var.K.1, ..., var.K.M = data (K = 1, 2, ..., N)
***************************************************************************/
SHORT SQL_Query
(
PDBPROCESS pdbp,
PSZ pszCommand,
PSZ pszVar,
SHORT sMaxRows,
SHORT sMaxColumns
)
{
int coltype;
RETCODE retcode;
SHORT sRow;
SHORT sColumn;
SHORT sNumCols;
SHORT rc;
char szSQLBuf[DATALEN + 1];
if (rc = RxsqlSetVar(pszVar, 0, 0, "ERROR"))
{
return rc;
}
/*** make a query ***/
if (SQL_Execute(pdbp, pszCommand) != SUCCEED)
{
if (sSQLError != 0)
{
if (rc = RxsqlSetVar(pszVar, 0, 0, szSQLMessage))
{
return rc;
}
}
return -1;
}
/*** retrieve data ***/
if (dbresults(pdbp) == SUCCEED)
{
/*** retrieve sColumn names ***/
sNumCols = (USHORT)dbnumcols(pdbp);
for (sColumn = 1; sColumn <= sMaxColumns; sColumn ++)
{
if (sColumn <= sNumCols)
{
if (rc = RxsqlSetVar(pszVar, 0, sColumn, dbcolname(pdbp, sColumn)))
{
return rc;
}
}
}
for (sRow = 1; sRow <= sMaxRows; sRow ++)
{
retcode = dbnextrow(pdbp);
if
(
(retcode == NO_MORE_ROWS)
||
(retcode == BUF_FULL)
||
(retcode == FAIL)
)
{
break;
}
else
{
sNumCols = (USHORT)dbnumcols(pdbp);
for (sColumn = 1; sColumn <= sMaxColumns; sColumn ++)
{
if (sColumn <= sNumCols)
{
if (dbdata(pdbp, sColumn))
{
coltype=dbcoltype(pdbp, sColumn);
dbconvert
(
pdbp,
coltype,
dbdata(pdbp, sColumn),
dbdatlen(pdbp, sColumn),
SQLCHAR,
szSQLBuf,
(DBINT)(-1)
);
}
else
{
strcpy(szSQLBuf, "NULL");
}
if (rc = RxsqlSetVar(pszVar, sRow, sColumn, szSQLBuf))
{
return -1;
}
}
}
}
}
dbcancel(pdbp);
sprintf(szSQLBuf, "%d", sRow);
if (rc = RxsqlSetVar(pszVar, 1, 0, szSQLBuf))
{
return -1;
}
sprintf(szSQLBuf, "%d", sNumCols);
if (rc = RxsqlSetVar(pszVar, 2, 0, szSQLBuf))
{
return -1;
}
if (rc = RxsqlSetVar(pszVar, 0, 0, "OK"))
{
return -1;
}
return 0;
}
return -1;
}
/****************************************************************************
SQL CONNECTION CACHE STRUCTURE
****************************************************************************/
#define NAMESIZE 32
typedef struct
{
PDBPROCESS pdbp;
char szServer[NAMESIZE];
char szUser[NAMESIZE];
}
SQLC, far * PSQLC;
/****************************************************************************
SQL CONNECTION CACHE
****************************************************************************/
#define MAXSQLC 8
SQLC sqlcArray[MAXSQLC];
PSQLC psqlcEndArray = sqlcArray + MAXSQLC;
/****************************************************************************
FIND AN EMPTY CACHE SLOT
****************************************************************************/
PSQLC EmptySlot()
{
PSQLC psqlc;
for (psqlc = sqlcArray; psqlc != psqlcEndArray; psqlc ++)
{
if (!psqlc->pdbp)
{
return psqlc;
}
}
return NULL;
}
/****************************************************************************
FIND A CACHED CONNECTION
****************************************************************************/
PSQLC FindSlot(PSZ pszServer, PSZ pszUser)
{
PSQLC psqlc;
for (psqlc = sqlcArray; psqlc != psqlcEndArray; psqlc ++)
{
if
(
(psqlc->pdbp)
&&
(!strncmp(psqlc->szServer, pszServer, NAMESIZE))
&&
(!strncmp(psqlc->szUser, pszUser, NAMESIZE))
)
{
return psqlc;
}
}
return NULL;
}
/****************************************************************************
KILL A CACHED CONNECTION
- close DB connection and make it empty
****************************************************************************/
PSQLC KillSlot(PSQLC psqlc)
{
if (psqlc->pdbp)
{
SQL_Disconnect(psqlc->pdbp);
}
psqlc->pdbp = NULL;
return psqlc;
}
/****************************************************************************
SELECT A CACHE SLOT RANDOMLY
****************************************************************************/
PSQLC AnySlot()
{
return sqlcArray + ((USHORT)rand() % MAXSQLC);
}
/****************************************************************************
OPEN A CHANNEL
****************************************************************************/
PDBPROCESS OpenChannel
(
PSZ pszServer,
PSZ pszDatabase,
PSZ pszUser,
PSZ pszPassword
)
{
PSQLC psqlc;
PDBPROCESS pdbp;
if ((*pszServer == '\0') || (*pszDatabase == '\0') || (*pszUser == '\0'))
{
return NULL;
}
if (psqlc = FindSlot(pszServer, pszUser))
{
pdbp = psqlc->pdbp;
}
else
{
if (!(psqlc = EmptySlot()))
{
psqlc = KillSlot(AnySlot());
}
pdbp = SQL_Connect(pszServer, pszUser, pszPassword, "RXSQL");
}
sprintf(szSQLBuf, "use %s", pszDatabase);
if (SQL_Execute(pdbp, szSQLBuf) == SUCCEED)
{
psqlc->pdbp = pdbp;
strncpy(psqlc->szServer, pszServer, NAMESIZE);
strncpy(psqlc->szUser, pszUser, NAMESIZE);
return pdbp;
}
else
{
return NULL;
}
}
/***************************************************************************
CREATE A PSZ FROM RXSTRING
***************************************************************************/
PSZ RxToPsz(PRXSTRING prx)
{
PSZ pszReturn;
SHORT sLength;
sLength = (SHORT)prx->strlength;
if (pszReturn = (PSZ)malloc(sLength + 1))
{
memcpy(pszReturn, prx->strptr, sLength);
pszReturn[sLength] = '\0';
}
return pszReturn;
}
/***************************************************************************
RXSQLQUERY
***************************************************************************/
SHORT DLL _loadds RXSQLQUERY
(
PSZ pszFuncName,
SHORT sArgc,
PRXSTRING prxArgv,
PSZ pszQueueName,
PRXSTRING prxReturn
)
{
PSZ pszServer;
PSZ pszDatabase;
PSZ pszUser;
PSZ pszPassword;
PSZ pszCommand;
PSZ pszVar;
PSZ pszMaxRows;
PSZ pszMaxColumns;
SHORT sMaxRows;
SHORT sMaxColumns;
SHORT sReturn;
PDBPROCESS pdbp;
if (!fMsgHandlerAdded)
{
dbmsghandle(RxsqlMsgHandler);
fMsgHandlerAdded = TRUE;
}
sprintf(prxReturn->strptr, "ERROR");
prxReturn->strlength = strlen("ERROR");
sReturn = -1;
if (sArgc == 8)
{
pszServer = RxToPsz(prxArgv + 0);
pszDatabase = RxToPsz(prxArgv + 1);
pszUser = RxToPsz(prxArgv + 2);
pszPassword = RxToPsz(prxArgv + 3);
pszCommand = RxToPsz(prxArgv + 4);
pszVar = RxToPsz(prxArgv + 5);
pszMaxRows = RxToPsz(prxArgv + 6);
pszMaxColumns = RxToPsz(prxArgv + 7);
if (pszMaxRows && pszMaxColumns)
{
sMaxRows = atoi(pszMaxRows);
sMaxColumns = atoi(pszMaxColumns);
if (pszServer && pszDatabase && pszUser && pszPassword && pszVar)
{
sReturn = 0;
if (pdbp = OpenChannel(pszServer, pszDatabase, pszUser, pszPassword))
{
if (!(SQL_Query(pdbp, pszCommand, pszVar, sMaxRows, sMaxColumns)))
{
sprintf(prxReturn->strptr, "OK");
prxReturn->strlength = strlen("OK");
}
}
}
}
free(pszServer);
free(pszDatabase);
free(pszUser);
free(pszPassword);
free(pszCommand);
free(pszVar);
free(pszMaxRows);
free(pszMaxColumns);
}
return sReturn;
}
/***************************************************************************
RXSQLCLOSE
- kills all connections (to cleanup)
***************************************************************************/
SHORT DLL _loadds RXSQLCLOSE
(
PSZ pszFuncName,
SHORT sArgc,
PRXSTRING prxArgv,
PSZ pszQueueName,
PRXSTRING prxReturn
)
{
PSQLC psqlc;
if (sArgc == 0)
{
for (psqlc = sqlcArray; psqlc != psqlcEndArray; psqlc ++)
{
KillSlot(psqlc);
}
}
return 0;
}