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