Fixes default log output to console for macOS
[sqlcipher.git] / ext / misc / dbdump.c
blobecf7d810d514833823227136af6bd8bfe0781093
1 /*
2 ** 2016-03-13
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 implements a C-language subroutine that converts the content
14 ** of an SQLite database into UTF-8 text SQL statements that can be used
15 ** to exactly recreate the original database. ROWID values are preserved.
17 ** A prototype of the implemented subroutine is this:
19 ** int sqlite3_db_dump(
20 ** sqlite3 *db,
21 ** const char *zSchema,
22 ** const char *zTable,
23 ** void (*xCallback)(void*, const char*),
24 ** void *pArg
25 ** );
27 ** The db parameter is the database connection. zSchema is the schema within
28 ** that database which is to be dumped. Usually the zSchema is "main" but
29 ** can also be "temp" or any ATTACH-ed database. If zTable is not NULL, then
30 ** only the content of that one table is dumped. If zTable is NULL, then all
31 ** tables are dumped.
33 ** The generate text is passed to xCallback() in multiple calls. The second
34 ** argument to xCallback() is a copy of the pArg parameter. The first
35 ** argument is some of the output text that this routine generates. The
36 ** signature to xCallback() is designed to make it compatible with fputs().
38 ** The sqlite3_db_dump() subroutine returns SQLITE_OK on success or some error
39 ** code if it encounters a problem.
41 ** If this file is compiled with -DDBDUMP_STANDALONE then a "main()" routine
42 ** is included so that this routine becomes a command-line utility. The
43 ** command-line utility takes two or three arguments which are the name
44 ** of the database file, the schema, and optionally the table, forming the
45 ** first three arguments of a single call to the library routine.
47 #include "sqlite3.h"
48 #include <stdarg.h>
49 #include <string.h>
50 #include <ctype.h>
53 ** The state of the dump process.
55 typedef struct DState DState;
56 struct DState {
57 sqlite3 *db; /* The database connection */
58 int nErr; /* Number of errors seen so far */
59 int rc; /* Error code */
60 int writableSchema; /* True if in writable_schema mode */
61 int (*xCallback)(const char*,void*); /* Send output here */
62 void *pArg; /* Argument to xCallback() */
66 ** A variable length string to which one can append text.
68 typedef struct DText DText;
69 struct DText {
70 char *z; /* The text */
71 int n; /* Number of bytes of content in z[] */
72 int nAlloc; /* Number of bytes allocated to z[] */
76 ** Initialize and destroy a DText object
78 static void initText(DText *p){
79 memset(p, 0, sizeof(*p));
81 static void freeText(DText *p){
82 sqlite3_free(p->z);
83 initText(p);
86 /* zIn is either a pointer to a NULL-terminated string in memory obtained
87 ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
88 ** added to zIn, and the result returned in memory obtained from malloc().
89 ** zIn, if it was not NULL, is freed.
91 ** If the third argument, quote, is not '\0', then it is used as a
92 ** quote character for zAppend.
94 static void appendText(DText *p, char const *zAppend, char quote){
95 int len;
96 int i;
97 int nAppend = (int)(strlen(zAppend) & 0x3fffffff);
99 len = nAppend+p->n+1;
100 if( quote ){
101 len += 2;
102 for(i=0; i<nAppend; i++){
103 if( zAppend[i]==quote ) len++;
107 if( p->n+len>=p->nAlloc ){
108 char *zNew;
109 p->nAlloc = p->nAlloc*2 + len + 20;
110 zNew = sqlite3_realloc(p->z, p->nAlloc);
111 if( zNew==0 ){
112 freeText(p);
113 return;
115 p->z = zNew;
118 if( quote ){
119 char *zCsr = p->z+p->n;
120 *zCsr++ = quote;
121 for(i=0; i<nAppend; i++){
122 *zCsr++ = zAppend[i];
123 if( zAppend[i]==quote ) *zCsr++ = quote;
125 *zCsr++ = quote;
126 p->n = (int)(zCsr - p->z);
127 *zCsr = '\0';
128 }else{
129 memcpy(p->z+p->n, zAppend, nAppend);
130 p->n += nAppend;
131 p->z[p->n] = '\0';
136 ** Attempt to determine if identifier zName needs to be quoted, either
137 ** because it contains non-alphanumeric characters, or because it is an
138 ** SQLite keyword. Be conservative in this estimate: When in doubt assume
139 ** that quoting is required.
141 ** Return '"' if quoting is required. Return 0 if no quoting is required.
143 static char quoteChar(const char *zName){
144 int i;
145 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
146 for(i=0; zName[i]; i++){
147 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
149 return sqlite3_keyword_check(zName, i) ? '"' : 0;
154 ** Release memory previously allocated by tableColumnList().
156 static void freeColumnList(char **azCol){
157 int i;
158 for(i=1; azCol[i]; i++){
159 sqlite3_free(azCol[i]);
161 /* azCol[0] is a static string */
162 sqlite3_free(azCol);
166 ** Return a list of pointers to strings which are the names of all
167 ** columns in table zTab. The memory to hold the names is dynamically
168 ** allocated and must be released by the caller using a subsequent call
169 ** to freeColumnList().
171 ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
172 ** value that needs to be preserved, then azCol[0] is filled in with the
173 ** name of the rowid column.
175 ** The first regular column in the table is azCol[1]. The list is terminated
176 ** by an entry with azCol[i]==0.
178 static char **tableColumnList(DState *p, const char *zTab){
179 char **azCol = 0;
180 sqlite3_stmt *pStmt = 0;
181 char *zSql;
182 int nCol = 0;
183 int nAlloc = 0;
184 int nPK = 0; /* Number of PRIMARY KEY columns seen */
185 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
186 int preserveRowid = 1;
187 int rc;
189 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
190 if( zSql==0 ) return 0;
191 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
192 sqlite3_free(zSql);
193 if( rc ) return 0;
194 while( sqlite3_step(pStmt)==SQLITE_ROW ){
195 if( nCol>=nAlloc-2 ){
196 char **azNew;
197 nAlloc = nAlloc*2 + nCol + 10;
198 azNew = sqlite3_realloc64(azCol, nAlloc*sizeof(azCol[0]));
199 if( azNew==0 ) goto col_oom;
200 azCol = azNew;
201 azCol[0] = 0;
203 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
204 if( azCol[nCol]==0 ) goto col_oom;
205 if( sqlite3_column_int(pStmt, 5) ){
206 nPK++;
207 if( nPK==1
208 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
209 "INTEGER")==0
211 isIPK = 1;
212 }else{
213 isIPK = 0;
217 sqlite3_finalize(pStmt);
218 pStmt = 0;
219 azCol[nCol+1] = 0;
221 /* The decision of whether or not a rowid really needs to be preserved
222 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
223 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
224 ** rowids on tables where the rowid is inaccessible because there are other
225 ** columns in the table named "rowid", "_rowid_", and "oid".
227 if( isIPK ){
228 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
229 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
230 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
231 ** ROWID aliases. To distinguish these cases, check to see if
232 ** there is a "pk" entry in "PRAGMA index_list". There will be
233 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
235 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
236 " WHERE origin='pk'", zTab);
237 if( zSql==0 ) goto col_oom;
238 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
239 sqlite3_free(zSql);
240 if( rc ){
241 freeColumnList(azCol);
242 return 0;
244 rc = sqlite3_step(pStmt);
245 sqlite3_finalize(pStmt);
246 pStmt = 0;
247 preserveRowid = rc==SQLITE_ROW;
249 if( preserveRowid ){
250 /* Only preserve the rowid if we can find a name to use for the
251 ** rowid */
252 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
253 int i, j;
254 for(j=0; j<3; j++){
255 for(i=1; i<=nCol; i++){
256 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
258 if( i>nCol ){
259 /* At this point, we know that azRowid[j] is not the name of any
260 ** ordinary column in the table. Verify that azRowid[j] is a valid
261 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
262 ** tables will fail this last check */
263 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
264 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
265 break;
269 return azCol;
271 col_oom:
272 sqlite3_finalize(pStmt);
273 freeColumnList(azCol);
274 p->nErr++;
275 p->rc = SQLITE_NOMEM;
276 return 0;
280 ** Send mprintf-formatted content to the output callback.
282 static void output_formatted(DState *p, const char *zFormat, ...){
283 va_list ap;
284 char *z;
285 va_start(ap, zFormat);
286 z = sqlite3_vmprintf(zFormat, ap);
287 va_end(ap);
288 p->xCallback(z, p->pArg);
289 sqlite3_free(z);
293 ** Find a string that is not found anywhere in z[]. Return a pointer
294 ** to that string.
296 ** Try to use zA and zB first. If both of those are already found in z[]
297 ** then make up some string and store it in the buffer zBuf.
299 static const char *unused_string(
300 const char *z, /* Result must not appear anywhere in z */
301 const char *zA, const char *zB, /* Try these first */
302 char *zBuf /* Space to store a generated string */
304 unsigned i = 0;
305 if( strstr(z, zA)==0 ) return zA;
306 if( strstr(z, zB)==0 ) return zB;
308 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
309 }while( strstr(z,zBuf)!=0 );
310 return zBuf;
314 ** Output the given string as a quoted string using SQL quoting conventions.
315 ** Additionallly , escape the "\n" and "\r" characters so that they do not
316 ** get corrupted by end-of-line translation facilities in some operating
317 ** systems.
319 static void output_quoted_escaped_string(DState *p, const char *z){
320 int i;
321 char c;
322 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
323 if( c==0 ){
324 output_formatted(p,"'%s'",z);
325 }else{
326 const char *zNL = 0;
327 const char *zCR = 0;
328 int nNL = 0;
329 int nCR = 0;
330 char zBuf1[20], zBuf2[20];
331 for(i=0; z[i]; i++){
332 if( z[i]=='\n' ) nNL++;
333 if( z[i]=='\r' ) nCR++;
335 if( nNL ){
336 p->xCallback("replace(", p->pArg);
337 zNL = unused_string(z, "\\n", "\\012", zBuf1);
339 if( nCR ){
340 p->xCallback("replace(", p->pArg);
341 zCR = unused_string(z, "\\r", "\\015", zBuf2);
343 p->xCallback("'", p->pArg);
344 while( *z ){
345 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
346 if( c=='\'' ) i++;
347 if( i ){
348 output_formatted(p, "%.*s", i, z);
349 z += i;
351 if( c=='\'' ){
352 p->xCallback("'", p->pArg);
353 continue;
355 if( c==0 ){
356 break;
358 z++;
359 if( c=='\n' ){
360 p->xCallback(zNL, p->pArg);
361 continue;
363 p->xCallback(zCR, p->pArg);
365 p->xCallback("'", p->pArg);
366 if( nCR ){
367 output_formatted(p, ",'%s',char(13))", zCR);
369 if( nNL ){
370 output_formatted(p, ",'%s',char(10))", zNL);
376 ** This is an sqlite3_exec callback routine used for dumping the database.
377 ** Each row received by this callback consists of a table name,
378 ** the table type ("index" or "table") and SQL to create the table.
379 ** This routine should print text sufficient to recreate the table.
381 static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
382 int rc;
383 const char *zTable;
384 const char *zType;
385 const char *zSql;
386 DState *p = (DState*)pArg;
387 sqlite3_stmt *pStmt;
389 (void)azCol;
390 if( nArg!=3 ) return 1;
391 zTable = azArg[0];
392 zType = azArg[1];
393 zSql = azArg[2];
395 if( strcmp(zTable, "sqlite_sequence")==0 ){
396 p->xCallback("DELETE FROM sqlite_sequence;\n", p->pArg);
397 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
398 p->xCallback("ANALYZE sqlite_schema;\n", p->pArg);
399 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
400 return 0;
401 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
402 if( !p->writableSchema ){
403 p->xCallback("PRAGMA writable_schema=ON;\n", p->pArg);
404 p->writableSchema = 1;
406 output_formatted(p,
407 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
408 "VALUES('table','%q','%q',0,'%q');",
409 zTable, zTable, zSql);
410 return 0;
411 }else{
412 if( sqlite3_strglob("CREATE TABLE ['\"]*", zSql)==0 ){
413 p->xCallback("CREATE TABLE IF NOT EXISTS ", p->pArg);
414 p->xCallback(zSql+13, p->pArg);
415 }else{
416 p->xCallback(zSql, p->pArg);
418 p->xCallback(";\n", p->pArg);
421 if( strcmp(zType, "table")==0 ){
422 DText sSelect;
423 DText sTable;
424 char **azTCol;
425 int i;
426 int nCol;
428 azTCol = tableColumnList(p, zTable);
429 if( azTCol==0 ) return 0;
431 initText(&sTable);
432 appendText(&sTable, "INSERT INTO ", 0);
434 /* Always quote the table name, even if it appears to be pure ascii,
435 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
436 appendText(&sTable, zTable, quoteChar(zTable));
438 /* If preserving the rowid, add a column list after the table name.
439 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
440 ** instead of the usual "INSERT INTO tab VALUES(...)".
442 if( azTCol[0] ){
443 appendText(&sTable, "(", 0);
444 appendText(&sTable, azTCol[0], 0);
445 for(i=1; azTCol[i]; i++){
446 appendText(&sTable, ",", 0);
447 appendText(&sTable, azTCol[i], quoteChar(azTCol[i]));
449 appendText(&sTable, ")", 0);
451 appendText(&sTable, " VALUES(", 0);
453 /* Build an appropriate SELECT statement */
454 initText(&sSelect);
455 appendText(&sSelect, "SELECT ", 0);
456 if( azTCol[0] ){
457 appendText(&sSelect, azTCol[0], 0);
458 appendText(&sSelect, ",", 0);
460 for(i=1; azTCol[i]; i++){
461 appendText(&sSelect, azTCol[i], quoteChar(azTCol[i]));
462 if( azTCol[i+1] ){
463 appendText(&sSelect, ",", 0);
466 nCol = i;
467 if( azTCol[0]==0 ) nCol--;
468 freeColumnList(azTCol);
469 appendText(&sSelect, " FROM ", 0);
470 appendText(&sSelect, zTable, quoteChar(zTable));
472 rc = sqlite3_prepare_v2(p->db, sSelect.z, -1, &pStmt, 0);
473 if( rc!=SQLITE_OK ){
474 p->nErr++;
475 if( p->rc==SQLITE_OK ) p->rc = rc;
476 }else{
477 while( SQLITE_ROW==sqlite3_step(pStmt) ){
478 p->xCallback(sTable.z, p->pArg);
479 for(i=0; i<nCol; i++){
480 if( i ) p->xCallback(",", p->pArg);
481 switch( sqlite3_column_type(pStmt,i) ){
482 case SQLITE_INTEGER: {
483 output_formatted(p, "%lld", sqlite3_column_int64(pStmt,i));
484 break;
486 case SQLITE_FLOAT: {
487 double r = sqlite3_column_double(pStmt,i);
488 sqlite3_uint64 ur;
489 memcpy(&ur,&r,sizeof(r));
490 if( ur==0x7ff0000000000000LL ){
491 p->xCallback("1e999", p->pArg);
492 }else if( ur==0xfff0000000000000LL ){
493 p->xCallback("-1e999", p->pArg);
494 }else{
495 output_formatted(p, "%!.20g", r);
497 break;
499 case SQLITE_NULL: {
500 p->xCallback("NULL", p->pArg);
501 break;
503 case SQLITE_TEXT: {
504 output_quoted_escaped_string(p,
505 (const char*)sqlite3_column_text(pStmt,i));
506 break;
508 case SQLITE_BLOB: {
509 int nByte = sqlite3_column_bytes(pStmt,i);
510 unsigned char *a = (unsigned char*)sqlite3_column_blob(pStmt,i);
511 int j;
512 p->xCallback("x'", p->pArg);
513 for(j=0; j<nByte; j++){
514 char zWord[3];
515 zWord[0] = "0123456789abcdef"[(a[j]>>4)&15];
516 zWord[1] = "0123456789abcdef"[a[j]&15];
517 zWord[2] = 0;
518 p->xCallback(zWord, p->pArg);
520 p->xCallback("'", p->pArg);
521 break;
525 p->xCallback(");\n", p->pArg);
528 sqlite3_finalize(pStmt);
529 freeText(&sTable);
530 freeText(&sSelect);
532 return 0;
537 ** Execute a query statement that will generate SQL output. Print
538 ** the result columns, comma-separated, on a line and then add a
539 ** semicolon terminator to the end of that line.
541 ** If the number of columns is 1 and that column contains text "--"
542 ** then write the semicolon on a separate line. That way, if a
543 ** "--" comment occurs at the end of the statement, the comment
544 ** won't consume the semicolon terminator.
546 static void output_sql_from_query(
547 DState *p, /* Query context */
548 const char *zSelect, /* SELECT statement to extract content */
551 sqlite3_stmt *pSelect;
552 int rc;
553 int nResult;
554 int i;
555 const char *z;
556 char *zSql;
557 va_list ap;
558 va_start(ap, zSelect);
559 zSql = sqlite3_vmprintf(zSelect, ap);
560 va_end(ap);
561 if( zSql==0 ){
562 p->rc = SQLITE_NOMEM;
563 p->nErr++;
564 return;
566 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pSelect, 0);
567 sqlite3_free(zSql);
568 if( rc!=SQLITE_OK || !pSelect ){
569 output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
570 sqlite3_errmsg(p->db));
571 p->nErr++;
572 return;
574 rc = sqlite3_step(pSelect);
575 nResult = sqlite3_column_count(pSelect);
576 while( rc==SQLITE_ROW ){
577 z = (const char*)sqlite3_column_text(pSelect, 0);
578 p->xCallback(z, p->pArg);
579 for(i=1; i<nResult; i++){
580 p->xCallback(",", p->pArg);
581 p->xCallback((const char*)sqlite3_column_text(pSelect,i), p->pArg);
583 if( z==0 ) z = "";
584 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
585 if( z[0] ){
586 p->xCallback("\n;\n", p->pArg);
587 }else{
588 p->xCallback(";\n", p->pArg);
590 rc = sqlite3_step(pSelect);
592 rc = sqlite3_finalize(pSelect);
593 if( rc!=SQLITE_OK ){
594 output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
595 sqlite3_errmsg(p->db));
596 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
601 ** Run zQuery. Use dump_callback() as the callback routine so that
602 ** the contents of the query are output as SQL statements.
604 ** If we get a SQLITE_CORRUPT error, rerun the query after appending
605 ** "ORDER BY rowid DESC" to the end.
607 static void run_schema_dump_query(
608 DState *p,
609 const char *zQuery,
612 char *zErr = 0;
613 char *z;
614 va_list ap;
615 va_start(ap, zQuery);
616 z = sqlite3_vmprintf(zQuery, ap);
617 va_end(ap);
618 sqlite3_exec(p->db, z, dump_callback, p, &zErr);
619 sqlite3_free(z);
620 if( zErr ){
621 output_formatted(p, "/****** %s ******/\n", zErr);
622 sqlite3_free(zErr);
623 p->nErr++;
624 zErr = 0;
629 ** Convert an SQLite database into SQL statements that will recreate that
630 ** database.
632 int sqlite3_db_dump(
633 sqlite3 *db, /* The database connection */
634 const char *zSchema, /* Which schema to dump. Usually "main". */
635 const char *zTable, /* Which table to dump. NULL means everything. */
636 int (*xCallback)(const char*,void*), /* Output sent to this callback */
637 void *pArg /* Second argument of the callback */
639 DState x;
640 memset(&x, 0, sizeof(x));
641 x.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
642 if( x.rc ) return x.rc;
643 x.db = db;
644 x.xCallback = xCallback;
645 x.pArg = pArg;
646 xCallback("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n", pArg);
647 if( zTable==0 ){
648 run_schema_dump_query(&x,
649 "SELECT name, type, sql FROM \"%w\".sqlite_schema "
650 "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
651 zSchema
653 run_schema_dump_query(&x,
654 "SELECT name, type, sql FROM \"%w\".sqlite_schema "
655 "WHERE name=='sqlite_sequence'", zSchema
657 output_sql_from_query(&x,
658 "SELECT sql FROM sqlite_schema "
659 "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
661 }else{
662 run_schema_dump_query(&x,
663 "SELECT name, type, sql FROM \"%w\".sqlite_schema "
664 "WHERE tbl_name=%Q COLLATE nocase AND type=='table'"
665 " AND sql NOT NULL",
666 zSchema, zTable
668 output_sql_from_query(&x,
669 "SELECT sql FROM \"%w\".sqlite_schema "
670 "WHERE sql NOT NULL"
671 " AND type IN ('index','trigger','view')"
672 " AND tbl_name=%Q COLLATE nocase",
673 zSchema, zTable
676 if( x.writableSchema ){
677 xCallback("PRAGMA writable_schema=OFF;\n", pArg);
679 xCallback(x.nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n", pArg);
680 sqlite3_exec(db, "COMMIT", 0, 0, 0);
681 return x.rc;
686 /* The generic subroutine is above. The code the follows implements
687 ** the command-line interface.
689 #ifdef DBDUMP_STANDALONE
690 #include <stdio.h>
693 ** Command-line interface
695 int main(int argc, char **argv){
696 sqlite3 *db;
697 const char *zDb;
698 const char *zSchema;
699 const char *zTable = 0;
700 int rc;
702 if( argc<2 || argc>4 ){
703 fprintf(stderr, "Usage: %s DATABASE ?SCHEMA? ?TABLE?\n", argv[0]);
704 return 1;
706 zDb = argv[1];
707 zSchema = argc>=3 ? argv[2] : "main";
708 zTable = argc==4 ? argv[3] : 0;
710 rc = sqlite3_open(zDb, &db);
711 if( rc ){
712 fprintf(stderr, "Cannot open \"%s\": %s\n", zDb, sqlite3_errmsg(db));
713 sqlite3_close(db);
714 return 1;
716 rc = sqlite3_db_dump(db, zSchema, zTable,
717 (int(*)(const char*,void*))fputs, (void*)stdout);
718 if( rc ){
719 fprintf(stderr, "Error: sqlite3_db_dump() returns %d\n", rc);
721 sqlite3_close(db);
722 return rc!=SQLITE_OK;
724 #endif /* DBDUMP_STANDALONE */