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)) {
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;
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) {
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     }
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";
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
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++] = ';';
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++] = '#';
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 */
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;
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;
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);
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:
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:
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);
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 {
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) {
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'");
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;
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;
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) {
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;
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 
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
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);
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                     }
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];
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);
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         }
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
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         }
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 23 Oct 2023 by doxygen.
Contact: chw@ch-werner.de