Make sure constraint checks occur in the correct order, even in the
[sqlite.git] / ext / rbu / rbu.c
blobbe5c72413d3b05b007393c81b0c18a399d3abf56
1 /*
2 ** 2014 August 30
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.
11 *************************************************************************
13 ** This file contains a command-line application that uses the RBU
14 ** extension. See the usage() function below for an explanation.
17 #include "sqlite3rbu.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
23 ** Print a usage message and exit.
25 void usage(const char *zArgv0){
26 fprintf(stderr,
27 "Usage: %s ?OPTIONS? TARGET-DB RBU-DB\n"
28 "\n"
29 "Where options are:\n"
30 "\n"
31 " -step NSTEP\n"
32 " -vacuum\n"
33 "\n"
34 " If the -vacuum switch is not present, argument RBU-DB must be an RBU\n"
35 " database containing an update suitable for target database TARGET-DB.\n"
36 " Or, if -vacuum is specified, then TARGET-DB is a database to vacuum using\n"
37 " RBU, and RBU-DB is used as the state database for the vacuum (refer to\n"
38 " API documentation for details).\n"
39 "\n"
40 " If NSTEP is set to less than or equal to zero (the default value), this \n"
41 " program attempts to perform the entire update or vacuum operation before\n"
42 " exiting\n"
43 "\n"
44 " If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n"
45 " to sqlite3rbu_step(). If the RBU update has not been completely applied\n"
46 " after the NSTEP'th call is made, the state is saved in the database RBU-DB\n"
47 " and the program exits. Subsequent invocations of this (or any other RBU)\n"
48 " application will use this state to resume applying the RBU update to the\n"
49 " target db.\n"
50 "\n"
51 , zArgv0);
52 exit(1);
55 void report_default_vfs(){
56 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
57 fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
60 void report_rbu_vfs(sqlite3rbu *pRbu){
61 sqlite3 *db = sqlite3rbu_db(pRbu, 0);
62 if( db ){
63 char *zName = 0;
64 sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName);
65 if( zName ){
66 fprintf(stdout, "using vfs \"%s\"\n", zName);
67 }else{
68 fprintf(stdout, "vfs name not available\n");
70 sqlite3_free(zName);
74 int main(int argc, char **argv){
75 int i;
76 const char *zTarget; /* Target database to apply RBU to */
77 const char *zRbu; /* Database containing RBU */
78 char zBuf[200]; /* Buffer for printf() */
79 char *zErrmsg; /* Error message, if any */
80 sqlite3rbu *pRbu; /* RBU handle */
81 int nStep = 0; /* Maximum number of step() calls */
82 int bVacuum = 0;
83 int rc;
84 sqlite3_int64 nProgress = 0;
85 int nArgc = argc-2;
87 if( argc<3 ) usage(argv[0]);
88 for(i=1; i<nArgc; i++){
89 const char *zArg = argv[i];
90 int nArg = strlen(zArg);
91 if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){
92 bVacuum = 1;
93 }else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){
94 i++;
95 nStep = atoi(argv[i]);
96 }else{
97 usage(argv[0]);
101 zTarget = argv[argc-2];
102 zRbu = argv[argc-1];
104 report_default_vfs();
106 /* Open an RBU handle. A vacuum handle if -vacuum was specified, or a
107 ** regular RBU update handle otherwise. */
108 if( bVacuum ){
109 pRbu = sqlite3rbu_vacuum(zTarget, zRbu);
110 }else{
111 pRbu = sqlite3rbu_open(zTarget, zRbu, 0);
113 report_rbu_vfs(pRbu);
115 /* If nStep is less than or equal to zero, call
116 ** sqlite3rbu_step() until either the RBU has been completely applied
117 ** or an error occurs. Or, if nStep is greater than zero, call
118 ** sqlite3rbu_step() a maximum of nStep times. */
119 for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++);
120 nProgress = sqlite3rbu_progress(pRbu);
121 rc = sqlite3rbu_close(pRbu, &zErrmsg);
123 /* Let the user know what happened. */
124 switch( rc ){
125 case SQLITE_OK:
126 sqlite3_snprintf(sizeof(zBuf), zBuf,
127 "SQLITE_OK: rbu update incomplete (%lld operations so far)\n",
128 nProgress
130 fprintf(stdout, "%s", zBuf);
131 break;
133 case SQLITE_DONE:
134 sqlite3_snprintf(sizeof(zBuf), zBuf,
135 "SQLITE_DONE: rbu update completed (%lld operations)\n",
136 nProgress
138 fprintf(stdout, "%s", zBuf);
139 break;
141 default:
142 fprintf(stderr, "error=%d: %s\n", rc, zErrmsg);
143 break;
146 sqlite3_free(zErrmsg);
147 return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1;