#include <stdio.h> #include <stdarg.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <io.h> #include <errno.h> #include <oci.h> #include "xmlapi.h" #include "../wftk_session.h" #include "../wftk_internals.h" |
adaptor_info
structure is used to pass adaptor info (duh) back to the
config module when it's building an adaptor instance. Here's what it contains:
static char *names[] = { "init", "free", "info", "insert", "select", "update", "delete", "colget", "colput", "xmlget", "xmlput", "procnew", "procdel", "procget", "procput", "proclist", "proccomplete", "procerror", "tasknew", "taskdel", "taskget", "taskput", "tasklist", "taskcomplete", "taskreject", "reqnew", "reqdel", "reqget", "reqput", "reqlist", "reqaccept", "reqdecline" }; XML * TASKINDEX_oracle_init (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_free (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_info (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_insert (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_select (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_update (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_delete (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_colget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_colput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_xmlget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_xmlput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_procnew (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_procdel (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_procget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_procput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_proclist (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_proccomplete (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_procerror (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_tasknew (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_taskdel (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_taskget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_taskput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_tasklist (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_taskcomplete (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_taskreject (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_reqnew (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_reqdel (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_reqget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_reqput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_reqlist (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_reqaccept (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_oracle_reqdecline (WFTK_ADAPTOR * ad, va_list args); static WFTK_API_FUNC vtab[] = { TASKINDEX_oracle_init, TASKINDEX_oracle_free, TASKINDEX_oracle_info, TASKINDEX_oracle_insert, TASKINDEX_oracle_select, TASKINDEX_oracle_update, TASKINDEX_oracle_delete, TASKINDEX_oracle_colget, TASKINDEX_oracle_colput, TASKINDEX_oracle_xmlget, TASKINDEX_oracle_xmlput, TASKINDEX_oracle_procnew, TASKINDEX_oracle_procdel, TASKINDEX_oracle_procget, TASKINDEX_oracle_procput, TASKINDEX_oracle_proclist, TASKINDEX_oracle_proccomplete, TASKINDEX_oracle_procerror, TASKINDEX_oracle_tasknew, TASKINDEX_oracle_taskdel, TASKINDEX_oracle_taskget, TASKINDEX_oracle_taskput, TASKINDEX_oracle_tasklist, TASKINDEX_oracle_taskcomplete, TASKINDEX_oracle_taskreject, TASKINDEX_oracle_reqnew, TASKINDEX_oracle_reqdel, TASKINDEX_oracle_reqget, TASKINDEX_oracle_reqput, TASKINDEX_oracle_reqlist, TASKINDEX_oracle_reqaccept, TASKINDEX_oracle_reqdecline }; static struct wftk_adaptor_info _TASKINDEX_oracle_info = { 32, names, vtab }; |
struct wftk_adaptor_info * TASKINDEX_oracle_get_info () { return & _TASKINDEX_oracle_info; } |
void _TASKINDEX_oracle_builderrmsg (XML * ap, const char * message, dvoid * errhp, sword status) { char buf[1024]; text errbuf[512]; sb4 errcode = 0; switch (status) { case OCI_SUCCESS_WITH_INFO: xml_setf (ap, "error", "%s - OCI_SUCCESS_WITH_INFO", message); break; case OCI_NEED_DATA: xml_setf (ap, "error", "%s - OCI_NEED_DATA", message); break; case OCI_NO_DATA: xml_setf (ap, "error", "%s - OCI_NO_DATA", message); break; case OCI_ERROR: *errbuf = '\0'; (void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR); xml_setf (ap, "error", "%s - Oracle error %d: %s", message, errcode, errbuf); break; case OCI_INVALID_HANDLE: xml_setf (ap, "error", "%s - OCI_INVALID_HANDLE", message); break; case OCI_STILL_EXECUTING: xml_setf (ap, "error", "%s - OCI_STILL_EXECUTING", message); break; case OCI_CONTINUE: xml_setf (ap, "error", "%s - OCI_CONTINUE", message); break; } } |
struct _TASKINDEX_oracle_handles { OCIEnv *envhp; OCIError *errhp; OCISession *authp; OCIServer *srvhp; OCISvcCtx *svchp; int ok; }; XML * TASKINDEX_oracle_init (WFTK_ADAPTOR * ad, va_list args) { const char * parms; char buf[1024]; sword status; struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) malloc (sizeof (struct _TASKINDEX_oracle_handles)); if (!handles) { xml_set (ad->parms, "error", "Unable to allocate binary stash."); return (XML *) 0; } ad->bindata = (void *) handles; /* The following sets up the Oracle environment and its various handles. It's taken from the OCI sample code. Wish me luck. */ handles->envhp = 0; handles->ok = 0; parms = xml_attrval (ad->parms, "parm"); if (!*parms) parms = wftk_config_get_value (ad->session, "taskindex.oracle.default"); if (!*parms) { xml_set (ad->parms, "error", "No connection specified and no default connection configured."); free ((void *)handles); ad->bindata = 0; return (XML *) 0; } xml_setf (ad->parms, "spec", "oracle:%s", parms); sprintf (buf, "taskindex.oracle.%s.conn", parms); xml_set (ad->parms, "conn", wftk_config_get_value (ad->session, buf)); sprintf (buf, "taskindex.oracle.%s.userid", parms); xml_set (ad->parms, "userid", wftk_config_get_value (ad->session, buf)); sprintf (buf, "taskindex.oracle.%s.password", parms); xml_set (ad->parms, "password", wftk_config_get_value (ad->session, buf)); /* OK, let's connect to this database specified. */ /* -- Initialize OCI and make an environment. */ (void) OCIInitialize((ub4) OCI_DEFAULT, 0, 0, 0, 0); (void) OCIEnvInit( (OCIEnv **) &(handles->envhp), OCI_DEFAULT, 0, 0); (void) OCIHandleAlloc( (dvoid *) (handles->envhp), (dvoid **) &(handles->errhp), OCI_HTYPE_ERROR, 0, 0); /* -- Server and service contexts */ (void) OCIHandleAlloc( (dvoid *) (handles->envhp), (dvoid **) &(handles->srvhp), OCI_HTYPE_SERVER, 0, 0); (void) OCIHandleAlloc( (dvoid *) (handles->envhp), (dvoid **) &(handles->svchp), OCI_HTYPE_SVCCTX, 0, 0); (void) OCIServerAttach( handles->srvhp, handles->errhp, (text *)xml_attrval (ad->parms, "conn"), strlen(xml_attrval (ad->parms, "conn")), 0); /* -- Attach server to service context and allocate an authentication context. */ (void) OCIAttrSet( (dvoid *) (handles->svchp), OCI_HTYPE_SVCCTX, (dvoid *)(handles->srvhp), 0, OCI_ATTR_SERVER, handles->errhp); (void) OCIHandleAlloc((dvoid *) (handles->envhp), (dvoid **)&(handles->authp), OCI_HTYPE_SESSION, 0, 0); /* -- Set username and password in the authentication context. */ (void) OCIAttrSet((dvoid *) (handles->authp), (ub4) OCI_HTYPE_SESSION, (dvoid *) xml_attrval (ad->parms, "userid"), (ub4) strlen(xml_attrval (ad->parms, "userid")), (ub4) OCI_ATTR_USERNAME, handles->errhp); (void) OCIAttrSet((dvoid *) (handles->authp), (ub4) OCI_HTYPE_SESSION, (dvoid *) xml_attrval (ad->parms, "password"), (ub4) strlen(xml_attrval (ad->parms, "password")), (ub4) OCI_ATTR_PASSWORD, handles->errhp); /* -- Start session! Finally! */ if (OCI_SUCCESS != (status = OCISessionBegin ( handles->svchp, handles->errhp, handles->authp, OCI_CRED_RDBMS, OCI_DEFAULT))) { _TASKINDEX_oracle_builderrmsg (ad->parms, "Unable to connect to server", (dvoid *) (handles->errhp), status); free ((void *)handles); ad->bindata = 0; return (XML *) 0; } /* -- And stash the authorization context in the service context. Why this doesn't happen beforehand, I don't know. */ (void) OCIAttrSet((dvoid *) (handles->svchp), (ub4) OCI_HTYPE_SVCCTX, (dvoid *) (handles->authp), (ub4) 0, (ub4) OCI_ATTR_SESSION, handles->errhp); handles->ok = 1; return (XML *) 0; } |
malloc
thing with these handles, in that you allocate an arbitrary buffer and attach it to a handle. Then when you clean the handle up,
it frees those buffers as well. I don't think I'll be using it, but it's kinda neat.
XML * TASKINDEX_oracle_free (WFTK_ADAPTOR * ad, va_list args) { struct _TASKINDEX_oracle_handles * handles = (struct _TASKINDEX_oracle_handles *) (ad->bindata); if (handles) { if (handles->envhp) OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_ENV); free (handles); ad->bindata = (void *) 0; } return (XML *) 0; } |
XML * TASKINDEX_oracle_info (WFTK_ADAPTOR * ad, va_list args) { XML * info; info = xml_create ("info"); xml_set (info, "type", "taskindex"); xml_set (info, "name", "oracle"); xml_set (info, "ver", "1.1.0"); xml_set (info, "compiled", __TIME__ " " __DATE__); xml_set (info, "author", "Michael Roberts"); xml_set (info, "contact", "wftk@vivtek.com"); xml_set (info, "extra_functions", "0"); return (info); } |
va_list
s.
The internal version just takes plain old parameters, and the externally visible version will be a va_list
-type
function, but just a thin wrapper around the internal version.
Let's start with insert: it's the one I have working from procnew
, so it shouldn't be too hard. An insert
function has a main query, plus a number of insertable values. These are arranged in an XML query structure like this:<sql query="insert into process (id, title, status, started) values (:id, :title, :status, SYSDATE)"> <value name="id" value="42"> <value name="title" value="My Process"> <value name="status" value="active"> </sql>This structure should work for basically any database, except that some of the details will naturally change: Oracle uses colons and named parameter slots, whereas ODBC uses question marks and bindings are strictly positional. We'll find out what the other folks do when we get that far. But the basic idea is the same: we can toss a parameterized query into a structure like this and have the adaptor do the Right Thing to get it done. Anyway, insertion just takes that query and nothing more. (July 25, 2001) And here we are for v1.1 of this adaptor, which will allow it to work with DSREP_database to store datasheets directly in the database. The chief requirement for this is the ability to use an autoincrement column for the datasheet ID, then using a RETURNING clause to retrieve the value of that column after insertion. To do this in the OCI, however, requires us to define and pass a couple of callback functions to retrieve the data, as Oracle's RETURNING bind mechanism is both complex and powerful. Kinda neat mechanism, really. I do like Oracle; if it were open-source I'd probably use it an awful lot. Anyway, these callbacks are pretty easy, really. A dynamic bind takes two callbacks; the "in bind" returns data to Oracle and the "out bind" receives from Oracle. In this case, we don't need the in bind, so we provide a dummy. This is taken with very little modification from the Oracle example code.
static sb4 _TASKINDEX_oracle_insert_incallback ( dvoid *ictxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 *alenp, ub1 *piecep, dvoid **indpp) { *bufpp = (dvoid *) 0; *indpp = (dvoid *) 0; *alenp = 0; *piecep = OCI_ONE_PIECE; return OCI_CONTINUE; } |
struct _TASKINDEX_oracle_insert_recvbuf { char * data; ub4 datalen; ub1 indicator; ub2 rcode; }; static sb4 _TASKINDEX_oracle_insert_outcallback ( dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcodepp) { struct _TASKINDEX_oracle_insert_recvbuf * rb = (struct _TASKINDEX_oracle_insert_recvbuf *) octxp; *bufpp = (dvoid *) (rb->data); *alenpp = &(rb->datalen); *piecep = OCI_ONE_PIECE; *indpp = &(rb->indicator); *rcodepp = &(rb->rcode); return OCI_CONTINUE; } |
void _TASKINDEX_oracle_insert (WFTK_ADAPTOR * ad, XML * query) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; sword status; char namebuf[64]; const char *value; OCIBind *bindp = 0; XML * parm; XML * idparm = NULL; struct _TASKINDEX_oracle_insert_recvbuf rb; char returning[256]; if (!handles) return; if (!handles->ok) return; if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); parm = xml_firstelem (query); while (parm) { if (strcmp (parm->name, "parm")) continue; sprintf (namebuf, ":%s", xml_attrval (parm, "name")); value = xml_attrval (parm, "value"); if (*xml_attrval (parm, "returning")) { idparm = parm; rb.data = returning; memset (returning, sizeof(returning), '\0'); rb.datalen = sizeof(returning); rb.indicator = 0; rb.rcode = 0; OCIBindByName (stmthp, &bindp, handles->errhp, (text*)namebuf, strlen (namebuf), (dvoid *) 0, (sword) 256, SQLT_CHR, 0, 0, 0, 0, 0, OCI_DATA_AT_EXEC); OCIBindDynamic (bindp, handles->errhp, NULL, _TASKINDEX_oracle_insert_incallback, &rb, _TASKINDEX_oracle_insert_outcallback); } else { OCIBindByName (stmthp, &bindp, handles->errhp, (text*)namebuf, strlen (namebuf), (dvoid *) value, (sword) strlen (value) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); } parm = xml_nextelem (parm); } status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); if (status == 1) { xml_set (ad->parms, "error", "not unique"); } else if (status) { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } /*OCI_SUCCESS != (status = OCITransCommit(handles->svchp, handles->errhp, 0))*/ OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); if (idparm) { xml_set (idparm, "value", returning); } } } XML * TASKINDEX_oracle_insert (WFTK_ADAPTOR * ad, va_list args) { XML * query = (XML *) 0; if (args) query = va_arg (args, XML *); if (!query) { xml_set (ad->parms, "error", "No query given."); return (XML *) 0; } _TASKINDEX_oracle_insert (ad, query); return (XML *) 0; } |
void _TASKINDEX_oracle_delete (WFTK_ADAPTOR * ad, XML * query) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; sword status; char namebuf[64]; const char *value; OCIBind *bindp = 0; XML * parm; if (!handles) return; if (!handles->ok) return; if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); parm = xml_firstelem (query); while (parm) { if (strcmp (parm->name, "parm")) continue; sprintf (namebuf, ":%s", xml_attrval (parm, "name")); value = xml_attrval (parm, "value"); OCIBindByName (stmthp, &bindp, handles->errhp, (text*)namebuf, -1, (dvoid *) value, (sword) strlen (value) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); parm = xml_nextelem (parm); } status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); if (status == OCI_SUCCESS_WITH_INFO) { xml_set (ad->parms, "error", "not unique"); } else if (status) { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); } } XML * TASKINDEX_oracle_delete (WFTK_ADAPTOR * ad, va_list args) { XML * query = (XML *) 0; if (args) query = va_arg (args, XML *); if (!query) { xml_set (ad->parms, "error", "No query given."); return (XML *) 0; } _TASKINDEX_oracle_delete (ad, query); return (XML *) 0; } |
void _TASKINDEX_oracle_update (WFTK_ADAPTOR * ad, XML * query) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; OCIStmt * stmt2hp; sword status; char namebuf[64]; const char *value; ub4 rows; OCIBind *bindp = 0; XML * parm; if (!handles) return; if (!handles->ok) return; if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); parm = xml_firstelem (query); while (parm) { if (!strcmp (parm->name, "parm")) { sprintf (namebuf, ":%s", xml_attrval (parm, "name")); value = xml_attrval (parm, "value"); OCIBindByName (stmthp, &bindp, handles->errhp, (text*)namebuf, -1, (dvoid *) value, (sword) strlen (value) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); } parm = xml_nextelem (parm); } status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); if (!status) { OCIAttrGet ((dvoid *)stmthp, OCI_HTYPE_STMT, &rows, NULL, OCI_ATTR_ROW_COUNT, handles->errhp); if (rows == 0) { if (strcmp ("", xml_attrval (query, "fallback"))) { OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmt2hp, OCI_HTYPE_STMT, 0, 0); OCIStmtPrepare(stmt2hp, handles->errhp, (text *) xml_attrval (query, "fallback"), strlen(xml_attrval (query, "fallback")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); parm = xml_firstelem (query); while (parm) { if (!strcmp (parm->name, "parm")) { sprintf (namebuf, ":%s", xml_attrval (parm, "name")); value = xml_attrval (parm, "value"); OCIBindByName (stmt2hp, &bindp, handles->errhp, (text*)namebuf, -1, (dvoid *) value, (sword) strlen (value) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); } parm = xml_nextelem (parm); } status = OCIStmtExecute(handles->svchp, stmt2hp, handles->errhp, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); } } } if (status) { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); } } XML * TASKINDEX_oracle_update (WFTK_ADAPTOR * ad, va_list args) { XML * query = (XML *) 0; if (args) query = va_arg (args, XML *); if (!query) { xml_set (ad->parms, "error", "No query given."); return (XML *) 0; } _TASKINDEX_oracle_update (ad, query); return (XML *) 0; } |
<sql query="select * from task where user=:owner" element="task" unique="no"> <map owner="user" description="label"/> <parm name="owner" value="ford_prefect"/> </sql>This retrieves all tasks belonging to Ford Prefect, and maps "owner" onto "user", etc. Other fields are simply copied into the new task elements by name. A second example, this one a retrieval query:
<sql query="select * from task where process=:process and id=:id" element="task" unique="yes"> <map owner="user" description="label"/> <parm name="process" value="48"/> <parm name="id" value="10"/> </sql>This retrieves task 10 from process 48 and returns the task as its return value.
XML * _TASKINDEX_oracle_select (WFTK_ADAPTOR * ad, XML * query, XML * list) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; sword status; char namebuf[64]; const char *value; OCIBind *bindp = 0; OCIDefine *defnp = 0; XML * parm; XML * map = NULL; OCIParam * parhp; ub4 cols; ub4 counter; ub4 len; char ** names; char ** mapped; char ** values; sb2 * indicators; ub2 * sizes; XML * ret; const char * element; const char * name; int rows = 0; if (!handles) return (list); if (!handles->ok) return (list); if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); parm = xml_firstelem (query); while (parm) { if (!strcmp (parm->name, "map")) map = parm; /* Stash name mapping if found. */ if (!strcmp (parm->name, "parm")) { sprintf (namebuf, ":%s", xml_attrval (parm, "name")); value = xml_attrval (parm, "value"); OCIBindByName (stmthp, &bindp, handles->errhp, (text*)namebuf, -1, (dvoid *) value, (sword) strlen (value) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); } parm = xml_nextelem (parm); } status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 0, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); if (status) { if (status != OCI_NO_DATA) { /* No rows are just no rows. Not an error. */ _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } } else { /* Retrieve data! */ /* -- First, get all the names and sizes of the data, and allocate room and define it to the statement. */ OCIAttrGet((dvoid*) stmthp, OCI_HTYPE_STMT, (dvoid*) &cols,(ub4 *) 0, (ub4) OCI_ATTR_PARAM_COUNT, handles->errhp); names = (char **) malloc (cols * sizeof (char *)); mapped = (char **) malloc (cols * sizeof (char *)); values = (char **) malloc (cols * sizeof (char *)); sizes = (ub2 *) malloc (cols * sizeof (ub2)); indicators = (sb2 *) malloc (cols * sizeof (sb2)); for (counter = 1; counter <= cols; counter++) { OCIParamGet(stmthp, OCI_HTYPE_STMT, handles->errhp, &parhp, counter); len = 64; names[counter - 1] = (char *) malloc (len + 1); OCIAttrGet((dvoid*) parhp, OCI_DTYPE_PARAM, (dvoid*) &name,(ub4 *) &len, (ub4) OCI_ATTR_NAME, handles->errhp); if (len > 64) len = 64; /* Just in case somebody someday goes a little overboard with naming, we don't want a buffer overflow. */ strncpy (names[counter-1], name, (size_t) len); names[counter-1][len] = '\0'; strlwr (names[counter-1]); if (map) { mapped[counter - 1] = (char *) xml_attrval (map, names[counter - 1]); if (!*mapped[counter - 1]) mapped[counter - 1] = names[counter - 1]; } else { mapped[counter - 1] = names[counter - 1]; } if (strcmp (mapped[counter - 1], "!hide")) { OCIAttrGet((dvoid*) parhp, OCI_DTYPE_PARAM, (dvoid*) &(sizes[counter-1]), 0, OCI_ATTR_DATA_SIZE, handles->errhp); if (sizes[counter-1] < 32) sizes[counter-1] = 32; /* Dates return 7 bytes, but expand when converted to strings. */ values[counter - 1] = (char *) malloc (sizes[counter-1] + 1); OCIDefineByPos (stmthp, &defnp, handles->errhp, counter, values[counter-1], sizes[counter-1] + 1, SQLT_STR, &indicators[counter-1], 0, 0, OCI_DEFAULT); } } /* -- OK, now fetch until there are no more rows. */ while (OCI_SUCCESS == (status = OCIStmtFetch (stmthp, handles->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT))) { rows ++; element = xml_attrval (query, "element"); if (!*element) element = "elem"; ret = xml_create (element); if (list) xml_append (list, ret); for (counter = 0; counter < cols; counter++) { if (strcmp (mapped[counter], "!hide")) { if (indicators[counter] != -1) { xml_set (ret, mapped[counter], values[counter]); } else { xml_set (ret, mapped[counter], ""); } } } } if (list) xml_setnum (list, "count", rows); if (status == -1) _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); /* -- Free up our temporary space. */ for (counter = 0; counter < cols; counter++) { free ((void *) names[counter]); free ((void *) mapped[counter]); free ((void *) values[counter]); } free ((void *) names); free ((void *) sizes); free ((void *) indicators); free ((void *) values); } OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); } return (ret); /* Note side effect: last row retrieved is always returned. */ } XML * TASKINDEX_oracle_select (WFTK_ADAPTOR * ad, va_list args) { XML * query = (XML *) 0; XML * list = (XML *) 0; if (args) query = va_arg (args, XML *); if (!query) { xml_set (ad->parms, "error", "No query given."); return (XML *) 0; } list = va_arg (args, XML *); return (_TASKINDEX_oracle_select (ad, query, list)); } |
void _TASKINDEX_oracle_xmlput (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col, XML * val) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; sword status; OCIBind *bindp = 0; OCIDefine *defnp = 0; OCILobLocator *clob; OCIParam * parhp; sb2 indicator; const char *value; int valuelen; XML * query; if (!handles) return; if (!handles->ok) return; if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { value = xml_string (val); /* Yeah, OK, I'm lazy here. TODO: write proper handler, like I said I would. */ valuelen = strlen (value); query = xml_create ("sql"); /* We can't write to a NULL lob. So let's make sure if it's NULL, we make it empty instead. */ xml_setf (query, "query", "update %s set %s=empty_clob() where %s=:keyval and %s is null", table, col, keycol, col); OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); OCIBindByName (stmthp, &bindp, handles->errhp, ":keyval", -1, keyval, strlen(keyval) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); xml_setf (query, "query", "select %s from %s where %s=:keyval for update", col, table, keycol); OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); OCIBindByName (stmthp, &bindp, handles->errhp, ":keyval", -1, keyval, strlen(keyval) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 0, 0, NULL, NULL, OCI_DEFAULT); if (status) { if (status != OCI_NO_DATA) { xml_setf (ad->parms, "error", "Unable to locate %s with %s '%s'", table, keycol, keyval); } else { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } } else { /* Retrieve data! */ status = OCIDescriptorAlloc(handles->envhp, &clob, OCI_DTYPE_LOB, 0, 0); status = OCIDefineByPos (stmthp, &defnp, handles->errhp, 1, &clob, -1, SQLT_CLOB, &indicator, 0, 0, OCI_DEFAULT); if (OCI_SUCCESS == (status = OCIStmtFetch (stmthp, handles->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT))) { status = OCILobWrite(handles->svchp, handles->errhp, clob, &valuelen, 1, (dvoid *) value, valuelen, OCI_ONE_PIECE, 0, 0, 0, SQLCS_IMPLICIT); } if (status != OCI_SUCCESS) { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } OCIDescriptorFree (clob, OCI_DTYPE_LOB); } OCITransCommit(handles->svchp, handles->errhp, 0); OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); xml_free (query); free (value); } return; } XML * TASKINDEX_oracle_xmlput (WFTK_ADAPTOR * ad, va_list args) { char * table = NULL; char * keycol = NULL; char * keyval = NULL; char * col = NULL; XML * val = (XML *) 0; if (!args) return (XML *) 0; table = va_arg (args, char *); keycol = va_arg (args, char *); keyval = va_arg (args, char *); col = va_arg (args, char *); val = va_arg (args, XML *); _TASKINDEX_oracle_xmlput (ad, table, keycol, keyval, col, val); return (XML *) 0; } |
struct _TASKINDEX_oracle_xmlget_structure { struct _TASKINDEX_oracle_handles *handles; OCILobLocator *clob; ub4 offset; sword status; }; size_t _TASKINDEX_oracle_xmlget_fetch (char * buf, size_t chunk, size_t num, void * st) { XML * error; struct _TASKINDEX_oracle_xmlget_structure *state = (struct _TASKINDEX_oracle_xmlget_structure *) st; ub4 value_len = 0; state->status = OCILobRead(state->handles->svchp, state->handles->errhp, state->clob, &value_len, state->offset, (dvoid *) buf, num*chunk, 0, 0, 0, SQLCS_IMPLICIT); state->offset += value_len; if (state->status == OCI_NEED_DATA) return num; /* There is more. */ if (state->status == OCI_SUCCESS) return value_len / chunk; /* Retrieved a partial piece. */ return 0; /* Error. I wonder what will happen? */ } XML * _TASKINDEX_oracle_xmlget (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; sword status; OCIBind *bindp = 0; OCIDefine *defnp = 0; OCILobLocator *clob; OCIParam * parhp; sb2 indicator; struct _TASKINDEX_oracle_xmlget_structure state; XML * query; XML * ret = NULL; char * stuff; ub4 loblen; if (!handles) return ((XML *) 0); if (!handles->ok) return ((XML *) 0); if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { query = xml_create ("sql"); xml_setf (query, "query", "select %s from %s where %s=:keyval", col, table, keycol); OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); OCIBindByName (stmthp, &bindp, handles->errhp, ":keyval", -1, keyval, strlen(keyval) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 0, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); if (status) { if (status != OCI_NO_DATA) { xml_setf (ad->parms, "error", "Unable to locate %s with %s '%s'", table, keycol, keyval); } else { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } } else { /* Retrieve data! */ status = OCIDescriptorAlloc(handles->envhp, &clob, OCI_DTYPE_LOB, 0, 0); OCIDefineByPos (stmthp, &defnp, handles->errhp, 1, (dvoid *) &clob, -1, SQLT_CLOB, &indicator, 0, 0, OCI_DEFAULT); if (OCI_SUCCESS == (status = OCIStmtFetch (stmthp, handles->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT))) { if (indicator == -1) { /* NULL clob */ ret = NULL; } else { state.handles = handles; state.offset = 1; state.clob = clob; ret = xml_parse_general ((void *) &state, _TASKINDEX_oracle_xmlget_fetch); if (ret) { if (xml_is (ret, "xml-error")) { if (xml_attrvalnum (ret, "code") != 3) { xml_setf (ad->parms, "error", "Unable to parse %s from %s with %s '%s': (%s) %s", col, table, keycol, keyval, xml_attrval (ret, "code"), xml_attrval (ret, "message")); } xml_free (ret); ret = NULL; } } else { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } } } else { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } OCIDescriptorFree (clob, OCI_DTYPE_LOB); } OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); xml_free (query); } return ret; } XML * TASKINDEX_oracle_xmlget (WFTK_ADAPTOR * ad, va_list args) { char * table = NULL; char * keycol = NULL; char * keyval = NULL; char * col = NULL; if (!args) return (XML *) 0; table = va_arg (args, char *); keycol = va_arg (args, char *); keyval = va_arg (args, char *); col = va_arg (args, char *); return _TASKINDEX_oracle_xmlget (ad, table, keycol, keyval, col); } |
void _TASKINDEX_oracle_colput (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col, char * value) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; XML * query; sword status; OCIBind *bindp = 0; if (!handles) return; if (!handles->ok) return; if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { query = xml_create ("sql"); xml_setf (query, "query", "update %s set %s=:val where %s=:keyval", table, col, keycol); OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); OCIBindByName (stmthp, &bindp, handles->errhp, ":val", -1, value, strlen(value) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); OCIBindByName (stmthp, &bindp, handles->errhp, ":keyval", -1, keyval, strlen(keyval) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 1, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); if (status) { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); xml_free (query); } } XML * TASKINDEX_oracle_colput (WFTK_ADAPTOR * ad, va_list args) { char * table = NULL; char * keycol = NULL; char * keyval = NULL; char * col = NULL; char * value = NULL; if (!args) return (XML *) 0; table = va_arg (args, char *); keycol = va_arg (args, char *); keyval = va_arg (args, char *); col = va_arg (args, char *); value = va_arg (args, char *); _TASKINDEX_oracle_colput (ad, table, keycol, keyval, col, value); return (XML *) 0; } |
XML * _TASKINDEX_oracle_colget (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col) { struct _TASKINDEX_oracle_handles *handles = (struct _TASKINDEX_oracle_handles *) ad->bindata; OCIStmt * stmthp; sword status; OCIBind *bindp = 0; OCIDefine *defnp = 0; char valuebuf[256]; OCIParam * parhp; sb2 indicator; XML * query; XML * ret = NULL; if (!handles) return ((XML *) 0); if (!handles->ok) return ((XML *) 0); if (OCI_SUCCESS == (status = OCIHandleAlloc ((dvoid *) (handles->envhp), (dvoid **) &stmthp, OCI_HTYPE_STMT, 0, 0))) { query = xml_create ("sql"); xml_setf (query, "query", "select %s from %s where %s=:keyval", col, table, keycol); OCIStmtPrepare(stmthp, handles->errhp, (text *) xml_attrval (query, "query"), strlen(xml_attrval (query, "query")), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); OCIBindByName (stmthp, &bindp, handles->errhp, ":keyval", -1, keyval, strlen(keyval) + 1, SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT); status = OCIStmtExecute(handles->svchp, stmthp, handles->errhp, 0, 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS); if (status) { if (status != OCI_NO_DATA) { xml_setf (ad->parms, "error", "Unable to locate %s with %s '%s'", table, keycol, keyval); } else { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } } else { /* Retrieve data! */ OCIDefineByPos (stmthp, &defnp, handles->errhp, 1, valuebuf, sizeof(valuebuf), SQLT_STR, &indicator, 0, 0, OCI_DEFAULT); if (OCI_SUCCESS == (status = OCIStmtFetch (stmthp, handles->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT))) { ret = xml_create ("value"); xml_set (ret, "value", valuebuf); } else { _TASKINDEX_oracle_builderrmsg (ad->parms, "Oracle error", (dvoid *) (handles->errhp), status); } } OCIHandleFree((dvoid *) (handles->envhp), OCI_HTYPE_STMT); xml_free (query); } return ret; } XML * TASKINDEX_oracle_colget (WFTK_ADAPTOR * ad, va_list args) { char * table = NULL; char * keycol = NULL; char * keyval = NULL; char * col = NULL; if (!args) return (XML *) 0; table = va_arg (args, char *); keycol = va_arg (args, char *); keyval = va_arg (args, char *); col = va_arg (args, char *); return _TASKINDEX_oracle_colget (ad, table, keycol, keyval, col); } |
XML * TASKINDEX_oracle_procnew (WFTK_ADAPTOR * ad, va_list args) { XML * datasheet = (XML *) 0; XML * sql; XML * parm; XML * idparm = NULL; if (args) datasheet = va_arg (args, XML *); if (!datasheet) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); if (*xml_attrval (datasheet, "id")) { xml_set (sql, "query", "insert into process (id, title, status, started) values (:id, :title, :status, SYSDATE)"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (datasheet, "id")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "title"); xml_set (parm, "value", xml_attrval (datasheet, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", xml_attrval (datasheet, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ xml_append (sql, parm); } else { xml_set (sql, "query", "insert into process (id, title, status, started) values ('auto' || process_id.nextval, :title, :status, SYSDATE) RETURNING id into :id"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (datasheet, "id")); xml_set (parm, "returning", "yes"); xml_append (sql, parm); idparm = parm; parm = xml_create ("parm"); xml_set (parm, "name", "title"); xml_set (parm, "value", xml_attrval (datasheet, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", xml_attrval (datasheet, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ xml_append (sql, parm); } _TASKINDEX_oracle_insert (ad, sql); if (idparm) { xml_set (datasheet, "id", xml_attrval (idparm, "value")); } xml_free (sql); return (XML *) 0; } |
SYSDATE
there. Under ODBC, that's {NOW()}
, and it's different on every database. Now, granted, ODBC's main purpose is to
abstract away some of this rubbish and work with any database, but it makes me uncomfortable. Microsoft doesn't ever quite finish
anything, and although I know there's OpenODBC on Unix, I don't know how stable it is. Anyway, on with the show.
XML * TASKINDEX_oracle_procdel (WFTK_ADAPTOR * ad, va_list args) { char *id = NULL; XML * sql; XML * parm; if (args) id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "delete from process where id=:id"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_delete (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_procget (WFTK_ADAPTOR * ad, va_list args) { char * id = NULL; XML * sql; XML * parm; XML * proc = (XML *) 0; char * stuff; if (args) id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "element", "proc"); xml_set (sql, "query", "select * from process where id=:id"); parm = xml_create ("map"); xml_set (parm, "title", "label"); xml_set (parm, "owner", "user"); xml_set (parm, "datasheet", "!hide"); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); proc = _TASKINDEX_oracle_select (ad, sql, NULL); xml_free (sql); return proc; } XML * TASKINDEX_oracle_procput (WFTK_ADAPTOR * ad, va_list args) { XML * datasheet = NULL; XML * sql; XML * parm; XML * idparm = NULL; if (args) datasheet = va_arg (args, XML *); if (!datasheet) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); if (*xml_attrval (datasheet, "id")) { xml_set (sql, "query", "update process set title=:title, status=:status where id=:id"); xml_set (sql, "fallback", "insert into process (id, title, status, started) values (:id, :title, :status, SYSDATE)"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (datasheet, "id")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "title"); xml_set (parm, "value", xml_attrval (datasheet, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", xml_attrval (datasheet, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); } else { /* We treat this as a plain old procnew with no ID. */ xml_set (sql, "query", "insert into process (id, title, status, started) values ('auto' || process_id.nextval, :title, :status, SYSDATE) RETURNING id into :id"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (datasheet, "id")); xml_set (parm, "returning", "yes"); xml_append (sql, parm); idparm = parm; parm = xml_create ("parm"); xml_set (parm, "name", "title"); xml_set (parm, "value", xml_attrval (datasheet, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", xml_attrval (datasheet, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ xml_append (sql, parm); _TASKINDEX_oracle_insert (ad, sql); xml_set (datasheet, "id", xml_attrval (idparm, "value")); } xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_proclist (WFTK_ADAPTOR * ad, va_list args) { XML * list = (XML *) 0; XML * sql; XML * parm; XML * ret; const char * field; int fields = 0; char query[1024]; if (args) list = va_arg (args, XML *); if (!list) { xml_set (ad->parms, "error", "No list specified."); return (XML *) 0; } sql = xml_create ("sql"); parm = xml_create ("map"); xml_set (parm, "title", "label"); xml_set (parm, "owner", "user"); xml_set (parm, "datasheet", "!hide"); xml_append (sql, parm); strcpy (query, "select * from process where "); field = xml_attrval (list, "status"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "status=:status "); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "user"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "owner=:owner "); parm = xml_create ("parm"); xml_set (parm, "name", "owner"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "where"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, field); } if (fields) { xml_set (sql, "query", query); } else { xml_set (sql, "query", "select * from process"); } xml_set (sql, "element", "process"); ret = _TASKINDEX_oracle_select (ad, sql, list); xml_free (sql); return ret; return (XML *) 0; } XML * TASKINDEX_oracle_proccomplete (WFTK_ADAPTOR * ad, va_list args) { char * id = NULL; XML * sql; XML * parm; if (args) id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "update process set status='complete', completed=SYSDATE where id=:id"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_procerror (WFTK_ADAPTOR * ad, va_list args) { char * id = NULL; XML * sql; XML * parm; if (args) id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "update process set status='error' where id=:id"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); xml_free (sql); return (XML *) 0; } |
XML * TASKINDEX_oracle_tasknew (WFTK_ADAPTOR * ad, va_list args) { XML * datasheet = (XML *) 0; XML * sql; XML * parm; if (args) datasheet = va_arg (args, XML *); if (!datasheet) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "insert into task (id, process, status, description, role, owner, created) values (:id, :process, 'active', :label, :role, :owner, SYSDATE)"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (datasheet, "id")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", xml_attrval (datasheet, "process")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "label"); xml_set (parm, "value", xml_attrval (datasheet, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "role"); xml_set (parm, "value", xml_attrval (datasheet, "role")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "owner"); xml_set (parm, "value", xml_attrval (datasheet, "user")); xml_append (sql, parm); _TASKINDEX_oracle_insert (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_taskdel (WFTK_ADAPTOR * ad, va_list args) { XML * task = (XML *) 0; char *process; char *id; XML * sql; XML * parm; if (args) process = va_arg (args, char *); if (!process) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "delete from task where process=:process and id=:id"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_delete (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_taskget (WFTK_ADAPTOR * ad, va_list args) { char * process = NULL; char * id = NULL; XML * sql; XML * parm; XML * proc = (XML *) 0; char * stuff; if (args) process = va_arg (args, char *); if (!process) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No task ID given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "element", "task"); xml_set (sql, "query", "select * from task where process=:process and id=:id"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); proc = _TASKINDEX_oracle_select (ad, sql, NULL); xml_free (sql); return proc; } XML * TASKINDEX_oracle_taskput (WFTK_ADAPTOR * ad, va_list args) { XML * task = (XML *) 0; XML * sql; XML * parm; if (args) task = va_arg (args, XML *); if (!task) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "update task set description=:label, role=:role, owner=:owner, status=:status where process=:process and id=:id"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", xml_attrval (task, "process")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (task, "id")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "label"); xml_set (parm, "value", xml_attrval (task, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "role"); xml_set (parm, "value", xml_attrval (task, "role")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "owner"); xml_set (parm, "value", xml_attrval (task, "user")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", xml_attrval (task, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); return (XML *) 0; } XML * TASKINDEX_oracle_tasklist (WFTK_ADAPTOR * ad, va_list args) { XML * list = (XML *) 0; XML * sql; XML * parm; XML * ret; const char * field; int fields = 0; char query[1024]; if (args) list = va_arg (args, XML *); if (!list) { xml_set (ad->parms, "error", "No list specified."); return (XML *) 0; } sql = xml_create ("sql"); parm = xml_create ("map"); xml_set (parm, "description", "label"); xml_set (parm, "owner", "user"); xml_append (sql, parm); strcpy (query, "select * from task where "); field = xml_attrval (list, "process"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "process=:process "); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "status"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "status=:status "); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "role"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "role=:role "); parm = xml_create ("parm"); xml_set (parm, "name", "role"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "user"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "owner=:owner "); parm = xml_create ("parm"); xml_set (parm, "name", "owner"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "where"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, field); } if (fields) { xml_set (sql, "query", query); } else { xml_set (sql, "query", "select * from task"); } xml_set (sql, "element", "task"); ret = _TASKINDEX_oracle_select (ad, sql, list); xml_free (sql); return ret; } XML * TASKINDEX_oracle_taskcomplete (WFTK_ADAPTOR * ad, va_list args) { char * process = NULL; char * id = NULL; XML * sql; XML * parm; if (args) process = va_arg (args, char *); if (!process) process = ""; if (args) id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "update task set status='complete', complete=SYSDATE where process=:process and id=:id and status='active'"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_taskreject (WFTK_ADAPTOR * ad, va_list args) { char * process = NULL; char * id = NULL; XML * sql; XML * parm; if (args) process = va_arg (args, char *); if (!process) process = ""; if (args) id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "update task set status='reject' where process=:process and id=:id and status='active'"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); xml_free (sql); return (XML *) 0; } |
XML * TASKINDEX_oracle_reqnew (WFTK_ADAPTOR * ad, va_list args) { XML * datasheet = (XML *) 0; XML * sql; XML * parm; char * query = "insert into task (id, title, status, started) values (:1, :2, :3, SYSDATE)"; if (args) datasheet = va_arg (args, XML *); if (!datasheet) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "insert into task (id, process, status, description, role, owner, created) values (:id, :process, 'request', :label, :role, :owner, SYSDATE)"); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (datasheet, "id")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", xml_attrval (datasheet, "process")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "label"); xml_set (parm, "value", xml_attrval (datasheet, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "role"); xml_set (parm, "value", xml_attrval (datasheet, "role")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "owner"); xml_set (parm, "value", xml_attrval (datasheet, "of")); xml_append (sql, parm); _TASKINDEX_oracle_insert (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_reqdel (WFTK_ADAPTOR * ad, va_list args) { XML * task = (XML *) 0; char *process; char *id; XML * sql; XML * parm; if (args) process = va_arg (args, char *); if (!process) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "delete from task where process=:process and id=:id and status='request'"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_delete (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_reqget (WFTK_ADAPTOR * ad, va_list args) { char * process = NULL; char * id = NULL; XML * sql; XML * parm; XML * proc = (XML *) 0; char * stuff; if (args) process = va_arg (args, char *); if (!process) { xml_set (ad->parms, "error", "No process given."); return (XML *) 0; } id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No request ID given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "element", "request"); xml_set (sql, "query", "select * from request where process=:process and id=:id and status='request'"); parm = xml_create ("map"); xml_set (parm, "owner", "of"); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); proc = _TASKINDEX_oracle_select (ad, sql, NULL); xml_free (sql); return proc; } XML * TASKINDEX_oracle_reqput (WFTK_ADAPTOR * ad, va_list args) { XML * task = (XML *) 0; XML * sql; XML * parm; if (args) task = va_arg (args, XML *); if (!task) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "update task set description=:label, role=:role, owner=:owner where process=:process and id=:id"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", xml_attrval (task, "process")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", xml_attrval (task, "id")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "label"); xml_set (parm, "value", xml_attrval (task, "label")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "role"); xml_set (parm, "value", xml_attrval (task, "role")); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "owner"); xml_set (parm, "value", xml_attrval (task, "of")); xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); return (XML *) 0; } XML * TASKINDEX_oracle_reqlist (WFTK_ADAPTOR * ad, va_list args) { XML * list = (XML *) 0; XML * sql; XML * parm; XML * ret; const char * field; int fields = 0; char query[1024]; if (args) list = va_arg (args, XML *); if (!list) { xml_set (ad->parms, "error", "No list specified."); return (XML *) 0; } sql = xml_create ("sql"); parm = xml_create ("map"); xml_set (parm, "description", "label"); xml_set (parm, "owner", "user"); xml_append (sql, parm); strcpy (query, "select * from task where status='request' "); field = xml_attrval (list, "process"); if (*field) { fields++; strcat (query, "and process=:process "); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "status"); if (*field) { fields++; strcat (query, "and status=:status "); parm = xml_create ("parm"); xml_set (parm, "name", "status"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "role"); if (*field) { fields++; strcat (query, "and role=:role "); parm = xml_create ("parm"); xml_set (parm, "name", "role"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "user"); if (*field) { fields++; strcat (query, "and owner=:owner "); parm = xml_create ("parm"); xml_set (parm, "name", "owner"); xml_set (parm, "value", field); xml_append (sql, parm); } field = xml_attrval (list, "where"); if (*field) { fields++; strcat (query, "and "); strcat (query, field); } if (fields) { xml_set (sql, "query", query); } xml_set (sql, "element", "task"); ret = _TASKINDEX_oracle_select (ad, sql, list); xml_free (sql); return ret; } XML * TASKINDEX_oracle_reqaccept (WFTK_ADAPTOR * ad, va_list args) { char * process = NULL; char * id = NULL; XML * sql; XML * parm; if (args) process = va_arg (args, char *); if (!process) process = ""; if (args) id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "update task set status='active' where process=:process and id=:id and status='request'"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_update (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_oracle_reqdecline (WFTK_ADAPTOR * ad, va_list args) { XML * task = (XML *) 0; char *process; char *id; XML * sql; XML * parm; if (args) process = va_arg (args, char *); if (!process) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } id = va_arg (args, char *); if (!id) { xml_set (ad->parms, "error", "No task given."); return (XML *) 0; } sql = xml_create ("sql"); xml_set (sql, "query", "delete from task where process=:process and id=:id and status='request'"); parm = xml_create ("parm"); xml_set (parm, "name", "process"); xml_set (parm, "value", process); xml_append (sql, parm); parm = xml_create ("parm"); xml_set (parm, "name", "id"); xml_set (parm, "value", id); xml_append (sql, parm); _TASKINDEX_oracle_delete (ad, sql); xml_free (sql); return (XML *) 0; } |
This code and documentation are released under the terms of the GNU license. They are additionally copyright (c) 2000, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license. This presentation was prepared with LPML. Try literate programming. You'll like it. |