1 /* 2 ** 2009 January 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 ** This file contains test logic for the sqlite3_backup() interface. 13 ** 14 */ 15 16 #include "tcl.h" 17 #include <sqlite3.h> 18 #include <assert.h> 19 20 /* These functions are implemented in main.c. */ 21 extern const char *sqlite3ErrName(int); 22 23 /* These functions are implemented in test1.c. */ 24 extern int getDbPointer(Tcl_Interp *, const char *, sqlite3 **); 25 26 static int backupTestCmd( 27 ClientData clientData, 28 Tcl_Interp *interp, 29 int objc, 30 Tcl_Obj *const*objv 31 ){ 32 enum BackupSubCommandEnum { 33 BACKUP_STEP, BACKUP_FINISH, BACKUP_REMAINING, BACKUP_PAGECOUNT 34 }; 35 struct BackupSubCommand { 36 const char *zCmd; 37 enum BackupSubCommandEnum eCmd; 38 int nArg; 39 const char *zArg; 40 } aSub[] = { 41 {"step", BACKUP_STEP , 1, "npage" }, 42 {"finish", BACKUP_FINISH , 0, "" }, 43 {"remaining", BACKUP_REMAINING , 0, "" }, 44 {"pagecount", BACKUP_PAGECOUNT , 0, "" }, 45 {0, 0, 0, 0} 46 }; 47 48 sqlite3_backup *p = (sqlite3_backup *)clientData; 49 int iCmd; 50 int rc; 51 52 rc = Tcl_GetIndexFromObjStruct( 53 interp, objv[1], aSub, sizeof(aSub[0]), "option", 0, &iCmd 54 ); 55 if( rc!=TCL_OK ){ 56 return rc; 57 } 58 if( objc!=(2 + aSub[iCmd].nArg) ){ 59 Tcl_WrongNumArgs(interp, 2, objv, aSub[iCmd].zArg); 60 return TCL_ERROR; 61 } 62 63 switch( aSub[iCmd].eCmd ){ 64 65 case BACKUP_FINISH: { 66 const char *zCmdName; 67 Tcl_CmdInfo cmdInfo; 68 zCmdName = Tcl_GetString(objv[0]); 69 Tcl_GetCommandInfo(interp, zCmdName, &cmdInfo); 70 cmdInfo.deleteProc = 0; 71 Tcl_SetCommandInfo(interp, zCmdName, &cmdInfo); 72 Tcl_DeleteCommand(interp, zCmdName); 73 74 rc = sqlite3_backup_finish(p); 75 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); 76 break; 77 } 78 79 case BACKUP_STEP: { 80 int nPage; 81 if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &nPage) ){ 82 return TCL_ERROR; 83 } 84 rc = sqlite3_backup_step(p, nPage); 85 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); 86 break; 87 } 88 89 case BACKUP_REMAINING: 90 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_backup_remaining(p))); 91 break; 92 93 case BACKUP_PAGECOUNT: 94 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_backup_pagecount(p))); 95 break; 96 } 97 98 return TCL_OK; 99 } 100 101 static void backupTestFinish(ClientData clientData){ 102 sqlite3_backup *pBackup = (sqlite3_backup *)clientData; 103 sqlite3_backup_finish(pBackup); 104 } 105 106 /* 107 ** sqlite3_backup CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME 108 ** 109 */ 110 static int backupTestInit( 111 ClientData clientData, 112 Tcl_Interp *interp, 113 int objc, 114 Tcl_Obj *const*objv 115 ){ 116 sqlite3_backup *pBackup; 117 sqlite3 *pDestDb; 118 sqlite3 *pSrcDb; 119 const char *zDestName; 120 const char *zSrcName; 121 const char *zCmd; 122 123 if( objc!=6 ){ 124 Tcl_WrongNumArgs( 125 interp, 1, objv, "CMDNAME DESTHANDLE DESTNAME SRCHANDLE SRCNAME" 126 ); 127 return TCL_ERROR; 128 } 129 130 zCmd = Tcl_GetString(objv[1]); 131 getDbPointer(interp, Tcl_GetString(objv[2]), &pDestDb); 132 zDestName = Tcl_GetString(objv[3]); 133 getDbPointer(interp, Tcl_GetString(objv[4]), &pSrcDb); 134 zSrcName = Tcl_GetString(objv[5]); 135 136 pBackup = sqlite3_backup_init(pDestDb, zDestName, pSrcDb, zSrcName); 137 if( !pBackup ){ 138 Tcl_AppendResult(interp, "sqlite3_backup_init() failed", 0); 139 return TCL_ERROR; 140 } 141 142 Tcl_CreateObjCommand(interp, zCmd, backupTestCmd, pBackup, backupTestFinish); 143 Tcl_SetObjResult(interp, objv[1]); 144 return TCL_OK; 145 } 146 147 int Sqlitetestbackup_Init(Tcl_Interp *interp){ 148 Tcl_CreateObjCommand(interp, "sqlite3_backup", backupTestInit, 0, 0); 149 return TCL_OK; 150 } 151