summaryrefslogtreecommitdiff
path: root/databases/tcl-Mysql/files/patch-sql.cc
diff options
context:
space:
mode:
Diffstat (limited to 'databases/tcl-Mysql/files/patch-sql.cc')
-rw-r--r--databases/tcl-Mysql/files/patch-sql.cc284
1 files changed, 284 insertions, 0 deletions
diff --git a/databases/tcl-Mysql/files/patch-sql.cc b/databases/tcl-Mysql/files/patch-sql.cc
new file mode 100644
index 000000000000..06ab82f8afb3
--- /dev/null
+++ b/databases/tcl-Mysql/files/patch-sql.cc
@@ -0,0 +1,284 @@
+This patch substantially revamps the sql.cc to make use of and better
+comply with Tcl-8.x object-paradigm. The correct programs will still
+execute the same way, but in some erroneous cases the error messages may
+be slightly different. The patch gets rid of a lot of sprintf and will
+make your scripts faster, especially when fetching multiple rows of the
+same queries.
+
+In modern MySQL mysql_error() returns a const-pointer, so getErrorMsg()
+had to be changed. However, since we are using TCL_STATIC anyway, we can
+just cast its result back down to plain char*
+
+--- sql.cc Fri Aug 13 15:28:56 1999
++++ sql.cc Wed Nov 10 17:40:19 2004
+@@ -12,24 +12,11 @@
+
+-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));
+-}
++#ifndef CONST84
++# define CONST84
++#endif
+
+ // -------------------------------------------------------------
+-int selectdbCmd(Tcl_Interp *interp, Sql_interface *conn, char *dbname) {
++int selectdbCmd(Tcl_Interp *interp, Sql_interface *conn, Tcl_Obj *const dbname) {
+
+- if (conn->selectdb(dbname)) {
+- Tcl_SetResult(interp, dbname, TCL_VOLATILE);
++ if (conn->selectdb(Tcl_GetString(dbname))) {
++ Tcl_SetObjResult(interp, dbname);
+ return TCL_OK;
+@@ -38,3 +25,3 @@
+ // An error occured.
+- Tcl_SetResult(interp, conn->getErrorMsg(), TCL_VOLATILE);
++ Tcl_SetResult(interp, (char *)conn->getErrorMsg(), TCL_STATIC);
+ return TCL_ERROR;
+@@ -47,3 +34,3 @@
+ // An error occured.
+- Tcl_SetResult(interp, conn->getErrorMsg(), TCL_VOLATILE);
++ Tcl_SetResult(interp, (char *)conn->getErrorMsg(), TCL_STATIC);
+ return TCL_ERROR;
+@@ -60,9 +47,9 @@
+ int queryCmd(Tcl_Interp *interp, Sql_interface *conn, char *cmd) {
+- int handle = -1;
++ int handle;
+ if ((handle = conn->query(cmd)) < 0) {
+ // An error occured.
+- Tcl_SetResult(interp, conn->getErrorMsg(), TCL_VOLATILE);
++ Tcl_SetResult(interp, (char *)conn->getErrorMsg(), TCL_STATIC);
+ return TCL_ERROR;
+ }
+- sprintf(interp->result, "%s%d", RESULT_PREFIX, handle);
++ Tcl_SetObjResult(interp, Tcl_NewIntObj(handle));
+ return TCL_OK;
+@@ -71,7 +58,3 @@
+ // -------------------------------------------------------------
+-int endqueryCmd(Tcl_Interp *interp, Sql_interface *conn, char *handle) {
+- int resHandle = 0;
+- if (handle) {
+- resHandle = stripPrefix(handle, RESULT_PREFIX);
+- }
++int endqueryCmd(Tcl_Interp *interp, Sql_interface *conn, int resHandle) {
+ conn->endquery(resHandle);
+@@ -81,14 +64,4 @@
+ // -------------------------------------------------------------
+-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);
++int numrowsCmd(Tcl_Interp *interp, Sql_interface *conn, int resHandle) {
++ Tcl_SetObjResult(interp, Tcl_NewIntObj(conn->numRows(resHandle)));
+ return TCL_OK;
+@@ -97,13 +70,3 @@
+ // -------------------------------------------------------------
+-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;
+- }
+-
++int fetchrowCmd(Tcl_Interp *interp, Sql_interface *conn, int resHandle) {
+ Sql_row *row;
+@@ -124,6 +87,7 @@
+ //
+-int SqlCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
++int SqlCmd(ClientData clientData, Tcl_Interp *interp,
++ int objc, Tcl_Obj * const objv[])
+ {
+- if (argc == 1) {
+- Tcl_SetResult(interp, "Usage: sql command ?handle?", TCL_STATIC);
++ if (objc == 1) {
++ Tcl_WrongNumArgs(interp, 1, objv, "command ?handle?");
+ return TCL_ERROR;
+@@ -133,58 +97,58 @@
+ Manager_sql *mgr = (Manager_sql *)clientData;
+- int res = TCL_OK;
++ int res;
+
+- int c = -1;
++ int connid;
+
+- // -----------------------------------
+- 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);
++ static CONST84 char * subCmds[] = {
++ "exec", "query", "endquery", "fetchrow",
++ "numrows", "disconnect", "selectdb", "connect",
++ (char *)NULL
++ };
++ enum e_subcommands {
++ Execute, Query, EndQuery, FetchRow,
++ NumRows, Disconnect, SelectDB, Connect
++ } subcommand;
++ if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "subcommand", 0,
++ (int *) &subcommand) != TCL_OK) return TCL_ERROR;
++ if (subcommand == Connect) {
++ char *argv[objc-2];
++ for (res = 0; res < objc-2; res++) {
++ argv[res] = Tcl_GetString(objv[res+2]);
++ }
++ connid = mgr->connect(objc-2, argv);
++ if (connid < 0) {
++ Tcl_SetResult(interp, (char *)mgr->getErrorMsg(), TCL_STATIC);
+ 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); */
++ Tcl_SetObjResult(interp, Tcl_NewIntObj(connid));
+ 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);
++ // Every other command needs a handle. Get it.
++ if (objc <= 2) {
++ Tcl_WrongNumArgs(interp, 2, objv, "handle");
++ return TCL_ERROR;
++ } else if (Tcl_GetIntFromObj(NULL, objv[2], &connid)
++ != TCL_OK || connid < 0) {
++ Tcl_SetObjResult(interp, objv[2]);
++ Tcl_AppendResult(interp, ": invalid handle", NULL);
++ return TCL_ERROR;
++ } else if (!mgr->inUse(connid)) {
++ // This connection is not currently being used
++ Tcl_SetObjResult(interp, objv[2]);
++ Tcl_AppendResult(interp, ": not connected on "
++ "this handle", 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);
++ // take care of the command:
++ if (subcommand < Disconnect && subcommand > Query) {
++ /* get the "result handle" returned previously */
++ if (objc < 4) res = 0; /* oddly, this is how it was -- bug? */
++ else if (Tcl_GetIntFromObj(NULL, objv[3], &res) != TCL_OK ||
++ res < 0) {
++ Tcl_SetObjResult(interp, objv[3]);
++ Tcl_AppendResult(interp, ": invalid result"
++ " handle", NULL);
+ return TCL_ERROR;
+@@ -192,16 +156,26 @@
+ }
+-
+- return res;
+-
++ switch (subcommand) {
++ case Execute:
++ return execCmd(interp, conn, Tcl_GetString(objv[3]));
++ case Query:
++ return queryCmd(interp, conn, Tcl_GetString(objv[3]));
++ case EndQuery:
++ return endqueryCmd(interp, conn, res);
++ case FetchRow:
++ return fetchrowCmd(interp, conn, res);
++ case NumRows:
++ return numrowsCmd(interp, conn, res);
++ case Disconnect:
++ return disconnectCmd(interp, mgr, connid);
++ case SelectDB:
++ return selectdbCmd(interp, conn, objv[3]);
++ /* default not needed -- handled by Tcl_GetIndexFromObj *\
++ \* if you suspect a programming error -- uncomment: */
+ #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;
++ default:
++ Tcl_SetResult(interp, "this is not reachable",
++ TCL_STATIC);
+ #endif
++ }
++ return TCL_ERROR; /* not reachable */
+ }
+@@ -222,3 +196,4 @@
+ //
+-int Sql_Init(Tcl_Interp *interp) {
++int
++Sql_Init(Tcl_Interp *interp) {
+
+@@ -226,7 +201,7 @@
+
+- Tcl_CreateCommand (interp, "sql", SqlCmd ,(ClientData) s,
+- (Tcl_CmdDeleteProc*) NULL);
++ Tcl_CreateObjCommand (interp, "sql", SqlCmd, (ClientData)s,
++ (Tcl_CmdDeleteProc*) NULL);
+
+- // Provide a package called Sample
+- if (Tcl_PkgProvide(interp, "Sql", "1.0") == TCL_ERROR)
++ // Provide a package called ``sql''
++ if (Tcl_PkgProvide(interp, "sql", "1.1") == TCL_ERROR)
+ return TCL_ERROR;