1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
// ------------------------------------------------------------
//
// Author: Tony Darugar, tdarugar@binevolve.com
//
// $Id: sql.cc,v 1.8 2000/01/13 01:53:15 tdarugar Exp $
// -------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include "tcl.h"
#include "sql-manager.h"
const char* HANDLE_PREFIX = "sql";
const char* RESULT_PREFIX = "res";
// -------------------------------------------------------------
// Convert a tcl style connection to an interger
// returns -1 on format error,
int stripPrefix(char *txt, const char* prefix) {
unsigned int prefixLen = strlen(prefix);
if (strlen(txt) <= prefixLen ||
strncmp(txt, prefix, prefixLen)!=0) {
return -1;
}
return (atoi(txt+prefixLen));
}
// -------------------------------------------------------------
int selectdbCmd(Tcl_Interp *interp, Sql_interface *conn, char *dbname) {
if (conn->selectdb(dbname)) {
Tcl_SetResult(interp, dbname, TCL_VOLATILE);
return TCL_OK;
}
// An error occured.
Tcl_SetResult(interp, conn->getErrorMsg(), TCL_VOLATILE);
return TCL_ERROR;
}
// -------------------------------------------------------------
int execCmd(Tcl_Interp *interp, Sql_interface *conn, char *cmd) {
if (conn->exec(cmd)) return TCL_OK;
// An error occured.
Tcl_SetResult(interp, conn->getErrorMsg(), TCL_VOLATILE);
return TCL_ERROR;
}
// -------------------------------------------------------------
int disconnectCmd(Tcl_Interp *interp, Manager_sql *mgr, int connid) {
if (mgr->disconnect(connid)) return TCL_OK;
else return TCL_ERROR;
}
// -------------------------------------------------------------
int queryCmd(Tcl_Interp *interp, Sql_interface *conn, char *cmd) {
int handle = -1;
if ((handle = conn->query(cmd)) < 0) {
// An error occured.
Tcl_SetResult(interp, conn->getErrorMsg(), TCL_VOLATILE);
return TCL_ERROR;
}
sprintf(interp->result, "%s%d", RESULT_PREFIX, handle);
return TCL_OK;
}
// -------------------------------------------------------------
int endqueryCmd(Tcl_Interp *interp, Sql_interface *conn, char *handle) {
int resHandle = 0;
if (handle) {
resHandle = stripPrefix(handle, RESULT_PREFIX);
}
conn->endquery(resHandle);
return TCL_OK;
}
// -------------------------------------------------------------
int numrowsCmd(Tcl_Interp *interp, Sql_interface *conn, char *handle) {
int resHandle = 0;
if (handle) {
resHandle = stripPrefix(handle, RESULT_PREFIX);
}
int nrows = conn->numRows(resHandle);
// Return the result of the command:
char retval[20];
sprintf(retval, "%d", nrows);
Tcl_SetResult(interp, retval, TCL_VOLATILE);
return TCL_OK;
}
// -------------------------------------------------------------
int fetchrowCmd(Tcl_Interp *interp, Sql_interface *conn, char *handle) {
int resHandle = 0;
if (handle) {
resHandle = stripPrefix(handle, RESULT_PREFIX);
}
if (resHandle < 0) {
Tcl_SetResult(interp, "Invalid result handle.", TCL_VOLATILE);
return TCL_ERROR;
}
Sql_row *row;
if ((row = conn->fetchrow(resHandle)) == NULL) {
// No data to fetch.
Tcl_ResetResult(interp);
return TCL_OK;
}
for (int i=0; i < row->numColumns(); i++) {
Tcl_AppendElement(interp, row->getColumn(i));
}
delete row;
return TCL_OK;
}
// -------------------------------------------------------------
//
int SqlCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
{
if (argc == 1) {
Tcl_SetResult(interp, "Usage: sql command ?handle?", TCL_STATIC);
return TCL_ERROR;
}
// Get a pointer to the sample object from the clientData:
Manager_sql *mgr = (Manager_sql *)clientData;
int res = TCL_OK;
int c = -1;
// -----------------------------------
if (strcmp(argv[1], "connect")==0) {
c = mgr->connect(argc-2, argv+2);
if (c < 0) {
char *basemsg = "Unable to Connect: ";
char *errmsg = mgr->getErrorMsg();
char *msg = Tcl_Alloc(strlen(errmsg)+strlen(basemsg));
strcpy(msg, basemsg);
strcat(msg, errmsg);
Tcl_SetResult(interp, msg, TCL_DYNAMIC);
return TCL_ERROR;
}
char errormsg[16];
sprintf(errormsg, "%s%d", HANDLE_PREFIX, c);
Tcl_SetResult(interp,errormsg,TCL_VOLATILE);
/* sprintf(interp->result, "%s%d", HANDLE_PREFIX, c); */
return TCL_OK;
} else {
// Every other command needs a handle. Get it.
int connid = -1;
if (argc <= 2) {
Tcl_SetResult(interp, "Usage:\nsql command handle", TCL_STATIC);
return TCL_ERROR;
} else if ((connid = stripPrefix(argv[2], HANDLE_PREFIX)) < 0) {
Tcl_AppendResult(interp, "sql: Invalid handle: ", argv[2], NULL);
return TCL_ERROR;
} else if (!mgr->inUse(connid)) {
// This connection is not currently being used
Tcl_AppendResult(interp, "sql: not connected on handle ", argv[2], NULL);
return TCL_ERROR;
}
Sql_interface *conn = mgr->connection(connid);
// take care of the command:
if (strcmp(argv[1], "exec") == 0) {
res = execCmd(interp, conn, argv[3]);
} else if (strcmp(argv[1], "query") == 0) {
res = queryCmd(interp, conn, argv[3]);
} else if (strcmp(argv[1], "endquery") == 0) {
res = endqueryCmd(interp, conn, argv[3]);
} else if (strcmp(argv[1], "fetchrow") == 0) {
res = fetchrowCmd(interp, conn, argv[3]);
} else if (strcmp(argv[1], "numrows") == 0) {
res = numrowsCmd(interp, conn, argv[3]);
} else if (strcmp(argv[1], "disconnect") == 0) {
res = disconnectCmd(interp, mgr, connid);
} else if (strcmp(argv[1], "selectdb")==0) {
res = selectdbCmd(interp, conn, argv[3]);
} else {
Tcl_AppendResult(interp, "sql: unknown sql command: ", argv[1], NULL);
return TCL_ERROR;
}
}
return res;
#if 0
// Return the result of the command:
char returnValue[10];
sprintf(returnValue, "%d", c);
// The TCL_VOLATILE means the memory for our returnValue was allocated
// from the stack. See Tcl_SetResult for details.
Tcl_SetResult(interp, returnValue, TCL_VOLATILE);
return TCL_OK;
#endif
}
// -------------------------------------------------------------
// It's necessary to declare the Init procedure as extern C to make
// tcl happy.
//
extern "C" {
int Sql_Init(Tcl_Interp *interp);
}
// -------------------------------------------------------------
// The initialization function. Tcl calls this function when you
// load the package. Its name must be the name of the package, with
// the first letter capitalized, the rest lower, and '_Init' appended
// to the end of it.
//
int Sql_Init(Tcl_Interp *interp) {
Manager_sql *s = new Manager_sql();
Tcl_CreateCommand (interp, "sql", SqlCmd ,(ClientData) s,
(Tcl_CmdDeleteProc*) NULL);
// Provide a package called Sample
if (Tcl_PkgProvide(interp, "Sql", "1.0") == TCL_ERROR)
return TCL_ERROR;
return TCL_OK;
}
|