2 * $Eid: mysqltcl.c,v 1.2 2002/02/15 18:52:08 artur Exp $
\r
4 * MYSQL interface to Tcl
\r
6 * Hakan Soderstrom, hs@soderstrom.se
\r
11 * Copyright (c) 1994, 1995 Hakan Soderstrom and Tom Poindexter
\r
13 * Permission to use, copy, modify, distribute, and sell this software
\r
14 * and its documentation for any purpose is hereby granted without fee,
\r
15 * provided that the above copyright notice and this permission notice
\r
16 * appear in all copies of the software and related documentation.
\r
18 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
\r
19 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
\r
20 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
\r
22 * IN NO EVENT SHALL HAKAN SODERSTROM OR SODERSTROM PROGRAMVARUVERKSTAD
\r
23 * AB BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL
\r
24 * DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
\r
25 * OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY
\r
26 * OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
\r
27 * CONNECTON WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
\r
31 Modified after version 2.0 by Artur Trzewik
\r
32 see http://www.xdobry.de/mysqltcl
\r
33 Patch for encoding option by Alexander Schoepe (version2.20)
\r
37 #include <windows.h>
\r
38 #define PACKAGE "mysqltcl"
\r
39 #define PACKAGE_VERSION "3.04"
\r
50 #define MYSQL_SMALL_SIZE TCL_RESULT_SIZE /* Smaller buffer size. */
\r
51 #define MYSQL_NAME_LEN 80 /* Max. database name length. */
\r
52 /* #define PREPARED_STATEMENT */
\r
54 enum MysqlHandleType {HT_CONNECTION=1,HT_QUERY=2,HT_STATEMENT=3};
\r
56 typedef struct MysqlTclHandle {
\r
57 MYSQL * connection; /* Connection handle, if connected; NULL otherwise. */
\r
58 char database[MYSQL_NAME_LEN]; /* Db name, if selected; NULL otherwise. */
\r
59 MYSQL_RES* result; /* Stored result, if any; NULL otherwise. */
\r
60 int res_count; /* Count of unfetched rows in result. */
\r
61 int col_count; /* Column count in result, if any. */
\r
62 int number; /* handle id */
\r
63 enum MysqlHandleType type; /* handle type */
\r
64 Tcl_Encoding encoding; /* encoding for connection */
\r
65 #ifdef PREPARED_STATEMENT
\r
66 MYSQL_STMT *statement; /* used only by prepared statements*/
\r
67 MYSQL_BIND *bindParam;
\r
68 MYSQL_BIND *bindResult;
\r
69 MYSQL_RES *resultMetadata;
\r
70 MYSQL_RES *paramMetadata;
\r
74 typedef struct MysqltclState {
\r
77 char *MysqlNullvalue;
\r
78 // Tcl_Obj *nullObjPtr;
\r
81 static char *MysqlHandlePrefix = "mysql";
\r
82 /* Prefix string used to identify handles.
\r
83 * The following must be strlen(MysqlHandlePrefix).
\r
85 #define MYSQL_HPREFIX_LEN 5
\r
87 /* Array for status info, and its elements. */
\r
88 #define MYSQL_STATUS_ARR "mysqlstatus"
\r
90 #define MYSQL_STATUS_CODE "code"
\r
91 #define MYSQL_STATUS_CMD "command"
\r
92 #define MYSQL_STATUS_MSG "message"
\r
93 #define MYSQL_STATUS_NULLV "nullvalue"
\r
95 #define FUNCTION_NOT_AVAILABLE "function not available"
\r
97 /* C variable corresponding to mysqlstatus(nullvalue) */
\r
98 #define MYSQL_NULLV_INIT ""
\r
100 /* Check Level for mysql_prologue */
\r
101 enum CONNLEVEL {CL_PLAIN,CL_CONN,CL_DB,CL_RES};
\r
103 /* Prototypes for all functions. */
\r
105 static int Mysqltcl_Use(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
106 static int Mysqltcl_Escape(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
107 static int Mysqltcl_Sel(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
108 static int Mysqltcl_Fetch(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
109 static int Mysqltcl_Seek(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
110 static int Mysqltcl_Map(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
111 static int Mysqltcl_Exec(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
112 static int Mysqltcl_Close(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
113 static int Mysqltcl_Info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
114 static int Mysqltcl_Result(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
115 static int Mysqltcl_Col(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
116 static int Mysqltcl_State(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
117 static int Mysqltcl_InsertId(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
118 static int Mysqltcl_Query(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
119 static int Mysqltcl_Receive(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
\r
120 static int MysqlHandleSet _ANSI_ARGS_((Tcl_Interp *interp,Tcl_Obj *objPtr));
\r
121 static void MysqlHandleFree _ANSI_ARGS_((Tcl_Obj *objPtr));
\r
122 static int MysqlNullSet _ANSI_ARGS_((Tcl_Interp *interp,Tcl_Obj *objPtr));
\r
123 static Tcl_Obj *Mysqltcl_NewNullObj(MysqltclState *mysqltclState);
\r
124 static void UpdateStringOfNull _ANSI_ARGS_((Tcl_Obj *objPtr));
\r
126 /* handle object type
\r
127 * This section defince funtions for Handling new Tcl_Obj type */
\r
129 Tcl_ObjType mysqlHandleType = {
\r
132 (Tcl_DupInternalRepProc *) NULL,
\r
136 Tcl_ObjType mysqlNullType = {
\r
138 (Tcl_FreeInternalRepProc *) NULL,
\r
139 (Tcl_DupInternalRepProc *) NULL,
\r
140 UpdateStringOfNull,
\r
145 static MysqltclState *getMysqltclState(Tcl_Interp *interp) {
\r
146 Tcl_CmdInfo cmdInfo;
\r
147 if (Tcl_GetCommandInfo(interp,"mysqlconnect",&cmdInfo)==0) {
\r
150 return (MysqltclState *)cmdInfo.objClientData;
\r
153 static int MysqlHandleSet(Tcl_Interp *interp, register Tcl_Obj *objPtr)
\r
155 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
\r
157 MysqlTclHandle *handle;
\r
158 Tcl_HashEntry *entryPtr;
\r
159 MysqltclState *statePtr;
\r
161 string = Tcl_GetStringFromObj(objPtr, NULL);
\r
162 statePtr = getMysqltclState(interp);
\r
163 if (statePtr==NULL) return TCL_ERROR;
\r
165 entryPtr = Tcl_FindHashEntry(&statePtr->hash,string);
\r
166 if (entryPtr == NULL) {
\r
170 handle=(MysqlTclHandle *)Tcl_GetHashValue(entryPtr);
\r
173 if (interp != NULL)
\r
176 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
\r
177 oldTypePtr->freeIntRepProc(objPtr);
\r
180 objPtr->internalRep.otherValuePtr = (MysqlTclHandle *) handle;
\r
181 objPtr->typePtr = &mysqlHandleType;
\r
182 Tcl_Preserve((char *)handle);
\r
185 static int MysqlNullSet(Tcl_Interp *interp, Tcl_Obj *objPtr)
\r
187 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
\r
189 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
\r
190 oldTypePtr->freeIntRepProc(objPtr);
\r
192 objPtr->typePtr = &mysqlNullType;
\r
195 static void UpdateStringOfNull(Tcl_Obj *objPtr) {
\r
197 MysqltclState *state = (MysqltclState *)objPtr->internalRep.otherValuePtr;
\r
199 valueLen = strlen(state->MysqlNullvalue);
\r
200 objPtr->bytes = Tcl_Alloc(valueLen+1);
\r
201 strcpy(objPtr->bytes,state->MysqlNullvalue);
\r
202 objPtr->length = valueLen;
\r
204 static void MysqlHandleFree(Tcl_Obj *obj)
\r
206 MysqlTclHandle *handle = (MysqlTclHandle *)obj->internalRep.otherValuePtr;
\r
207 Tcl_Release((char *)handle);
\r
210 static int GetHandleFromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,MysqlTclHandle **handlePtr)
\r
212 if (Tcl_ConvertToType(interp, objPtr, &mysqlHandleType) != TCL_OK)
\r
214 *handlePtr = (MysqlTclHandle *)objPtr->internalRep.otherValuePtr;
\r
218 static Tcl_Obj *Tcl_NewHandleObj(MysqltclState *statePtr,MysqlTclHandle *handle)
\r
220 register Tcl_Obj *objPtr;
\r
221 char buffer[MYSQL_HPREFIX_LEN+TCL_DOUBLE_SPACE+1];
\r
223 Tcl_HashEntry *entryPtr;
\r
226 objPtr=Tcl_NewObj();
\r
227 /* the string for "query" can not be longer as MysqlHandlePrefix see buf variable */
\r
228 len=sprintf(buffer, "%s%d", (handle->type==HT_QUERY) ? "query" : MysqlHandlePrefix,handle->number);
\r
229 objPtr->bytes = Tcl_Alloc((unsigned) len + 1);
\r
230 strcpy(objPtr->bytes, buffer);
\r
231 objPtr->length = len;
\r
233 entryPtr=Tcl_CreateHashEntry(&statePtr->hash,buffer,&newflag);
\r
234 Tcl_SetHashValue(entryPtr,handle);
\r
236 objPtr->internalRep.otherValuePtr = handle;
\r
237 objPtr->typePtr = &mysqlHandleType;
\r
239 Tcl_Preserve((char *)handle);
\r
247 /* CONFLICT HANDLING
\r
249 * Every command begins by calling 'mysql_prologue'.
\r
250 * This function resets mysqlstatus(code) to zero; the other array elements
\r
251 * retain their previous values.
\r
252 * The function also saves objc/objv in global variables.
\r
253 * After this the command processing proper begins.
\r
255 * If there is a conflict, the message is taken from one of the following
\r
257 * -- this code (mysql_prim_confl),
\r
258 * -- the database server (mysql_server_confl),
\r
259 * A complete message is put together from the above plus the name of the
\r
260 * command where the conflict was detected.
\r
261 * The complete message is returned as the Tcl result and is also stored in
\r
262 * mysqlstatus(message).
\r
263 * mysqlstatus(code) is set to "-1" for a primitive conflict or to mysql_errno
\r
264 * for a server conflict
\r
265 * In addition, the whole command where the conflict was detected is put
\r
266 * together from the saved objc/objv and is copied into mysqlstatus(command).
\r
270 *-----------------------------------------------------------
\r
272 * Help procedure to set Tcl global array with mysqltcl internal
\r
276 static void set_statusArr(Tcl_Interp *interp,char *elem_name,Tcl_Obj *tobj)
\r
278 Tcl_SetVar2Ex (interp,MYSQL_STATUS_ARR,elem_name,tobj,TCL_GLOBAL_ONLY);
\r
282 *----------------------------------------------------------------------
\r
285 * Clears all error and message elements in the global array variable.
\r
290 clear_msg(Tcl_Interp *interp)
\r
292 set_statusArr(interp,MYSQL_STATUS_CODE,Tcl_NewIntObj(0));
\r
293 set_statusArr(interp,MYSQL_STATUS_CMD,Tcl_NewObj());
\r
294 set_statusArr(interp,MYSQL_STATUS_MSG,Tcl_NewObj());
\r
298 *----------------------------------------------------------------------
\r
300 * Reassembles the current command from the saved objv; copies it into
\r
301 * mysqlstatus(command).
\r
304 static void mysql_reassemble(Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[])
\r
306 set_statusArr(interp,MYSQL_STATUS_CMD,Tcl_NewListObj(objc, objv));
\r
310 * free result from handle and consume left result of multresult statement
\r
312 static void freeResult(MysqlTclHandle *handle)
\r
315 if (handle->result != NULL) {
\r
316 mysql_free_result(handle->result);
\r
317 handle->result = NULL ;
\r
319 #if (MYSQL_VERSION_ID >= 50000)
\r
320 while (!mysql_next_result(handle->connection)) {
\r
321 result = mysql_store_result(handle->connection);
\r
323 mysql_free_result(result);
\r
330 *----------------------------------------------------------------------
\r
332 * Conflict handling after a primitive conflict.
\r
336 static int mysql_prim_confl(Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[],char *msg)
\r
338 set_statusArr(interp,MYSQL_STATUS_CODE,Tcl_NewIntObj(-1));
\r
340 Tcl_ResetResult(interp) ;
\r
341 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
\r
342 Tcl_GetString(objv[0]), ": ", msg, (char*)NULL);
\r
344 set_statusArr(interp,MYSQL_STATUS_MSG,Tcl_GetObjResult(interp));
\r
346 mysql_reassemble(interp,objc,objv) ;
\r
352 *----------------------------------------------------------------------
\r
353 * mysql_server_confl
\r
354 * Conflict handling after an mySQL conflict.
\r
355 * If error it set error message and return TCL_ERROR
\r
356 * If no error occurs it returns TCL_OK
\r
359 static int mysql_server_confl(Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[],MYSQL * connection)
\r
361 const char* mysql_errorMsg;
\r
362 if (mysql_errno(connection)) {
\r
363 mysql_errorMsg = mysql_error(connection);
\r
365 set_statusArr(interp,MYSQL_STATUS_CODE,Tcl_NewIntObj(mysql_errno(connection)));
\r
368 Tcl_ResetResult(interp) ;
\r
369 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
\r
370 Tcl_GetString(objv[0]), "/db server: ",
\r
371 (mysql_errorMsg == NULL) ? "" : mysql_errorMsg,
\r
374 set_statusArr(interp,MYSQL_STATUS_MSG,Tcl_GetObjResult(interp));
\r
376 mysql_reassemble(interp,objc,objv);
\r
383 static MysqlTclHandle *get_handle(Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[],int check_level)
\r
385 MysqlTclHandle *handle;
\r
386 if (GetHandleFromObj(interp, objv[1], &handle) != TCL_OK) {
\r
387 mysql_prim_confl(interp,objc,objv,"not mysqltcl handle") ;
\r
390 if (check_level==CL_PLAIN) return handle;
\r
391 if (handle->connection == 0) {
\r
392 mysql_prim_confl(interp,objc,objv,"handle already closed (dangling pointer)") ;
\r
395 if (check_level==CL_CONN) return handle;
\r
396 if (check_level!=CL_RES) {
\r
397 if (handle->database[0] == '\0') {
\r
398 mysql_prim_confl(interp,objc,objv,"no current database") ;
\r
401 if (check_level==CL_DB) return handle;
\r
403 if (handle->result == NULL) {
\r
404 mysql_prim_confl(interp,objc,objv,"no result pending") ;
\r
410 /*----------------------------------------------------------------------
\r
412 * mysql_QueryTclObj
\r
413 * This to method control how tcl data is transfered to mysql and
\r
414 * how data is imported into tcl from mysql
\r
415 * Return value : Zero on success, Non-zero if an error occurred.
\r
417 static int mysql_QueryTclObj(MysqlTclHandle *handle,Tcl_Obj *obj)
\r
420 int result,queryLen;
\r
422 Tcl_DString queryDS;
\r
424 query=Tcl_GetStringFromObj(obj, &queryLen);
\r
427 if (handle->encoding==NULL) {
\r
428 query = (char *) Tcl_GetByteArrayFromObj(obj, &queryLen);
\r
429 result = mysql_real_query(handle->connection,query,queryLen);
\r
431 Tcl_UtfToExternalDString(handle->encoding, query, -1, &queryDS);
\r
432 queryLen = Tcl_DStringLength(&queryDS);
\r
433 result = mysql_real_query(handle->connection,Tcl_DStringValue(&queryDS),queryLen);
\r
434 Tcl_DStringFree(&queryDS);
\r
438 static Tcl_Obj *getRowCellAsObject(MysqltclState *mysqltclState,MysqlTclHandle *handle,MYSQL_ROW row,int length)
\r
444 if (handle->encoding!=NULL) {
\r
445 Tcl_ExternalToUtfDString(handle->encoding, *row, length, &ds);
\r
446 obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
\r
447 Tcl_DStringFree(&ds);
\r
449 obj = Tcl_NewByteArrayObj((unsigned char *)*row,length);
\r
452 obj = Mysqltcl_NewNullObj(mysqltclState);
\r
457 static MysqlTclHandle *createMysqlHandle(MysqltclState *statePtr)
\r
459 MysqlTclHandle *handle;
\r
460 handle=(MysqlTclHandle *)Tcl_Alloc(sizeof(MysqlTclHandle));
\r
461 memset(handle,0,sizeof(MysqlTclHandle));
\r
463 panic("no memory for handle");
\r
466 handle->type = HT_CONNECTION;
\r
468 /* MT-safe, because every thread in tcl has own interpreter */
\r
469 handle->number=statePtr->handleNum++;
\r
473 static MysqlTclHandle *createHandleFrom(MysqltclState *statePtr,MysqlTclHandle *handle,enum MysqlHandleType handleType)
\r
476 MysqlTclHandle *qhandle;
\r
477 qhandle = createMysqlHandle(statePtr);
\r
478 /* do not overwrite the number */
\r
479 number = qhandle->number;
\r
480 if (!qhandle) return qhandle;
\r
481 memcpy(qhandle,handle,sizeof(MysqlTclHandle));
\r
482 qhandle->type=handleType;
\r
483 qhandle->number=number;
\r
486 static void closeHandle(MysqlTclHandle *handle)
\r
488 freeResult(handle);
\r
489 if (handle->type==HT_CONNECTION) {
\r
490 mysql_close(handle->connection);
\r
492 #ifdef PREPARED_STATEMENT
\r
493 if (handle->type==HT_STATEMENT) {
\r
494 if (handle->statement!=NULL)
\r
495 mysql_stmt_close(handle->statement);
\r
496 if (handle->bindResult!=NULL)
\r
497 Tcl_Free((char *)handle->bindResult);
\r
498 if (handle->bindParam!=NULL)
\r
499 Tcl_Free((char *)handle->bindParam);
\r
500 if (handle->resultMetadata!=NULL)
\r
501 mysql_free_result(handle->resultMetadata);
\r
502 if (handle->paramMetadata!=NULL)
\r
503 mysql_free_result(handle->paramMetadata);
\r
506 handle->connection = (MYSQL *)NULL;
\r
507 if (handle->encoding!=NULL && handle->type==HT_CONNECTION)
\r
509 Tcl_FreeEncoding(handle->encoding);
\r
510 handle->encoding = NULL;
\r
512 Tcl_EventuallyFree((char *)handle,TCL_DYNAMIC);
\r
516 *----------------------------------------------------------------------
\r
519 * Does most of standard command prologue; required for all commands
\r
520 * having conflict handling.
\r
521 * 'req_min_args' must be the minimum number of arguments for the command,
\r
522 * including the command word.
\r
523 * 'req_max_args' must be the maximum number of arguments for the command,
\r
524 * including the command word.
\r
525 * 'usage_msg' must be a usage message, leaving out the command name.
\r
526 * Checks the handle assumed to be present in objv[1] if 'check' is not NULL.
\r
527 * RETURNS: Handle index or -1 on failure.
\r
528 * SIDE EFFECT: Sets the Tcl result on failure.
\r
531 static MysqlTclHandle *mysql_prologue(Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[],int req_min_args,int req_max_args,int check_level,char *usage_msg)
\r
533 /* Check number of args. */
\r
534 if (objc < req_min_args || objc > req_max_args) {
\r
535 Tcl_WrongNumArgs(interp, 1, objv, usage_msg);
\r
539 /* Reset mysqlstatus(code). */
\r
540 set_statusArr(interp,MYSQL_STATUS_CODE,Tcl_NewIntObj(0));
\r
542 /* Check the handle.
\r
543 * The function is assumed to set the status array on conflict.
\r
545 return (get_handle(interp,objc,objv,check_level));
\r
549 *----------------------------------------------------------------------
\r
552 * Given an MYSQL_FIELD struct and a string keyword appends a piece of
\r
553 * column info (one item) to the Tcl result.
\r
554 * ASSUMES 'fld' is non-null.
\r
555 * RETURNS 0 on success, 1 otherwise.
\r
556 * SIDE EFFECT: Sets the result and status on failure.
\r
559 static Tcl_Obj *mysql_colinfo(Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[],MYSQL_FIELD* fld,Tcl_Obj * keyw)
\r
563 static CONST char* MysqlColkey[] =
\r
565 "table", "name", "type", "length", "prim_key", "non_null", "numeric", "decimals", NULL
\r
568 MYSQL_COL_TABLE_K, MYSQL_COL_NAME_K, MYSQL_COL_TYPE_K, MYSQL_COL_LENGTH_K,
\r
569 MYSQL_COL_PRIMKEY_K, MYSQL_COL_NONNULL_K, MYSQL_COL_NUMERIC_K, MYSQL_COL_DECIMALS_K};
\r
571 if (Tcl_GetIndexFromObj(interp, keyw, MysqlColkey, "option",
\r
572 TCL_EXACT, &idx) != TCL_OK)
\r
577 case MYSQL_COL_TABLE_K:
\r
578 return Tcl_NewStringObj(fld->table, -1) ;
\r
579 case MYSQL_COL_NAME_K:
\r
580 return Tcl_NewStringObj(fld->name, -1) ;
\r
581 case MYSQL_COL_TYPE_K:
\r
586 case FIELD_TYPE_DECIMAL:
\r
587 return Tcl_NewStringObj("decimal", -1);
\r
588 case FIELD_TYPE_TINY:
\r
589 return Tcl_NewStringObj("tiny", -1);
\r
590 case FIELD_TYPE_SHORT:
\r
591 return Tcl_NewStringObj("short", -1);
\r
592 case FIELD_TYPE_LONG:
\r
593 return Tcl_NewStringObj("long", -1) ;
\r
594 case FIELD_TYPE_FLOAT:
\r
595 return Tcl_NewStringObj("float", -1);
\r
596 case FIELD_TYPE_DOUBLE:
\r
597 return Tcl_NewStringObj("double", -1);
\r
598 case FIELD_TYPE_NULL:
\r
599 return Tcl_NewStringObj("null", -1);
\r
600 case FIELD_TYPE_TIMESTAMP:
\r
601 return Tcl_NewStringObj("timestamp", -1);
\r
602 case FIELD_TYPE_LONGLONG:
\r
603 return Tcl_NewStringObj("long long", -1);
\r
604 case FIELD_TYPE_INT24:
\r
605 return Tcl_NewStringObj("int24", -1);
\r
606 case FIELD_TYPE_DATE:
\r
607 return Tcl_NewStringObj("date", -1);
\r
608 case FIELD_TYPE_TIME:
\r
609 return Tcl_NewStringObj("time", -1);
\r
610 case FIELD_TYPE_DATETIME:
\r
611 return Tcl_NewStringObj("date time", -1);
\r
612 case FIELD_TYPE_YEAR:
\r
613 return Tcl_NewStringObj("year", -1);
\r
614 case FIELD_TYPE_NEWDATE:
\r
615 return Tcl_NewStringObj("new date", -1);
\r
616 case FIELD_TYPE_ENUM:
\r
617 return Tcl_NewStringObj("enum", -1);
\r
618 case FIELD_TYPE_SET:
\r
619 return Tcl_NewStringObj("set", -1);
\r
620 case FIELD_TYPE_TINY_BLOB:
\r
621 return Tcl_NewStringObj("tiny blob", -1);
\r
622 case FIELD_TYPE_MEDIUM_BLOB:
\r
623 return Tcl_NewStringObj("medium blob", -1);
\r
624 case FIELD_TYPE_LONG_BLOB:
\r
625 return Tcl_NewStringObj("long blob", -1);
\r
626 case FIELD_TYPE_BLOB:
\r
627 return Tcl_NewStringObj("blob", -1);
\r
628 case FIELD_TYPE_VAR_STRING:
\r
629 return Tcl_NewStringObj("var string", -1);
\r
630 case FIELD_TYPE_STRING:
\r
631 return Tcl_NewStringObj("string", -1);
\r
632 #if MYSQL_VERSION_ID >= 50000
\r
633 case MYSQL_TYPE_NEWDECIMAL:
\r
634 return Tcl_NewStringObj("newdecimal", -1);
\r
635 case MYSQL_TYPE_GEOMETRY:
\r
636 return Tcl_NewStringObj("geometry", -1);
\r
637 case MYSQL_TYPE_BIT:
\r
638 return Tcl_NewStringObj("bit", -1);
\r
641 return Tcl_NewStringObj("unknown", -1);
\r
644 case MYSQL_COL_LENGTH_K:
\r
645 return Tcl_NewIntObj(fld->length) ;
\r
646 case MYSQL_COL_PRIMKEY_K:
\r
647 return Tcl_NewBooleanObj(IS_PRI_KEY(fld->flags));
\r
648 case MYSQL_COL_NONNULL_K:
\r
649 return Tcl_NewBooleanObj(IS_NOT_NULL(fld->flags));
\r
650 case MYSQL_COL_NUMERIC_K:
\r
651 return Tcl_NewBooleanObj(IS_NUM(fld->type));
\r
652 case MYSQL_COL_DECIMALS_K:
\r
653 return IS_NUM(fld->type)? Tcl_NewIntObj(fld->decimals): Tcl_NewIntObj(-1);
\r
654 default: /* should never happen */
\r
655 mysql_prim_confl(interp,objc,objv,"weirdness in mysql_colinfo");
\r
661 * Mysqltcl_CloseAll
\r
662 * Close all connections.
\r
665 static void Mysqltcl_CloseAll(ClientData clientData)
\r
667 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
668 Tcl_HashSearch search;
\r
669 MysqlTclHandle *handle;
\r
670 Tcl_HashEntry *entryPtr;
\r
673 for (entryPtr=Tcl_FirstHashEntry(&statePtr->hash,&search);
\r
675 entryPtr=Tcl_NextHashEntry(&search)) {
\r
677 handle=(MysqlTclHandle *)Tcl_GetHashValue(entryPtr);
\r
679 if (handle->connection == 0) continue;
\r
680 closeHandle(handle);
\r
683 Tcl_DeleteHashTable(&statePtr->hash);
\r
684 Tcl_InitHashTable(&statePtr->hash, TCL_STRING_KEYS);
\r
688 * Invoked from Interpreter by removing mysqltcl command
\r
690 * Warnign: This procedure can be called only once
\r
692 static void Mysqltcl_Kill(ClientData clientData)
\r
694 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
695 Tcl_HashEntry *entryPtr;
\r
696 MysqlTclHandle *handle;
\r
697 Tcl_HashSearch search;
\r
699 for (entryPtr=Tcl_FirstHashEntry(&statePtr->hash,&search);
\r
701 entryPtr=Tcl_NextHashEntry(&search)) {
\r
702 handle=(MysqlTclHandle *)Tcl_GetHashValue(entryPtr);
\r
703 if (handle->connection == 0) continue;
\r
704 closeHandle(handle);
\r
706 Tcl_Free(statePtr->MysqlNullvalue);
\r
707 Tcl_Free((char *)statePtr);
\r
711 *----------------------------------------------------------------------
\r
714 * Implements the mysqlconnect command:
\r
715 * usage: mysqlconnect ?option value ...?
\r
718 * handle - a character string of newly open handle
\r
719 * TCL_OK - connect successful
\r
720 * TCL_ERROR - connect not successful - error message returned
\r
723 static CONST char* MysqlConnectOpt[] =
\r
725 "-host", "-user", "-password", "-db", "-port", "-socket","-encoding",
\r
726 "-ssl", "-compress", "-noschema","-odbc",
\r
727 #if (MYSQL_VERSION_ID >= 40107)
\r
728 "-multistatement","-multiresult",
\r
730 "-localfiles","-ignorespace","-foundrows","-interactive","-sslkey","-sslcert",
\r
731 "-sslca","-sslcapath","-sslciphers",NULL
\r
734 static int Mysqltcl_Connect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
736 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
738 char *hostname = NULL;
\r
740 char *password = NULL;
\r
742 int port = 0, flags = 0, booleanflag;
\r
743 char *socket = NULL;
\r
744 char *encodingname = NULL;
\r
746 #if (MYSQL_VERSION_ID >= 40107)
\r
749 char *sslkey = NULL;
\r
750 char *sslcert = NULL;
\r
751 char *sslca = NULL;
\r
752 char *sslcapath = NULL;
\r
753 char *sslcipher = NULL;
\r
755 MysqlTclHandle *handle;
\r
756 const char *groupname = "mysqltcl";
\r
759 enum connectoption {
\r
760 MYSQL_CONNHOST_OPT, MYSQL_CONNUSER_OPT, MYSQL_CONNPASSWORD_OPT,
\r
761 MYSQL_CONNDB_OPT, MYSQL_CONNPORT_OPT, MYSQL_CONNSOCKET_OPT, MYSQL_CONNENCODING_OPT,
\r
762 MYSQL_CONNSSL_OPT, MYSQL_CONNCOMPRESS_OPT, MYSQL_CONNNOSCHEMA_OPT, MYSQL_CONNODBC_OPT,
\r
763 #if (MYSQL_VERSION_ID >= 40107)
\r
764 MYSQL_MULTISTATEMENT_OPT,MYSQL_MULTIRESULT_OPT,
\r
766 MYSQL_LOCALFILES_OPT,MYSQL_IGNORESPACE_OPT,
\r
767 MYSQL_FOUNDROWS_OPT,MYSQL_INTERACTIVE_OPT,MYSQL_SSLKEY_OPT,MYSQL_SSLCERT_OPT,
\r
768 MYSQL_SSLCA_OPT,MYSQL_SSLCAPATH_OPT,MYSQL_SSLCIPHERS_OPT
\r
771 if (!(objc & 1) ||
\r
772 objc>(sizeof(MysqlConnectOpt)/sizeof(MysqlConnectOpt[0]-1)*2+1)) {
\r
773 Tcl_WrongNumArgs(interp, 1, objv, "[-user xxx] [-db mysql] [-port 3306] [-host localhost] [-socket sock] [-password pass] [-encoding encoding] [-ssl boolean] [-compress boolean] [-odbc boolean] [-noschema boolean]"
\r
778 for (i = 1; i < objc; i++) {
\r
779 if (Tcl_GetIndexFromObj(interp, objv[i], MysqlConnectOpt, "option",
\r
780 0, &idx) != TCL_OK)
\r
784 case MYSQL_CONNHOST_OPT:
\r
785 hostname = Tcl_GetStringFromObj(objv[++i],NULL);
\r
787 case MYSQL_CONNUSER_OPT:
\r
788 user = Tcl_GetStringFromObj(objv[++i],NULL);
\r
790 case MYSQL_CONNPASSWORD_OPT:
\r
791 password = Tcl_GetStringFromObj(objv[++i],NULL);
\r
793 case MYSQL_CONNDB_OPT:
\r
794 db = Tcl_GetStringFromObj(objv[++i],NULL);
\r
796 case MYSQL_CONNPORT_OPT:
\r
797 if (Tcl_GetIntFromObj(interp, objv[++i], &port) != TCL_OK)
\r
800 case MYSQL_CONNSOCKET_OPT:
\r
801 socket = Tcl_GetStringFromObj(objv[++i],NULL);
\r
803 case MYSQL_CONNENCODING_OPT:
\r
804 encodingname = Tcl_GetStringFromObj(objv[++i],NULL);
\r
806 case MYSQL_CONNSSL_OPT:
\r
807 #if (MYSQL_VERSION_ID >= 40107)
\r
808 if (Tcl_GetBooleanFromObj(interp,objv[++i],&isSSL) != TCL_OK )
\r
811 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
814 flags |= CLIENT_SSL;
\r
817 case MYSQL_CONNCOMPRESS_OPT:
\r
818 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
821 flags |= CLIENT_COMPRESS;
\r
823 case MYSQL_CONNNOSCHEMA_OPT:
\r
824 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
827 flags |= CLIENT_NO_SCHEMA;
\r
829 case MYSQL_CONNODBC_OPT:
\r
830 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
833 flags |= CLIENT_ODBC;
\r
835 #if (MYSQL_VERSION_ID >= 40107)
\r
836 case MYSQL_MULTISTATEMENT_OPT:
\r
837 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
840 flags |= CLIENT_MULTI_STATEMENTS;
\r
842 case MYSQL_MULTIRESULT_OPT:
\r
843 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
846 flags |= CLIENT_MULTI_RESULTS;
\r
849 case MYSQL_LOCALFILES_OPT:
\r
850 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
853 flags |= CLIENT_LOCAL_FILES;
\r
855 case MYSQL_IGNORESPACE_OPT:
\r
856 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
859 flags |= CLIENT_IGNORE_SPACE;
\r
861 case MYSQL_FOUNDROWS_OPT:
\r
862 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
865 flags |= CLIENT_FOUND_ROWS;
\r
867 case MYSQL_INTERACTIVE_OPT:
\r
868 if (Tcl_GetBooleanFromObj(interp,objv[++i],&booleanflag) != TCL_OK )
\r
871 flags |= CLIENT_INTERACTIVE;
\r
873 case MYSQL_SSLKEY_OPT:
\r
874 sslkey = Tcl_GetStringFromObj(objv[++i],NULL);
\r
876 case MYSQL_SSLCERT_OPT:
\r
877 sslcert = Tcl_GetStringFromObj(objv[++i],NULL);
\r
879 case MYSQL_SSLCA_OPT:
\r
880 sslca = Tcl_GetStringFromObj(objv[++i],NULL);
\r
882 case MYSQL_SSLCAPATH_OPT:
\r
883 sslcapath = Tcl_GetStringFromObj(objv[++i],NULL);
\r
885 case MYSQL_SSLCIPHERS_OPT:
\r
886 sslcipher = Tcl_GetStringFromObj(objv[++i],NULL);
\r
889 return mysql_prim_confl(interp,objc,objv,"Weirdness in options");
\r
893 handle = createMysqlHandle(statePtr);
\r
896 panic("no memory for handle");
\r
901 handle->connection = mysql_init(NULL);
\r
903 /* the function below caused in version pre 3.23.50 segmentation fault */
\r
904 #if (MYSQL_VERSION_ID>=32350)
\r
905 mysql_options(handle->connection,MYSQL_READ_DEFAULT_GROUP,groupname);
\r
907 #if (MYSQL_VERSION_ID >= 40107)
\r
909 mysql_ssl_set(handle->connection,sslkey,sslcert, sslca, sslcapath, sslcipher);
\r
913 if (!mysql_real_connect(handle->connection, hostname, user,
\r
914 password, db, port, socket, flags)) {
\r
915 mysql_server_confl(interp,objc,objv,handle->connection);
\r
916 closeHandle(handle);
\r
921 strncpy(handle->database, db, MYSQL_NAME_LEN) ;
\r
922 handle->database[MYSQL_NAME_LEN - 1] = '\0' ;
\r
925 if (encodingname==NULL || (encodingname!=NULL && strcmp(encodingname, "binary") != 0)) {
\r
926 if (encodingname==NULL)
\r
927 encodingname = (char *)Tcl_GetEncodingName(NULL);
\r
928 handle->encoding = Tcl_GetEncoding(interp, encodingname);
\r
929 if (handle->encoding == NULL)
\r
933 Tcl_SetObjResult(interp, Tcl_NewHandleObj(statePtr,handle));
\r
941 *----------------------------------------------------------------------
\r
944 * Implements the mysqluse command:
\r
946 * usage: mysqluse handle dbname
\r
949 * Sets current database to dbname.
\r
952 static int Mysqltcl_Use(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
956 MysqlTclHandle *handle;
\r
958 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
959 "handle dbname")) == 0)
\r
962 db=Tcl_GetStringFromObj(objv[2], &len);
\r
963 if (len >= MYSQL_NAME_LEN) {
\r
964 mysql_prim_confl(interp,objc,objv,"database name too long");
\r
968 if (mysql_select_db(handle->connection, db)!=0) {
\r
969 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
971 strcpy(handle->database, db);
\r
978 *----------------------------------------------------------------------
\r
981 * Implements the mysqlescape command:
\r
982 * usage: mysqlescape string
\r
985 * Escaped string for use in queries.
\r
988 static int Mysqltcl_Escape(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
991 char *inString, *outString;
\r
992 MysqlTclHandle *handle;
\r
994 if (objc <2 || objc>3) {
\r
995 Tcl_WrongNumArgs(interp, 1, objv, "?handle? string");
\r
999 inString=Tcl_GetStringFromObj(objv[1], &len);
\r
1000 outString=Tcl_Alloc((len<<1) + 1);
\r
1001 len=mysql_escape_string(outString, inString, len);
\r
1002 Tcl_SetStringObj(Tcl_GetObjResult(interp), outString, len);
\r
1003 Tcl_Free(outString);
\r
1005 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
1006 "handle string")) == 0)
\r
1008 inString=Tcl_GetStringFromObj(objv[2], &len);
\r
1009 outString=Tcl_Alloc((len<<1) + 1);
\r
1010 len=mysql_real_escape_string(handle->connection, outString, inString, len);
\r
1011 Tcl_SetStringObj(Tcl_GetObjResult(interp), outString, len);
\r
1012 Tcl_Free(outString);
\r
1020 *----------------------------------------------------------------------
\r
1023 * Implements the mysqlsel command:
\r
1024 * usage: mysqlsel handle sel-query ?-list|-flatlist?
\r
1028 * SIDE EFFECT: Flushes any pending result, even in case of conflict.
\r
1029 * Stores new results.
\r
1032 static int Mysqltcl_Sel(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1034 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
1035 Tcl_Obj *res, *resList;
\r
1037 MysqlTclHandle *handle;
\r
1038 unsigned long *lengths;
\r
1041 static CONST char* selOptions[] = {"-list", "-flatlist", NULL};
\r
1042 /* Warning !! no option number */
\r
1043 int i,selOption=2,colCount;
\r
1045 if ((handle = mysql_prologue(interp, objc, objv, 3, 4, CL_CONN,
\r
1046 "handle sel-query ?-list|-flatlist?")) == 0)
\r
1051 if (Tcl_GetIndexFromObj(interp, objv[3], selOptions, "option",
\r
1052 TCL_EXACT, &selOption) != TCL_OK)
\r
1056 /* Flush any previous result. */
\r
1057 freeResult(handle);
\r
1059 if (mysql_QueryTclObj(handle,objv[2])) {
\r
1060 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1062 if (selOption<2) {
\r
1063 /* If imadiatly result than do not store result in mysql client library cache */
\r
1064 handle->result = mysql_use_result(handle->connection);
\r
1066 handle->result = mysql_store_result(handle->connection);
\r
1069 if (handle->result == NULL) {
\r
1070 if (selOption==2) Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
\r
1072 colCount = handle->col_count = mysql_num_fields(handle->result);
\r
1073 res = Tcl_GetObjResult(interp);
\r
1074 handle->res_count = 0;
\r
1075 switch (selOption) {
\r
1076 case 0: /* -list */
\r
1077 while ((row = mysql_fetch_row(handle->result)) != NULL) {
\r
1078 resList = Tcl_NewListObj(0, NULL);
\r
1079 lengths = mysql_fetch_lengths(handle->result);
\r
1080 for (i=0; i< colCount; i++, row++) {
\r
1081 Tcl_ListObjAppendElement(interp, resList,getRowCellAsObject(statePtr,handle,row,lengths[i]));
\r
1083 Tcl_ListObjAppendElement(interp, res, resList);
\r
1086 case 1: /* -flatlist */
\r
1087 while ((row = mysql_fetch_row(handle->result)) != NULL) {
\r
1088 lengths = mysql_fetch_lengths(handle->result);
\r
1089 for (i=0; i< colCount; i++, row++) {
\r
1090 Tcl_ListObjAppendElement(interp, res,getRowCellAsObject(statePtr,handle,row,lengths[i]));
\r
1094 case 2: /* No option */
\r
1095 handle->res_count = mysql_num_rows(handle->result);
\r
1096 Tcl_SetIntObj(res, handle->res_count);
\r
1104 * Works as mysqltclsel but return an $query handle that allow to build
\r
1105 * nested queries on simple handle
\r
1108 static int Mysqltcl_Query(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1110 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
1111 MYSQL_RES *result;
\r
1112 MysqlTclHandle *handle, *qhandle;
\r
1114 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
1116 "handle sqlstatement")) == 0)
\r
1119 if (mysql_QueryTclObj(handle,objv[2])) {
\r
1120 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1123 if ((result = mysql_store_result(handle->connection)) == NULL) {
\r
1124 Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
\r
1127 if ((qhandle = createHandleFrom(statePtr,handle,HT_QUERY)) == NULL) return TCL_ERROR;
\r
1128 qhandle->result = result;
\r
1129 qhandle->col_count = mysql_num_fields(qhandle->result) ;
\r
1132 qhandle->res_count = mysql_num_rows(qhandle->result);
\r
1133 Tcl_SetObjResult(interp, Tcl_NewHandleObj(statePtr,qhandle));
\r
1138 * Mysqltcl_Enquery
\r
1139 * close and free a query handle
\r
1140 * if handle is not query than the result will be discarted
\r
1143 static int Mysqltcl_EndQuery(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1145 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
1146 Tcl_HashEntry *entryPtr;
\r
1147 MysqlTclHandle *handle;
\r
1149 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
1150 "queryhandle")) == 0)
\r
1153 if (handle->type==HT_QUERY) {
\r
1154 entryPtr = Tcl_FindHashEntry(&statePtr->hash,Tcl_GetStringFromObj(objv[1],NULL));
\r
1156 Tcl_DeleteHashEntry(entryPtr);
\r
1158 closeHandle(handle);
\r
1160 freeResult(handle);
\r
1166 *----------------------------------------------------------------------
\r
1169 * Implements the mysqlexec command:
\r
1170 * usage: mysqlexec handle sql-statement
\r
1173 * Number of affected rows on INSERT, UPDATE or DELETE, 0 otherwise.
\r
1175 * SIDE EFFECT: Flushes any pending result, even in case of conflict.
\r
1180 static int Mysqltcl_Exec(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1182 MysqlTclHandle *handle;
\r
1185 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,"handle sql-statement")) == 0)
\r
1188 /* Flush any previous result. */
\r
1189 freeResult(handle);
\r
1191 if (mysql_QueryTclObj(handle,objv[2]))
\r
1192 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1194 if ((affected=mysql_affected_rows(handle->connection)) < 0) affected=0;
\r
1196 #if (MYSQL_VERSION_ID >= 50000)
\r
1197 if (!mysql_next_result(handle->connection)) {
\r
1198 resList = Tcl_GetObjResult(interp);
\r
1199 Tcl_ListObjAppendElement(interp, resList, Tcl_NewIntObj(affected));
\r
1201 if ((affected=mysql_affected_rows(handle->connection)) < 0) affected=0;
\r
1202 Tcl_ListObjAppendElement(interp, resList, Tcl_NewIntObj(affected));
\r
1203 } while (!mysql_next_result(handle->connection));
\r
1207 Tcl_SetIntObj(Tcl_GetObjResult(interp),affected);
\r
1214 *----------------------------------------------------------------------
\r
1217 * Implements the mysqlnext command:
\r
1219 * usage: mysql::fetch handle
\r
1222 * next row from pending results as tcl list, or null list.
\r
1225 static int Mysqltcl_Fetch(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1227 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
1228 MysqlTclHandle *handle;
\r
1232 unsigned long *lengths;
\r
1234 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_RES,"handle")) == 0)
\r
1238 if (handle->res_count == 0)
\r
1240 else if ((row = mysql_fetch_row(handle->result)) == NULL) {
\r
1241 handle->res_count = 0 ;
\r
1242 return mysql_prim_confl(interp,objc,objv,"result counter out of sync") ;
\r
1244 handle->res_count-- ;
\r
1246 lengths = mysql_fetch_lengths(handle->result);
\r
1249 resList = Tcl_GetObjResult(interp);
\r
1250 for (idx = 0 ; idx < handle->col_count ; idx++, row++) {
\r
1251 Tcl_ListObjAppendElement(interp, resList,getRowCellAsObject(statePtr,handle,row,lengths[idx]));
\r
1258 *----------------------------------------------------------------------
\r
1261 * Implements the mysqlseek command:
\r
1262 * usage: mysqlseek handle rownumber
\r
1265 * number of remaining rows
\r
1268 static int Mysqltcl_Seek(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1270 MysqlTclHandle *handle;
\r
1274 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_RES,
\r
1275 " handle row-index")) == 0)
\r
1278 if (Tcl_GetIntFromObj(interp, objv[2], &row) != TCL_OK)
\r
1281 total = mysql_num_rows(handle->result);
\r
1283 if (total + row < 0) {
\r
1284 mysql_data_seek(handle->result, 0);
\r
1286 handle->res_count = total;
\r
1287 } else if (row < 0) {
\r
1288 mysql_data_seek(handle->result, total + row);
\r
1289 handle->res_count = -row;
\r
1290 } else if (row >= total) {
\r
1291 mysql_data_seek(handle->result, row);
\r
1292 handle->res_count = 0;
\r
1294 mysql_data_seek(handle->result, row);
\r
1295 handle->res_count = total - row;
\r
1298 Tcl_SetObjResult(interp, Tcl_NewIntObj(handle->res_count)) ;
\r
1304 *----------------------------------------------------------------------
\r
1307 * Implements the mysqlmap command:
\r
1308 * usage: mysqlmap handle binding-list script
\r
1311 * SIDE EFFECT: For each row the column values are bound to the variables
\r
1312 * in the binding list and the script is evaluated.
\r
1313 * The variables are created in the current context.
\r
1314 * NOTE: mysqlmap works very much like a 'foreach' construct.
\r
1315 * The 'continue' and 'break' commands may be used with their usual effect.
\r
1318 static int Mysqltcl_Map(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1320 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
1324 MysqlTclHandle *handle;
\r
1327 Tcl_Obj *tempObj,*varNameObj;
\r
1330 unsigned long *lengths;
\r
1332 if ((handle = mysql_prologue(interp, objc, objv, 4, 4, CL_RES,
\r
1333 "handle binding-list script")) == 0)
\r
1336 if (Tcl_ListObjLength(interp, objv[2], &listObjc) != TCL_OK)
\r
1337 return TCL_ERROR ;
\r
1340 if (listObjc > handle->col_count)
\r
1342 return mysql_prim_confl(interp,objc,objv,"too many variables in binding list") ;
\r
1345 count = (listObjc < handle->col_count)?listObjc
\r
1346 :handle->col_count ;
\r
1348 val=(int*)Tcl_Alloc((count * sizeof(int)));
\r
1350 for (idx=0; idx<count; idx++) {
\r
1352 if (Tcl_ListObjIndex(interp, objv[2], idx, &varNameObj)!=TCL_OK)
\r
1354 if (Tcl_GetStringFromObj(varNameObj,0)[0] != '-')
\r
1360 while (handle->res_count > 0) {
\r
1361 /* Get next row, decrement row counter. */
\r
1362 if ((row = mysql_fetch_row(handle->result)) == NULL) {
\r
1363 handle->res_count = 0 ;
\r
1364 Tcl_Free((char *)val);
\r
1365 return mysql_prim_confl(interp,objc,objv,"result counter out of sync") ;
\r
1367 handle->res_count-- ;
\r
1369 /* Bind variables to column values. */
\r
1370 for (idx = 0; idx < count; idx++, row++) {
\r
1371 lengths = mysql_fetch_lengths(handle->result);
\r
1373 tempObj = getRowCellAsObject(statePtr,handle,row,lengths[idx]);
\r
1374 if (Tcl_ListObjIndex(interp, objv[2], idx, &varNameObj) != TCL_OK)
\r
1376 if (Tcl_ObjSetVar2 (interp,varNameObj,NULL,tempObj,0) == NULL)
\r
1381 /* Evaluate the script. */
\r
1382 switch(code=Tcl_EvalObjEx(interp, objv[3],0)) {
\r
1383 case TCL_CONTINUE:
\r
1387 Tcl_Free((char *)val);
\r
1390 Tcl_Free((char *)val);
\r
1394 Tcl_Free((char *)val);
\r
1397 Tcl_Free((char *)val);
\r
1398 return TCL_ERROR;
\r
1402 *----------------------------------------------------------------------
\r
1404 * Mysqltcl_Receive
\r
1405 * Implements the mysqlmap command:
\r
1406 * usage: mysqlmap handle sqlquery binding-list script
\r
1408 * The method use internal mysql_use_result that no cache statment on client but
\r
1409 * receive it direct from server
\r
1412 * SIDE EFFECT: For each row the column values are bound to the variables
\r
1413 * in the binding list and the script is evaluated.
\r
1414 * The variables are created in the current context.
\r
1415 * NOTE: mysqlmap works very much like a 'foreach' construct.
\r
1416 * The 'continue' and 'break' commands may be used with their usual effect.
\r
1420 static int Mysqltcl_Receive(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1422 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
1426 MysqlTclHandle *handle;
\r
1429 Tcl_Obj *tempObj,*varNameObj;
\r
1432 int breakLoop = 0;
\r
1433 unsigned long *lengths;
\r
1436 if ((handle = mysql_prologue(interp, objc, objv, 5, 5, CL_CONN,
\r
1437 "handle sqlquery binding-list script")) == 0)
\r
1440 if (Tcl_ListObjLength(interp, objv[3], &listObjc) != TCL_OK)
\r
1443 freeResult(handle);
\r
1445 if (mysql_QueryTclObj(handle,objv[2])) {
\r
1446 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1449 if ((handle->result = mysql_use_result(handle->connection)) == NULL) {
\r
1450 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1452 while ((row = mysql_fetch_row(handle->result))!= NULL) {
\r
1454 /* first row compute all data */
\r
1455 handle->col_count = mysql_num_fields(handle->result);
\r
1456 if (listObjc > handle->col_count) {
\r
1457 return mysql_prim_confl(interp,objc,objv,"too many variables in binding list") ;
\r
1459 count = (listObjc < handle->col_count)?listObjc:handle->col_count ;
\r
1461 val=(int*)Tcl_Alloc((count * sizeof(int)));
\r
1462 for (idx=0; idx<count; idx++) {
\r
1463 if (Tcl_ListObjIndex(interp, objv[3], idx, &varNameObj)!=TCL_OK)
\r
1465 if (Tcl_GetStringFromObj(varNameObj,0)[0] != '-')
\r
1471 for (idx = 0; idx < count; idx++, row++) {
\r
1472 lengths = mysql_fetch_lengths(handle->result);
\r
1475 if (Tcl_ListObjIndex(interp, objv[3], idx, &varNameObj)!=TCL_OK) {
\r
1476 Tcl_Free((char *)val);
\r
1479 tempObj = getRowCellAsObject(statePtr,handle,row,lengths[idx]);
\r
1480 if (Tcl_ObjSetVar2 (interp,varNameObj,NULL,tempObj,TCL_LEAVE_ERR_MSG) == NULL) {
\r
1481 Tcl_Free((char *)val);
\r
1482 return TCL_ERROR ;
\r
1487 /* Evaluate the script. */
\r
1488 switch(code=Tcl_EvalObjEx(interp, objv[4],0)) {
\r
1489 case TCL_CONTINUE:
\r
1499 if (breakLoop==1) break;
\r
1503 Tcl_Free((char *)val);
\r
1505 /* Read all rest rows that leave in error or break case */
\r
1506 while ((row = mysql_fetch_row(handle->result))!= NULL);
\r
1507 if (code!=TCL_CONTINUE && code!=TCL_OK && code!=TCL_BREAK) {
\r
1510 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1516 *----------------------------------------------------------------------
\r
1519 * Implements the mysqlinfo command:
\r
1520 * usage: mysqlinfo handle option
\r
1526 static int Mysqltcl_Info(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1530 MysqlTclHandle *handle;
\r
1536 static CONST char* MysqlDbOpt[] =
\r
1538 "dbname", "dbname?", "tables", "host", "host?", "databases",
\r
1539 "info","serverversion",
\r
1540 #if (MYSQL_VERSION_ID >= 40107)
\r
1541 "serverversionid","sqlstate",
\r
1546 MYSQL_INFNAME_OPT, MYSQL_INFNAMEQ_OPT, MYSQL_INFTABLES_OPT,
\r
1547 MYSQL_INFHOST_OPT, MYSQL_INFHOSTQ_OPT, MYSQL_INFLIST_OPT, MYSQL_INFO,
\r
1548 MYSQL_INF_SERVERVERSION,MYSQL_INFO_SERVERVERSION_ID,MYSQL_INFO_SQLSTATE,MYSQL_INFO_STATE
\r
1551 /* We can't fully check the handle at this stage. */
\r
1552 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_PLAIN,
\r
1553 "handle option")) == 0)
\r
1556 if (Tcl_GetIndexFromObj(interp, objv[2], MysqlDbOpt, "option",
\r
1557 TCL_EXACT, &idx) != TCL_OK)
\r
1560 /* First check the handle. Checking depends on the option. */
\r
1562 case MYSQL_INFNAMEQ_OPT:
\r
1563 if ((handle = get_handle(interp,objc,objv,CL_CONN))!=NULL) {
\r
1564 if (handle->database[0] == '\0')
\r
1565 return TCL_OK ; /* Return empty string if no current db. */
\r
1568 case MYSQL_INFNAME_OPT:
\r
1569 case MYSQL_INFTABLES_OPT:
\r
1570 case MYSQL_INFHOST_OPT:
\r
1571 case MYSQL_INFLIST_OPT:
\r
1573 handle = get_handle(interp,objc,objv,CL_CONN);
\r
1576 case MYSQL_INF_SERVERVERSION:
\r
1577 #if (MYSQL_VERSION_ID >= 40107)
\r
1578 case MYSQL_INFO_SERVERVERSION_ID:
\r
1579 case MYSQL_INFO_SQLSTATE:
\r
1581 case MYSQL_INFO_STATE:
\r
1584 case MYSQL_INFHOSTQ_OPT:
\r
1585 if (handle->connection == 0)
\r
1586 return TCL_OK ; /* Return empty string if not connected. */
\r
1588 default: /* should never happen */
\r
1589 return mysql_prim_confl(interp,objc,objv,"weirdness in Mysqltcl_Info") ;
\r
1592 if (handle == 0) return TCL_ERROR ;
\r
1594 /* Handle OK, return the requested info. */
\r
1596 case MYSQL_INFNAME_OPT:
\r
1597 case MYSQL_INFNAMEQ_OPT:
\r
1598 Tcl_SetObjResult(interp, Tcl_NewStringObj(handle->database, -1));
\r
1600 case MYSQL_INFTABLES_OPT:
\r
1601 if ((list = mysql_list_tables(handle->connection,(char*)NULL)) == NULL)
\r
1602 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1604 resList = Tcl_GetObjResult(interp);
\r
1605 for (count = mysql_num_rows(list); count > 0; count--) {
\r
1606 val = *(row = mysql_fetch_row(list)) ;
\r
1607 Tcl_ListObjAppendElement(interp, resList, Tcl_NewStringObj((val == NULL)?"":val,-1));
\r
1609 mysql_free_result(list) ;
\r
1611 case MYSQL_INFHOST_OPT:
\r
1613 case MYSQL_INFHOSTQ_OPT:
\r
1614 Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_get_host_info(handle->connection), -1));
\r
1616 case MYSQL_INFLIST_OPT:
\r
1617 if ((list = mysql_list_dbs(handle->connection,(char*)NULL)) == NULL)
\r
1618 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
1620 resList = Tcl_GetObjResult(interp);
\r
1621 for (count = mysql_num_rows(list); count > 0; count--) {
\r
1622 val = *(row = mysql_fetch_row(list)) ;
\r
1623 Tcl_ListObjAppendElement(interp, resList,
\r
1624 Tcl_NewStringObj((val == NULL)?"":val,-1));
\r
1626 mysql_free_result(list) ;
\r
1629 val = mysql_info(handle->connection);
\r
1631 Tcl_SetObjResult(interp, Tcl_NewStringObj(val,-1));
\r
1634 case MYSQL_INF_SERVERVERSION:
\r
1635 Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_get_server_info(handle->connection),-1));
\r
1637 #if (MYSQL_VERSION_ID >= 40107)
\r
1638 case MYSQL_INFO_SERVERVERSION_ID:
\r
1639 Tcl_SetObjResult(interp, Tcl_NewIntObj(mysql_get_server_version(handle->connection)));
\r
1641 case MYSQL_INFO_SQLSTATE:
\r
1642 Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_sqlstate(handle->connection),-1));
\r
1645 case MYSQL_INFO_STATE:
\r
1646 Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_stat(handle->connection),-1));
\r
1648 default: /* should never happen */
\r
1649 return mysql_prim_confl(interp,objc,objv,"weirdness in Mysqltcl_Info") ;
\r
1656 *----------------------------------------------------------------------
\r
1658 * Mysqltcl_BaseInfo
\r
1659 * Implements the mysqlinfo command:
\r
1660 * usage: mysqlbaseinfo option
\r
1664 static int Mysqltcl_BaseInfo(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1669 static CONST char* MysqlInfoOpt[] =
\r
1671 "connectparameters", "clientversion",
\r
1672 #if (MYSQL_VERSION_ID >= 40107)
\r
1673 "clientversionid",
\r
1678 MYSQL_BINFO_CONNECT, MYSQL_BINFO_CLIENTVERSION,MYSQL_BINFO_CLIENTVERSIONID
\r
1682 Tcl_WrongNumArgs(interp, 1, objv, "connectparameters | clientversion");
\r
1686 if (Tcl_GetIndexFromObj(interp, objv[1], MysqlInfoOpt, "option",
\r
1687 TCL_EXACT, &idx) != TCL_OK)
\r
1690 /* First check the handle. Checking depends on the option. */
\r
1692 case MYSQL_BINFO_CONNECT:
\r
1693 option = (char **)MysqlConnectOpt;
\r
1694 resList = Tcl_NewListObj(0, NULL);
\r
1696 while (*option!=NULL) {
\r
1697 Tcl_ListObjAppendElement(interp, resList, Tcl_NewStringObj(*option,-1));
\r
1700 Tcl_SetObjResult(interp, resList);
\r
1702 case MYSQL_BINFO_CLIENTVERSION:
\r
1703 Tcl_SetObjResult(interp, Tcl_NewStringObj(mysql_get_client_info(),-1));
\r
1705 #if (MYSQL_VERSION_ID >= 40107)
\r
1706 case MYSQL_BINFO_CLIENTVERSIONID:
\r
1707 Tcl_SetObjResult(interp, Tcl_NewIntObj(mysql_get_client_version()));
\r
1716 *----------------------------------------------------------------------
\r
1720 * Implements the mysqlresult command:
\r
1721 * usage: mysqlresult handle option
\r
1725 static int Mysqltcl_Result(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1728 MysqlTclHandle *handle;
\r
1729 static CONST char* MysqlResultOpt[] =
\r
1731 "rows", "rows?", "cols", "cols?", "current", "current?", NULL
\r
1733 enum resultoption {
\r
1734 MYSQL_RESROWS_OPT, MYSQL_RESROWSQ_OPT, MYSQL_RESCOLS_OPT,
\r
1735 MYSQL_RESCOLSQ_OPT, MYSQL_RESCUR_OPT, MYSQL_RESCURQ_OPT
\r
1737 /* We can't fully check the handle at this stage. */
\r
1738 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_PLAIN,
\r
1739 " handle option")) == 0)
\r
1743 if (Tcl_GetIndexFromObj(interp, objv[2], MysqlResultOpt, "option",
\r
1744 TCL_EXACT, &idx) != TCL_OK)
\r
1747 /* First check the handle. Checking depends on the option. */
\r
1749 case MYSQL_RESROWS_OPT:
\r
1750 case MYSQL_RESCOLS_OPT:
\r
1751 case MYSQL_RESCUR_OPT:
\r
1752 handle = get_handle(interp,objc,objv,CL_RES) ;
\r
1754 case MYSQL_RESROWSQ_OPT:
\r
1755 case MYSQL_RESCOLSQ_OPT:
\r
1756 case MYSQL_RESCURQ_OPT:
\r
1757 if ((handle = get_handle(interp,objc,objv,CL_RES))== NULL)
\r
1758 return TCL_OK ; /* Return empty string if no pending result. */
\r
1760 default: /* should never happen */
\r
1761 return mysql_prim_confl(interp,objc,objv,"weirdness in Mysqltcl_Result") ;
\r
1766 return TCL_ERROR ;
\r
1768 /* Handle OK; return requested info. */
\r
1770 case MYSQL_RESROWS_OPT:
\r
1771 case MYSQL_RESROWSQ_OPT:
\r
1772 Tcl_SetObjResult(interp, Tcl_NewIntObj(handle->res_count));
\r
1774 case MYSQL_RESCOLS_OPT:
\r
1775 case MYSQL_RESCOLSQ_OPT:
\r
1776 Tcl_SetObjResult(interp, Tcl_NewIntObj(handle->col_count));
\r
1778 case MYSQL_RESCUR_OPT:
\r
1779 case MYSQL_RESCURQ_OPT:
\r
1780 Tcl_SetObjResult(interp,
\r
1781 Tcl_NewIntObj(mysql_num_rows(handle->result)
\r
1782 - handle->res_count)) ;
\r
1785 return mysql_prim_confl(interp,objc,objv,"weirdness in Mysqltcl_Result");
\r
1792 *----------------------------------------------------------------------
\r
1796 * Implements the mysqlcol command:
\r
1797 * usage: mysqlcol handle table-name option ?option ...?
\r
1798 * mysqlcol handle -current option ?option ...?
\r
1799 * '-current' can only be used if there is a pending result.
\r
1802 * List of lists containing column attributes.
\r
1803 * If a single attribute is requested the result is a simple list.
\r
1805 * SIDE EFFECT: '-current' disturbs the field position of the result.
\r
1808 static int Mysqltcl_Col(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1812 MysqlTclHandle *handle;
\r
1815 Tcl_Obj **listObjv, *colinfo, *resList, *resSubList;
\r
1816 MYSQL_FIELD* fld ;
\r
1817 MYSQL_RES* result ;
\r
1820 /* This check is enough only without '-current'. */
\r
1821 if ((handle = mysql_prologue(interp, objc, objv, 4, 99, CL_CONN,
\r
1822 "handle table-name option ?option ...?")) == 0)
\r
1825 /* Fetch column info.
\r
1826 * Two ways: explicit database and table names, or current.
\r
1828 argv=Tcl_GetStringFromObj(objv[2],NULL);
\r
1829 current_db = strcmp(argv, "-current") == 0;
\r
1832 if ((handle = get_handle(interp,objc,objv,CL_RES)) == 0)
\r
1833 return TCL_ERROR ;
\r
1835 result = handle->result ;
\r
1837 if ((result = mysql_list_fields(handle->connection, argv, (char*)NULL)) == NULL) {
\r
1838 return mysql_server_confl(interp,objc,objv,handle->connection) ;
\r
1841 /* Must examine the first specifier at this point. */
\r
1842 if (Tcl_ListObjGetElements(interp, objv[3], &listObjc, &listObjv) != TCL_OK)
\r
1843 return TCL_ERROR ;
\r
1844 resList = Tcl_GetObjResult(interp);
\r
1845 if (objc == 4 && listObjc == 1) {
\r
1846 mysql_field_seek(result, 0) ;
\r
1847 while ((fld = mysql_fetch_field(result)) != NULL)
\r
1848 if ((colinfo = mysql_colinfo(interp,objc,objv,fld, objv[3])) != NULL) {
\r
1849 Tcl_ListObjAppendElement(interp, resList, colinfo);
\r
1853 } else if (objc == 4 && listObjc > 1) {
\r
1854 mysql_field_seek(result, 0) ;
\r
1855 while ((fld = mysql_fetch_field(result)) != NULL) {
\r
1856 resSubList = Tcl_NewListObj(0, NULL);
\r
1857 for (coln = 0; coln < listObjc; coln++)
\r
1858 if ((colinfo = mysql_colinfo(interp,objc,objv,fld, listObjv[coln])) != NULL) {
\r
1859 Tcl_ListObjAppendElement(interp, resSubList, colinfo);
\r
1864 Tcl_ListObjAppendElement(interp, resList, resSubList);
\r
1867 for (idx = 3; idx < objc; idx++) {
\r
1868 resSubList = Tcl_NewListObj(0, NULL);
\r
1869 mysql_field_seek(result, 0) ;
\r
1870 while ((fld = mysql_fetch_field(result)) != NULL)
\r
1871 if ((colinfo = mysql_colinfo(interp,objc,objv,fld, objv[idx])) != NULL) {
\r
1873 Tcl_ListObjAppendElement(interp, resSubList, colinfo);
\r
1877 Tcl_ListObjAppendElement(interp, resList, resSubList);
\r
1880 if (!current_db) mysql_free_result(result) ;
\r
1884 if (!current_db) mysql_free_result(result) ;
\r
1890 *----------------------------------------------------------------------
\r
1893 * Implements the mysqlstate command:
\r
1894 * usage: mysqlstate handle ?-numeric?
\r
1899 static int Mysqltcl_State(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1901 MysqlTclHandle *handle;
\r
1905 if (objc!=2 && objc!=3) {
\r
1906 Tcl_WrongNumArgs(interp, 1, objv, "handle ?-numeric");
\r
1911 if (strcmp(Tcl_GetStringFromObj(objv[2],NULL), "-numeric"))
\r
1912 return mysql_prim_confl(interp,objc,objv,"last parameter should be -numeric");
\r
1918 if (GetHandleFromObj(interp, objv[1], &handle) != TCL_OK)
\r
1919 res = (numeric)?Tcl_NewIntObj(0):Tcl_NewStringObj("NOT_A_HANDLE",-1);
\r
1920 else if (handle->connection == 0)
\r
1921 res = (numeric)?Tcl_NewIntObj(1):Tcl_NewStringObj("UNCONNECTED",-1);
\r
1922 else if (handle->database[0] == '\0')
\r
1923 res = (numeric)?Tcl_NewIntObj(2):Tcl_NewStringObj("CONNECTED",-1);
\r
1924 else if (handle->result == NULL)
\r
1925 res = (numeric)?Tcl_NewIntObj(3):Tcl_NewStringObj("IN_USE",-1);
\r
1927 res = (numeric)?Tcl_NewIntObj(4):Tcl_NewStringObj("RESULT_PENDING",-1);
\r
1929 Tcl_SetObjResult(interp, res);
\r
1935 *----------------------------------------------------------------------
\r
1937 * Mysqltcl_InsertId
\r
1938 * Implements the mysqlstate command:
\r
1939 * usage: mysqlinsertid handle
\r
1940 * Returns the auto increment id of the last INSERT statement
\r
1944 static int Mysqltcl_InsertId(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1947 MysqlTclHandle *handle;
\r
1949 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
1953 Tcl_SetObjResult(interp, Tcl_NewIntObj(mysql_insert_id(handle->connection)));
\r
1959 *----------------------------------------------------------------------
\r
1962 * usage: mysqlping handle
\r
1963 * It can be used to check and refresh (reconnect after time out) the connection
\r
1964 * Returns 0 if connection is OK
\r
1968 static int Mysqltcl_Ping(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1970 MysqlTclHandle *handle;
\r
1972 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
1976 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(mysql_ping(handle->connection)==0));
\r
1982 *----------------------------------------------------------------------
\r
1984 * Mysqltcl_ChangeUser
\r
1985 * usage: mysqlchangeuser handle user password database
\r
1986 * return TCL_ERROR if operation failed
\r
1989 static int Mysqltcl_ChangeUser(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
1991 MysqlTclHandle *handle;
\r
1993 char *user,*password,*database=NULL;
\r
1995 if ((handle = mysql_prologue(interp, objc, objv, 4, 5, CL_CONN,
\r
1996 "handle user password ?database?")) == 0)
\r
1999 user = Tcl_GetStringFromObj(objv[2],NULL);
\r
2000 password = Tcl_GetStringFromObj(objv[3],NULL);
\r
2002 database = Tcl_GetStringFromObj(objv[4],&len);
\r
2003 if (len >= MYSQL_NAME_LEN) {
\r
2004 mysql_prim_confl(interp,objc,objv,"database name too long");
\r
2008 if (mysql_change_user(handle->connection, user, password, database)!=0) {
\r
2009 mysql_server_confl(interp,objc,objv,handle->connection);
\r
2012 if (database!=NULL)
\r
2013 strcpy(handle->database, database);
\r
2017 *----------------------------------------------------------------------
\r
2019 * Mysqltcl_AutoCommit
\r
2020 * usage: mysql::autocommit bool
\r
2021 * set autocommit mode
\r
2024 static int Mysqltcl_AutoCommit(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2026 #if (MYSQL_VERSION_ID < 40107)
\r
2027 Tcl_AddErrorInfo(interp, FUNCTION_NOT_AVAILABLE);
\r
2030 MysqlTclHandle *handle;
\r
2031 int isAutocommit = 0;
\r
2033 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
2034 "handle bool")) == 0)
\r
2036 if (Tcl_GetBooleanFromObj(interp,objv[2],&isAutocommit) != TCL_OK )
\r
2038 if (mysql_autocommit(handle->connection, isAutocommit)!=0) {
\r
2039 mysql_server_confl(interp,objc,objv,handle->connection);
\r
2045 *----------------------------------------------------------------------
\r
2048 * usage: mysql::commit
\r
2052 static int Mysqltcl_Commit(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2054 #if (MYSQL_VERSION_ID < 40107)
\r
2055 Tcl_AddErrorInfo(interp, FUNCTION_NOT_AVAILABLE);
\r
2058 MysqlTclHandle *handle;
\r
2060 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
2063 if (mysql_commit(handle->connection)!=0) {
\r
2064 mysql_server_confl(interp,objc,objv,handle->connection);
\r
2070 *----------------------------------------------------------------------
\r
2072 * Mysqltcl_Rollback
\r
2073 * usage: mysql::rollback
\r
2077 static int Mysqltcl_Rollback(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2079 #if (MYSQL_VERSION_ID < 40107)
\r
2080 Tcl_AddErrorInfo(interp, FUNCTION_NOT_AVAILABLE);
\r
2083 MysqlTclHandle *handle;
\r
2085 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
2088 if (mysql_rollback(handle->connection)!=0) {
\r
2089 mysql_server_confl(interp,objc,objv,handle->connection);
\r
2095 *----------------------------------------------------------------------
\r
2097 * Mysqltcl_MoreResult
\r
2098 * usage: mysql::moreresult handle
\r
2099 * return true if more results exists
\r
2102 static int Mysqltcl_MoreResult(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2104 #if (MYSQL_VERSION_ID < 40107)
\r
2105 Tcl_AddErrorInfo(interp, FUNCTION_NOT_AVAILABLE);
\r
2108 MysqlTclHandle *handle;
\r
2109 int boolResult = 0;
\r
2111 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_RES,
\r
2114 boolResult = mysql_more_results(handle->connection);
\r
2115 Tcl_SetObjResult(interp,Tcl_NewBooleanObj(boolResult));
\r
2121 *----------------------------------------------------------------------
\r
2123 * Mysqltcl_NextResult
\r
2124 * usage: mysql::nextresult
\r
2126 * return nummber of rows in result set. 0 if no next result
\r
2129 static int Mysqltcl_NextResult(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2131 #if (MYSQL_VERSION_ID < 40107)
\r
2132 Tcl_AddErrorInfo(interp, FUNCTION_NOT_AVAILABLE);
\r
2135 MysqlTclHandle *handle;
\r
2138 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_RES,
\r
2141 if (handle->result != NULL) {
\r
2142 mysql_free_result(handle->result) ;
\r
2143 handle->result = NULL ;
\r
2145 result = mysql_next_result(handle->connection);
\r
2147 Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
\r
2151 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
2153 handle->result = mysql_store_result(handle->connection);
\r
2154 if (handle->result == NULL) {
\r
2155 Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
\r
2157 handle->res_count = mysql_num_rows(handle->result);
\r
2158 Tcl_SetObjResult(interp, Tcl_NewIntObj(handle->res_count));
\r
2164 *----------------------------------------------------------------------
\r
2166 * Mysqltcl_WarningCount
\r
2167 * usage: mysql::warningcount
\r
2171 static int Mysqltcl_WarningCount(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2173 #if (MYSQL_VERSION_ID < 40107)
\r
2174 Tcl_AddErrorInfo(interp, FUNCTION_NOT_AVAILABLE);
\r
2177 MysqlTclHandle *handle;
\r
2180 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
2183 count = mysql_warning_count(handle->connection);
\r
2184 Tcl_SetObjResult(interp,Tcl_NewIntObj(count));
\r
2189 *----------------------------------------------------------------------
\r
2192 * usage: mysql::isnull value
\r
2196 static int Mysqltcl_IsNull(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2198 int boolResult = 0;
\r
2200 Tcl_WrongNumArgs(interp, 1, objv, "value");
\r
2203 boolResult = objv[1]->typePtr == &mysqlNullType;
\r
2204 Tcl_SetObjResult(interp,Tcl_NewBooleanObj(boolResult));
\r
2210 * Create new Mysql NullObject
\r
2211 * (similar to Tcl API for example Tcl_NewIntObj)
\r
2213 static Tcl_Obj *Mysqltcl_NewNullObj(MysqltclState *mysqltclState) {
\r
2215 objPtr = Tcl_NewObj();
\r
2216 objPtr->bytes = NULL;
\r
2217 objPtr->typePtr = &mysqlNullType;
\r
2218 objPtr->internalRep.otherValuePtr = mysqltclState;
\r
2222 *----------------------------------------------------------------------
\r
2224 * Mysqltcl_NewNull
\r
2225 * usage: mysql::newnull
\r
2229 static int Mysqltcl_NewNull(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2232 Tcl_WrongNumArgs(interp, 1, objv, "");
\r
2235 Tcl_SetObjResult(interp,Mysqltcl_NewNullObj((MysqltclState *)clientData));
\r
2239 *----------------------------------------------------------------------
\r
2241 * Mysqltcl_SetServerOption
\r
2242 * usage: mysql::setserveroption (-
\r
2245 #if (MYSQL_VERSION_ID >= 40107)
\r
2246 static CONST char* MysqlServerOpt[] =
\r
2248 "-multi_statment_on", "-multi_statment_off",NULL
\r
2252 static int Mysqltcl_SetServerOption(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2254 #if (MYSQL_VERSION_ID < 40107)
\r
2255 Tcl_AddErrorInfo(interp, FUNCTION_NOT_AVAILABLE);
\r
2258 MysqlTclHandle *handle;
\r
2260 enum enum_mysql_set_option mysqlServerOption;
\r
2262 enum serveroption {
\r
2263 MYSQL_MSTATMENT_ON_SOPT, MYSQL_MSTATMENT_OFF_SOPT
\r
2266 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
2267 "handle option")) == 0)
\r
2270 if (Tcl_GetIndexFromObj(interp, objv[2], MysqlServerOpt, "option",
\r
2271 0, &idx) != TCL_OK)
\r
2275 case MYSQL_MSTATMENT_ON_SOPT:
\r
2276 mysqlServerOption = MYSQL_OPTION_MULTI_STATEMENTS_ON;
\r
2278 case MYSQL_MSTATMENT_OFF_SOPT:
\r
2279 mysqlServerOption = MYSQL_OPTION_MULTI_STATEMENTS_OFF;
\r
2282 return mysql_prim_confl(interp,objc,objv,"Weirdness in server options");
\r
2284 if (mysql_set_server_option(handle->connection,mysqlServerOption)!=0) {
\r
2285 mysql_server_confl(interp,objc,objv,handle->connection);
\r
2291 *----------------------------------------------------------------------
\r
2293 * Mysqltcl_ShutDown
\r
2294 * usage: mysql::shutdown handle
\r
2297 static int Mysqltcl_ShutDown(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2299 MysqlTclHandle *handle;
\r
2301 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
2304 #if (MYSQL_VERSION_ID >= 40107)
\r
2305 if (mysql_shutdown(handle->connection,SHUTDOWN_DEFAULT)!=0) {
\r
2307 if (mysql_shutdown(handle->connection)!=0) {
\r
2309 mysql_server_confl(interp,objc,objv,handle->connection);
\r
2314 *----------------------------------------------------------------------
\r
2316 * Mysqltcl_Encoding
\r
2317 * usage: mysql::encoding handle ?encoding|binary?
\r
2320 static int Mysqltcl_Encoding(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2322 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
2323 Tcl_HashSearch search;
\r
2324 Tcl_HashEntry *entryPtr;
\r
2325 MysqlTclHandle *handle,*qhandle;
\r
2326 char *encodingname;
\r
2327 Tcl_Encoding encoding;
\r
2329 if ((handle = mysql_prologue(interp, objc, objv, 2, 3, CL_CONN,
\r
2333 if (handle->encoding == NULL)
\r
2334 Tcl_SetObjResult(interp, Tcl_NewStringObj("binary",-1));
\r
2336 Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetEncodingName(handle->encoding),-1));
\r
2338 if (handle->type!=HT_CONNECTION) {
\r
2339 Tcl_SetObjResult(interp, Tcl_NewStringObj("encoding set can be used only on connection handle",-1));
\r
2342 encodingname = Tcl_GetStringFromObj(objv[2],NULL);
\r
2343 if (strcmp(encodingname, "binary") == 0) {
\r
2346 encoding = Tcl_GetEncoding(interp, encodingname);
\r
2347 if (encoding == NULL)
\r
2350 if (handle->encoding!=NULL)
\r
2351 Tcl_FreeEncoding(handle->encoding);
\r
2352 handle->encoding = encoding;
\r
2354 /* change encoding of all subqueries */
\r
2355 for (entryPtr=Tcl_FirstHashEntry(&statePtr->hash,&search);
\r
2357 entryPtr=Tcl_NextHashEntry(&search)) {
\r
2358 qhandle=(MysqlTclHandle *)Tcl_GetHashValue(entryPtr);
\r
2359 if (qhandle->type==HT_QUERY && handle->connection==qhandle->connection) {
\r
2360 qhandle->encoding = encoding;
\r
2368 *----------------------------------------------------------------------
\r
2370 * Mysqltcl_Close --
\r
2371 * Implements the mysqlclose command:
\r
2372 * usage: mysqlclose ?handle?
\r
2378 static int Mysqltcl_Close(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2381 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
2382 MysqlTclHandle *handle,*thandle;
\r
2383 Tcl_HashEntry *entryPtr;
\r
2384 Tcl_HashEntry *qentries[16];
\r
2385 Tcl_HashSearch search;
\r
2390 /* If handle omitted, close all connections. */
\r
2392 Mysqltcl_CloseAll(clientData) ;
\r
2396 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
2397 "?handle?")) == 0)
\r
2401 /* Search all queries and statements on this handle and close those */
\r
2402 if (handle->type==HT_CONNECTION) {
\r
2404 for (entryPtr=Tcl_FirstHashEntry(&statePtr->hash,&search);
\r
2406 entryPtr=Tcl_NextHashEntry(&search)) {
\r
2408 thandle=(MysqlTclHandle *)Tcl_GetHashValue(entryPtr);
\r
2409 if (thandle->connection == handle->connection &&
\r
2410 thandle->type!=HT_CONNECTION) {
\r
2411 qentries[qfound++] = entryPtr;
\r
2413 if (qfound==16) break;
\r
2416 for(i=0;i<qfound;i++) {
\r
2417 entryPtr=qentries[i];
\r
2418 thandle=(MysqlTclHandle *)Tcl_GetHashValue(entryPtr);
\r
2419 Tcl_DeleteHashEntry(entryPtr);
\r
2420 closeHandle(thandle);
\r
2423 if (qfound!=16) break;
\r
2427 entryPtr = Tcl_FindHashEntry(&statePtr->hash,Tcl_GetStringFromObj(objv[1],NULL));
\r
2428 if (entryPtr) Tcl_DeleteHashEntry(entryPtr);
\r
2429 closeHandle(handle);
\r
2433 #ifdef PREPARED_STATEMENT
\r
2435 *----------------------------------------------------------------------
\r
2437 * Mysqltcl_Prepare --
\r
2438 * Implements the mysql::prepare command:
\r
2439 * usage: mysql::prepare handle statements
\r
2442 * prepared statment handle
\r
2445 static int Mysqltcl_Prepare(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2447 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
2449 MysqlTclHandle *handle;
\r
2450 MysqlTclHandle *shandle;
\r
2451 MYSQL_STMT *statement;
\r
2454 int resultColumns;
\r
2457 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
2458 "handle sql-statement")) == 0)
\r
2461 statement = mysql_stmt_init(handle->connection);
\r
2462 if (statement==NULL) {
\r
2465 query = (char *)Tcl_GetByteArrayFromObj(objv[2], &queryLen);
\r
2466 if (mysql_stmt_prepare(statement,query,queryLen)) {
\r
2468 mysql_stmt_close(statement);
\r
2469 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
2471 if ((shandle = createHandleFrom(statePtr,handle,HT_STATEMENT)) == NULL) return TCL_ERROR;
\r
2472 shandle->statement=statement;
\r
2473 shandle->resultMetadata = mysql_stmt_result_metadata(statement);
\r
2474 shandle->paramMetadata = mysql_stmt_param_metadata(statement);
\r
2475 /* set result bind memory */
\r
2476 resultColumns = mysql_stmt_field_count(statement);
\r
2477 if (resultColumns>0) {
\r
2478 shandle->bindResult = (MYSQL_BIND *)Tcl_Alloc(sizeof(MYSQL_BIND)*resultColumns);
\r
2479 memset(shandle->bindResult,0,sizeof(MYSQL_BIND)*resultColumns);
\r
2481 paramCount = mysql_stmt_param_count(statement);
\r
2482 if (resultColumns>0) {
\r
2483 shandle->bindParam = (MYSQL_BIND *)Tcl_Alloc(sizeof(MYSQL_BIND)*paramCount);
\r
2484 memset(shandle->bindParam,0,sizeof(MYSQL_BIND)*paramCount);
\r
2486 Tcl_SetObjResult(interp, Tcl_NewHandleObj(statePtr,shandle));
\r
2489 static int Mysqltcl_ParamMetaData(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2491 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
2492 MysqlTclHandle *handle;
\r
2495 Tcl_Obj *colinfo,*resObj;
\r
2496 unsigned long *lengths;
\r
2501 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
2502 "statement-handle")) == 0)
\r
2504 if(handle->type!=HT_STATEMENT)
\r
2507 resObj = Tcl_GetObjResult(interp);
\r
2508 printf("statement %p count %d\n",handle->statement,mysql_stmt_param_count(handle->statement));
\r
2509 res = mysql_stmt_result_metadata(handle->statement);
\r
2510 printf("res %p\n",res);
\r
2514 mysql_field_seek(res, 0) ;
\r
2515 while ((fld = mysql_fetch_field(res)) != NULL) {
\r
2516 if ((colinfo = mysql_colinfo(interp,objc,objv,fld, objv[2])) != NULL) {
\r
2517 Tcl_ListObjAppendElement(interp, resObj, colinfo);
\r
2524 mysql_free_result(res);
\r
2527 /*----------------------------------------------------------------------
\r
2529 * Mysqltcl_PSelect --
\r
2530 * Implements the mysql::pselect command:
\r
2531 * usage: mysql::pselect $statement_handle ?arguments...?
\r
2534 * number of returned rows
\r
2537 static int Mysqltcl_PSelect(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2539 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
2540 MysqlTclHandle *handle;
\r
2542 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
2543 "handle sql-statement")) == 0)
\r
2545 if (handle->type!=HT_STATEMENT) {
\r
2548 mysql_stmt_reset(handle->statement);
\r
2549 if (mysql_stmt_execute(handle->statement)) {
\r
2550 return mysql_server_confl(interp,objc,objv,handle->connection);
\r
2552 mysql_stmt_bind_result(handle->statement, handle->bindResult);
\r
2553 mysql_stmt_store_result(handle->statement);
\r
2556 /*----------------------------------------------------------------------
\r
2558 * Mysqltcl_PFetch --
\r
2559 * Implements the mysql::pfetch command:
\r
2560 * usage: mysql::pfetch $statement_handle
\r
2563 * number of returned rows
\r
2566 static int Mysqltcl_PFetch(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2568 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
2569 MysqlTclHandle *handle;
\r
2571 if ((handle = mysql_prologue(interp, objc, objv, 2, 2, CL_CONN,
\r
2572 "prep-stat-handle")) == 0)
\r
2574 if (handle->type!=HT_STATEMENT) {
\r
2580 /*----------------------------------------------------------------------
\r
2582 * Mysqltcl_PExecute --
\r
2583 * Implements the mysql::pexecute command:
\r
2584 * usage: mysql::pexecute statement-handle ?arguments...?
\r
2587 * number of effected rows
\r
2590 static int Mysqltcl_PExecute(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
\r
2592 MysqltclState *statePtr = (MysqltclState *)clientData;
\r
2593 MysqlTclHandle *handle;
\r
2595 if ((handle = mysql_prologue(interp, objc, objv, 3, 3, CL_CONN,
\r
2596 "handle sql-statement")) == 0)
\r
2598 if (handle->type!=HT_STATEMENT) {
\r
2601 mysql_stmt_reset(handle->statement);
\r
2603 if (mysql_stmt_param_count(handle->statement)!=0) {
\r
2604 Tcl_SetStringObj(Tcl_GetObjResult(interp),"works only for 0 params",-1);
\r
2607 if (mysql_stmt_execute(handle->statement))
\r
2609 Tcl_SetStringObj(Tcl_GetObjResult(interp),mysql_stmt_error(handle->statement),-1);
\r
2617 *----------------------------------------------------------------------
\r
2619 * Perform all initialization for the MYSQL to Tcl interface.
\r
2620 * Adds additional commands to interp, creates message array, initializes
\r
2623 * A call to Mysqltcl_Init should exist in Tcl_CreateInterp or
\r
2624 * Tcl_CreateExtendedInterp.
\r
2630 __declspec( dllexport )
\r
2632 int Mysqltcl_Init(interp)
\r
2633 Tcl_Interp *interp;
\r
2635 char nbuf[MYSQL_SMALL_SIZE];
\r
2636 MysqltclState *statePtr;
\r
2638 if (Tcl_InitStubs(interp, "8.1", 0) == NULL)
\r
2640 if (Tcl_PkgRequire(interp, "Tcl", "8.1", 0) == NULL)
\r
2642 if (Tcl_PkgProvide(interp, "mysqltcl" , PACKAGE_VERSION) != TCL_OK)
\r
2646 * Initialize the new Tcl commands.
\r
2647 * Deleting any command will close all connections.
\r
2649 statePtr = (MysqltclState*)Tcl_Alloc(sizeof(MysqltclState));
\r
2650 Tcl_InitHashTable(&statePtr->hash, TCL_STRING_KEYS);
\r
2651 statePtr->handleNum = 0;
\r
2653 Tcl_CreateObjCommand(interp,"mysqlconnect",Mysqltcl_Connect,(ClientData)statePtr, NULL);
\r
2654 Tcl_CreateObjCommand(interp,"mysqluse", Mysqltcl_Use,(ClientData)statePtr, NULL);
\r
2655 Tcl_CreateObjCommand(interp,"mysqlescape", Mysqltcl_Escape,(ClientData)statePtr, NULL);
\r
2656 Tcl_CreateObjCommand(interp,"mysqlsel", Mysqltcl_Sel,(ClientData)statePtr, NULL);
\r
2657 Tcl_CreateObjCommand(interp,"mysqlnext", Mysqltcl_Fetch,(ClientData)statePtr, NULL);
\r
2658 Tcl_CreateObjCommand(interp,"mysqlseek", Mysqltcl_Seek,(ClientData)statePtr, NULL);
\r
2659 Tcl_CreateObjCommand(interp,"mysqlmap", Mysqltcl_Map,(ClientData)statePtr, NULL);
\r
2660 Tcl_CreateObjCommand(interp,"mysqlexec", Mysqltcl_Exec,(ClientData)statePtr, NULL);
\r
2661 Tcl_CreateObjCommand(interp,"mysqlclose", Mysqltcl_Close,(ClientData)statePtr, NULL);
\r
2662 Tcl_CreateObjCommand(interp,"mysqlinfo", Mysqltcl_Info,(ClientData)statePtr, NULL);
\r
2663 Tcl_CreateObjCommand(interp,"mysqlresult", Mysqltcl_Result,(ClientData)statePtr, NULL);
\r
2664 Tcl_CreateObjCommand(interp,"mysqlcol", Mysqltcl_Col,(ClientData)statePtr, NULL);
\r
2665 Tcl_CreateObjCommand(interp,"mysqlstate", Mysqltcl_State,(ClientData)statePtr, NULL);
\r
2666 Tcl_CreateObjCommand(interp,"mysqlinsertid", Mysqltcl_InsertId,(ClientData)statePtr, NULL);
\r
2667 Tcl_CreateObjCommand(interp,"mysqlquery", Mysqltcl_Query,(ClientData)statePtr, NULL);
\r
2668 Tcl_CreateObjCommand(interp,"mysqlendquery", Mysqltcl_EndQuery,(ClientData)statePtr, NULL);
\r
2669 Tcl_CreateObjCommand(interp,"mysqlbaseinfo", Mysqltcl_BaseInfo,(ClientData)statePtr, NULL);
\r
2670 Tcl_CreateObjCommand(interp,"mysqlping", Mysqltcl_Ping,(ClientData)statePtr, NULL);
\r
2671 Tcl_CreateObjCommand(interp,"mysqlchangeuser", Mysqltcl_ChangeUser,(ClientData)statePtr, NULL);
\r
2672 Tcl_CreateObjCommand(interp,"mysqlreceive", Mysqltcl_Receive,(ClientData)statePtr, NULL);
\r
2674 Tcl_CreateObjCommand(interp,"::mysql::connect",Mysqltcl_Connect,(ClientData)statePtr, Mysqltcl_Kill);
\r
2675 Tcl_CreateObjCommand(interp,"::mysql::use", Mysqltcl_Use,(ClientData)statePtr, NULL);
\r
2676 Tcl_CreateObjCommand(interp,"::mysql::escape", Mysqltcl_Escape,(ClientData)statePtr, NULL);
\r
2677 Tcl_CreateObjCommand(interp,"::mysql::sel", Mysqltcl_Sel,(ClientData)statePtr, NULL);
\r
2678 Tcl_CreateObjCommand(interp,"::mysql::fetch", Mysqltcl_Fetch,(ClientData)statePtr, NULL);
\r
2679 Tcl_CreateObjCommand(interp,"::mysql::seek", Mysqltcl_Seek,(ClientData)statePtr, NULL);
\r
2680 Tcl_CreateObjCommand(interp,"::mysql::map", Mysqltcl_Map,(ClientData)statePtr, NULL);
\r
2681 Tcl_CreateObjCommand(interp,"::mysql::exec", Mysqltcl_Exec,(ClientData)statePtr, NULL);
\r
2682 Tcl_CreateObjCommand(interp,"::mysql::close", Mysqltcl_Close,(ClientData)statePtr, NULL);
\r
2683 Tcl_CreateObjCommand(interp,"::mysql::info", Mysqltcl_Info,(ClientData)statePtr, NULL);
\r
2684 Tcl_CreateObjCommand(interp,"::mysql::result", Mysqltcl_Result,(ClientData)statePtr, NULL);
\r
2685 Tcl_CreateObjCommand(interp,"::mysql::col", Mysqltcl_Col,(ClientData)statePtr, NULL);
\r
2686 Tcl_CreateObjCommand(interp,"::mysql::state", Mysqltcl_State,(ClientData)statePtr, NULL);
\r
2687 Tcl_CreateObjCommand(interp,"::mysql::insertid", Mysqltcl_InsertId,(ClientData)statePtr, NULL);
\r
2688 /* new in mysqltcl 2.0 */
\r
2689 Tcl_CreateObjCommand(interp,"::mysql::query", Mysqltcl_Query,(ClientData)statePtr, NULL);
\r
2690 Tcl_CreateObjCommand(interp,"::mysql::endquery", Mysqltcl_EndQuery,(ClientData)statePtr, NULL);
\r
2691 Tcl_CreateObjCommand(interp,"::mysql::baseinfo", Mysqltcl_BaseInfo,(ClientData)statePtr, NULL);
\r
2692 Tcl_CreateObjCommand(interp,"::mysql::ping", Mysqltcl_Ping,(ClientData)statePtr, NULL);
\r
2693 Tcl_CreateObjCommand(interp,"::mysql::changeuser", Mysqltcl_ChangeUser,(ClientData)statePtr, NULL);
\r
2694 Tcl_CreateObjCommand(interp,"::mysql::receive", Mysqltcl_Receive,(ClientData)statePtr, NULL);
\r
2695 /* new in mysqltcl 3.0 */
\r
2696 Tcl_CreateObjCommand(interp,"::mysql::autocommit", Mysqltcl_AutoCommit,(ClientData)statePtr, NULL);
\r
2697 Tcl_CreateObjCommand(interp,"::mysql::commit", Mysqltcl_Commit,(ClientData)statePtr, NULL);
\r
2698 Tcl_CreateObjCommand(interp,"::mysql::rollback", Mysqltcl_Rollback,(ClientData)statePtr, NULL);
\r
2699 Tcl_CreateObjCommand(interp,"::mysql::nextresult", Mysqltcl_NextResult,(ClientData)statePtr, NULL);
\r
2700 Tcl_CreateObjCommand(interp,"::mysql::moreresult", Mysqltcl_MoreResult,(ClientData)statePtr, NULL);
\r
2701 Tcl_CreateObjCommand(interp,"::mysql::warningcount", Mysqltcl_WarningCount,(ClientData)statePtr, NULL);
\r
2702 Tcl_CreateObjCommand(interp,"::mysql::isnull", Mysqltcl_IsNull,(ClientData)statePtr, NULL);
\r
2703 Tcl_CreateObjCommand(interp,"::mysql::newnull", Mysqltcl_NewNull,(ClientData)statePtr, NULL);
\r
2704 Tcl_CreateObjCommand(interp,"::mysql::setserveroption", Mysqltcl_SetServerOption,(ClientData)statePtr, NULL);
\r
2705 Tcl_CreateObjCommand(interp,"::mysql::shutdown", Mysqltcl_ShutDown,(ClientData)statePtr, NULL);
\r
2706 Tcl_CreateObjCommand(interp,"::mysql::encoding", Mysqltcl_Encoding,(ClientData)statePtr, NULL);
\r
2707 /* prepared statements */
\r
2709 #ifdef PREPARED_STATEMENT
\r
2710 Tcl_CreateObjCommand(interp,"::mysql::prepare", Mysqltcl_Prepare,(ClientData)statePtr, NULL);
\r
2711 // Tcl_CreateObjCommand(interp,"::mysql::parammetadata", Mysqltcl_ParamMetaData,(ClientData)statePtr, NULL);
\r
2712 Tcl_CreateObjCommand(interp,"::mysql::pselect", Mysqltcl_PSelect,(ClientData)statePtr, NULL);
\r
2713 Tcl_CreateObjCommand(interp,"::mysql::pselect", Mysqltcl_PFetch,(ClientData)statePtr, NULL);
\r
2714 Tcl_CreateObjCommand(interp,"::mysql::pexecute", Mysqltcl_PExecute,(ClientData)statePtr, NULL);
\r
2719 /* Initialize mysqlstatus global array. */
\r
2721 clear_msg(interp);
\r
2723 /* Link the null value element to the corresponding C variable. */
\r
2724 if ((statePtr->MysqlNullvalue = Tcl_Alloc (12)) == NULL) return TCL_ERROR;
\r
2725 strcpy (statePtr->MysqlNullvalue, MYSQL_NULLV_INIT);
\r
2726 sprintf (nbuf, "%s(%s)", MYSQL_STATUS_ARR, MYSQL_STATUS_NULLV);
\r
2728 /* set null object in mysqltcl state */
\r
2729 /* statePtr->nullObjPtr = Mysqltcl_NewNullObj(statePtr); */
\r
2731 if (Tcl_LinkVar(interp,nbuf,(char *)&statePtr->MysqlNullvalue, TCL_LINK_STRING) != TCL_OK)
\r
2734 /* Register the handle object type */
\r
2735 Tcl_RegisterObjType(&mysqlHandleType);
\r
2736 /* Register own null type object */
\r
2737 Tcl_RegisterObjType(&mysqlNullType);
\r
2739 /* A little sanity check.
\r
2740 * If this message appears you must change the source code and recompile.
\r
2742 if (strlen(MysqlHandlePrefix) == MYSQL_HPREFIX_LEN)
\r
2745 panic("*** mysqltcl (mysqltcl.c): handle prefix inconsistency!\n");
\r
2746 return TCL_ERROR ;
\r
2751 __declspec( dllexport )
\r
2753 int Mysqltcl_SafeInit(interp)
\r
2754 Tcl_Interp *interp;
\r
2756 return Mysqltcl_Init(interp);
\r