#include <stdio.h> #include <stdarg.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <io.h> #include <errno.h> #include <windows.h> /* Boy, *this* feels weird! */ #include <sql.h> #include <sqlext.h> #include <sqltypes.h> #include "xmlapi.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_odbc_init (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_free (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_info (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_insert (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_select (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_update (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_delete (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_colget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_colput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_xmlget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_xmlput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_procnew (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_procdel (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_procget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_procput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_proclist (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_proccomplete (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_procerror (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_tasknew (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_taskdel (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_taskget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_taskput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_tasklist (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_taskcomplete (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_taskreject (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_reqnew (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_reqdel (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_reqget (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_reqput (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_reqlist (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_reqaccept (WFTK_ADAPTOR * ad, va_list args); XML * TASKINDEX_odbc_reqdecline (WFTK_ADAPTOR * ad, va_list args); static WFTK_API_FUNC vtab[] = { TASKINDEX_odbc_init, TASKINDEX_odbc_free, TASKINDEX_odbc_info, TASKINDEX_odbc_insert, TASKINDEX_odbc_select, TASKINDEX_odbc_update, TASKINDEX_odbc_delete, TASKINDEX_odbc_colget, TASKINDEX_odbc_colput, TASKINDEX_odbc_xmlget, TASKINDEX_odbc_xmlput, TASKINDEX_odbc_procnew, TASKINDEX_odbc_procdel, TASKINDEX_odbc_procget, TASKINDEX_odbc_procput, TASKINDEX_odbc_proclist, TASKINDEX_odbc_proccomplete, TASKINDEX_odbc_procerror, TASKINDEX_odbc_tasknew, TASKINDEX_odbc_taskdel, TASKINDEX_odbc_taskget, TASKINDEX_odbc_taskput, TASKINDEX_odbc_tasklist, TASKINDEX_odbc_taskcomplete, TASKINDEX_odbc_taskreject, TASKINDEX_odbc_reqnew, TASKINDEX_odbc_reqdel, TASKINDEX_odbc_reqget, TASKINDEX_odbc_reqput, TASKINDEX_odbc_reqlist, TASKINDEX_odbc_reqaccept, TASKINDEX_odbc_reqdecline }; static struct adaptor_info _TASKINDEX_odbc_info = { 32, names, vtab }; |
struct adaptor_info * TASKINDEX_odbc_get_info () { return & _TASKINDEX_odbc_info; } |
bindata
member
of the WFTK_ADAPTOR
structure.
struct _TASKINDEX_odbc_handles { SQLHENV henv; SQLHDBC hdbc; int ok; }; XML * TASKINDEX_odbc_init (WFTK_ADAPTOR * ad, va_list args) { SQLRETURN rslt; const char * parms; char spec[256]; char buf[1024]; SQLSMALLINT junk; struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) malloc (sizeof (struct _TASKINDEX_odbc_handles)); if (!handles) { xml_set (ad->parms, "error", "Unable to allocate binary stash."); return (XML *) 0; } ad->bindata = (void *) handles; handles->henv = SQL_NULL_HANDLE; handles->hdbc = SQL_NULL_HANDLE; handles->ok = 0; parms = xml_attrval (ad->parms, "parm"); if (!*parms) parms = config_get_value (ad->session, "taskindex.odbc.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; } strcpy (spec, "odbc:"); strcat (spec, parms); xml_set (ad->parms, "spec", spec); if (strchr (parms, '=')) { xml_set (ad->parms, "conn", parms); } else { sprintf (buf, "taskindex.odbc.%s.conn", parms); xml_set (ad->parms, "conn", config_get_value (ad->session, buf)); } /* OK, let's connect to this database specified. */ rslt = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(handles->henv)); /* My first C ODBC statement ever! */ if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "Unable to allocate ODBC environment handle."); free ((void *) handles); ad->bindata = 0; return (XML *) 0; } SQLSetEnvAttr (handles->henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC2, 0); rslt = SQLAllocHandle (SQL_HANDLE_DBC, handles->henv, &(handles->hdbc)); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "Unable to allocate ODBC connection handle."); SQLFreeHandle (SQL_HANDLE_ENV, handles->henv); free ((void *) handles); ad->bindata = 0; return (XML *) 0; } rslt = SQLDriverConnect (handles->hdbc, NULL, (char *) xml_attrval (ad->parms, "conn"), (SQLSMALLINT) strlen (xml_attrval (ad->parms, "conn")), buf, (SQLSMALLINT) sizeof(buf), &junk, SQL_DRIVER_NOPROMPT); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "Unable to connect to database specified."); SQLFreeHandle (SQL_HANDLE_DBC, handles->hdbc); SQLFreeHandle (SQL_HANDLE_ENV, handles->henv); free ((void *) handles); ad->bindata = 0; return (XML *) 0; } handles->ok = 1; return (XML *) 0; } |
XML * TASKINDEX_odbc_free (WFTK_ADAPTOR * ad, va_list args) { struct _TASKINDEX_odbc_handles * handles = (struct _TASKINDEX_odbc_handles *) (ad->bindata); if (handles) { SQLDisconnect (handles->hdbc); SQLFreeHandle (SQL_HANDLE_DBC, handles->hdbc); SQLFreeHandle (SQL_HANDLE_ENV, handles->henv); free (handles); ad->bindata = (void *) 0; } return (XML *) 0; } |
XML * TASKINDEX_odbc_info (WFTK_ADAPTOR * ad, va_list args) { XML * info; info = xml_create ("info"); xml_set (info, "type", "taskindex"); xml_set (info, "name", "odbc"); 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); } |
SQLGetDiagRec
call.
void _TASKINDEX_odbc_builderrmsg (XML * ap, SQLHSTMT stmt) { char buf[1024]; char msg[128]; SQLSMALLINT len; char code[16]; SQLINTEGER native; SQLGetDiagRec (SQL_HANDLE_STMT, stmt, 1, code, &native, msg, sizeof(msg), &len); sprintf (buf, "%s[%s %d] %s", xml_attrval (ap, "error"), code, native, msg); xml_set (ap, "error", buf); } |
<sql query="insert into process (id, title, status, started) values (?, ?, ?, {fn NOW()})"> <value name="id" return="yes"> <value name="title" value="My Process"> <value name="status" value="active"> </sql>This form asks the adaptor to generate a value for id and make sure it's unique. The only really disappointing thing here is that the query is still adaptor-specific. So insertion of a process by the dsrep-on-db adaptor is still going to require the taskindex adaptor to do the procnew. Thus procnew needs to be aware of the case where we call it with no key. And it has to be careful not to re-add the row when called later. Tricky indeed. I'm not entirely sure how I'll solve it.
void _TASKINDEX_odbc_insert (WFTK_ADAPTOR * ad, XML * query) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; SQLHSTMT stmt; SQLRETURN rslt; char namebuf[64]; char state[6]; char unique[32]; char buf[1024]; SQLSMALLINT junk; XML * ret = NULL; UWORD i; int ir; SDWORD * len; const char *value; XML * parm; if (!handles) return; if (!handles->ok) return; rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { parm = xml_firstelem (query); i = 1; while (parm) { if (xml_is (parm, "parm")) i++; parm = xml_nextelem (parm); } len = malloc (i * sizeof (int)); parm = xml_firstelem(query); i = 1; while (parm) { if (xml_is (parm, "parm")) { if (!*xml_attrval (parm, "return")) { len[i] = strlen (xml_attrval (parm, "value")); SQLBindParameter (stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, len[i], 0, (void *) xml_attrval (parm, "value"), len[i], &(len[i])); } else { len[i] = sizeof(unique) - 1; ir = i; SQLBindParameter (stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof (unique) - 1, 0, (void *) unique, sizeof (unique)-1, &(len[i])); srand ((unsigned) time (NULL)); ret = parm; } i++; } parm = xml_nextelem (parm); } rslt = SQL_ERROR; while (rslt == SQL_ERROR) { if (ret) { sprintf (unique, "%d%d", time(NULL), rand() * 100 / RAND_MAX); len[ir] = strlen (unique); xml_set (ret, "value", unique); } rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt == SQL_ERROR) { SQLError (SQL_NULL_HENV, SQL_NULL_HDBC, stmt, state, NULL, NULL, 0, 0); if (strcmp (state, "23000") || !ret) { /* Integrity constraint: try again. */ xml_set (ad->parms, "error", "SQL error performing insertion "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); break; } } } SQLTransact (handles->henv, handles->hdbc, SQL_COMMIT); SQLFreeHandle (SQL_HANDLE_STMT, stmt); } return; } XML * TASKINDEX_odbc_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_odbc_insert (ad, query); return (XML *) 0; } |
void _TASKINDEX_odbc_delete (WFTK_ADAPTOR * ad, XML * query) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; SQLHSTMT stmt; SQLRETURN rslt; char namebuf[64]; UWORD i; SDWORD * len; const char *value; XML * parm; if (!handles) return; if (!handles->ok) return; rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { parm = xml_firstelem (query); i = 1; while (parm) { if (xml_is (parm, "parm")) i++; parm = xml_nextelem (parm); } len = malloc (i * sizeof (int)); parm = xml_firstelem(query); i = 1; while (parm) { if (xml_is (parm, "parm")) { len[i] = strlen (xml_attrval (parm, "value")); SQLBindParameter (stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, len[i], 0, (void *) xml_attrval (parm, "value"), len[i], &(len[i])); i++; } parm = xml_nextelem (parm); } rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "SQL error performing delete "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); } SQLTransact (handles->henv, handles->hdbc, SQL_COMMIT); SQLFreeHandle (SQL_HANDLE_STMT, stmt); } return; } XML * TASKINDEX_odbc_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_odbc_delete (ad, query); return (XML *) 0; } |
void _TASKINDEX_odbc_update (WFTK_ADAPTOR * ad, XML * query) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; SQLHSTMT stmt; SQLHSTMT stmt2; SQLRETURN rslt; SDWORD rows; char namebuf[64]; UWORD i; SDWORD * len; const char *value; XML * parm; if (!handles) return; if (!handles->ok) return; rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { parm = xml_firstelem (query); i = 1; while (parm) { if (xml_is (parm, "parm")) i++; parm = xml_nextelem (parm); } len = malloc (i * sizeof (int)); parm = xml_firstelem(query); i = 1; while (parm) { if (xml_is (parm, "parm")) { len[i] = strlen (xml_attrval (parm, "value")); SQLBindParameter (stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, len[i], 0, (void *) xml_attrval (parm, "value"), len[i], &(len[i])); i++; } parm = xml_nextelem (parm); } rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt != SQL_ERROR) { SQLRowCount (stmt, &rows); if (rows == 0 && strcmp ("", xml_attrval (query, "fallback"))) { rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "fallback"), SQL_NTS); } } if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "SQL error performing update "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); } SQLTransact (handles->henv, handles->hdbc, SQL_COMMIT); SQLFreeHandle (SQL_HANDLE_STMT, stmt); } return; } XML * TASKINDEX_odbc_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_odbc_update (ad, query); return (XML *) 0; } |
XML * _TASKINDEX_odbc_select (WFTK_ADAPTOR * ad, XML * query, XML * list) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; XML * ret = NULL; XML * map = NULL; XML * parm; UWORD i; SQLHSTMT stmt; SQLRETURN rslt; const char * name; SDWORD * len; char column[64]; SQLSMALLINT column_len; char value[256]; long value_len; SQLUSMALLINT binding = 1; SQLSMALLINT numcols; SQLSMALLINT col; int count = 0; if (!handles) return (XML *) 0; if (!handles->ok) return (XML *) 0; rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { parm = xml_firstelem (query); i = 1; while (parm) { if (xml_is (parm, "map")) map = parm; if (xml_is (parm, "parm")) i++; parm = xml_nextelem (parm); } len = malloc (i * sizeof (int)); parm = xml_firstelem(query); i = 1; while (parm) { if (xml_is (parm, "parm")) { len[i] = strlen (xml_attrval (parm, "value")); SQLBindParameter (stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, len[i], 0, (void *) xml_attrval (parm, "value"), len[i], &(len[i])); i++; } parm = xml_nextelem (parm); } rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "SQL error selecting data "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); } else { /* Here's where we build the list. */ SQLNumResultCols (stmt, &numcols); while (SQL_SUCCESS == SQLFetch (stmt)) { ret = xml_create (*xml_attrval (query, "element") ? xml_attrval (query, "element") : "elem"); count++; for (col=1; col < numcols; col++) { SQLColAttribute (stmt, col, SQL_DESC_NAME, column, sizeof(column), &column_len, NULL); strlwr (column); name = column; if (map) { if (*xml_attrval (map, column)) { name = xml_attrval (map, column); if (!strcmp (name, "!hide")) continue; } } value_len = sizeof(value); SQLGetData (stmt, col, SQL_C_CHAR, value, sizeof(value), &value_len); xml_set (ret, name, value); } if (list) xml_append (list, ret); else break; /* If no list is passed in, we just get the first row returned. */ } } if (list) xml_setnum (list, "count", count); SQLFreeHandle (SQL_HANDLE_STMT, stmt); } else { xml_set (ad->parms, "error", "Unable to allocate statement handle."); } return (ret); /* Note side effect: last row retrieved is always returned. */ } XML * TASKINDEX_odbc_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_odbc_select (ad, query, list)); } |
void _TASKINDEX_odbc_xmlput (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col, XML * val) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; SQLHSTMT stmt; SQLRETURN rslt; SDWORD len; int keylen; const char *value; XML * query; if (!handles) return; if (!handles->ok) return; rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { value = xml_string (val); /* TODO: see if there's a more scalable way to do this with ODBC. */ len = strlen (value); SQLBindParameter (stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, len, 0, (void *) value, len, &len); keylen = strlen (keyval); SQLBindParameter (stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, keylen, 0, (void *) keyval, keylen, &keylen); query = xml_create ("sql"); xml_setf (query, "query", "update %s set %s=? where %s=?", table, col, keycol); rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "SQL error performing xmlput "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); } SQLTransact (handles->henv, handles->hdbc, SQL_COMMIT); SQLFreeHandle (SQL_HANDLE_STMT, stmt); free ((void *)value); xml_free (query); } return; } XML * TASKINDEX_odbc_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_odbc_xmlput (ad, table, keycol, keyval, col, val); return (XML *) 0; } |
size_t _TASKINDEX_odbc_xmlget_fetch (char * buf, size_t chunk, size_t num, void * stmt) { size_t retval; SQLRETURN rslt; size_t value_len = num * chunk; rslt = SQLGetData (stmt, 1, SQL_C_CHAR, buf, num * chunk, &value_len); if (value_len == SQL_NULL_DATA) return 0; if (rslt == SQL_NO_DATA_FOUND) return 0; if (rslt == SQL_SUCCESS_WITH_INFO) return num; return value_len / chunk; } XML * _TASKINDEX_odbc_xmlget (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; SQLHSTMT stmt; SQLRETURN rslt; SDWORD keylen; XML * query; XML * ret; if (!handles) return ((XML *) 0); if (!handles->ok) return ((XML *) 0); rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { keylen = strlen (keyval); SQLBindParameter (stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, keylen, 0, (void *) keyval, keylen, &keylen); query = xml_create ("sql"); xml_setf (query, "query", "select %s from %s where %s=?", col, table, keycol); rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "SQL error performing xmlget "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); } else { if (SQL_SUCCESS == SQLFetch (stmt)) { ret = xml_parse_general ((void *) stmt, _TASKINDEX_odbc_xmlget_fetch); 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 = 0; } } else { xml_setf (ad->parms, "error", "Unable to locate %s with %s '%s'", table, keycol, keyval); } } SQLFreeHandle (SQL_HANDLE_STMT, stmt); xml_free (query); } return ret; } XML * TASKINDEX_odbc_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_odbc_xmlget (ad, table, keycol, keyval, col); } |
void _TASKINDEX_odbc_colput (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col, char * value) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; SQLHSTMT stmt; SQLRETURN rslt; SDWORD len; SDWORD keylen; XML * query; if (!handles) return; if (!handles->ok) return; rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { len = strlen (value); SQLBindParameter (stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, len, 0, (void *) value, len, &len); keylen = strlen (keyval); SQLBindParameter (stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, keylen, 0, (void *) keyval, keylen, &keylen); query = xml_create ("sql"); xml_setf (query, "query", "update %s set %s=? where %s=?", table, col, keycol); rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "SQL error performing colput "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); } SQLTransact (handles->henv, handles->hdbc, SQL_COMMIT); SQLFreeHandle (SQL_HANDLE_STMT, stmt); xml_free (query); } return; } XML * TASKINDEX_odbc_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_odbc_colput (ad, table, keycol, keyval, col, value); return (XML *) 0; } |
XML * _TASKINDEX_odbc_colget (WFTK_ADAPTOR * ad, char * table, char * keycol, char * keyval, char * col) { struct _TASKINDEX_odbc_handles *handles = (struct _TASKINDEX_odbc_handles *) ad->bindata; SQLHSTMT stmt; SQLRETURN rslt; SDWORD keylen; char buf[256]; int buf_len; XML * query; XML * ret = NULL; if (!handles) return ((XML *) 0); if (!handles->ok) return ((XML *) 0); rslt = SQLAllocHandle (SQL_HANDLE_STMT, handles->hdbc, &stmt); if (rslt != SQL_ERROR) { keylen = strlen (keyval); SQLBindParameter (stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, keylen, 0, (void *) keyval, keylen, &keylen); query = xml_create ("sql"); xml_setf (query, "query", "select %s from %s where %s=?", col, table, keycol); rslt = SQLExecDirect (stmt, (char *)xml_attrval (query, "query"), SQL_NTS); if (rslt == SQL_ERROR) { xml_set (ad->parms, "error", "SQL error performing xmlget "); _TASKINDEX_odbc_builderrmsg (ad->parms, stmt); } else { if (SQL_SUCCESS == SQLFetch (stmt)) { buf_len = sizeof (buf); rslt = SQLGetData (stmt, 1, SQL_C_CHAR, buf, buf_len, &buf_len); ret = xml_create ("value"); xml_set (ret, "value", buf); } else { xml_setf (ad->parms, "error", "Unable to locate %s with %s '%s'", table, keycol, keyval); } } SQLFreeHandle (SQL_HANDLE_STMT, stmt); xml_free (query); } return ret; } XML * TASKINDEX_odbc_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_odbc_colget (ad, table, keycol, keyval, col); } |
#define SET_PARM(p,v) \ parm = xml_create ("parm"); \ xml_set(parm, "name", p); \ xml_set(parm, "value", v); \ xml_append(sql, parm); |
XML * TASKINDEX_odbc_procnew (WFTK_ADAPTOR * ad, va_list args) { XML * datasheet = (XML *) 0; XML * sql; XML * parm; XML * idparm; 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 process (id, title, status, started) values (?, ?, ?, {fn NOW()})"); SET_PARM ("id", xml_attrval (datasheet, "id")); if (*xml_attrval (datasheet, "id")) { xml_set (parm, "value", xml_attrval (datasheet, "id")); } else { xml_set (parm, "return", "yes"); } idparm = parm; SET_PARM ("title", xml_attrval (datasheet, "label")); SET_PARM ("status", xml_attrval (datasheet, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ _TASKINDEX_odbc_insert (ad, sql); if (!*xml_attrval (datasheet, "id")) { xml_set (datasheet, "id", xml_attrval (idparm, "value")); } xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=?"); SET_PARM ("id", id); _TASKINDEX_odbc_delete (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=?"); parm = xml_create ("map"); xml_set (parm, "title", "label"); xml_set (parm, "owner", "user"); xml_set (parm, "datasheet", "!hide"); xml_append (sql, parm); SET_PARM ("id", id); proc = _TASKINDEX_odbc_select (ad, sql, NULL); xml_free (sql); return proc; } XML * TASKINDEX_odbc_procput (WFTK_ADAPTOR * ad, va_list args) { XML * datasheet = NULL; XML * sql; XML * parm; XML * idparm; 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=?, status=? where id=?"); xml_set (sql, "fallback", "insert into process (title, status, id, started) values (?, ?, ?, {fn NOW()})"); SET_PARM ("title", xml_attrval (datasheet, "label")); SET_PARM ("status", xml_attrval (datasheet, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ SET_PARM ("id", xml_attrval (datasheet, "id")); _TASKINDEX_odbc_update (ad, sql); } else { xml_set (sql, "query", "insert into process (id, title, status, started) values (?, ?, ?, {fn NOW()})"); SET_PARM ("id", xml_attrval (datasheet, "id")); xml_set (parm, "return", "yes"); idparm = parm; SET_PARM ("title", xml_attrval (datasheet, "label")); SET_PARM ("status", xml_attrval (datasheet, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ _TASKINDEX_odbc_insert (ad, sql); xml_set (datasheet, "id", xml_attrval (idparm, "value")); } xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=? "); SET_PARM ("status", field); } field = xml_attrval (list, "user"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "owner=? "); SET_PARM ("owner", field); } 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_odbc_select (ad, sql, list); xml_free (sql); return ret; return (XML *) 0; } XML * TASKINDEX_odbc_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={fn NOW()} where id=?"); SET_PARM ("id", id); _TASKINDEX_odbc_update (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=?"); SET_PARM ("id", id); _TASKINDEX_odbc_update (ad, sql); xml_free (sql); return (XML *) 0; } |
XML * TASKINDEX_odbc_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 (?, ?, 'active', ?, ?, ?, {fn NOW()})"); SET_PARM ("id", xml_attrval (datasheet, "id")); SET_PARM ("process", xml_attrval (datasheet, "process")); SET_PARM ("label", xml_attrval (datasheet, "label")); SET_PARM ("role", xml_attrval (datasheet, "role")); SET_PARM ("owner", xml_attrval (datasheet, "user")); _TASKINDEX_odbc_insert (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=? and 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_odbc_delete (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_taskget (WFTK_ADAPTOR * ad, va_list args) { char * process = NULL; char * id = NULL; XML * sql; XML * parm; XML * task = (XML *) 0; 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, "element", "task"); xml_set (sql, "query", "select * from task where process=? and id=?"); parm = xml_create ("map"); xml_set (parm, "description", "label"); xml_set (parm, "owner", "user"); xml_append (sql, parm); SET_PARM ("process", process); SET_PARM ("id", id); task = _TASKINDEX_odbc_select (ad, sql, NULL); xml_free (sql); return task; } XML * TASKINDEX_odbc_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=?, role=?, owner=?, status=? where process=? and id=?"); xml_set (sql, "fallback", "insert into task (description, role, owner, status, started, process, id) values (?, ?, ?, ?, {fn NOW()}, ?, ?)"); SET_PARM ("label", xml_attrval (task, "label")); SET_PARM ("role", xml_attrval (task, "role")); SET_PARM ("owner", xml_attrval (task, "user")); SET_PARM ("status", xml_attrval (task, "status")); if (!*xml_attrval (parm, "value")) xml_set (parm, "value", "active"); /* Default status is active. */ SET_PARM ("process", xml_attrval (task, "process")); SET_PARM ("id", xml_attrval (task, "id")); _TASKINDEX_odbc_update (ad, sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=? "); SET_PARM ("process", field); } field = xml_attrval (list, "status"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "status=? "); SET_PARM ("status", field); } field = xml_attrval (list, "role"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "role=? "); SET_PARM ("role", field); } field = xml_attrval (list, "user"); if (*field) { if (fields++) strcat (query, "and "); strcat (query, "owner=? "); SET_PARM ("owner", field); } 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_odbc_select (ad, sql, list); xml_free (sql); return ret; } XML * TASKINDEX_odbc_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={fn NOW()} where process=? and id=? and status='active'"); SET_PARM ("process", process); SET_PARM ("id", id); _TASKINDEX_odbc_update (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=? and id=? and status='active'"); SET_PARM ("process", process); SET_PARM ("id", id); _TASKINDEX_odbc_update (ad, sql); xml_free (sql); return (XML *) 0; } |
XML * TASKINDEX_odbc_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 (?, ?, 'request', ?, ?, ?, {fn NOW()})"); SET_PARM ("id", xml_attrval (datasheet, "id")); SET_PARM ("process", xml_attrval (datasheet, "process")); SET_PARM ("label", xml_attrval (datasheet, "label")); SET_PARM ("role", xml_attrval (datasheet, "role")); SET_PARM ("owner", xml_attrval (datasheet, "of")); _TASKINDEX_odbc_insert (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=? and 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_odbc_delete (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_reqget (WFTK_ADAPTOR * ad, va_list args) { char * process = NULL; char * id = NULL; XML * sql; XML * parm; XML * task = (XML *) 0; 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, "element", "request"); xml_set (sql, "query", "select * from task where process=? and id=? and status='request'"); parm = xml_create ("map"); xml_set (parm, "owner", "of"); xml_append (sql, parm); SET_PARM ("process", process); SET_PARM ("id", id); task = _TASKINDEX_odbc_select (ad, sql, NULL); xml_free (sql); return task; } XML * TASKINDEX_odbc_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=?, role=?, owner=?, status=? where process=? and id=?"); xml_set (sql, "fallback", "insert into task (description, role, owner, status, started, process, id) values (?, ?, ?, 'request', {fn NOW()}, ?, ?)"); SET_PARM ("label", xml_attrval (task, "label")); SET_PARM ("role", xml_attrval (task, "role")); SET_PARM ("owner", xml_attrval (task, "of")); SET_PARM ("process", xml_attrval (task, "process")); SET_PARM ("id", xml_attrval (task, "id")); _TASKINDEX_odbc_update (ad, sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=? "); SET_PARM ("process", field); } field = xml_attrval (list, "status"); if (*field) { fields++; strcat (query, "and status=? "); SET_PARM ("status", field); } field = xml_attrval (list, "role"); if (*field) { fields++; strcat (query, "and role=? "); SET_PARM ("role", field); } field = xml_attrval (list, "user"); if (*field) { fields++; strcat (query, "and owner=? "); SET_PARM ("owner", field); } 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_odbc_select (ad, sql, list); xml_free (sql); return ret; } XML * TASKINDEX_odbc_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=? and id=? and status='request'"); SET_PARM ("process", process); SET_PARM ("id", id); _TASKINDEX_odbc_update (ad, sql); xml_free (sql); return (XML *) 0; } XML * TASKINDEX_odbc_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=? and id=? and status='request'"); SET_PARM ("process", process); SET_PARM ("id", id); _TASKINDEX_odbc_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. |