You are on page 1of 32

10/02/2017 impexp.

c Source File

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

impexp.c
Go to the documentation of this file.
00001  
00183 #ifdef STANDALONE 
00184 #include <sqlite3.h> 
00185 #define sqlite3_api_routines void 
00186 #else 
00187 #include <sqlite3ext.h> 
00188 static SQLITE_EXTENSION_INIT1 
00189 #endif 
00190  
00191 #include <stdlib.h> 
00192 #include <string.h> 
00193 #include <stdio.h> 
00194 #include <stddef.h> 
00195  
00196 #ifdef _WIN32 
00197 #include <windows.h> 
00198 #define strcasecmp  _stricmp
00199 #define strncasecmp _strnicmp 
00200 #else 
00201 #include <unistd.h> 
00202 #endif 
00203  
00204 #include "impexp.h" 
00205  
00212 typedef struct { 
00213     impexp_putc pfunc;   
00214     void *parg;          
00215 } json_pfs; 
00216  
00217 static const char space_chars[] = " \f\n\r\t\v"; 
00218  
00219 #define ISSPACE(c) ((c) && (strchr(space_chars, (c)) != 0)) 
00220  
00228 static char * 
00229 one_input_line(FILE *fin) 
00230 { 
00231     char *line, *tmp; 
00232     int nline; 
00233     int n; 
00234     int eol; 
00235  
00236     nline = 256; 
00237     line = sqlite3_malloc(nline); 
00238     if (!line) { 
00239         return 0; 
00240     } 
00241     n = 0; 
00242     eol = 0; 
00243     while (!eol) { 
00244         if (n + 256 > nline) { 
00245             nline = nline * 2 + 256; 
00246             tmp = sqlite3_realloc(line, nline); 
00247             if (!tmp) { 
00248                 sqlite3_free(line); 
00249                 return 0; 
00250             } 
00251             line = tmp; 
00252         } 
00253         if (!fgets(line + n, nline ‐ n, fin)) { 

http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 1/32
10/02/2017 impexp.c Source File

00254             if (n == 0) { 
00255                 sqlite3_free(line); 
00256                 return 0; 
00257             } 
00258             line[n] = 0; 
00259             eol = 1; 
00260             break; 
00261         } 
00262         while (line[n]) { 
00263             n++; 
00264         } 
00265         if ((n > 0) && (line[n‐1] == '\n')) { 
00266             n‐‐; 
00267             line[n] = 0; 
00268             eol = 1; 
00269         } 
00270     } 
00271     tmp = sqlite3_realloc(line, n + 1); 
00272     if (!tmp) { 
00273         sqlite3_free(line); 
00274     } 
00275     return tmp; 
00276 } 
00277  
00285 static int 
00286 ends_with_semicolon(const char *str, int n) 
00287 { 
00288     while ((n > 0) && ISSPACE(str[n ‐ 1])) { 
00289         n‐‐; 
00290     } 
00291     return (n > 0) && (str[n ‐ 1] == ';'); 
00292 } 
00293  
00300 static int 
00301 all_whitespace(const char *str) 
00302 { 
00303     for (; str[0]; str++) { 
00304         if (ISSPACE(str[0])) { 
00305             continue; 
00306         } 
00307         if ((str[0] == '/') && (str[1] == '*')) { 
00308             str += 2; 
00309             while (str[0] && ((str[0] != '*') || (str[1] != '/'))) { 
00310                 str++; 
00311             } 
00312             if (!str[0]) { 
00313                 return 0; 
00314             } 
00315             str++; 
00316             continue; 
00317         } 
00318         if ((str[0] == '‐') && (str[1] == '‐')) { 
00319             str += 2; 
00320             while (str[0] && (str[0] != '\n')) { 
00321                 str++; 
00322             } 
00323             if (!str[0]) { 
00324                 return 1; 
00325             } 
00326             continue; 
00327         } 
00328         return 0; 
00329     } 
00330     return 1; 
00331 } 
00332  
00340 static int 
00341 process_input(sqlite3 *db, FILE *fin) 
00342 { 

00343     char *line = 0; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 2/32
10/02/2017 impexp.c Source File

00343     char *line = 0; 
00344     char *sql = 0; 
00345     int nsql = 0; 
00346     int rc; 
00347     int errors = 0; 
00348  
00349     while (1) { 
00350         line = one_input_line(fin); 
00351         if (!line) { 
00352             break; 
00353         } 
00354         if ((!sql || !sql[0]) && all_whitespace(line)) { 
00355             continue; 
00356         } 
00357         if (!sql) { 
00358             int i; 
00359             for (i = 0; line[i] && ISSPACE(line[i]); i++) { 
00360                 /* empty loop body */ 
00361             } 
00362             if (line[i]) { 
00363                 nsql = strlen(line); 
00364                 sql = sqlite3_malloc(nsql + 1); 
00365                 if (!sql) { 
00366                     errors++; 
00367                     break; 
00368                 } 
00369                 strcpy(sql, line); 
00370             } 
00371         } else { 
00372             int len = strlen(line); 
00373             char *tmp; 
00374  
00375             tmp = sqlite3_realloc(sql, nsql + len + 2); 
00376             if (!tmp) { 
00377                 errors++; 
00378                 break; 
00379             } 
00380             sql = tmp; 
00381             strcpy(sql + nsql, "\n"); 
00382             nsql++; 
00383             strcpy(sql + nsql, line); 
00384             nsql += len; 
00385         } 
00386         sqlite3_free(line); 
00387         line = 0; 
00388         if (sql && ends_with_semicolon(sql, nsql) && sqlite3_complete(sql)) { 
00389             rc = sqlite3_exec(db, sql, 0, 0, 0); 
00390             if (rc != SQLITE_OK) { 
00391                 errors++; 
00392             } 
00393             sqlite3_free(sql); 
00394             sql = 0; 
00395             nsql = 0; 
00396         } 
00397     } 
00398     if (sql) { 
00399         sqlite3_free(sql); 
00400     } 
00401     if (line) { 
00402         sqlite3_free(line); 
00403     } 
00404     return errors; 
00405 } 
00406  
00419 static void 
00420 quote_func(sqlite3_context *context, int argc, sqlite3_value **argv) 
00421 { 
00422     int mode = 0; 
00423  
00424     if (argc < 1) { 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 3/32
10/02/2017 impexp.c Source File

00424     if (argc < 1) { 
00425         return; 
00426     } 
00427     if (argc > 1) { 
00428         mode = sqlite3_value_int(argv[1]); 
00429     } 
00430     switch (sqlite3_value_type(argv[0])) { 
00431     case SQLITE_NULL: { 
00432         sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); 
00433         break; 
00434     } 
00435     case SQLITE_INTEGER: 
00436     case SQLITE_FLOAT: { 
00437         sqlite3_result_value(context, argv[0]); 
00438         break; 
00439     } 
00440     case SQLITE_BLOB: { 
00441         char *text = 0; 
00442         unsigned char *blob = (unsigned char *) sqlite3_value_blob(argv[0]); 
00443         int nblob = sqlite3_value_bytes(argv[0]); 
00444  
00445         if (2 * nblob + 4 > 1000000000) { 
00446             sqlite3_result_error(context, "value too large", ‐1); 
00447             return; 
00448         } 
00449         text = (char *) sqlite3_malloc((2 * nblob) + 4); 
00450         if (!text) { 
00451             sqlite3_result_error(context, "out of memory", ‐1); 
00452         } else { 
00453             int i, k = 0; 
00454             static const char xdigits[] = "0123456789ABCDEF"; 
00455  
00456             if (mode == 1) { 
00457                 /* ORACLE enclosed in '' */ 
00458                 text[k++] = '\''; 
00459             } else if (mode == 2) {
00460                 /* SQL Server 0x prefix */ 
00461                 text[k++] = '0'; 
00462                 text[k++] = 'x'; 
00463             } else if (mode == 3) {
00464                 /* MySQL x'..' */ 
00465                 text[k++] = 'x'; 
00466                 text[k++] = '\''; 
00467             } else { 
00468                 /* default */ 
00469                 text[k++] = 'X'; 
00470                 text[k++] = '\''; 
00471             } 
00472             for (i = 0; i < nblob; i++) { 
00473                 text[k++] = xdigits[(blob[i] >> 4 ) & 0x0F]; 
00474                 text[k++] = xdigits[blob[i] & 0x0F]; 
00475             } 
00476             if (mode == 1) { 
00477                 /* ORACLE enclosed in '' */ 
00478                 text[k++] = '\''; 
00479             } else if (mode == 2) {
00480                 /* SQL Server 0x prefix */ 
00481             } else if (mode == 3) {
00482                 /* MySQL x'..' */ 
00483                 text[k++] = '\''; 
00484             } else { 
00485                 /* default */ 
00486                 text[k++] = '\''; 
00487             } 
00488             text[k] = '\0'; 
00489             sqlite3_result_text(context, text, k, SQLITE_TRANSIENT); 
00490             sqlite3_free(text); 
00491         } 
00492         break; 

00493     } 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 4/32
10/02/2017 impexp.c Source File

00493     } 
00494     case SQLITE_TEXT: { 
00495         int i, n; 
00496         const unsigned char *arg = sqlite3_value_text(argv[0]); 
00497         char *p; 
00498  
00499         if (!arg) { 
00500             return; 
00501         } 
00502         for (i = 0, n = 0; arg[i]; i++) { 
00503             if (arg[i] == '\'') { 
00504                 n++; 
00505             } 
00506         } 
00507         if (i + n + 3 > 1000000000) { 
00508             sqlite3_result_error(context, "value too large", ‐1); 
00509             return; 
00510         } 
00511         p = sqlite3_malloc(i + n + 3); 
00512         if (!p) { 
00513             sqlite3_result_error(context, "out of memory", ‐1); 
00514             return; 
00515         } 
00516         p[0] = '\''; 
00517         for (i = 0, n = 1; arg[i]; i++) { 
00518             p[n++] = arg[i];
00519             if (arg[i] == '\'') { 
00520                 p[n++] = '\''; 
00521             } 
00522         } 
00523         p[n++] = '\''; 
00524         p[n] = 0; 
00525         sqlite3_result_text(context, p, n, SQLITE_TRANSIENT); 
00526         sqlite3_free(p); 
00527         break; 
00528     } 
00529     } 
00530 } 
00531  
00539 static void 
00540 quote_csv_func(sqlite3_context *context, int argc, sqlite3_value **argv) 
00541 { 
00542     if (argc < 1) { 
00543         return; 
00544     } 
00545     switch (sqlite3_value_type(argv[0])) { 
00546     case SQLITE_NULL: { 
00547         sqlite3_result_text(context, "", 0, SQLITE_STATIC); 
00548         break; 
00549     } 
00550     case SQLITE_INTEGER: 
00551     case SQLITE_FLOAT: { 
00552         sqlite3_result_value(context, argv[0]); 
00553         break; 
00554     } 
00555     case SQLITE_BLOB: { 
00556         char *text = 0; 
00557         unsigned char *blob = (unsigned char *) sqlite3_value_blob(argv[0]); 
00558         int nblob = sqlite3_value_bytes(argv[0]); 
00559  
00560         if (2 * nblob + 4 > 1000000000) { 
00561             sqlite3_result_error(context, "value too large", ‐1); 
00562             return; 
00563         } 
00564         text = (char *) sqlite3_malloc((2 * nblob) + 4); 
00565         if (!text) { 
00566             sqlite3_result_error(context, "out of memory", ‐1); 
00567         } else { 
00568             int i, k = 0; 

00569             static const char xdigits[] = "0123456789ABCDEF"; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 5/32
10/02/2017 impexp.c Source File

00569             static const char xdigits[] = "0123456789ABCDEF"; 
00570  
00571             text[k++] = '"';
00572             for (i = 0; i < nblob; i++) { 
00573                 text[k++] = xdigits[(blob[i] >> 4 ) & 0x0F]; 
00574                 text[k++] = xdigits[blob[i] & 0x0F]; 
00575             } 
00576             text[k++] = '"';
00577             text[k] = '\0'; 
00578             sqlite3_result_text(context, text, k, SQLITE_TRANSIENT); 
00579             sqlite3_free(text); 
00580         } 
00581         break; 
00582     } 
00583     case SQLITE_TEXT: { 
00584         int i, n; 
00585         const unsigned char *arg = sqlite3_value_text(argv[0]); 
00586         char *p; 
00587  
00588         if (!arg) { 
00589             return; 
00590         } 
00591         for (i = 0, n = 0; arg[i]; i++) { 
00592             if (arg[i] == '"') { 
00593                 n++; 
00594             } 
00595         } 
00596         if (i + n + 3 > 1000000000) { 
00597             sqlite3_result_error(context, "value too large", ‐1); 
00598             return; 
00599         } 
00600         p = sqlite3_malloc(i + n + 3); 
00601         if (!p) { 
00602             sqlite3_result_error(context, "out of memory", ‐1); 
00603             return; 
00604         } 
00605         p[0] = '"'; 
00606         for (i = 0, n = 1; arg[i]; i++) { 
00607             p[n++] = arg[i];
00608             if (arg[i] == '"') { 
00609                 p[n++] = '"'; 
00610             } 
00611         } 
00612         p[n++] = '"'; 
00613         p[n] = 0; 
00614         sqlite3_result_text(context, p, n, SQLITE_TRANSIENT); 
00615         sqlite3_free(p); 
00616         break; 
00617     } 
00618     } 
00619 } 
00620  
00628 static void 
00629 indent_xml_func(sqlite3_context *context, int argc, sqlite3_value **argv) 
00630 { 
00631     static const char spaces[] = "                                "; 
00632     int n = 0; 
00633  
00634     if (argc > 0) { 
00635         n = sqlite3_value_int(argv[0]); 
00636         if (n > 32) { 
00637             n = 32; 
00638         } else if (n < 0) { 
00639             n = 0; 
00640         } 
00641     } 
00642     sqlite3_result_text(context, spaces, n, SQLITE_STATIC); 
00643 } 
00644  

00652 static void 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 6/32
10/02/2017 impexp.c Source File

00652 static void 
00653 quote_xml_func(sqlite3_context *context, int argc, sqlite3_value **argv) 
00654 { 
00655     static const char xdigits[] = "0123456789ABCDEF"; 
00656     int type, addtype = 0; 
00657  
00658     if (argc < 1) { 
00659         return; 
00660     } 
00661     if (argc > 1) { 
00662         addtype = sqlite3_value_int(argv[1]); 
00663     } 
00664     type = sqlite3_value_type(argv[0]); 
00665     switch (type) { 
00666     case SQLITE_NULL: { 
00667         if (addtype > 0) { 
00668             sqlite3_result_text(context, " TYPE=\"NULL\">", ‐1, SQLITE_STATIC); 
00669         } else { 
00670             sqlite3_result_text(context, "", 0, SQLITE_STATIC); 
00671         } 
00672         break; 
00673     } 
00674     case SQLITE_INTEGER: 
00675     case SQLITE_FLOAT: { 
00676         if (addtype > 0) { 
00677             char *text = (char *) sqlite3_malloc(128); 
00678             int k; 
00679  
00680             if (!text) { 
00681                 sqlite3_result_error(context, "out of memory", ‐1); 
00682                 return; 
00683             } 
00684             strcpy(text, (type == SQLITE_FLOAT) ? " TYPE=\"REAL\">" : 
00685                    " TYPE=\"INTEGER\">"); 
00686             k = strlen(text); 
00687             strcpy(text + k, (char *) sqlite3_value_text(argv[0])); 
00688             k = strlen(text); 
00689             sqlite3_result_text(context, text, k, SQLITE_TRANSIENT); 
00690             sqlite3_free(text); 
00691         } else { 
00692             sqlite3_result_value(context, argv[0]); 
00693         } 
00694         break; 
00695     } 
00696     case SQLITE_BLOB: { 
00697         char *text = 0; 
00698         unsigned char *blob = (unsigned char *) sqlite3_value_blob(argv[0]); 
00699         int nblob = sqlite3_value_bytes(argv[0]); 
00700         int i, k = 0; 
00701  
00702         if (6 * nblob + 34 > 1000000000) { 
00703             sqlite3_result_error(context, "value too large", ‐1); 
00704             return; 
00705         } 
00706         text = (char *) sqlite3_malloc((6 * nblob) + 34); 
00707         if (!text) { 
00708             sqlite3_result_error(context, "out of memory", ‐1); 
00709             return; 
00710         } 
00711         if (addtype > 0) { 
00712             strcpy(text, " TYPE=\"BLOB\">"); 
00713             k = strlen(text); 
00714         } 
00715         for (i = 0; i < nblob; i++) { 
00716             text[k++] = '&';
00717             text[k++] = '#';
00718             text[k++] = 'x';
00719             text[k++] = xdigits[(blob[i] >> 4 ) & 0x0F]; 
00720             text[k++] = xdigits[blob[i] & 0x0F]; 

00721             text[k++] = ';';
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 7/32
10/02/2017 impexp.c Source File

00721             text[k++] = ';';
00722         } 
00723         text[k] = '\0'; 
00724         sqlite3_result_text(context, text, k, SQLITE_TRANSIENT); 
00725         sqlite3_free(text); 
00726         break; 
00727     } 
00728     case SQLITE_TEXT: { 
00729         int i, n; 
00730         const unsigned char *arg = sqlite3_value_text(argv[0]); 
00731         char *p; 
00732  
00733         if (!arg) { 
00734             return; 
00735         } 
00736         for (i = 0, n = 0; arg[i]; i++) { 
00737             if ((arg[i] == '"') || (arg[i] == '\'') || 
00738                 (arg[i] == '<') || (arg[i] == '>') || 
00739                 (arg[i] == '&') || (arg[i] < ' ')) { 
00740                 n += 5; 
00741             } 
00742         } 
00743         if (i + n + 32 > 1000000000) { 
00744             sqlite3_result_error(context, "value too large", ‐1); 
00745             return; 
00746         } 
00747         p = sqlite3_malloc(i + n + 32); 
00748         if (!p) { 
00749             sqlite3_result_error(context, "out of memory", ‐1); 
00750             return; 
00751         } 
00752         n = 0; 
00753         if (addtype > 0) { 
00754             strcpy(p, " TYPE=\"TEXT\">"); 
00755             n = strlen(p); 
00756         } 
00757         for (i = 0; arg[i]; i++) { 
00758             if (arg[i] == '"') { 
00759                 p[n++] = '&'; 
00760                 p[n++] = 'q'; 
00761                 p[n++] = 'u'; 
00762                 p[n++] = 'o'; 
00763                 p[n++] = 't'; 
00764                 p[n++] = ';'; 
00765             } else if (arg[i] == '\'') { 
00766                 p[n++] = '&'; 
00767                 p[n++] = 'a'; 
00768                 p[n++] = 'p'; 
00769                 p[n++] = 'o'; 
00770                 p[n++] = 's'; 
00771                 p[n++] = ';'; 
00772             } else if (arg[i] == '<') { 
00773                 p[n++] = '&'; 
00774                 p[n++] = 'l'; 
00775                 p[n++] = 't'; 
00776                 p[n++] = ';'; 
00777             } else if (arg[i] == '>') { 
00778                 p[n++] = '&'; 
00779                 p[n++] = 'g'; 
00780                 p[n++] = 't'; 
00781                 p[n++] = ';'; 
00782             } else if (arg[i] == '&') { 
00783                 p[n++] = '&'; 
00784                 p[n++] = 'a'; 
00785                 p[n++] = 'm'; 
00786                 p[n++] = 'p'; 
00787                 p[n++] = ';'; 
00788             } else if (arg[i] < ' ') { 
00789                 p[n++] = '&'; 

00790                 p[n++] = '#'; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 8/32
10/02/2017 impexp.c Source File

00790                 p[n++] = '#'; 
00791                 p[n++] = 'x'; 
00792                 p[n++] = xdigits[(arg[i] >> 4 ) & 0x0F]; 
00793                 p[n++] = xdigits[arg[i] & 0x0F]; 
00794                 p[n++] = ';'; 
00795             } else if (addtype < 0 && (arg[i] == ' ')) { 
00796                 p[n++] = '&'; 
00797                 p[n++] = '#'; 
00798                 p[n++] = 'x'; 
00799                 p[n++] = xdigits[(arg[i] >> 4 ) & 0x0F]; 
00800                 p[n++] = xdigits[arg[i] & 0x0F]; 
00801                 p[n++] = ';'; 
00802             } else { 
00803                 p[n++] = arg[i]; 
00804             } 
00805         } 
00806         p[n] = '\0'; 
00807         sqlite3_result_text(context, p, n, SQLITE_TRANSIENT); 
00808         sqlite3_free(p); 
00809         break; 
00810     } 
00811     } 
00812 } 
00813  
00821 static void 
00822 import_func(sqlite3_context *ctx, int nargs, sqlite3_value **args) 
00823 { 
00824     sqlite3 *db = (sqlite3 *) sqlite3_user_data(ctx); 
00825     int changes0 = sqlite3_changes(db); 
00826     char *filename = 0; 
00827     FILE *fin; 
00828 #ifdef _WIN32 
00829     char fnbuf[MAX_PATH]; 
00830 #endif 
00831  
00832     if (nargs > 0) { 
00833         if (sqlite3_value_type(args[0]) != SQLITE_NULL) { 
00834             filename = (char *) sqlite3_value_text(args[0]); 
00835         } 
00836     } 
00837 #ifdef _WIN32 
00838     if (!filename) { 
00839         OPENFILENAME ofn; 
00840  
00841         memset(&ofn, 0, sizeof (ofn)); 
00842         memset(fnbuf, 0, sizeof (fnbuf)); 
00843         ofn.lStructSize = sizeof (ofn); 
00844         ofn.lpstrFile = fnbuf; 
00845         ofn.nMaxFile = MAX_PATH; 
00846         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | 
00847                     OFN_EXPLORER | OFN_PATHMUSTEXIST; 
00848         if (GetOpenFileName(&ofn)) { 
00849             filename = fnbuf; 
00850         } 
00851     } 
00852 #endif 
00853     if (!filename) { 
00854         goto done; 
00855     } 
00856     fin = fopen(filename, "r"); 
00857     if (!fin) { 
00858         goto done; 
00859     } 
00860     process_input(db, fin); 
00861     fclose(fin); 
00862 done: 
00863     sqlite3_result_int(ctx, sqlite3_changes(db) ‐ changes0); 
00864 } 
00865  

00866 /* see doc in impexp.h */ 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 9/32
10/02/2017 impexp.c Source File

00866 /* see doc in impexp.h */ 
00867  
00868 int 
00869 impexp_import_sql(sqlite3 *db, char *filename) 
00870 { 
00871     int changes0; 
00872     FILE *fin; 
00873 #ifdef _WIN32 
00874     char fnbuf[MAX_PATH]; 
00875 #endif 
00876  
00877     if (!db) { 
00878         return 0; 
00879     } 
00880     changes0 = sqlite3_changes(db); 
00881 #ifdef _WIN32 
00882     if (!filename) { 
00883         OPENFILENAME ofn; 
00884  
00885         memset(&ofn, 0, sizeof (ofn)); 
00886         memset(fnbuf, 0, sizeof (fnbuf)); 
00887         ofn.lStructSize = sizeof (ofn); 
00888         ofn.lpstrFile = fnbuf; 
00889         ofn.nMaxFile = MAX_PATH; 
00890         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | 
00891                     OFN_EXPLORER | OFN_PATHMUSTEXIST; 
00892         if (GetOpenFileName(&ofn)) { 
00893             filename = fnbuf; 
00894         } 
00895     } 
00896 #endif 
00897     if (!filename) { 
00898         goto done; 
00899     } 
00900     fin = fopen(filename, "r"); 
00901     if (!fin) { 
00902         goto done; 
00903     } 
00904     process_input(db, fin); 
00905     fclose(fin); 
00906 done: 
00907     return sqlite3_changes(db) ‐ changes0; 
00908 } 
00909  
00916 typedef struct { 
00917     sqlite3 *db;         
00918     int with_schema;     
00919     int quote_mode;      
00920     char *where;         
00921     int nlines;          
00922     int indent;          
00923     FILE *out;           
00924 } DUMP_DATA; 
00925  
00931 static void 
00932 indent(DUMP_DATA *dd) 
00933 { 
00934     int i; 
00935  
00936     for (i = 0; i < dd‐>indent; i++) { 
00937         fputc(' ', dd‐>out); 
00938     } 
00939 } 
00940  
00951 static int 
00952 table_dump(DUMP_DATA *dd, char **errp, int fmt, const char *query, ...) 
00953 { 
00954     sqlite3_stmt *select = 0; 
00955     int rc; 

00956     const char *rest, *q = query; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 10/32
10/02/2017 impexp.c Source File

00956     const char *rest, *q = query; 
00957     va_list ap; 
00958  
00959     if (errp && *errp) { 
00960         sqlite3_free(*errp);
00961         *errp = 0; 
00962     } 
00963     if (fmt) { 
00964         va_start(ap, query);
00965         q = sqlite3_vmprintf(query, ap); 
00966         va_end(ap); 
00967         if (!q) { 
00968             return SQLITE_NOMEM; 
00969         } 
00970     } 
00971 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2 
00972     rc = sqlite3_prepare_v2(dd‐>db, q, ‐1, &select, &rest); 
00973 #else 
00974     rc = sqlite3_prepare(dd‐>db, q, ‐1, &select, &rest); 
00975 #endif 
00976     if (fmt) { 
00977         sqlite3_free((char *) q); 
00978     } 
00979     if ((rc != SQLITE_OK) || !select) { 
00980         return rc; 
00981     } 
00982     rc = sqlite3_step(select); 
00983     while (rc == SQLITE_ROW) { 
00984         if (fputs((char *) sqlite3_column_text(select, 0), dd‐>out) > 0) { 
00985             dd‐>nlines++; 
00986         } 
00987         if (dd‐>quote_mode >= 0) { 
00988             fputc(';', dd‐>out); 
00989         } 
00990         if (dd‐>quote_mode == ‐1) {
00991             fputc('\r', dd‐>out); 
00992         } 
00993         if (dd‐>quote_mode >= ‐1) {
00994             fputc('\n', dd‐>out); 
00995         } 
00996         rc = sqlite3_step(select); 
00997     } 
00998     rc = sqlite3_finalize(select); 
00999     if (rc != SQLITE_OK) { 
01000         if (errp) { 
01001             *errp = sqlite3_mprintf("%s", sqlite3_errmsg(dd‐>db)); 
01002         } 
01003     } 
01004     return rc; 
01005 } 
01006  
01012 static void 
01013 append_free(char **in) 
01014 { 
01015     long *p = (long *) *in; 
01016  
01017     if (p) { 
01018         p ‐= 2; 
01019         sqlite3_free(p); 
01020         *in = 0; 
01021     } 
01022 } 
01023  
01033 static char * 
01034 append(char **in, char const *append, char quote)
01035 { 
01036     long *p = (long *) *in; 
01037     long len, maxlen, actlen; 
01038     int i; 
01039     char *pp; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 11/32
10/02/2017 impexp.c Source File

01039     char *pp; 
01040     int nappend = append ? strlen(append) : 0; 
01041  
01042     if (p) { 
01043         p ‐= 2; 
01044         maxlen = p[0]; 
01045         actlen = p[1]; 
01046     } else { 
01047         maxlen = actlen = 0;
01048     } 
01049     len = nappend + actlen; 
01050     if (quote) { 
01051         len += 2; 
01052         for (i = 0; i < nappend; i++) { 
01053             if (append[i] == quote) { 
01054                 len++; 
01055             } 
01056         } 
01057     } else if (!nappend) { 
01058         return *in; 
01059     } 
01060     if (len >= maxlen ‐ 1) { 
01061         long *q; 
01062  
01063         maxlen = (len + 0x03ff) & (~0x3ff); 
01064         q = (long *) sqlite3_realloc(p, maxlen + 1 + 2 * sizeof (long)); 
01065         if (!q) { 
01066             return 0; 
01067         } 
01068         if (!p) { 
01069             q[1] = 0; 
01070         } 
01071         p = q; 
01072         p[0] = maxlen; 
01073         *in = (char *) (p + 2); 
01074     } 
01075     pp = *in + actlen; 
01076     if (quote) { 
01077         *pp++ = quote; 
01078         for (i = 0; i < nappend; i++) { 
01079             *pp++ = append[i]; 
01080             if (append[i] == quote) { 
01081                 *pp++ = quote; 
01082             } 
01083         } 
01084         *pp++ = quote; 
01085         *pp = '\0'; 
01086     } else { 
01087         if (nappend) { 
01088             memcpy(pp, append, nappend); 
01089             pp += nappend; 
01090             *pp = '\0'; 
01091         } 
01092     } 
01093     p[1] = pp ‐ *in; 
01094     return *in; 
01095 } 
01096  
01103 static void 
01104 quote_xml_str(DUMP_DATA *dd, char *str) 
01105 { 
01106     static const char xdigits[] = "0123456789ABCDEF"; 
01107     int i; 
01108  
01109     if (!str) { 
01110         return; 
01111     } 
01112     for (i = 0; str[i]; i++) { 
01113         if (str[i] == '"') { 
01114             fputs("&quot;", dd‐>out); 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 12/32
10/02/2017 impexp.c Source File

01114             fputs("&quot;", dd‐>out); 
01115         } else if (str[i] == '\'') { 
01116             fputs("&apos;", dd‐>out); 
01117         } else if (str[i] == '<') {
01118             fputs("&lt;", dd‐>out);
01119         } else if (str[i] == '>') {
01120             fputs("&gt;", dd‐>out);
01121         } else if (str[i] == '&') {
01122             fputs("&amp;", dd‐>out); 
01123         } else if ((unsigned char) str[i] <= ' ') { 
01124             char buf[8]; 
01125  
01126             buf[0] = '&'; 
01127             buf[1] = '&'; 
01128             buf[2] = '#'; 
01129             buf[3] = 'x'; 
01130             buf[4] = xdigits[(str[i] >> 4 ) & 0x0F]; 
01131             buf[5] = xdigits[str[i] & 0x0F]; 
01132             buf[6] = ';'; 
01133             buf[7] = '\0'; 
01134             fputs(buf, dd‐>out); 
01135         } else { 
01136             fputc(str[i], dd‐>out); 
01137         } 
01138     } 
01139 } 
01140  
01150 static int 
01151 dump_cb(void *udata, int nargs, char **args, char **cols) 
01152 { 
01153     int rc; 
01154     const char *table, *type, *sql; 
01155     DUMP_DATA *dd = (DUMP_DATA *) udata; 
01156  
01157     if ((nargs != 3) || (args == NULL)) { 
01158         return 1; 
01159     } 
01160     table = args[0]; 
01161     type = args[1]; 
01162     sql = args[2]; 
01163     if (strcmp(table, "sqlite_sequence") == 0) { 
01164         if (dd‐>with_schema) { 
01165             if (fputs("DELETE FROM sqlite_sequence;\n", dd‐>out) >= 0) { 
01166                 dd‐>nlines++; 
01167             } 
01168         } 
01169     } else if (strcmp(table, "sqlite_stat1") == 0) { 
01170         if (dd‐>with_schema) { 
01171             if (fputs("ANALYZE sqlite_master;\n", dd‐>out) >= 0) { 
01172                 dd‐>nlines++; 
01173             } 
01174         } 
01175     } else if (strncmp(table, "sqlite_", 7) == 0) { 
01176         return 0; 
01177     } else if (strncmp(sql, "CREATE VIRTUAL TABLE", 20) == 0) { 
01178         if (dd‐>with_schema) { 
01179             sqlite3_stmt *stmt = 0; 
01180             char *creat = 0, *table_info = 0; 
01181  
01182             append(&table_info, "PRAGMA table_info(", 0); 
01183             append(&table_info, table, '"'); 
01184             append(&table_info, ")", 0); 
01185 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2 
01186             rc = sqlite3_prepare_v2(dd‐>db, table_info, ‐1, &stmt, 0); 
01187 #else 
01188             rc = sqlite3_prepare(dd‐>db, table_info, ‐1, &stmt, 0); 
01189 #endif 
01190             append_free(&table_info); 
01191             if ((rc != SQLITE_OK) || !stmt) { 
01192 bailout0: 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 13/32
10/02/2017 impexp.c Source File

01192 bailout0: 
01193                 if (stmt) { 
01194                     sqlite3_finalize(stmt); 
01195                 } 
01196                 append_free(&creat); 
01197                 return 1; 
01198             } 
01199             append(&creat, table, '"'); 
01200             append(&creat, "(", 0);
01201             rc = sqlite3_step(stmt); 
01202             while (rc == SQLITE_ROW) { 
01203                 const char *p; 
01204  
01205                 p = (const char *) sqlite3_column_text(stmt, 1); 
01206                 append(&creat, p, '"'); 
01207                 append(&creat, " ", 0); 
01208                 p = (const char *) sqlite3_column_text(stmt, 2); 
01209                 if (p && p[0]) { 
01210                     append(&creat, p, 0); 
01211                 } 
01212                 if (sqlite3_column_int(stmt, 5)) { 
01213                     append(&creat, " PRIMARY KEY", 0); 
01214                 } 
01215                 if (sqlite3_column_int(stmt, 3)) { 
01216                     append(&creat, " NOT NULL", 0); 
01217                 } 
01218                 p = (const char *) sqlite3_column_text(stmt, 4); 
01219                 if (p && p[0]) { 
01220                     append(&creat, " DEFAULT ", 0); 
01221                     append(&creat, p, 0); 
01222                 } 
01223                 rc = sqlite3_step(stmt); 
01224                 if (rc == SQLITE_ROW) { 
01225                     append(&creat, ",", 0); 
01226                 } 
01227             } 
01228             if (rc != SQLITE_DONE) { 
01229                 goto bailout0; 
01230             } 
01231             sqlite3_finalize(stmt); 
01232             append(&creat, ")", 0);
01233             if (creat && fprintf(dd‐>out, "CREATE TABLE %s;\n", creat) > 0) { 
01234                 dd‐>nlines++; 
01235             } 
01236             append_free(&creat); 
01237         } 
01238     } else { 
01239         if (dd‐>with_schema) { 
01240             if (fprintf(dd‐>out, "%s;\n", sql) > 0) { 
01241                 dd‐>nlines++; 
01242             } 
01243         } 
01244     } 
01245     if ((strcmp(type, "table") == 0) || 
01246         ((dd‐>quote_mode < 0) && (strcmp(type, "view") == 0))) { 
01247         sqlite3_stmt *stmt = 0; 
01248         char *select = 0, *hdr = 0, *table_info = 0; 
01249         char buffer[256]; 
01250  
01251         append(&table_info, "PRAGMA table_info(", 0); 
01252         append(&table_info, table, '"'); 
01253         append(&table_info, ")", 0); 
01254 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2 
01255         rc = sqlite3_prepare_v2(dd‐>db, table_info, ‐1, &stmt, 0); 
01256 #else 
01257         rc = sqlite3_prepare(dd‐>db, table_info, ‐1, &stmt, 0); 
01258 #endif 
01259         append_free(&table_info); 
01260         if ((rc != SQLITE_OK) || !stmt) { 
01261 bailout1: 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 14/32
10/02/2017 impexp.c Source File

01261 bailout1: 
01262             if (stmt) { 
01263                 sqlite3_finalize(stmt); 
01264             } 
01265             append_free(&hdr); 
01266             append_free(&select); 
01267             return 1; 
01268         } 
01269         if (dd‐>quote_mode < ‐1) { 
01270             if (dd‐>where) { 
01271                 append(&select, "SELECT ", 0); 
01272                 sprintf(buffer, "indent_xml(%d)", dd‐>indent); 
01273                 append(&select, buffer, 0); 
01274                 append(&select, " || '<' || quote_xml(", 0); 
01275                 append(&select, dd‐>where, '"'); 
01276                 append(&select, ",‐1) || '>\n' || ", 0); 
01277             } else { 
01278                 append(&select, "SELECT ", 0); 
01279             } 
01280         } else if (dd‐>quote_mode < 0) { 
01281             if (dd‐>where) { 
01282                 append(&select, "SELECT quote_csv(", 0); 
01283                 append(&select, dd‐>where, '"'); 
01284                 append(&select, ") || ',' || ", 0); 
01285             } else { 
01286                 append(&select, "SELECT ", 0); 
01287             } 
01288             if (dd‐>indent) { 
01289                 append(&hdr, select, 0); 
01290             } 
01291         } else { 
01292             char *tmp = 0; 
01293  
01294             if (dd‐>with_schema) { 
01295                 append(&select, "SELECT 'INSERT INTO ' || ", 0); 
01296             } else { 
01297                 append(&select, "SELECT 'INSERT OR REPLACE INTO ' || ", 0); 
01298             } 
01299             append(&tmp, table, '"'); 
01300             if (tmp) { 
01301                 append(&select, tmp, '\''); 
01302                 append_free(&tmp); 
01303             } 
01304         } 
01305         if ((dd‐>quote_mode >= 0) && !dd‐>with_schema) { 
01306             char *tmp = 0; 
01307  
01308             append(&select, " || ' (' || ", 0); 
01309             rc = sqlite3_step(stmt); 
01310             while (rc == SQLITE_ROW) { 
01311                 const char *text = (const char *) sqlite3_column_text(stmt, 1); 
01312  
01313                 append(&tmp, text, '"'); 
01314                 if (tmp) { 
01315                     append(&select, tmp, '\''); 
01316                     append_free(&tmp); 
01317                 } 
01318                 rc = sqlite3_step(stmt); 
01319                 if (rc == SQLITE_ROW) { 
01320                     append(&select, " || ',' || ", 0); 
01321                 } 
01322             } 
01323             if (rc != SQLITE_DONE) { 
01324                 goto bailout1; 
01325             } 
01326             sqlite3_reset(stmt); 
01327             append(&select, "|| ')'", 0); 
01328         } 
01329         if ((dd‐>quote_mode == ‐1) && dd‐>indent) { 
01330             rc = sqlite3_step(stmt); 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 15/32
10/02/2017 impexp.c Source File

01330             rc = sqlite3_step(stmt); 
01331             while (rc == SQLITE_ROW) { 
01332                 const char *text = (const char *) sqlite3_column_text(stmt, 1); 
01333  
01334                 append(&hdr, "quote_csv(", 0); 
01335                 append(&hdr, text, '"'); 
01336                 rc = sqlite3_step(stmt); 
01337                 if (rc == SQLITE_ROW) { 
01338                     append(&hdr, ") || ',' || ", 0); 
01339                 } else { 
01340                     append(&hdr, ")", 0); 
01341                 } 
01342             } 
01343             if (rc != SQLITE_DONE) { 
01344                 goto bailout1; 
01345             } 
01346             sqlite3_reset(stmt); 
01347         } 
01348         if (dd‐>quote_mode >= 0) { 
01349             append(&select, " || ' VALUES(' || ", 0); 
01350         } 
01351         rc = sqlite3_step(stmt); 
01352         while (rc == SQLITE_ROW) { 
01353             const char *text = (const char *) sqlite3_column_text(stmt, 1); 
01354             const char *type = (const char *) sqlite3_column_text(stmt, 2); 
01355             int tlen = strlen(type ? type : ""); 
01356  
01357             if (dd‐>quote_mode < ‐1) { 
01358                 sprintf(buffer, "indent_xml(%d)", dd‐>indent + 1); 
01359                 append(&select, buffer, 0); 
01360                 append(&select, "|| '<' || quote_xml(", 0); 
01361                 append(&select, text, '\''); 
01362                 append(&select, ",‐1) || quote_xml(", 0); 
01363                 append(&select, text, '"'); 
01364                 append(&select, ",1) || '</' || quote_xml(", 0); 
01365                 append(&select, text, '\''); 
01366                 append(&select, ",‐1) || '>\n'", 0); 
01367             } else if (dd‐>quote_mode < 0) { 
01368                 /* leave out BLOB columns */ 
01369                 if (((tlen >= 4) && (strncasecmp(type, "BLOB", 4) == 0)) || 
01370                     ((tlen >= 6) && (strncasecmp(type, "BINARY", 6) == 0))) { 
01371                     rc = sqlite3_step(stmt); 
01372                     if (rc != SQLITE_ROW) { 
01373                         tlen = strlen(select); 
01374                         if (tlen > 10) { 
01375                             select[tlen ‐ 10] = '\0'; 
01376                         } 
01377                     } 
01378                     continue; 
01379                 } 
01380                 append(&select, "quote_csv(", 0); 
01381                 append(&select, text, '"'); 
01382             } else { 
01383                 append(&select, "quote_sql(", 0); 
01384                 append(&select, text, '"'); 
01385                 if (dd‐>quote_mode) { 
01386                     char mbuf[32]; 
01387  
01388                     sprintf(mbuf, ",%d", dd‐>quote_mode); 
01389                     append(&select, mbuf, 0); 
01390                 } 
01391             } 
01392             rc = sqlite3_step(stmt); 
01393             if (rc == SQLITE_ROW) { 
01394                 if (dd‐>quote_mode >= ‐1) { 
01395                     append(&select, ") || ',' || ", 0); 
01396                 } else { 
01397                     append(&select, " || ", 0); 
01398                 } 
01399             } else { 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 16/32
10/02/2017 impexp.c Source File

01399             } else { 
01400                 if (dd‐>quote_mode >= ‐1) { 
01401                     append(&select, ") ", 0); 
01402                 } else { 
01403                     append(&select, " ", 0); 
01404                 } 
01405             } 
01406         } 
01407         if (rc != SQLITE_DONE) { 
01408             goto bailout1; 
01409         } 
01410         sqlite3_finalize(stmt); 
01411         stmt = 0; 
01412         if (dd‐>quote_mode >= 0) { 
01413             append(&select, "|| ')' FROM ", 0); 
01414         } else { 
01415             if ((dd‐>quote_mode < ‐1) && dd‐>where) { 
01416                 sprintf(buffer, " || indent_xml(%d)", dd‐>indent); 
01417                 append(&select, buffer, 0); 
01418                 append(&select, " || '</' || quote_xml(", 0); 
01419                 append(&select, dd‐>where, '"'); 
01420                 append(&select, ",‐1) || '>\n' FROM ", 0); 
01421             } else { 
01422                 append(&select, "FROM ", 0); 
01423             } 
01424         } 
01425         append(&select, table, '"'); 
01426         if ((dd‐>quote_mode >= 0) && dd‐>where) { 
01427             append(&select, " ", 0); 
01428             append(&select, dd‐>where, 0); 
01429         } 
01430         if (hdr) { 
01431             rc = table_dump(dd, 0, 0, hdr); 
01432             append_free(&hdr); 
01433             hdr = 0; 
01434         } 
01435         rc = table_dump(dd, 0, 0, select); 
01436         if (rc == SQLITE_CORRUPT) { 
01437             append(&select, " ORDER BY rowid DESC", 0); 
01438             rc = table_dump(dd, 0, 0, select); 
01439         } 
01440         append_free(&select); 
01441     } 
01442     return 0; 
01443 } 
01444  
01454 static int 
01455 schema_dump(DUMP_DATA *dd, char **errp, const char *query, ...) 
01456 { 
01457     int rc; 
01458     char *q; 
01459     va_list ap; 
01460  
01461     if (errp) { 
01462         sqlite3_free(*errp);
01463         *errp = 0; 
01464     } 
01465     va_start(ap, query); 
01466     q = sqlite3_vmprintf(query, ap); 
01467     va_end(ap); 
01468     if (!q) { 
01469         return SQLITE_NOMEM;
01470     } 
01471     rc = sqlite3_exec(dd‐>db, q, dump_cb, dd, errp); 
01472     if (rc == SQLITE_CORRUPT) { 
01473         char *tmp; 
01474  
01475         tmp = sqlite3_mprintf("%s ORDER BY rowid DESC", q); 
01476         sqlite3_free(q); 
01477         if (!tmp) { 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 17/32
10/02/2017 impexp.c Source File

01477         if (!tmp) { 
01478             return rc; 
01479         } 
01480         q = tmp; 
01481         if (errp) { 
01482             sqlite3_free(*errp); 
01483             *errp = 0; 
01484         } 
01485         rc = sqlite3_exec(dd‐>db, q, dump_cb, dd, errp); 
01486     } 
01487     sqlite3_free(q); 
01488     return rc; 
01489 } 
01490  
01498 static void 
01499 export_func(sqlite3_context *ctx, int nargs, sqlite3_value **args) 
01500 { 
01501     DUMP_DATA dd0, *dd = &dd0; 
01502     sqlite3 *db = (sqlite3 *) sqlite3_user_data(ctx); 
01503     int i, mode = 0; 
01504     char *filename = 0; 
01505 #ifdef _WIN32 
01506     char fnbuf[MAX_PATH]; 
01507 #endif 
01508  
01509     dd‐>db = db; 
01510     dd‐>where = 0; 
01511     dd‐>nlines = ‐1; 
01512     dd‐>indent = 0; 
01513     if (nargs > 0) { 
01514         if (sqlite3_value_type(args[0]) != SQLITE_NULL) { 
01515             filename = (char *) sqlite3_value_text(args[0]); 
01516         } 
01517     } 
01518 #ifdef _WIN32 
01519     if (!filename) { 
01520         OPENFILENAME ofn; 
01521  
01522         memset(&ofn, 0, sizeof (ofn)); 
01523         memset(fnbuf, 0, sizeof (fnbuf)); 
01524         ofn.lStructSize = sizeof (ofn); 
01525         ofn.lpstrFile = fnbuf; 
01526         ofn.nMaxFile = MAX_PATH; 
01527         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | 
01528                     OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 
01529         if (GetSaveFileName(&ofn)) { 
01530             filename = fnbuf; 
01531         } 
01532     } 
01533 #endif 
01534     if (!filename) { 
01535         goto done; 
01536     } 
01537     dd‐>out = fopen(filename, "w"); 
01538     if (!dd‐>out) { 
01539         goto done; 
01540     } 
01541     if (nargs > 1) { 
01542         mode = sqlite3_value_int(args[1]); 
01543     } 
01544     dd‐>with_schema = !(mode & 1); 
01545     dd‐>quote_mode = (mode >> 8) & 3; 
01546     dd‐>nlines = 0; 
01547     if (fputs("BEGIN TRANSACTION;\n", dd‐>out) >= 0) { 
01548         dd‐>nlines++; 
01549     } 
01550     if (nargs <= 2) { 
01551         schema_dump(dd, 0, 
01552                     "SELECT name, type, sql FROM sqlite_master" 
01553                     " WHERE sql NOT NULL AND type = 'table'");
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 18/32
10/02/2017 impexp.c Source File

01553                     " WHERE sql NOT NULL AND type = 'table'");
01554         if (dd‐>with_schema) { 
01555             table_dump(dd, 0, 0, 
01556                        "SELECT sql FROM sqlite_master WHERE" 
01557                        " sql NOT NULL AND type IN ('index','trigger','view')"); 
01558         } 
01559     } else { 
01560         for (i = 2; i < nargs; i += (mode & 2) ? 2 : 1) { 
01561             dd‐>where = 0; 
01562             if ((mode & 2) && (i + 1 < nargs)) { 
01563                 dd‐>where = (char *) sqlite3_value_text(args[i + 1]); 
01564             } 
01565             schema_dump(dd, 0, 
01566                         "SELECT name, type, sql FROM sqlite_master" 
01567                         " WHERE tbl_name LIKE %Q AND type = 'table'" 
01568                         " AND sql NOT NULL", 
01569                         sqlite3_value_text(args[i])); 
01570             if (dd‐>with_schema) { 
01571                 table_dump(dd, 0, 1, 
01572                            "SELECT sql FROM sqlite_master" 
01573                            " WHERE sql NOT NULL" 
01574                            " AND type IN ('index','trigger','view')" 
01575                            " AND tbl_name LIKE %Q", 
01576                            sqlite3_value_text(args[i])); 
01577             } 
01578         } 
01579     } 
01580     if (fputs("COMMIT;\n", dd‐>out) >= 0) { 
01581         dd‐>nlines++; 
01582     } 
01583     fclose(dd‐>out); 
01584 done: 
01585     sqlite3_result_int(ctx, dd‐>nlines); 
01586 } 
01587  
01595 static void 
01596 export_csv_func(sqlite3_context *ctx, int nargs, sqlite3_value **args) 
01597 { 
01598     DUMP_DATA dd0, *dd = &dd0; 
01599     sqlite3 *db = (sqlite3 *) sqlite3_user_data(ctx); 
01600     int i; 
01601     char *filename = 0; 
01602 #ifdef _WIN32 
01603     char fnbuf[MAX_PATH]; 
01604 #endif 
01605  
01606     dd‐>db = db; 
01607     dd‐>where = 0; 
01608     dd‐>nlines = ‐1; 
01609     dd‐>indent = 0; 
01610     dd‐>with_schema = 0; 
01611     dd‐>quote_mode = ‐1; 
01612     if (nargs > 0) { 
01613         if (sqlite3_value_type(args[0]) != SQLITE_NULL) { 
01614             filename = (char *) sqlite3_value_text(args[0]); 
01615         } 
01616     } 
01617 #ifdef _WIN32 
01618     if (!filename) { 
01619         OPENFILENAME ofn; 
01620  
01621         memset(&ofn, 0, sizeof (ofn)); 
01622         memset(fnbuf, 0, sizeof (fnbuf)); 
01623         ofn.lStructSize = sizeof (ofn); 
01624         ofn.lpstrFile = fnbuf; 
01625         ofn.nMaxFile = MAX_PATH; 
01626         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | 
01627                     OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 
01628         if (GetSaveFileName(&ofn)) { 
01629             filename = fnbuf; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 19/32
10/02/2017 impexp.c Source File

01629             filename = fnbuf; 
01630         } 
01631     } 
01632 #endif 
01633     if (!filename) { 
01634         goto done; 
01635     } 
01636 #ifdef _WIN32 
01637     dd‐>out = fopen(filename, "wb"); 
01638 #else 
01639     dd‐>out = fopen(filename, "w");
01640 #endif 
01641     if (!dd‐>out) { 
01642         goto done; 
01643     } 
01644     dd‐>nlines = 0; 
01645     if (nargs > 1) { 
01646         if (sqlite3_value_type(args[1]) != SQLITE_NULL) { 
01647             if (sqlite3_value_int(args[1])) { 
01648                 dd‐>indent = 1; 
01649             } 
01650         } 
01651     } 
01652     for (i = 2; i <= nargs ‐ 3; i += 3) { 
01653         char *schema = 0, *sql; 
01654  
01655         dd‐>where = 0; 
01656         if (sqlite3_value_type(args[i]) != SQLITE_NULL) { 
01657             dd‐>where = (char *) sqlite3_value_text(args[i]); 
01658             if (dd‐>where && !dd‐>where[0]) { 
01659                 dd‐>where = 0; 
01660             } 
01661         } 
01662         if (sqlite3_value_type(args[i + 2]) != SQLITE_NULL) { 
01663             schema = (char *) sqlite3_value_text(args[i + 2]);
01664         } 
01665         if (!schema || (schema[0] == '\0')) { 
01666             schema = "sqlite_master"; 
01667         } 
01668         sql = sqlite3_mprintf("SELECT name, type, sql FROM %s" 
01669                               " WHERE tbl_name LIKE %%Q AND " 
01670                               " (type = 'table' OR type = 'view')" 
01671                               " AND sql NOT NULL", schema); 
01672         if (sql) { 
01673             schema_dump(dd, 0, sql, sqlite3_value_text(args[i + 1])); 
01674             sqlite3_free(sql); 
01675         } 
01676     } 
01677     fclose(dd‐>out); 
01678 done: 
01679     sqlite3_result_int(ctx, dd‐>nlines); 
01680 } 
01681  
01689 static void 
01690 export_xml_func(sqlite3_context *ctx, int nargs, sqlite3_value **args) 
01691 { 
01692     DUMP_DATA dd0, *dd = &dd0; 
01693     sqlite3 *db = (sqlite3 *) sqlite3_user_data(ctx); 
01694     int i; 
01695     char *filename = 0; 
01696     char *openmode = "w"; 
01697 #ifdef _WIN32 
01698     char fnbuf[MAX_PATH]; 
01699 #endif 
01700  
01701     dd‐>db = db; 
01702     dd‐>where = 0; 
01703     dd‐>nlines = ‐1; 
01704     dd‐>indent = 0; 

01705     dd‐>with_schema = 0; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 20/32
10/02/2017 impexp.c Source File

01705     dd‐>with_schema = 0; 
01706     dd‐>quote_mode = ‐2; 
01707     if (nargs > 0) { 
01708         if (sqlite3_value_type(args[0]) != SQLITE_NULL) { 
01709             filename = (char *) sqlite3_value_text(args[0]); 
01710         } 
01711     } 
01712 #ifdef _WIN32 
01713     if (!filename) { 
01714         OPENFILENAME ofn; 
01715  
01716         memset(&ofn, 0, sizeof (ofn)); 
01717         memset(fnbuf, 0, sizeof (fnbuf)); 
01718         ofn.lStructSize = sizeof (ofn); 
01719         ofn.lpstrFile = fnbuf; 
01720         ofn.nMaxFile = MAX_PATH; 
01721         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | 
01722                     OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 
01723         if (GetSaveFileName(&ofn)) { 
01724             filename = fnbuf; 
01725         } 
01726     } 
01727 #endif 
01728     if (!filename) { 
01729         goto done; 
01730     } 
01731     if (nargs > 1) { 
01732         if (sqlite3_value_type(args[1]) != SQLITE_NULL) { 
01733             if (sqlite3_value_int(args[1])) { 
01734                 openmode = "a"; 
01735             } 
01736         } 
01737     } 
01738     if (nargs > 2) { 
01739         if (sqlite3_value_type(args[2]) != SQLITE_NULL) { 
01740             dd‐>indent = sqlite3_value_int(args[2]); 
01741             if (dd‐>indent < 0) { 
01742                 dd‐>indent = 0; 
01743             } 
01744         } 
01745     } 
01746     dd‐>out = fopen(filename, openmode); 
01747     if (!dd‐>out) { 
01748         goto done; 
01749     } 
01750     dd‐>nlines = 0; 
01751     for (i = 3; i <= nargs ‐ 4; i += 4) { 
01752         char *root = 0, *schema = 0, *sql; 
01753  
01754         if (sqlite3_value_type(args[i]) != SQLITE_NULL) { 
01755             root = (char *) sqlite3_value_text(args[i]); 
01756             if (root && !root[0]) { 
01757                 root = 0; 
01758             } 
01759         } 
01760         dd‐>where = 0; 
01761         if (sqlite3_value_type(args[i + 1]) != SQLITE_NULL) { 
01762             dd‐>where = (char *) sqlite3_value_text(args[i + 1]); 
01763             if (dd‐>where && !dd‐>where[0]) { 
01764                 dd‐>where = 0; 
01765             } 
01766         } 
01767         if (root) { 
01768             indent(dd); 
01769             dd‐>indent++; 
01770             fputs("<", dd‐>out); 
01771             quote_xml_str(dd, root); 
01772             fputs(">\n", dd‐>out); 
01773         } 
01774         if (sqlite3_value_type(args[i + 3]) != SQLITE_NULL) { 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 21/32
10/02/2017 impexp.c Source File

01774         if (sqlite3_value_type(args[i + 3]) != SQLITE_NULL) { 
01775             schema = (char *) sqlite3_value_text(args[i + 3]);
01776         } 
01777         if (!schema || (schema[0] == '\0')) { 
01778             schema = "sqlite_master"; 
01779         } 
01780         sql = sqlite3_mprintf("SELECT name, type, sql FROM %s" 
01781                               " WHERE tbl_name LIKE %%Q AND" 
01782                               " (type = 'table' OR type = 'view')" 
01783                               " AND sql NOT NULL", schema); 
01784         if (sql) { 
01785             schema_dump(dd, 0, sql, sqlite3_value_text(args[i + 2])); 
01786             sqlite3_free(sql); 
01787         } 
01788         if (root) { 
01789             dd‐>indent‐‐; 
01790             indent(dd); 
01791             fputs("</", dd‐>out); 
01792             quote_xml_str(dd, root); 
01793             fputs(">\n", dd‐>out); 
01794         } 
01795     } 
01796     fclose(dd‐>out); 
01797 done: 
01798     sqlite3_result_int(ctx, dd‐>nlines); 
01799 } 
01800  
01801 /* see doc in impexp.h */ 
01802  
01803 int 
01804 impexp_export_sql(sqlite3 *db, char *filename, int mode, ...) 
01805 { 
01806     DUMP_DATA dd0, *dd = &dd0; 
01807     va_list ap; 
01808     char *table; 
01809 #ifdef _WIN32 
01810     char fnbuf[MAX_PATH]; 
01811 #endif 
01812  
01813     if (!db) { 
01814         return 0; 
01815     } 
01816     dd‐>db = db; 
01817     dd‐>where = 0; 
01818     dd‐>nlines = ‐1; 
01819 #ifdef _WIN32 
01820     if (!filename) { 
01821         OPENFILENAME ofn; 
01822  
01823         memset(&ofn, 0, sizeof (ofn)); 
01824         memset(fnbuf, 0, sizeof (fnbuf)); 
01825         ofn.lStructSize = sizeof (ofn); 
01826         ofn.lpstrFile = fnbuf; 
01827         ofn.nMaxFile = MAX_PATH; 
01828         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | 
01829                     OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 
01830         if (GetSaveFileName(&ofn)) { 
01831             filename = fnbuf; 
01832         } 
01833     } 
01834 #endif 
01835     if (!filename) { 
01836         goto done; 
01837     } 
01838     dd‐>out = fopen(filename, "w"); 
01839     if (!dd‐>out) { 
01840         goto done; 
01841     } 
01842     dd‐>with_schema = !(mode & 1); 

01843     dd‐>nlines = 0; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 22/32
10/02/2017 impexp.c Source File

01843     dd‐>nlines = 0; 
01844     if (fputs("BEGIN TRANSACTION;\n", dd‐>out) >= 0) { 
01845         dd‐>nlines++; 
01846     } 
01847     va_start(ap, mode); 
01848     table = va_arg(ap, char *); 
01849     if (!table) { 
01850         schema_dump(dd, 0, 
01851                     "SELECT name, type, sql FROM sqlite_master" 
01852                     " WHERE sql NOT NULL AND type = 'table'");
01853         if (dd‐>with_schema) { 
01854             table_dump(dd, 0, 0, 
01855                        "SELECT sql FROM sqlite_master WHERE" 
01856                        " sql NOT NULL AND type IN ('index','trigger','view')"); 
01857         } 
01858     } else { 
01859         while (table) { 
01860             dd‐>where = 0; 
01861             if ((mode & 2)) { 
01862                 dd‐>where = va_arg(ap, char *); 
01863             } 
01864             schema_dump(dd, 0, 
01865                         "SELECT name, type, sql FROM sqlite_master" 
01866                         " WHERE tbl_name LIKE %Q AND type = 'table'" 
01867                         " AND sql NOT NULL", table); 
01868             if (dd‐>with_schema) { 
01869                 table_dump(dd, 0, 1, 
01870                            "SELECT sql FROM sqlite_master" 
01871                            " WHERE sql NOT NULL" 
01872                            " AND type IN ('index','trigger','view')" 
01873                            " AND tbl_name LIKE %Q", table); 
01874             } 
01875             table = va_arg(ap, char *); 
01876         } 
01877     } 
01878     va_end(ap); 
01879     if (fputs("COMMIT;\n", dd‐>out) >= 0) { 
01880         dd‐>nlines++; 
01881     } 
01882     fclose(dd‐>out); 
01883 done: 
01884     return dd‐>nlines; 
01885 } 
01886  
01887 /* see doc in impexp.h */ 
01888  
01889 int 
01890 impexp_export_csv(sqlite3 *db, char *filename, int hdr, ...) 
01891 { 
01892     DUMP_DATA dd0, *dd = &dd0; 
01893     va_list ap; 
01894     char *prefix, *table, *schema; 
01895 #ifdef _WIN32 
01896     char fnbuf[MAX_PATH]; 
01897 #endif 
01898  
01899     if (!db) { 
01900         return 0; 
01901     } 
01902     dd‐>db = db; 
01903     dd‐>where = 0; 
01904     dd‐>nlines = ‐1; 
01905     dd‐>indent = 0; 
01906     dd‐>with_schema = 0; 
01907     dd‐>quote_mode = ‐1; 
01908     dd‐>indent = hdr != 0; 
01909 #ifdef _WIN32 
01910     if (!filename) { 
01911         OPENFILENAME ofn; 
01912  
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 23/32
10/02/2017 impexp.c Source File

01912  
01913         memset(&ofn, 0, sizeof (ofn)); 
01914         memset(fnbuf, 0, sizeof (fnbuf)); 
01915         ofn.lStructSize = sizeof (ofn); 
01916         ofn.lpstrFile = fnbuf; 
01917         ofn.nMaxFile = MAX_PATH; 
01918         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | 
01919                     OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 
01920         if (GetSaveFileName(&ofn)) { 
01921             filename = fnbuf; 
01922         } 
01923     } 
01924 #endif 
01925     if (!filename) { 
01926         goto done; 
01927     } 
01928 #ifdef _WIN32 
01929     dd‐>out = fopen(filename, "wb"); 
01930 #else 
01931     if ((hdr < 0) && access(filename, W_OK) == 0) { 
01932         dd‐>out = fopen(filename, "a"); 
01933         dd‐>indent = 0; 
01934     } else { 
01935         dd‐>out = fopen(filename, "w"); 
01936     } 
01937 #endif 
01938     if (!dd‐>out) { 
01939         goto done; 
01940     } 
01941     dd‐>nlines = 0; 
01942     va_start(ap, hdr); 
01943     prefix = va_arg(ap, char *); 
01944     table = va_arg(ap, char *); 
01945     schema = va_arg(ap, char *); 
01946     while (table != NULL) { 
01947         char *sql; 
01948  
01949         dd‐>where = (prefix && prefix[0]) ? prefix : 0; 
01950         if (!schema || (schema[0] == '\0')) { 
01951             schema = "sqlite_master"; 
01952         } 
01953         sql = sqlite3_mprintf("SELECT name, type, sql FROM %s" 
01954                               " WHERE tbl_name LIKE %%Q AND" 
01955                               " (type = 'table' OR type = 'view')" 
01956                               " AND sql NOT NULL", schema); 
01957         if (sql) { 
01958             schema_dump(dd, 0, sql, table); 
01959             sqlite3_free(sql); 
01960         } 
01961         prefix = va_arg(ap, char *); 
01962         table = va_arg(ap, char *); 
01963         schema = va_arg(ap, char *); 
01964     } 
01965     va_end(ap); 
01966     fclose(dd‐>out); 
01967 done: 
01968     return dd‐>nlines; 
01969 } 
01970  
01971 /* see doc in impexp.h */ 
01972  
01973 int 
01974 impexp_export_xml(sqlite3 *db, char *filename, int append, int indnt, 
01975                   char *root, char *item, char *tablename, char *schema) 
01976 { 
01977     DUMP_DATA dd0, *dd = &dd0; 
01978     char *sql; 
01979 #ifdef _WIN32 
01980     char fnbuf[MAX_PATH]; 

01981 #endif 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 24/32
10/02/2017 impexp.c Source File

01981 #endif 
01982  
01983     if (!db) { 
01984         return 0; 
01985     } 
01986     dd‐>db = db; 
01987     dd‐>where = item; 
01988     dd‐>nlines = ‐1; 
01989     dd‐>indent = (indnt > 0) ? indnt : 0; 
01990     dd‐>with_schema = 0; 
01991     dd‐>quote_mode = ‐2; 
01992 #ifdef _WIN32 
01993     if (!filename) { 
01994         OPENFILENAME ofn; 
01995  
01996         memset(&ofn, 0, sizeof (ofn)); 
01997         memset(fnbuf, 0, sizeof (fnbuf)); 
01998         ofn.lStructSize = sizeof (ofn); 
01999         ofn.lpstrFile = fnbuf; 
02000         ofn.nMaxFile = MAX_PATH; 
02001         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | 
02002                     OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 
02003         if (GetSaveFileName(&ofn)) { 
02004             filename = fnbuf; 
02005         } 
02006     } 
02007 #endif 
02008     if (!filename) { 
02009         goto done; 
02010     } 
02011     dd‐>out = fopen(filename, append ? "a" : "w"); 
02012     if (!dd‐>out) { 
02013         goto done; 
02014     } 
02015     dd‐>nlines = 0; 
02016     if (root) { 
02017         indent(dd); 
02018         dd‐>indent++; 
02019         fputs("<", dd‐>out); 
02020         quote_xml_str(dd, root); 
02021         fputs(">\n", dd‐>out); 
02022     } 
02023     if (!schema || (schema[0] == '\0')) { 
02024         schema = "sqlite_master"; 
02025     } 
02026     sql = sqlite3_mprintf("SELECT name, type, sql FROM %s" 
02027                           " WHERE tbl_name LIKE %%Q AND" 
02028                           " (type = 'table' OR type = 'view')" 
02029                           " AND sql NOT NULL", schema); 
02030     if (sql) { 
02031         schema_dump(dd, 0, sql, tablename); 
02032         sqlite3_free(sql); 
02033     } 
02034     if (root) { 
02035         dd‐>indent‐‐; 
02036         indent(dd); 
02037         fputs("</", dd‐>out); 
02038         quote_xml_str(dd, root); 
02039         fputs(">\n", dd‐>out); 
02040     } 
02041     fclose(dd‐>out); 
02042 done: 
02043     return dd‐>nlines; 
02044 } 
02045  
02052 static void 
02053 json_pstr(const char *string, json_pfs *pfs) 
02054 { 
02055     while (*string) { 
02056         pfs‐>pfunc(*string, pfs‐>parg); 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 25/32
10/02/2017 impexp.c Source File

02056         pfs‐>pfunc(*string, pfs‐>parg); 
02057         string++; 
02058     } 
02059 } 
02060  
02067 static void 
02068 json_pstrq(const char *string, json_pfs *pfs) 
02069 { 
02070     impexp_putc pfunc = pfs‐>pfunc; 
02071     void *parg = pfs‐>parg; 
02072     char buf[64]; 
02073  
02074     if (!string) { 
02075         json_pstr("null", pfs); 
02076         return; 
02077     } 
02078     pfunc('"', parg); 
02079     while (*string) { 
02080         switch (*string) { 
02081         case '"': 
02082         case '\\': 
02083             pfunc('\\', parg); 
02084             pfunc(*string, parg); 
02085             break; 
02086         case '\b': 
02087             pfunc('\\', parg); 
02088             pfunc('b', parg); 
02089             break; 
02090         case '\f': 
02091             pfunc('\\', parg); 
02092             pfunc('f', parg); 
02093             break; 
02094         case '\n': 
02095             pfunc('\\', parg); 
02096             pfunc('n', parg); 
02097             break; 
02098         case '\r': 
02099             pfunc('\\', parg); 
02100             pfunc('r', parg); 
02101             break; 
02102         case '\t': 
02103             pfunc('\\', parg); 
02104             pfunc('t', parg); 
02105             break; 
02106         default: 
02107             if (((*string < ' ') && (*string > 0)) || (*string == 0x7f)) { 
02108                 sprintf(buf, "\\u%04x", *string); 
02109                 json_pstr(buf, pfs); 
02110             } else if (*string < 0) { 
02111                 unsigned char c = string[0]; 
02112                 unsigned long uc = 0; 
02113  
02114                 if (c < 0xc0) { 
02115                     uc = c; 
02116                 } else if (c < 0xe0) { 
02117                     if ((string[1] & 0xc0) == 0x80) { 
02118                         uc = ((c & 0x1f) << 6) | (string[1] & 0x3f); 
02119                         ++string; 
02120                     } else { 
02121                         uc = c; 
02122                     } 
02123                 } else if (c < 0xf0) { 
02124                     if (((string[1] & 0xc0) == 0x80) && 
02125                         ((string[2] & 0xc0) == 0x80)) { 
02126                         uc = ((c & 0x0f) << 12) | 
02127                              ((string[1] & 0x3f) << 6) | (string[2] & 0x3f); 
02128                         string += 2; 
02129                     } else { 
02130                         uc = c; 

02131                     } 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 26/32
10/02/2017 impexp.c Source File

02131                     } 
02132                 } else if (c < 0xf8) { 
02133                     if (((string[1] & 0xc0) == 0x80) && 
02134                         ((string[2] & 0xc0) == 0x80) && 
02135                         ((string[3] & 0xc0) == 0x80)) { 
02136                         uc = ((c & 0x03) << 18) | 
02137                              ((string[1] & 0x3f) << 12) | 
02138                              ((string[2] & 0x3f) << 6) | 
02139                              (string[4] & 0x3f); 
02140                         string += 3; 
02141                     } else { 
02142                         uc = c; 
02143                     } 
02144                 } else if (c < 0xfc) { 
02145                     if (((string[1] & 0xc0) == 0x80) && 
02146                         ((string[2] & 0xc0) == 0x80) && 
02147                         ((string[3] & 0xc0) == 0x80) && 
02148                         ((string[4] & 0xc0) == 0x80)) { 
02149                         uc = ((c & 0x01) << 24) | 
02150                              ((string[1] & 0x3f) << 18) | 
02151                              ((string[2] & 0x3f) << 12) | 
02152                              ((string[4] & 0x3f) << 6) | 
02153                              (string[5] & 0x3f); 
02154                         string += 4; 
02155                     } else { 
02156                         uc = c; 
02157                     } 
02158                 } else { 
02159                     /* ignore */ 
02160                     ++string; 
02161                 } 
02162                 if (uc < 0x10000) { 
02163                     sprintf(buf, "\\u%04lx", uc); 
02164                 } else if (uc < 0x100000) { 
02165                     uc ‐= 0x10000; 
02166  
02167                     sprintf(buf, "\\u%04lx", 0xd800 | ((uc >> 10) & 0x3ff)); 
02168                     json_pstr(buf, pfs); 
02169                     sprintf(buf, "\\u%04lx", 0xdc00 | (uc & 0x3ff)); 
02170                 } else { 
02171                     strcpy(buf, "\\ufffd"); 
02172                 } 
02173                 json_pstr(buf, pfs); 
02174             } else { 
02175                 pfunc(*string, parg); 
02176             } 
02177             break; 
02178         } 
02179         ++string; 
02180     } 
02181     pfunc('"', parg); 
02182 } 
02183  
02190 static void 
02191 json_pstrc(const char *string, json_pfs *pfs) 
02192 { 
02193     if (*string && strchr(".0123456789‐+", *string)) { 
02194         json_pstr(string, pfs); 
02195     } else { 
02196         json_pstrq(string, pfs); 
02197     } 
02198 } 
02199  
02207 static void 
02208 json_pb64(const unsigned char *blk, int len, json_pfs *pfs) 
02209 { 
02210     impexp_putc pfunc = pfs‐>pfunc; 
02211     void *parg = pfs‐>parg; 
02212     int i, reg[5]; 
02213     char buf[16]; 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 27/32
10/02/2017 impexp.c Source File

02213     char buf[16]; 
02214     static const char *b64 = 
02215         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 
02216  
02217     if (!blk) { 
02218         json_pstr("null", pfs); 
02219         return; 
02220     } 
02221     buf[4] = '\0'; 
02222     pfunc('"', parg); 
02223     for (i = 0; i < len; i += 3) { 
02224         reg[1] = reg[2] = reg[3] = reg[4] = 0; 
02225         reg[0] = blk[i]; 
02226         if (i + 1 < len) { 
02227             reg[1] = blk[i + 1]; 
02228             reg[3] = 1; 
02229         } 
02230         if (i + 2 < len) { 
02231             reg[2] = blk[i + 2]; 
02232             reg[4] = 1; 
02233         } 
02234         buf[0] = b64[reg[0] >> 2]; 
02235         buf[1] = b64[((reg[0] << 4) & 0x30) | (reg[1] >> 4)]; 
02236         if (reg[3]) { 
02237             buf[2] = b64[((reg[1] << 2) & 0x3c) | (reg[2] >> 6)]; 
02238         } else { 
02239             buf[2] = '='; 
02240         } 
02241         if (reg[4]) { 
02242             buf[3] = b64[reg[2] & 0x3f]; 
02243         } else { 
02244             buf[3] = '='; 
02245         } 
02246         json_pstr(buf, pfs); 
02247     } 
02248     pfunc('"', parg); 
02249 } 
02250  
02260 static int 
02261 json_output(sqlite3 *db, char *sql, impexp_putc pfunc, void *parg) 
02262 { 
02263     json_pfs pfs0, *pfs = &pfs0; 
02264     const char *tail = sql; 
02265     int i, nresults = 0, result = SQLITE_ERROR; 
02266  
02267     pfs‐>pfunc = pfunc; 
02268     pfs‐>parg = parg; 
02269     json_pstr("{\"sql\":", pfs); 
02270     json_pstrq(sql, pfs); 
02271     json_pstr(",\"results\":[", pfs); 
02272     do { 
02273         sqlite3_stmt *stmt; 
02274         int firstrow = 1, nrows = 0; 
02275         char buf[256]; 
02276  
02277         ++nresults; 
02278         json_pstr((nresults == 1) ? "{" : ",{", pfs); 
02279         result = sqlite3_prepare(db, tail, ‐1, &stmt, &tail); 
02280         if (result != SQLITE_OK) { 
02281 doerr: 
02282             if (nrows == 0) { 
02283                 json_pstr("\"columns\":null,\"rows\":null,\"changes\":0," 
02284                           "\"last_insert_rowid\":null,", pfs); 
02285             } 
02286             json_pstr("\"error:\"", pfs); 
02287             json_pstrq(sqlite3_errmsg(db), pfs); 
02288             pfunc('}', parg); 
02289             break; 
02290         } 

02291         result = sqlite3_step(stmt); 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 28/32
10/02/2017 impexp.c Source File

02291         result = sqlite3_step(stmt); 
02292         while ((result == SQLITE_ROW) || (result == SQLITE_DONE)) { 
02293             if (firstrow) { 
02294                 for (i = 0; i < sqlite3_column_count(stmt); i++) { 
02295                     char *type; 
02296  
02297                     json_pstr((i == 0) ? "\"columns\":[" : ",", pfs); 
02298                     json_pstr("{\"name\":", pfs); 
02299                     json_pstrq(sqlite3_column_name(stmt, i), pfs); 
02300                     json_pstr(",\"decltype\":", pfs); 
02301                     json_pstrq(sqlite3_column_decltype(stmt, i), pfs); 
02302                     json_pstr(",\"type\":", pfs); 
02303                     switch (sqlite3_column_type(stmt, i)) { 
02304                     case SQLITE_INTEGER: 
02305                         type = "integer"; 
02306                         break; 
02307                     case SQLITE_FLOAT: 
02308                         type = "float"; 
02309                         break; 
02310                     case SQLITE_BLOB: 
02311                         type = "blob"; 
02312                         break; 
02313                     case SQLITE_TEXT: 
02314                         type = "text"; 
02315                         break; 
02316                     case SQLITE_NULL: 
02317                         type = "null"; 
02318                         break; 
02319                     default:
02320                         type = "unknown"; 
02321                         break; 
02322                     } 
02323                     json_pstrq(type, pfs); 
02324                     pfunc('}', parg); 
02325                 } 
02326                 if (i) { 
02327                     pfunc(']', parg); 
02328                 } 
02329                 firstrow = 0; 
02330             } 
02331             if (result == SQLITE_DONE) { 
02332                 break; 
02333             } 
02334             ++nrows; 
02335             json_pstr((nrows == 1) ? ",\"rows\":[" : ",", pfs); 
02336             for (i = 0; i < sqlite3_column_count(stmt); i++) { 
02337                 pfunc((i == 0) ? '[' : ',', parg); 
02338                 switch (sqlite3_column_type(stmt, i)) { 
02339                 case SQLITE_INTEGER: 
02340                     json_pstr((char *) sqlite3_column_text(stmt, i), pfs); 
02341                     break; 
02342                 case SQLITE_FLOAT: 
02343                     json_pstrc((char *) sqlite3_column_text(stmt, i), pfs); 
02344                     break; 
02345                 case SQLITE_BLOB: 
02346                     json_pb64((unsigned char *) sqlite3_column_blob(stmt, i), 
02347                               sqlite3_column_bytes(stmt, i), pfs); 
02348                     break; 
02349                 case SQLITE_TEXT: 
02350                     json_pstrq((char *) sqlite3_column_text(stmt, i), pfs); 
02351                     break; 
02352                 case SQLITE_NULL: 
02353                 default: 
02354                     json_pstr("null", pfs); 
02355                     break; 
02356                 } 
02357             } 
02358             json_pstr((i == 0) ? "null]" : "]", pfs); 
02359             result = sqlite3_step(stmt); 

02360         } 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 29/32
10/02/2017 impexp.c Source File

02360         } 
02361         if (nrows > 0) { 
02362             pfunc(']', parg); 
02363         } 
02364         result = sqlite3_finalize(stmt); 
02365         if (result != SQLITE_OK) { 
02366             if (nrows > 0) { 
02367                 sprintf(buf,
02368 #ifdef _WIN32 
02369                         ",\"changes\":%d,\"last_insert_rowid\":%I64d", 
02370 #else 
02371                         ",\"changes\":%d,\"last_insert_rowid\":%lld", 
02372 #endif 
02373                         sqlite3_changes(db), 
02374                         sqlite3_last_insert_rowid(db)); 
02375                 json_pstr(buf, pfs); 
02376             } 
02377             goto doerr; 
02378         } 
02379         if (nrows == 0) { 
02380             json_pstr("\"columns\":null,\"rows\":null", pfs); 
02381         } 
02382         sprintf(buf, 
02383 #ifdef _WIN32 
02384                 ",\"changes\":%d,\"last_insert_rowid\":%I64d",
02385 #else 
02386                 ",\"changes\":%d,\"last_insert_rowid\":%lld", 
02387 #endif 
02388                 sqlite3_changes(db), 
02389                 sqlite3_last_insert_rowid(db)); 
02390         json_pstr(buf, pfs); 
02391         json_pstr(",\"error\":null}", pfs); 
02392     } while (tail && *tail);
02393     json_pstr("]}", pfs); 
02394     return result; 
02395 } 
02396  
02404 static void 
02405 export_json_func(sqlite3_context *ctx, int nargs, sqlite3_value **args) 
02406 { 
02407     sqlite3 *db = (sqlite3 *) sqlite3_user_data(ctx); 
02408     int result = ‐1; 
02409     char *filename = 0; 
02410     char *sql = 0; 
02411     FILE *out = 0; 
02412 #ifdef _WIN32 
02413     char fnbuf[MAX_PATH]; 
02414 #endif 
02415  
02416     if (nargs > 0) { 
02417         if (sqlite3_value_type(args[0]) != SQLITE_NULL) { 
02418             filename = (char *) sqlite3_value_text(args[0]); 
02419         } 
02420     } 
02421 #ifdef _WIN32 
02422     if (!filename) { 
02423         OPENFILENAME ofn; 
02424  
02425         memset(&ofn, 0, sizeof (ofn)); 
02426         memset(fnbuf, 0, sizeof (fnbuf)); 
02427         ofn.lStructSize = sizeof (ofn); 
02428         ofn.lpstrFile = fnbuf; 
02429         ofn.nMaxFile = MAX_PATH; 
02430         ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER | 
02431                     OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; 
02432         if (GetSaveFileName(&ofn)) { 
02433             filename = fnbuf; 
02434         } 
02435     } 

02436 #endif 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 30/32
10/02/2017 impexp.c Source File

02436 #endif 
02437     if (!filename) { 
02438         goto done; 
02439     } 
02440     out = fopen(filename, "w"); 
02441     if (!out) { 
02442         goto done; 
02443     } 
02444     if (nargs > 1) { 
02445         sql = (char *) sqlite3_value_text(args[1]); 
02446     } 
02447     if (sql) { 
02448         result = json_output(db, sql, (impexp_putc) fputc, out); 
02449     } 
02450     fclose(out); 
02451 done: 
02452     sqlite3_result_int(ctx, result); 
02453 } 
02454  
02455 /* see doc in impexp.h */ 
02456  
02457 int 
02458 impexp_export_json(sqlite3 *db, char *sql, impexp_putc pfunc, 
02459                    void *parg) 
02460 { 
02461     return json_output(db, sql, pfunc, parg); 
02462 } 
02463  
02472 #ifdef STANDALONE 
02473 static int 
02474 #else 
02475 int 
02476 #endif 
02477 sqlite3_extension_init(sqlite3 *db, char **errmsg, 
02478                        const sqlite3_api_routines *api) 
02479 { 
02480     int rc, i; 
02481     static const struct { 
02482         const char *name; 
02483         void (*func)(sqlite3_context *, int, sqlite3_value **); 
02484         int nargs; 
02485         int textrep; 
02486     } ftab[] = { 
02487         { "quote_sql",   quote_func,       ‐1, SQLITE_UTF8 }, 
02488         { "import_sql",  import_func,      ‐1, SQLITE_UTF8 }, 
02489         { "export_sql",  export_func,      ‐1, SQLITE_UTF8 }, 
02490         { "quote_csv",   quote_csv_func,   ‐1, SQLITE_UTF8 }, 
02491         { "export_csv",  export_csv_func,  ‐1, SQLITE_UTF8 }, 
02492         { "indent_xml",  indent_xml_func,   1, SQLITE_UTF8 }, 
02493         { "quote_xml",   quote_xml_func,   ‐1, SQLITE_UTF8 }, 
02494         { "export_xml",  export_xml_func,  ‐1, SQLITE_UTF8 }, 
02495         { "export_json", export_json_func, ‐1, SQLITE_UTF8 } 
02496     }; 
02497  
02498 #ifndef STANDALONE 
02499     if (api != NULL) { 
02500         SQLITE_EXTENSION_INIT2(api); 
02501     } 
02502 #endif 
02503  
02504     for (i = 0; i < sizeof (ftab) / sizeof (ftab[0]); i++) { 
02505         rc = sqlite3_create_function(db, ftab[i].name, ftab[i].nargs, 
02506                                      ftab[i].textrep, db, ftab[i].func, 0, 0); 
02507         if (rc != SQLITE_OK) { 
02508             for (‐‐i; i >= 0; ‐‐i) { 
02509                 sqlite3_create_function(db, ftab[i].name, ftab[i].nargs, 
02510                                         ftab[i].textrep, 0, 0, 0, 0); 
02511             } 
02512             break; 

02513         } 
http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 31/32
10/02/2017 impexp.c Source File

02513         } 
02514     } 
02515     return rc; 
02516 } 
02517  
02518 /* see doc in impexp.h */ 
02519  
02520 int 
02521 impexp_init(sqlite3 *db) 
02522 { 
02523     return sqlite3_extension_init(db, NULL, NULL); 
02524 } 

Generated on 1 Dec 2016 by doxygen.
Contact: chw@ch­werner.de

http://www.ch­werner.de/sqliteodbc/html/impexp_8c­source.html 32/32

You might also like