1688633cbSdrh /*
2688633cbSdrh ** 2016-03-13
3688633cbSdrh **
4688633cbSdrh ** The author disclaims copyright to this source code. In place of
5688633cbSdrh ** a legal notice, here is a blessing:
6688633cbSdrh **
7688633cbSdrh ** May you do good and not evil.
8688633cbSdrh ** May you find forgiveness for yourself and forgive others.
9688633cbSdrh ** May you share freely, never taking more than you give.
10688633cbSdrh **
11688633cbSdrh ******************************************************************************
12688633cbSdrh **
13688633cbSdrh ** This file implements a C-language subroutine that converts the content
14688633cbSdrh ** of an SQLite database into UTF-8 text SQL statements that can be used
15473af4feSdrh ** to exactly recreate the original database. ROWID values are preserved.
16688633cbSdrh **
17688633cbSdrh ** A prototype of the implemented subroutine is this:
18688633cbSdrh **
19688633cbSdrh ** int sqlite3_db_dump(
20688633cbSdrh ** sqlite3 *db,
21688633cbSdrh ** const char *zSchema,
22688633cbSdrh ** const char *zTable,
23688633cbSdrh ** void (*xCallback)(void*, const char*),
24688633cbSdrh ** void *pArg
25688633cbSdrh ** );
26688633cbSdrh **
27688633cbSdrh ** The db parameter is the database connection. zSchema is the schema within
28688633cbSdrh ** that database which is to be dumped. Usually the zSchema is "main" but
29688633cbSdrh ** can also be "temp" or any ATTACH-ed database. If zTable is not NULL, then
30688633cbSdrh ** only the content of that one table is dumped. If zTable is NULL, then all
31688633cbSdrh ** tables are dumped.
32688633cbSdrh **
33688633cbSdrh ** The generate text is passed to xCallback() in multiple calls. The second
34688633cbSdrh ** argument to xCallback() is a copy of the pArg parameter. The first
35688633cbSdrh ** argument is some of the output text that this routine generates. The
36688633cbSdrh ** signature to xCallback() is designed to make it compatible with fputs().
37688633cbSdrh **
38688633cbSdrh ** The sqlite3_db_dump() subroutine returns SQLITE_OK on success or some error
39688633cbSdrh ** code if it encounters a problem.
40688633cbSdrh **
41688633cbSdrh ** If this file is compiled with -DDBDUMP_STANDALONE then a "main()" routine
42688633cbSdrh ** is included so that this routine becomes a command-line utility. The
43688633cbSdrh ** command-line utility takes two or three arguments which are the name
44688633cbSdrh ** of the database file, the schema, and optionally the table, forming the
45688633cbSdrh ** first three arguments of a single call to the library routine.
46688633cbSdrh */
47688633cbSdrh #include "sqlite3.h"
48473af4feSdrh #include <stdarg.h>
49473af4feSdrh #include <string.h>
50473af4feSdrh #include <ctype.h>
51473af4feSdrh
52473af4feSdrh /*
53473af4feSdrh ** The state of the dump process.
54473af4feSdrh */
55473af4feSdrh typedef struct DState DState;
56473af4feSdrh struct DState {
57473af4feSdrh sqlite3 *db; /* The database connection */
58473af4feSdrh int nErr; /* Number of errors seen so far */
59473af4feSdrh int rc; /* Error code */
60473af4feSdrh int writableSchema; /* True if in writable_schema mode */
61473af4feSdrh int (*xCallback)(const char*,void*); /* Send output here */
62473af4feSdrh void *pArg; /* Argument to xCallback() */
63473af4feSdrh };
64473af4feSdrh
65473af4feSdrh /*
66473af4feSdrh ** A variable length string to which one can append text.
67473af4feSdrh */
68473af4feSdrh typedef struct DText DText;
69473af4feSdrh struct DText {
70473af4feSdrh char *z; /* The text */
71473af4feSdrh int n; /* Number of bytes of content in z[] */
72473af4feSdrh int nAlloc; /* Number of bytes allocated to z[] */
73473af4feSdrh };
74473af4feSdrh
75473af4feSdrh /*
76473af4feSdrh ** Initialize and destroy a DText object
77473af4feSdrh */
initText(DText * p)78473af4feSdrh static void initText(DText *p){
79473af4feSdrh memset(p, 0, sizeof(*p));
80473af4feSdrh }
freeText(DText * p)81473af4feSdrh static void freeText(DText *p){
82473af4feSdrh sqlite3_free(p->z);
83473af4feSdrh initText(p);
84473af4feSdrh }
85473af4feSdrh
86473af4feSdrh /* zIn is either a pointer to a NULL-terminated string in memory obtained
87473af4feSdrh ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
88473af4feSdrh ** added to zIn, and the result returned in memory obtained from malloc().
89473af4feSdrh ** zIn, if it was not NULL, is freed.
90473af4feSdrh **
91473af4feSdrh ** If the third argument, quote, is not '\0', then it is used as a
92473af4feSdrh ** quote character for zAppend.
93473af4feSdrh */
appendText(DText * p,char const * zAppend,char quote)94473af4feSdrh static void appendText(DText *p, char const *zAppend, char quote){
95473af4feSdrh int len;
96473af4feSdrh int i;
97473af4feSdrh int nAppend = (int)(strlen(zAppend) & 0x3fffffff);
98473af4feSdrh
99473af4feSdrh len = nAppend+p->n+1;
100473af4feSdrh if( quote ){
101473af4feSdrh len += 2;
102473af4feSdrh for(i=0; i<nAppend; i++){
103473af4feSdrh if( zAppend[i]==quote ) len++;
104473af4feSdrh }
105473af4feSdrh }
106473af4feSdrh
107473af4feSdrh if( p->n+len>=p->nAlloc ){
108473af4feSdrh char *zNew;
109473af4feSdrh p->nAlloc = p->nAlloc*2 + len + 20;
110473af4feSdrh zNew = sqlite3_realloc(p->z, p->nAlloc);
111473af4feSdrh if( zNew==0 ){
112473af4feSdrh freeText(p);
113473af4feSdrh return;
114473af4feSdrh }
115473af4feSdrh p->z = zNew;
116473af4feSdrh }
117473af4feSdrh
118473af4feSdrh if( quote ){
119473af4feSdrh char *zCsr = p->z+p->n;
120473af4feSdrh *zCsr++ = quote;
121473af4feSdrh for(i=0; i<nAppend; i++){
122473af4feSdrh *zCsr++ = zAppend[i];
123473af4feSdrh if( zAppend[i]==quote ) *zCsr++ = quote;
124473af4feSdrh }
125473af4feSdrh *zCsr++ = quote;
126473af4feSdrh p->n = (int)(zCsr - p->z);
127473af4feSdrh *zCsr = '\0';
128473af4feSdrh }else{
129473af4feSdrh memcpy(p->z+p->n, zAppend, nAppend);
130473af4feSdrh p->n += nAppend;
131473af4feSdrh p->z[p->n] = '\0';
132473af4feSdrh }
133473af4feSdrh }
134473af4feSdrh
135473af4feSdrh /*
136473af4feSdrh ** Attempt to determine if identifier zName needs to be quoted, either
137473af4feSdrh ** because it contains non-alphanumeric characters, or because it is an
138473af4feSdrh ** SQLite keyword. Be conservative in this estimate: When in doubt assume
139473af4feSdrh ** that quoting is required.
140473af4feSdrh **
141473af4feSdrh ** Return '"' if quoting is required. Return 0 if no quoting is required.
142473af4feSdrh */
quoteChar(const char * zName)143473af4feSdrh static char quoteChar(const char *zName){
144fc0ec3e5Sdrh int i;
145473af4feSdrh if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
146473af4feSdrh for(i=0; zName[i]; i++){
147473af4feSdrh if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
148473af4feSdrh }
149fc0ec3e5Sdrh return sqlite3_keyword_check(zName, i) ? '"' : 0;
150473af4feSdrh }
151473af4feSdrh
152473af4feSdrh
153473af4feSdrh /*
154473af4feSdrh ** Release memory previously allocated by tableColumnList().
155473af4feSdrh */
freeColumnList(char ** azCol)156473af4feSdrh static void freeColumnList(char **azCol){
157473af4feSdrh int i;
158473af4feSdrh for(i=1; azCol[i]; i++){
159473af4feSdrh sqlite3_free(azCol[i]);
160473af4feSdrh }
161473af4feSdrh /* azCol[0] is a static string */
162473af4feSdrh sqlite3_free(azCol);
163473af4feSdrh }
164473af4feSdrh
165473af4feSdrh /*
166473af4feSdrh ** Return a list of pointers to strings which are the names of all
167473af4feSdrh ** columns in table zTab. The memory to hold the names is dynamically
168473af4feSdrh ** allocated and must be released by the caller using a subsequent call
169473af4feSdrh ** to freeColumnList().
170473af4feSdrh **
171473af4feSdrh ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
172473af4feSdrh ** value that needs to be preserved, then azCol[0] is filled in with the
173473af4feSdrh ** name of the rowid column.
174473af4feSdrh **
175473af4feSdrh ** The first regular column in the table is azCol[1]. The list is terminated
176473af4feSdrh ** by an entry with azCol[i]==0.
177473af4feSdrh */
tableColumnList(DState * p,const char * zTab)178473af4feSdrh static char **tableColumnList(DState *p, const char *zTab){
179473af4feSdrh char **azCol = 0;
180473af4feSdrh sqlite3_stmt *pStmt = 0;
181473af4feSdrh char *zSql;
182473af4feSdrh int nCol = 0;
183473af4feSdrh int nAlloc = 0;
184473af4feSdrh int nPK = 0; /* Number of PRIMARY KEY columns seen */
185473af4feSdrh int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
186473af4feSdrh int preserveRowid = 1;
187473af4feSdrh int rc;
188473af4feSdrh
189473af4feSdrh zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
190473af4feSdrh if( zSql==0 ) return 0;
191473af4feSdrh rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
192473af4feSdrh sqlite3_free(zSql);
193473af4feSdrh if( rc ) return 0;
194473af4feSdrh while( sqlite3_step(pStmt)==SQLITE_ROW ){
195473af4feSdrh if( nCol>=nAlloc-2 ){
196473af4feSdrh char **azNew;
197473af4feSdrh nAlloc = nAlloc*2 + nCol + 10;
1982d77d80aSdrh azNew = sqlite3_realloc64(azCol, nAlloc*sizeof(azCol[0]));
199473af4feSdrh if( azNew==0 ) goto col_oom;
200473af4feSdrh azCol = azNew;
201d3bc75fbSdrh azCol[0] = 0;
202473af4feSdrh }
203473af4feSdrh azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
204473af4feSdrh if( azCol[nCol]==0 ) goto col_oom;
205473af4feSdrh if( sqlite3_column_int(pStmt, 5) ){
206473af4feSdrh nPK++;
207473af4feSdrh if( nPK==1
208473af4feSdrh && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
209473af4feSdrh "INTEGER")==0
210473af4feSdrh ){
211473af4feSdrh isIPK = 1;
212473af4feSdrh }else{
213473af4feSdrh isIPK = 0;
214473af4feSdrh }
215473af4feSdrh }
216473af4feSdrh }
217473af4feSdrh sqlite3_finalize(pStmt);
218473af4feSdrh pStmt = 0;
219473af4feSdrh azCol[nCol+1] = 0;
220473af4feSdrh
221473af4feSdrh /* The decision of whether or not a rowid really needs to be preserved
222473af4feSdrh ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
223473af4feSdrh ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
224473af4feSdrh ** rowids on tables where the rowid is inaccessible because there are other
225473af4feSdrh ** columns in the table named "rowid", "_rowid_", and "oid".
226473af4feSdrh */
227473af4feSdrh if( isIPK ){
228473af4feSdrh /* If a single PRIMARY KEY column with type INTEGER was seen, then it
229473af4feSdrh ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
230473af4feSdrh ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
231473af4feSdrh ** ROWID aliases. To distinguish these cases, check to see if
232473af4feSdrh ** there is a "pk" entry in "PRAGMA index_list". There will be
233473af4feSdrh ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
234473af4feSdrh */
235473af4feSdrh zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
236473af4feSdrh " WHERE origin='pk'", zTab);
237473af4feSdrh if( zSql==0 ) goto col_oom;
238473af4feSdrh rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
239473af4feSdrh sqlite3_free(zSql);
240473af4feSdrh if( rc ){
241473af4feSdrh freeColumnList(azCol);
242473af4feSdrh return 0;
243473af4feSdrh }
244473af4feSdrh rc = sqlite3_step(pStmt);
245473af4feSdrh sqlite3_finalize(pStmt);
246473af4feSdrh pStmt = 0;
247473af4feSdrh preserveRowid = rc==SQLITE_ROW;
248473af4feSdrh }
249473af4feSdrh if( preserveRowid ){
250473af4feSdrh /* Only preserve the rowid if we can find a name to use for the
251473af4feSdrh ** rowid */
252473af4feSdrh static char *azRowid[] = { "rowid", "_rowid_", "oid" };
253473af4feSdrh int i, j;
254473af4feSdrh for(j=0; j<3; j++){
255473af4feSdrh for(i=1; i<=nCol; i++){
256473af4feSdrh if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
257473af4feSdrh }
258473af4feSdrh if( i>nCol ){
259473af4feSdrh /* At this point, we know that azRowid[j] is not the name of any
260473af4feSdrh ** ordinary column in the table. Verify that azRowid[j] is a valid
261473af4feSdrh ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
262473af4feSdrh ** tables will fail this last check */
263473af4feSdrh rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
264473af4feSdrh if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
265473af4feSdrh break;
266473af4feSdrh }
267473af4feSdrh }
268473af4feSdrh }
269473af4feSdrh return azCol;
270473af4feSdrh
271473af4feSdrh col_oom:
272473af4feSdrh sqlite3_finalize(pStmt);
273473af4feSdrh freeColumnList(azCol);
274473af4feSdrh p->nErr++;
275473af4feSdrh p->rc = SQLITE_NOMEM;
276473af4feSdrh return 0;
277473af4feSdrh }
278473af4feSdrh
279473af4feSdrh /*
280473af4feSdrh ** Send mprintf-formatted content to the output callback.
281473af4feSdrh */
output_formatted(DState * p,const char * zFormat,...)282473af4feSdrh static void output_formatted(DState *p, const char *zFormat, ...){
283473af4feSdrh va_list ap;
284473af4feSdrh char *z;
285473af4feSdrh va_start(ap, zFormat);
286d3bc75fbSdrh z = sqlite3_vmprintf(zFormat, ap);
287473af4feSdrh va_end(ap);
288473af4feSdrh p->xCallback(z, p->pArg);
289473af4feSdrh sqlite3_free(z);
290473af4feSdrh }
291473af4feSdrh
292473af4feSdrh /*
29326849e14Sdrh ** Find a string that is not found anywhere in z[]. Return a pointer
29426849e14Sdrh ** to that string.
295473af4feSdrh **
29626849e14Sdrh ** Try to use zA and zB first. If both of those are already found in z[]
29726849e14Sdrh ** then make up some string and store it in the buffer zBuf.
298473af4feSdrh */
unused_string(const char * z,const char * zA,const char * zB,char * zBuf)29926849e14Sdrh static const char *unused_string(
30026849e14Sdrh const char *z, /* Result must not appear anywhere in z */
30126849e14Sdrh const char *zA, const char *zB, /* Try these first */
30226849e14Sdrh char *zBuf /* Space to store a generated string */
30326849e14Sdrh ){
30426849e14Sdrh unsigned i = 0;
30526849e14Sdrh if( strstr(z, zA)==0 ) return zA;
30626849e14Sdrh if( strstr(z, zB)==0 ) return zB;
30726849e14Sdrh do{
30826849e14Sdrh sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
30926849e14Sdrh }while( strstr(z,zBuf)!=0 );
31026849e14Sdrh return zBuf;
31126849e14Sdrh }
31226849e14Sdrh
31326849e14Sdrh /*
31426849e14Sdrh ** Output the given string as a quoted string using SQL quoting conventions.
31526849e14Sdrh ** Additionallly , escape the "\n" and "\r" characters so that they do not
31626849e14Sdrh ** get corrupted by end-of-line translation facilities in some operating
31726849e14Sdrh ** systems.
31826849e14Sdrh */
output_quoted_escaped_string(DState * p,const char * z)31926849e14Sdrh static void output_quoted_escaped_string(DState *p, const char *z){
320473af4feSdrh int i;
321473af4feSdrh char c;
322473af4feSdrh for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
323473af4feSdrh if( c==0 ){
324473af4feSdrh output_formatted(p,"'%s'",z);
32526849e14Sdrh }else{
32626849e14Sdrh const char *zNL = 0;
32726849e14Sdrh const char *zCR = 0;
32826849e14Sdrh int nNL = 0;
32926849e14Sdrh int nCR = 0;
33026849e14Sdrh char zBuf1[20], zBuf2[20];
33126849e14Sdrh for(i=0; z[i]; i++){
33226849e14Sdrh if( z[i]=='\n' ) nNL++;
33326849e14Sdrh if( z[i]=='\r' ) nCR++;
334473af4feSdrh }
33526849e14Sdrh if( nNL ){
33626849e14Sdrh p->xCallback("replace(", p->pArg);
33726849e14Sdrh zNL = unused_string(z, "\\n", "\\012", zBuf1);
33826849e14Sdrh }
33926849e14Sdrh if( nCR ){
34026849e14Sdrh p->xCallback("replace(", p->pArg);
34126849e14Sdrh zCR = unused_string(z, "\\r", "\\015", zBuf2);
34226849e14Sdrh }
34326849e14Sdrh p->xCallback("'", p->pArg);
344473af4feSdrh while( *z ){
345473af4feSdrh for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
346473af4feSdrh if( c=='\'' ) i++;
347473af4feSdrh if( i ){
348473af4feSdrh output_formatted(p, "%.*s", i, z);
349473af4feSdrh z += i;
350473af4feSdrh }
351473af4feSdrh if( c=='\'' ){
352473af4feSdrh p->xCallback("'", p->pArg);
353473af4feSdrh continue;
354473af4feSdrh }
355473af4feSdrh if( c==0 ){
356473af4feSdrh break;
357473af4feSdrh }
35826849e14Sdrh z++;
35926849e14Sdrh if( c=='\n' ){
36026849e14Sdrh p->xCallback(zNL, p->pArg);
36126849e14Sdrh continue;
362473af4feSdrh }
36326849e14Sdrh p->xCallback(zCR, p->pArg);
364473af4feSdrh }
36526849e14Sdrh p->xCallback("'", p->pArg);
36626849e14Sdrh if( nCR ){
36726849e14Sdrh output_formatted(p, ",'%s',char(13))", zCR);
36826849e14Sdrh }
36926849e14Sdrh if( nNL ){
37026849e14Sdrh output_formatted(p, ",'%s',char(10))", zNL);
37126849e14Sdrh }
37226849e14Sdrh }
373473af4feSdrh }
374473af4feSdrh
375473af4feSdrh /*
376473af4feSdrh ** This is an sqlite3_exec callback routine used for dumping the database.
377473af4feSdrh ** Each row received by this callback consists of a table name,
378473af4feSdrh ** the table type ("index" or "table") and SQL to create the table.
379473af4feSdrh ** This routine should print text sufficient to recreate the table.
380473af4feSdrh */
dump_callback(void * pArg,int nArg,char ** azArg,char ** azCol)381473af4feSdrh static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
382473af4feSdrh int rc;
383473af4feSdrh const char *zTable;
384473af4feSdrh const char *zType;
385473af4feSdrh const char *zSql;
386473af4feSdrh DState *p = (DState*)pArg;
387473af4feSdrh sqlite3_stmt *pStmt;
388473af4feSdrh
389473af4feSdrh (void)azCol;
390473af4feSdrh if( nArg!=3 ) return 1;
391473af4feSdrh zTable = azArg[0];
392473af4feSdrh zType = azArg[1];
393473af4feSdrh zSql = azArg[2];
394473af4feSdrh
395473af4feSdrh if( strcmp(zTable, "sqlite_sequence")==0 ){
396473af4feSdrh p->xCallback("DELETE FROM sqlite_sequence;\n", p->pArg);
397473af4feSdrh }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
398*067b92baSdrh p->xCallback("ANALYZE sqlite_schema;\n", p->pArg);
399473af4feSdrh }else if( strncmp(zTable, "sqlite_", 7)==0 ){
400473af4feSdrh return 0;
401473af4feSdrh }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
402473af4feSdrh if( !p->writableSchema ){
403473af4feSdrh p->xCallback("PRAGMA writable_schema=ON;\n", p->pArg);
404473af4feSdrh p->writableSchema = 1;
405473af4feSdrh }
406473af4feSdrh output_formatted(p,
407*067b92baSdrh "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
408473af4feSdrh "VALUES('table','%q','%q',0,'%q');",
409473af4feSdrh zTable, zTable, zSql);
410473af4feSdrh return 0;
411473af4feSdrh }else{
412473af4feSdrh if( sqlite3_strglob("CREATE TABLE ['\"]*", zSql)==0 ){
413473af4feSdrh p->xCallback("CREATE TABLE IF NOT EXISTS ", p->pArg);
414473af4feSdrh p->xCallback(zSql+13, p->pArg);
415473af4feSdrh }else{
416473af4feSdrh p->xCallback(zSql, p->pArg);
417473af4feSdrh }
418473af4feSdrh p->xCallback(";\n", p->pArg);
419473af4feSdrh }
420473af4feSdrh
421473af4feSdrh if( strcmp(zType, "table")==0 ){
422473af4feSdrh DText sSelect;
423473af4feSdrh DText sTable;
424f7c8a35bSmistachkin char **azTCol;
425473af4feSdrh int i;
426473af4feSdrh int nCol;
427473af4feSdrh
428f7c8a35bSmistachkin azTCol = tableColumnList(p, zTable);
429f7c8a35bSmistachkin if( azTCol==0 ) return 0;
430473af4feSdrh
431d3bc75fbSdrh initText(&sTable);
432d3bc75fbSdrh appendText(&sTable, "INSERT INTO ", 0);
433d3bc75fbSdrh
434473af4feSdrh /* Always quote the table name, even if it appears to be pure ascii,
435473af4feSdrh ** in case it is a keyword. Ex: INSERT INTO "table" ... */
436473af4feSdrh appendText(&sTable, zTable, quoteChar(zTable));
437d3bc75fbSdrh
438473af4feSdrh /* If preserving the rowid, add a column list after the table name.
439473af4feSdrh ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
440473af4feSdrh ** instead of the usual "INSERT INTO tab VALUES(...)".
441473af4feSdrh */
442f7c8a35bSmistachkin if( azTCol[0] ){
443473af4feSdrh appendText(&sTable, "(", 0);
444f7c8a35bSmistachkin appendText(&sTable, azTCol[0], 0);
445f7c8a35bSmistachkin for(i=1; azTCol[i]; i++){
446473af4feSdrh appendText(&sTable, ",", 0);
447f7c8a35bSmistachkin appendText(&sTable, azTCol[i], quoteChar(azTCol[i]));
448473af4feSdrh }
449473af4feSdrh appendText(&sTable, ")", 0);
450473af4feSdrh }
451473af4feSdrh appendText(&sTable, " VALUES(", 0);
452473af4feSdrh
453473af4feSdrh /* Build an appropriate SELECT statement */
454473af4feSdrh initText(&sSelect);
455473af4feSdrh appendText(&sSelect, "SELECT ", 0);
456f7c8a35bSmistachkin if( azTCol[0] ){
457f7c8a35bSmistachkin appendText(&sSelect, azTCol[0], 0);
458473af4feSdrh appendText(&sSelect, ",", 0);
459473af4feSdrh }
460f7c8a35bSmistachkin for(i=1; azTCol[i]; i++){
461f7c8a35bSmistachkin appendText(&sSelect, azTCol[i], quoteChar(azTCol[i]));
462f7c8a35bSmistachkin if( azTCol[i+1] ){
463473af4feSdrh appendText(&sSelect, ",", 0);
464473af4feSdrh }
465473af4feSdrh }
466d3bc75fbSdrh nCol = i;
467f7c8a35bSmistachkin if( azTCol[0]==0 ) nCol--;
468f7c8a35bSmistachkin freeColumnList(azTCol);
469473af4feSdrh appendText(&sSelect, " FROM ", 0);
470473af4feSdrh appendText(&sSelect, zTable, quoteChar(zTable));
471473af4feSdrh
472473af4feSdrh rc = sqlite3_prepare_v2(p->db, sSelect.z, -1, &pStmt, 0);
473473af4feSdrh if( rc!=SQLITE_OK ){
474473af4feSdrh p->nErr++;
475473af4feSdrh if( p->rc==SQLITE_OK ) p->rc = rc;
476473af4feSdrh }else{
477473af4feSdrh while( SQLITE_ROW==sqlite3_step(pStmt) ){
478473af4feSdrh p->xCallback(sTable.z, p->pArg);
479473af4feSdrh for(i=0; i<nCol; i++){
480473af4feSdrh if( i ) p->xCallback(",", p->pArg);
481473af4feSdrh switch( sqlite3_column_type(pStmt,i) ){
482473af4feSdrh case SQLITE_INTEGER: {
483473af4feSdrh output_formatted(p, "%lld", sqlite3_column_int64(pStmt,i));
484473af4feSdrh break;
485473af4feSdrh }
486473af4feSdrh case SQLITE_FLOAT: {
487473af4feSdrh double r = sqlite3_column_double(pStmt,i);
4882f1f8801Sdrh sqlite3_uint64 ur;
4892f1f8801Sdrh memcpy(&ur,&r,sizeof(r));
4902f1f8801Sdrh if( ur==0x7ff0000000000000LL ){
4912f1f8801Sdrh p->xCallback("1e999", p->pArg);
4922f1f8801Sdrh }else if( ur==0xfff0000000000000LL ){
4932f1f8801Sdrh p->xCallback("-1e999", p->pArg);
4942f1f8801Sdrh }else{
495473af4feSdrh output_formatted(p, "%!.20g", r);
4962f1f8801Sdrh }
497473af4feSdrh break;
498473af4feSdrh }
499473af4feSdrh case SQLITE_NULL: {
500473af4feSdrh p->xCallback("NULL", p->pArg);
501473af4feSdrh break;
502473af4feSdrh }
503473af4feSdrh case SQLITE_TEXT: {
50426849e14Sdrh output_quoted_escaped_string(p,
50526849e14Sdrh (const char*)sqlite3_column_text(pStmt,i));
506473af4feSdrh break;
507473af4feSdrh }
508473af4feSdrh case SQLITE_BLOB: {
509473af4feSdrh int nByte = sqlite3_column_bytes(pStmt,i);
510473af4feSdrh unsigned char *a = (unsigned char*)sqlite3_column_blob(pStmt,i);
511473af4feSdrh int j;
512473af4feSdrh p->xCallback("x'", p->pArg);
513473af4feSdrh for(j=0; j<nByte; j++){
514473af4feSdrh char zWord[3];
515473af4feSdrh zWord[0] = "0123456789abcdef"[(a[j]>>4)&15];
516473af4feSdrh zWord[1] = "0123456789abcdef"[a[j]&15];
517473af4feSdrh zWord[2] = 0;
518473af4feSdrh p->xCallback(zWord, p->pArg);
519473af4feSdrh }
520473af4feSdrh p->xCallback("'", p->pArg);
521473af4feSdrh break;
522473af4feSdrh }
523473af4feSdrh }
524473af4feSdrh }
525473af4feSdrh p->xCallback(");\n", p->pArg);
526473af4feSdrh }
527473af4feSdrh }
528473af4feSdrh sqlite3_finalize(pStmt);
529473af4feSdrh freeText(&sTable);
530473af4feSdrh freeText(&sSelect);
531473af4feSdrh }
532473af4feSdrh return 0;
533473af4feSdrh }
534473af4feSdrh
535473af4feSdrh
536473af4feSdrh /*
537473af4feSdrh ** Execute a query statement that will generate SQL output. Print
538473af4feSdrh ** the result columns, comma-separated, on a line and then add a
539473af4feSdrh ** semicolon terminator to the end of that line.
540473af4feSdrh **
541473af4feSdrh ** If the number of columns is 1 and that column contains text "--"
542473af4feSdrh ** then write the semicolon on a separate line. That way, if a
543473af4feSdrh ** "--" comment occurs at the end of the statement, the comment
544473af4feSdrh ** won't consume the semicolon terminator.
545473af4feSdrh */
output_sql_from_query(DState * p,const char * zSelect,...)546473af4feSdrh static void output_sql_from_query(
547473af4feSdrh DState *p, /* Query context */
548473af4feSdrh const char *zSelect, /* SELECT statement to extract content */
549473af4feSdrh ...
550473af4feSdrh ){
551473af4feSdrh sqlite3_stmt *pSelect;
552473af4feSdrh int rc;
553473af4feSdrh int nResult;
554473af4feSdrh int i;
555473af4feSdrh const char *z;
556473af4feSdrh char *zSql;
557473af4feSdrh va_list ap;
558473af4feSdrh va_start(ap, zSelect);
559d3bc75fbSdrh zSql = sqlite3_vmprintf(zSelect, ap);
560473af4feSdrh va_end(ap);
561473af4feSdrh if( zSql==0 ){
562473af4feSdrh p->rc = SQLITE_NOMEM;
563473af4feSdrh p->nErr++;
564473af4feSdrh return;
565473af4feSdrh }
566473af4feSdrh rc = sqlite3_prepare_v2(p->db, zSql, -1, &pSelect, 0);
567473af4feSdrh sqlite3_free(zSql);
568473af4feSdrh if( rc!=SQLITE_OK || !pSelect ){
569473af4feSdrh output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
570473af4feSdrh sqlite3_errmsg(p->db));
571473af4feSdrh p->nErr++;
572473af4feSdrh return;
573473af4feSdrh }
574473af4feSdrh rc = sqlite3_step(pSelect);
575473af4feSdrh nResult = sqlite3_column_count(pSelect);
576473af4feSdrh while( rc==SQLITE_ROW ){
577473af4feSdrh z = (const char*)sqlite3_column_text(pSelect, 0);
578473af4feSdrh p->xCallback(z, p->pArg);
579473af4feSdrh for(i=1; i<nResult; i++){
580473af4feSdrh p->xCallback(",", p->pArg);
581473af4feSdrh p->xCallback((const char*)sqlite3_column_text(pSelect,i), p->pArg);
582473af4feSdrh }
583473af4feSdrh if( z==0 ) z = "";
584473af4feSdrh while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
585473af4feSdrh if( z[0] ){
586473af4feSdrh p->xCallback("\n;\n", p->pArg);
587473af4feSdrh }else{
588473af4feSdrh p->xCallback(";\n", p->pArg);
589473af4feSdrh }
590473af4feSdrh rc = sqlite3_step(pSelect);
591473af4feSdrh }
592473af4feSdrh rc = sqlite3_finalize(pSelect);
593473af4feSdrh if( rc!=SQLITE_OK ){
594473af4feSdrh output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
595473af4feSdrh sqlite3_errmsg(p->db));
596473af4feSdrh if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
597473af4feSdrh }
598473af4feSdrh }
599473af4feSdrh
600473af4feSdrh /*
601473af4feSdrh ** Run zQuery. Use dump_callback() as the callback routine so that
602473af4feSdrh ** the contents of the query are output as SQL statements.
603473af4feSdrh **
604473af4feSdrh ** If we get a SQLITE_CORRUPT error, rerun the query after appending
605473af4feSdrh ** "ORDER BY rowid DESC" to the end.
606473af4feSdrh */
run_schema_dump_query(DState * p,const char * zQuery,...)607473af4feSdrh static void run_schema_dump_query(
608473af4feSdrh DState *p,
609473af4feSdrh const char *zQuery,
610473af4feSdrh ...
611473af4feSdrh ){
612473af4feSdrh char *zErr = 0;
613473af4feSdrh char *z;
614473af4feSdrh va_list ap;
615473af4feSdrh va_start(ap, zQuery);
616d3bc75fbSdrh z = sqlite3_vmprintf(zQuery, ap);
617473af4feSdrh va_end(ap);
618473af4feSdrh sqlite3_exec(p->db, z, dump_callback, p, &zErr);
619473af4feSdrh sqlite3_free(z);
620473af4feSdrh if( zErr ){
621473af4feSdrh output_formatted(p, "/****** %s ******/\n", zErr);
622473af4feSdrh sqlite3_free(zErr);
623473af4feSdrh p->nErr++;
624473af4feSdrh zErr = 0;
625473af4feSdrh }
626473af4feSdrh }
627688633cbSdrh
628688633cbSdrh /*
629688633cbSdrh ** Convert an SQLite database into SQL statements that will recreate that
630688633cbSdrh ** database.
631688633cbSdrh */
sqlite3_db_dump(sqlite3 * db,const char * zSchema,const char * zTable,int (* xCallback)(const char *,void *),void * pArg)632688633cbSdrh int sqlite3_db_dump(
633688633cbSdrh sqlite3 *db, /* The database connection */
634688633cbSdrh const char *zSchema, /* Which schema to dump. Usually "main". */
635688633cbSdrh const char *zTable, /* Which table to dump. NULL means everything. */
636688633cbSdrh int (*xCallback)(const char*,void*), /* Output sent to this callback */
637688633cbSdrh void *pArg /* Second argument of the callback */
638688633cbSdrh ){
639473af4feSdrh DState x;
640473af4feSdrh memset(&x, 0, sizeof(x));
641473af4feSdrh x.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
642473af4feSdrh if( x.rc ) return x.rc;
643473af4feSdrh x.db = db;
644473af4feSdrh x.xCallback = xCallback;
645473af4feSdrh x.pArg = pArg;
646473af4feSdrh xCallback("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n", pArg);
647473af4feSdrh if( zTable==0 ){
648473af4feSdrh run_schema_dump_query(&x,
649*067b92baSdrh "SELECT name, type, sql FROM \"%w\".sqlite_schema "
650473af4feSdrh "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
651473af4feSdrh zSchema
652473af4feSdrh );
653473af4feSdrh run_schema_dump_query(&x,
654*067b92baSdrh "SELECT name, type, sql FROM \"%w\".sqlite_schema "
655473af4feSdrh "WHERE name=='sqlite_sequence'", zSchema
656473af4feSdrh );
657473af4feSdrh output_sql_from_query(&x,
658*067b92baSdrh "SELECT sql FROM sqlite_schema "
659473af4feSdrh "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
660473af4feSdrh );
661473af4feSdrh }else{
662473af4feSdrh run_schema_dump_query(&x,
663*067b92baSdrh "SELECT name, type, sql FROM \"%w\".sqlite_schema "
664473af4feSdrh "WHERE tbl_name=%Q COLLATE nocase AND type=='table'"
665473af4feSdrh " AND sql NOT NULL",
666473af4feSdrh zSchema, zTable
667473af4feSdrh );
668473af4feSdrh output_sql_from_query(&x,
669*067b92baSdrh "SELECT sql FROM \"%w\".sqlite_schema "
670473af4feSdrh "WHERE sql NOT NULL"
671473af4feSdrh " AND type IN ('index','trigger','view')"
672473af4feSdrh " AND tbl_name=%Q COLLATE nocase",
673473af4feSdrh zSchema, zTable
674473af4feSdrh );
675473af4feSdrh }
676473af4feSdrh if( x.writableSchema ){
677473af4feSdrh xCallback("PRAGMA writable_schema=OFF;\n", pArg);
678473af4feSdrh }
679473af4feSdrh xCallback(x.nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n", pArg);
680473af4feSdrh sqlite3_exec(db, "COMMIT", 0, 0, 0);
681473af4feSdrh return x.rc;
682688633cbSdrh }
683688633cbSdrh
684688633cbSdrh
685688633cbSdrh
686688633cbSdrh /* The generic subroutine is above. The code the follows implements
687688633cbSdrh ** the command-line interface.
688688633cbSdrh */
689688633cbSdrh #ifdef DBDUMP_STANDALONE
690688633cbSdrh #include <stdio.h>
691688633cbSdrh
692688633cbSdrh /*
693688633cbSdrh ** Command-line interface
694688633cbSdrh */
main(int argc,char ** argv)695688633cbSdrh int main(int argc, char **argv){
696688633cbSdrh sqlite3 *db;
697688633cbSdrh const char *zDb;
698688633cbSdrh const char *zSchema;
699688633cbSdrh const char *zTable = 0;
700688633cbSdrh int rc;
701688633cbSdrh
702688633cbSdrh if( argc<2 || argc>4 ){
703688633cbSdrh fprintf(stderr, "Usage: %s DATABASE ?SCHEMA? ?TABLE?\n", argv[0]);
704688633cbSdrh return 1;
705688633cbSdrh }
706688633cbSdrh zDb = argv[1];
707688633cbSdrh zSchema = argc>=3 ? argv[2] : "main";
708688633cbSdrh zTable = argc==4 ? argv[3] : 0;
709688633cbSdrh
710688633cbSdrh rc = sqlite3_open(zDb, &db);
711688633cbSdrh if( rc ){
712688633cbSdrh fprintf(stderr, "Cannot open \"%s\": %s\n", zDb, sqlite3_errmsg(db));
713688633cbSdrh sqlite3_close(db);
714688633cbSdrh return 1;
715688633cbSdrh }
716688633cbSdrh rc = sqlite3_db_dump(db, zSchema, zTable,
717688633cbSdrh (int(*)(const char*,void*))fputs, (void*)stdout);
718688633cbSdrh if( rc ){
719688633cbSdrh fprintf(stderr, "Error: sqlite3_db_dump() returns %d\n", rc);
720688633cbSdrh }
721688633cbSdrh sqlite3_close(db);
722688633cbSdrh return rc!=SQLITE_OK;
723688633cbSdrh }
724688633cbSdrh #endif /* DBDUMP_STANDALONE */
725