4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 *************************************************************************
14 #if defined(SQLITE_TEST)
16 #include "sqlite3expert.h"
20 #if defined(INCLUDE_SQLITE_TCL_H)
21 # include "sqlite_tcl.h"
24 # ifndef SQLITE_TCLAPI
25 # define SQLITE_TCLAPI
29 #ifndef SQLITE_OMIT_VIRTUALTABLE
32 ** Extract an sqlite3* db handle from the object passed as the second
33 ** argument. If successful, set *pDb to point to the db handle and return
34 ** TCL_OK. Otherwise, return TCL_ERROR.
36 static int dbHandleFromObj(Tcl_Interp
*interp
, Tcl_Obj
*pObj
, sqlite3
**pDb
){
38 if( 0==Tcl_GetCommandInfo(interp
, Tcl_GetString(pObj
), &info
) ){
39 Tcl_AppendResult(interp
, "no such handle: ", Tcl_GetString(pObj
), 0);
43 *pDb
= *(sqlite3
**)info
.objClientData
;
49 ** Tclcmd: $expert sql SQL
52 ** $expert report STMT EREPORT
55 static int SQLITE_TCLAPI
testExpertCmd(
61 sqlite3expert
*pExpert
= (sqlite3expert
*)clientData
;
67 { "sql", 1, "TABLE", }, /* 0 */
68 { "analyze", 0, "", }, /* 1 */
69 { "count", 0, "", }, /* 2 */
70 { "report", 2, "STMT EREPORT", }, /* 3 */
71 { "destroy", 0, "", }, /* 4 */
79 Tcl_WrongNumArgs(interp
, 1, objv
, "SUBCOMMAND ...");
82 rc
= Tcl_GetIndexFromObjStruct(interp
,
83 objv
[1], aSub
, sizeof(aSub
[0]), "sub-command", 0, &iSub
85 if( rc
!=TCL_OK
) return rc
;
86 if( objc
!=2+aSub
[iSub
].nArg
){
87 Tcl_WrongNumArgs(interp
, 2, objv
, aSub
[iSub
].zMsg
);
93 char *zArg
= Tcl_GetString(objv
[2]);
94 rc
= sqlite3_expert_sql(pExpert
, zArg
, &zErr
);
98 case 1: { /* analyze */
99 rc
= sqlite3_expert_analyze(pExpert
, &zErr
);
103 case 2: { /* count */
104 int n
= sqlite3_expert_count(pExpert
);
105 Tcl_SetObjResult(interp
, Tcl_NewIntObj(n
));
109 case 3: { /* report */
110 const char *aEnum
[] = {
111 "sql", "indexes", "plan", "candidates", 0
117 if( Tcl_GetIntFromObj(interp
, objv
[2], &iStmt
)
118 || Tcl_GetIndexFromObj(interp
, objv
[3], aEnum
, "report", 0, &iEnum
)
123 assert( EXPERT_REPORT_SQL
==1 );
124 assert( EXPERT_REPORT_INDEXES
==2 );
125 assert( EXPERT_REPORT_PLAN
==3 );
126 assert( EXPERT_REPORT_CANDIDATES
==4 );
127 zReport
= sqlite3_expert_report(pExpert
, iStmt
, 1+iEnum
);
128 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zReport
, -1));
132 default: /* destroy */
134 Tcl_DeleteCommand(interp
, Tcl_GetString(objv
[0]));
140 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zErr
, -1));
142 extern const char *sqlite3ErrName(int);
143 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
150 static void SQLITE_TCLAPI
testExpertDel(void *clientData
){
151 sqlite3expert
*pExpert
= (sqlite3expert
*)clientData
;
152 sqlite3_expert_destroy(pExpert
);
156 ** sqlite3_expert_new DB
158 static int SQLITE_TCLAPI
test_sqlite3_expert_new(
162 Tcl_Obj
*CONST objv
[]
168 sqlite3expert
*pExpert
;
172 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
175 if( dbHandleFromObj(interp
, objv
[1], &db
) ){
179 zCmd
= sqlite3_mprintf("sqlite3expert%d", ++iCmd
);
181 Tcl_AppendResult(interp
, "out of memory", (char*)0);
185 pExpert
= sqlite3_expert_new(db
, &zErr
);
187 Tcl_AppendResult(interp
, zErr
, (char*)0);
190 void *p
= (void*)pExpert
;
191 Tcl_CreateObjCommand(interp
, zCmd
, testExpertCmd
, p
, testExpertDel
);
192 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zCmd
, -1));
200 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
202 int TestExpert_Init(Tcl_Interp
*interp
){
203 #ifndef SQLITE_OMIT_VIRTUALTABLE
206 Tcl_ObjCmdProc
*xProc
;
208 { "sqlite3_expert_new", test_sqlite3_expert_new
},
212 for(i
=0; i
<sizeof(aCmd
)/sizeof(struct Cmd
); i
++){
213 struct Cmd
*p
= &aCmd
[i
];
214 Tcl_CreateObjCommand(interp
, p
->zCmd
, p
->xProc
, 0, 0);