test_intck.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. ** 2010 August 28
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  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.
  10. **
  11. *************************************************************************
  12. ** Code for testing all sorts of SQLite interfaces. This code
  13. ** is not included in the SQLite library.
  14. */
  15. #include "sqlite3.h"
  16. #include "sqlite3intck.h"
  17. #include "tclsqlite.h"
  18. #include <string.h>
  19. #include <assert.h>
  20. /* In test1.c */
  21. int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
  22. const char *sqlite3ErrName(int);
  23. typedef struct TestIntck TestIntck;
  24. struct TestIntck {
  25. sqlite3_intck *intck;
  26. };
  27. static int testIntckCmd(
  28. void * clientData,
  29. Tcl_Interp *interp,
  30. int objc,
  31. Tcl_Obj *CONST objv[]
  32. ){
  33. struct Subcmd {
  34. const char *zName;
  35. int nArg;
  36. const char *zExpect;
  37. } aCmd[] = {
  38. {"close", 0, ""}, /* 0 */
  39. {"step", 0, ""}, /* 1 */
  40. {"message", 0, ""}, /* 2 */
  41. {"error", 0, ""}, /* 3 */
  42. {"unlock", 0, ""}, /* 4 */
  43. {"test_sql", 1, ""}, /* 5 */
  44. {0 , 0}
  45. };
  46. int rc = TCL_OK;
  47. int iIdx = -1;
  48. TestIntck *p = (TestIntck*)clientData;
  49. if( objc<2 ){
  50. Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
  51. return TCL_ERROR;
  52. }
  53. rc = Tcl_GetIndexFromObjStruct(
  54. interp, objv[1], aCmd, sizeof(aCmd[0]), "SUB-COMMAND", 0, &iIdx
  55. );
  56. if( rc ) return rc;
  57. if( objc!=2+aCmd[iIdx].nArg ){
  58. Tcl_WrongNumArgs(interp, 2, objv, aCmd[iIdx].zExpect);
  59. return TCL_ERROR;
  60. }
  61. switch( iIdx ){
  62. case 0: assert( 0==strcmp("close", aCmd[iIdx].zName) ); {
  63. Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0));
  64. break;
  65. }
  66. case 1: assert( 0==strcmp("step", aCmd[iIdx].zName) ); {
  67. rc = sqlite3_intck_step(p->intck);
  68. Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  69. break;
  70. }
  71. case 2: assert( 0==strcmp("message", aCmd[iIdx].zName) ); {
  72. const char *z = sqlite3_intck_message(p->intck);
  73. Tcl_SetObjResult(interp, Tcl_NewStringObj(z ? z : "", -1));
  74. break;
  75. }
  76. case 3: assert( 0==strcmp("error", aCmd[iIdx].zName) ); {
  77. const char *zErr = 0;
  78. Tcl_Obj *pRes;
  79. rc = sqlite3_intck_error(p->intck, 0);
  80. pRes = Tcl_NewObj();
  81. Tcl_ListObjAppendElement(
  82. interp, pRes, Tcl_NewStringObj(sqlite3ErrName(rc), -1)
  83. );
  84. sqlite3_intck_error(p->intck, &zErr);
  85. Tcl_ListObjAppendElement(
  86. interp, pRes, Tcl_NewStringObj(zErr ? zErr : 0, -1)
  87. );
  88. Tcl_SetObjResult(interp, pRes);
  89. break;
  90. }
  91. case 4: assert( 0==strcmp("unlock", aCmd[iIdx].zName) ); {
  92. rc = sqlite3_intck_unlock(p->intck);
  93. Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  94. break;
  95. }
  96. case 5: assert( 0==strcmp("test_sql", aCmd[iIdx].zName) ); {
  97. const char *zObj = Tcl_GetString(objv[2]);
  98. const char *zSql = sqlite3_intck_test_sql(p->intck, zObj[0] ? zObj : 0);
  99. Tcl_SetObjResult(interp, Tcl_NewStringObj(zSql, -1));
  100. break;
  101. }
  102. }
  103. return TCL_OK;
  104. }
  105. /*
  106. ** Destructor for commands created by test_sqlite3_intck().
  107. */
  108. static void testIntckFree(void *clientData){
  109. TestIntck *p = (TestIntck*)clientData;
  110. sqlite3_intck_close(p->intck);
  111. ckfree(p);
  112. }
  113. /*
  114. ** tclcmd: sqlite3_intck DB DBNAME
  115. */
  116. static int test_sqlite3_intck(
  117. void * clientData,
  118. Tcl_Interp *interp,
  119. int objc,
  120. Tcl_Obj *CONST objv[]
  121. ){
  122. char zName[64];
  123. int iName = 0;
  124. Tcl_CmdInfo info;
  125. TestIntck *p = 0;
  126. sqlite3 *db = 0;
  127. const char *zDb = 0;
  128. int rc = SQLITE_OK;
  129. if( objc!=3 ){
  130. Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
  131. return TCL_ERROR;
  132. }
  133. p = (TestIntck*)ckalloc(sizeof(TestIntck));
  134. memset(p, 0, sizeof(TestIntck));
  135. if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  136. return TCL_ERROR;
  137. }
  138. zDb = Tcl_GetString(objv[2]);
  139. if( zDb[0]=='\0' ) zDb = 0;
  140. rc = sqlite3_intck_open(db, zDb, &p->intck);
  141. if( rc!=SQLITE_OK ){
  142. ckfree(p);
  143. Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errstr(rc), -1));
  144. return TCL_ERROR;
  145. }
  146. do {
  147. sprintf(zName, "intck%d", iName++);
  148. }while( Tcl_GetCommandInfo(interp, zName, &info)!=0 );
  149. Tcl_CreateObjCommand(interp, zName, testIntckCmd, (void*)p, testIntckFree);
  150. Tcl_SetObjResult(interp, Tcl_NewStringObj(zName, -1));
  151. return TCL_OK;
  152. }
  153. /*
  154. ** tclcmd: test_do_intck DB DBNAME
  155. */
  156. static int test_do_intck(
  157. void * clientData,
  158. Tcl_Interp *interp,
  159. int objc,
  160. Tcl_Obj *CONST objv[]
  161. ){
  162. sqlite3 *db = 0;
  163. const char *zDb = 0;
  164. int rc = SQLITE_OK;
  165. sqlite3_intck *pCk = 0;
  166. Tcl_Obj *pRet = 0;
  167. const char *zErr = 0;
  168. if( objc!=3 ){
  169. Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
  170. return TCL_ERROR;
  171. }
  172. if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
  173. return TCL_ERROR;
  174. }
  175. zDb = Tcl_GetString(objv[2]);
  176. pRet = Tcl_NewObj();
  177. Tcl_IncrRefCount(pRet);
  178. rc = sqlite3_intck_open(db, zDb, &pCk);
  179. if( rc==SQLITE_OK ){
  180. while( sqlite3_intck_step(pCk)==SQLITE_OK ){
  181. const char *zMsg = sqlite3_intck_message(pCk);
  182. if( zMsg ){
  183. Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zMsg, -1));
  184. }
  185. }
  186. rc = sqlite3_intck_error(pCk, &zErr);
  187. }
  188. if( rc!=SQLITE_OK ){
  189. if( zErr ){
  190. Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
  191. }else{
  192. Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  193. }
  194. }else{
  195. Tcl_SetObjResult(interp, pRet);
  196. }
  197. Tcl_DecrRefCount(pRet);
  198. sqlite3_intck_close(pCk);
  199. sqlite3_intck_close(0);
  200. return rc ? TCL_ERROR : TCL_OK;
  201. }
  202. int Sqlitetestintck_Init(Tcl_Interp *interp){
  203. Tcl_CreateObjCommand(interp, "sqlite3_intck", test_sqlite3_intck, 0, 0);
  204. Tcl_CreateObjCommand(interp, "test_do_intck", test_do_intck, 0, 0);
  205. return TCL_OK;
  206. }