Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add the --preserve-rowids option to the ".dump" command in the CLI. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c60aee24714a47ce12ee2a4dcefb9f55 |
User & Date: | drh 2017-03-08 11:44:00.069 |
Context
2017-03-08
| ||
12:25 | In the CLI, avoid unnecessary identifier quoting in the ".dump" output. Also add new ".dump" test cases. (check-in: de65f90761 user: drh tags: trunk) | |
11:44 | Add the --preserve-rowids option to the ".dump" command in the CLI. (check-in: c60aee2471 user: drh tags: trunk) | |
2017-03-07
| ||
20:03 | Add test script ext/rbu/rbu_round_trip.tcl. Uses "dbselftest" to test that "rbu" and "sqldiff" work together. (check-in: 961e79da73 user: dan tags: trunk) | |
Changes
Changes to src/shell.c.
︙ | ︙ | |||
450 451 452 453 454 455 456 | if( *z=='+' || *z=='-' ) z++; if( !IsDigit(*z) ) return 0; while( IsDigit(*z) ){ z++; } if( realnum ) *realnum = 1; } return *z==0; } | < < < < < < < < < < < < < < < < < < < < < < | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | if( *z=='+' || *z=='-' ) z++; if( !IsDigit(*z) ) return 0; while( IsDigit(*z) ){ z++; } if( realnum ) *realnum = 1; } return *z==0; } /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. */ static int strlen30(const char *z){ const char *z2 = z; |
︙ | ︙ | |||
614 615 616 617 618 619 620 621 622 623 624 625 626 627 | int autoExplain; /* Automatically turn on .explain mode */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ int scanstatsOn; /* True to display scan stats before each finalize */ int countChanges; /* True to display change counts */ int backslashOn; /* Resolve C-style \x escapes in SQL input text */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int cMode; /* temporary output mode for the current query */ int normalMode; /* Output mode before ".explain on" */ | > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | int autoExplain; /* Automatically turn on .explain mode */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ int scanstatsOn; /* True to display scan stats before each finalize */ int countChanges; /* True to display change counts */ int backslashOn; /* Resolve C-style \x escapes in SQL input text */ int outCount; /* Revert to stdout when reaching zero */ int preserveRowid; /* Preserver ROWID values on a ".dump" command */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int cMode; /* temporary output mode for the current query */ int normalMode; /* Output mode before ".explain on" */ |
︙ | ︙ | |||
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 | for(i=0; zName[i]; i++){ z[n++] = zName[i]; if( zName[i]=='\'' ) z[n++] = '\''; } if( needQuote ) z[n++] = '\''; z[n] = 0; } /* zIn is either a pointer to a NULL-terminated string in memory obtained ** from malloc(), or a NULL pointer. The string pointed to by zAppend is ** added to zIn, and the result returned in memory obtained from malloc(). ** zIn, if it was not NULL, is freed. ** ** If the third argument, quote, is not '\0', then it is used as a ** quote character for zAppend. */ | > > > > > > > > > > | < | > > | | > | > | > | < | > | < < | 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 | for(i=0; zName[i]; i++){ z[n++] = zName[i]; if( zName[i]=='\'' ) z[n++] = '\''; } if( needQuote ) z[n++] = '\''; z[n] = 0; } /* ** A variable length string to which one can append text. */ typedef struct ShellString ShellString; struct ShellString { char *z; int n; int nAlloc; }; /* zIn is either a pointer to a NULL-terminated string in memory obtained ** from malloc(), or a NULL pointer. The string pointed to by zAppend is ** added to zIn, and the result returned in memory obtained from malloc(). ** zIn, if it was not NULL, is freed. ** ** If the third argument, quote, is not '\0', then it is used as a ** quote character for zAppend. */ static void appendText(ShellString *p, char const *zAppend, char quote){ int len; int i; int nAppend = strlen30(zAppend); len = nAppend+p->n+1; if( quote ){ len += 2; for(i=0; i<nAppend; i++){ if( zAppend[i]==quote ) len++; } } if( p->n+len>=p->nAlloc ){ p->nAlloc = p->nAlloc*2 + len + 20; p->z = realloc(p->z, p->nAlloc); if( p->z==0 ){ memset(p, 0, sizeof(*p)); return; } } if( quote ){ char *zCsr = p->z+p->n; *zCsr++ = quote; for(i=0; i<nAppend; i++){ *zCsr++ = zAppend[i]; if( zAppend[i]==quote ) *zCsr++ = quote; } *zCsr++ = quote; p->n = (int)(zCsr - p->z); *zCsr = '\0'; }else{ memcpy(p->z+p->n, zAppend, nAppend); p->n += nAppend; p->z[p->n] = '\0'; } } /* ** Execute a query statement that will generate SQL output. Print ** the result columns, comma-separated, on a line and then add a ** semicolon terminator to the end of that line. |
︙ | ︙ | |||
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 | } } } /* end while */ return rc; } /* ** This is a different callback routine used for dumping the database. ** Each row received by this callback consists of a table name, ** the table type ("index" or "table") and SQL to create the table. ** This routine should print text sufficient to recreate the table. */ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ int rc; const char *zTable; const char *zType; const char *zSql; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | | 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 | } } } /* end while */ return rc; } /* ** Release memory previously allocated by tableColumnList(). */ static void freeColumnList(char **azCol){ int i; for(i=1; azCol[i]; i++){ sqlite3_free(azCol[i]); } /* azCol[0] is a static string */ sqlite3_free(azCol); } /* ** Return a list of pointers to strings which are the names of all ** columns in table zTab. The memory to hold the names is dynamically ** allocated and must be released by the caller using a subsequent call ** to freeColumnList(). ** ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid ** value that needs to be preserved, then azCol[0] is filled in with the ** name of the rowid column. ** ** The first regular column in the table is azCol[1]. The list is terminated ** by an entry with azCol[i]==0. */ static char **tableColumnList(ShellState *p, const char *zTab){ char **azCol = 0; sqlite3_stmt *pStmt; char *zSql; int nCol = 0; int nAlloc = 0; int nPK = 0; /* Number of PRIMARY KEY columns seen */ int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */ int preserveRowid = p->preserveRowid; int rc; zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ) return 0; while( sqlite3_step(pStmt)==SQLITE_ROW ){ if( nCol>=nAlloc-2 ){ nAlloc = nAlloc*2 + nCol + 10; azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); if( azCol==0 ){ raw_printf(stderr, "Error: out of memory\n"); exit(1); } } azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); if( sqlite3_column_int(pStmt, 5) ){ nPK++; if( nPK==1 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), "INTEGER")==0 ){ isIPK = 1; }else{ isIPK = 0; } } } sqlite3_finalize(pStmt); azCol[0] = 0; azCol[nCol+1] = 0; /* The decision of whether or not a rowid really needs to be preserved ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve ** rowids on tables where the rowid is inaccessible because there are other ** columns in the table named "rowid", "_rowid_", and "oid". */ if( preserveRowid && isIPK ){ /* If a single PRIMARY KEY column with type INTEGER was seen, then it ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID ** table or a INTEGER PRIMARY KEY DESC column, neither of which are ** ROWID aliases. To distinguish these cases, check to see if ** there is a "pk" entry in "PRAGMA index_list". There will be ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID. */ zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)" " WHERE origin='pk'", zTab); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ){ freeColumnList(azCol); return 0; } rc = sqlite3_step(pStmt); sqlite3_finalize(pStmt); preserveRowid = rc==SQLITE_ROW; } if( preserveRowid ){ /* Only preserve the rowid if we can find a name to use for the ** rowid */ static char *azRowid[] = { "rowid", "_rowid_", "oid" }; int i, j; for(j=0; j<3; j++){ for(i=1; i<=nCol; i++){ if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break; } if( i>nCol ){ /* At this point, we know that azRowid[j] is not the name of any ** ordinary column in the table. Verify that azRowid[j] is a valid ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID ** tables will fail this last check */ int rc; rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0); if( rc==SQLITE_OK ) azCol[0] = azRowid[j]; break; } } } return azCol; } /* ** This is a different callback routine used for dumping the database. ** Each row received by this callback consists of a table name, ** the table type ("index" or "table") and SQL to create the table. ** This routine should print text sufficient to recreate the table. */ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ int rc; const char *zTable; const char *zType; const char *zSql; ShellState *p = (ShellState *)pArg; UNUSED_PARAMETER(azCol); if( nArg!=3 ) return 1; zTable = azArg[0]; zType = azArg[1]; zSql = azArg[2]; if( strcmp(zTable, "sqlite_sequence")==0 ){ raw_printf(p->out, "DELETE FROM sqlite_sequence;\n"); }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ raw_printf(p->out, "ANALYZE sqlite_master;\n"); }else if( strncmp(zTable, "sqlite_", 7)==0 ){ return 0; }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ char *zIns; if( !p->writableSchema ){ |
︙ | ︙ | |||
2065 2066 2067 2068 2069 2070 2071 | sqlite3_free(zIns); return 0; }else{ printSchemaLine(p->out, zSql, ";\n"); } if( strcmp(zType, "table")==0 ){ | < | | | | | < < < > < | | > | < > | > > > > | | < > > > > | | > | < < > | | < | | < | | | > > > | < < < < > | | | | > > | > > | < | > | 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 | sqlite3_free(zIns); return 0; }else{ printSchemaLine(p->out, zSql, ";\n"); } if( strcmp(zType, "table")==0 ){ ShellString sSelect; ShellString sTable; char **azCol; int i; char *savedDestTable; int savedMode; azCol = tableColumnList(p, zTable); if( azCol==0 ){ p->nErr++; return 0; } /* Always quote the table name, even if it appears to be pure ascii, ** in case it is a keyword. Ex: INSERT INTO "table" ... */ memset(&sTable, 0, sizeof(sTable)); appendText(&sTable, zTable, '"'); /* If preserving the rowid, add a column list after the table name. ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)" ** instead of the usual "INSERT INTO tab VALUES(...)". */ if( azCol[0] ){ appendText(&sTable, "(", 0); appendText(&sTable, azCol[0], 0); for(i=1; azCol[i]; i++){ appendText(&sTable, ",", 0); appendText(&sTable, azCol[i], '"'); } appendText(&sTable, ")", 0); } /* Build an appropriate SELECT statement */ memset(&sSelect, 0, sizeof(sSelect)); appendText(&sSelect, "SELECT ", 0); if( azCol[0] ){ appendText(&sSelect, azCol[0], 0); appendText(&sSelect, ",", 0); } for(i=1; azCol[i]; i++){ appendText(&sSelect, azCol[i], 0); if( azCol[i+1] ){ appendText(&sSelect, ",", 0); } } freeColumnList(azCol); appendText(&sSelect, " FROM ", 0); appendText(&sSelect, zTable, '"'); savedDestTable = p->zDestTable; savedMode = p->mode; p->zDestTable = sTable.z; p->mode = p->cMode = MODE_Insert; rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0); p->zDestTable = savedDestTable; p->mode = savedMode; free(sTable.z); free(sSelect.z); if( rc ) p->nErr++; } return 0; } /* ** Run zQuery. Use dump_callback() as the callback routine so that ** the contents of the query are output as SQL statements. |
︙ | ︙ | |||
2421 2422 2423 2424 2425 2426 2427 | ** the database fails to open, print an error message and exit. */ static void open_db(ShellState *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); globalDb = p->db; | < < < < | 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 | ** the database fails to open, print an error message and exit. */ static void open_db(ShellState *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); globalDb = p->db; if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", p->zDbFilename, sqlite3_errmsg(p->db)); if( keepAlive ) return; exit(1); } #ifndef SQLITE_OMIT_LOAD_EXTENSION |
︙ | ︙ | |||
3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 | }else if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ rc = shell_dbinfo_command(p, nArg, azArg); }else if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ open_db(p, 0); /* When playing back a "dump", the content might appear in an order ** which causes immediate foreign key constraints to be violated. ** So disable foreign-key constraint enforcement to prevent problems. */ | > > > > > > > > > > > > > > > > > > > > > > > < < < < < > > > | | < | < | | | | > > | | | | | | < | 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 | }else if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ rc = shell_dbinfo_command(p, nArg, azArg); }else if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ const char *zLike = 0; int i; p->preserveRowid = 0; for(i=1; i<nArg; i++){ if( azArg[i][0]=='-' ){ const char *z = azArg[i]+1; if( z[0]=='-' ) z++; if( strcmp(z,"preserve-rowids")==0 ){ p->preserveRowid = 1; }else { raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]); rc = 1; goto meta_command_exit; } }else if( zLike ){ raw_printf(stderr, "Usage: .dump ?--preserve-rowids? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; }else{ zLike = azArg[i]; } } open_db(p, 0); /* When playing back a "dump", the content might appear in an order ** which causes immediate foreign key constraints to be violated. ** So disable foreign-key constraint enforcement to prevent problems. */ raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); raw_printf(p->out, "BEGIN TRANSACTION;\n"); p->writableSchema = 0; /* Set writable_schema=ON since doing so forces SQLite to initialize ** as much of the schema as it can even if the sqlite_master table is ** corrupt. */ sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); p->nErr = 0; if( zLike==0 ){ run_schema_dump_query(p, "SELECT name, type, sql FROM sqlite_master " "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" ); run_schema_dump_query(p, "SELECT name, type, sql FROM sqlite_master " "WHERE name=='sqlite_sequence'" ); run_table_dump_query(p, "SELECT sql FROM sqlite_master " "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 ); }else{ char *zSql; zSql = sqlite3_mprintf( "SELECT name, type, sql FROM sqlite_master " "WHERE tbl_name LIKE %Q AND type=='table'" " AND sql NOT NULL", zLike); run_schema_dump_query(p,zSql); sqlite3_free(zSql); zSql = sqlite3_mprintf( "SELECT sql FROM sqlite_master " "WHERE sql NOT NULL" " AND type IN ('index','trigger','view')" " AND tbl_name LIKE %Q", zLike); run_table_dump_query(p, zSql, 0); sqlite3_free(zSql); } if( p->writableSchema ){ raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); p->writableSchema = 0; } sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); |
︙ | ︙ | |||
4570 4571 4572 4573 4574 4575 4576 | ")"; new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); rc = SQLITE_OK; }else{ | | | | | | | | 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 | ")"; new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); rc = SQLITE_OK; }else{ char *zSql; zSql = sqlite3_mprintf( "SELECT sql FROM " " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " "WHERE lower(tbl_name) LIKE %Q" " AND type!='meta' AND sql NOTNULL " "ORDER BY rowid", azArg[1]); rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg); sqlite3_free(zSql); } }else if( nArg==1 ){ rc = sqlite3_exec(p->db, "SELECT sql FROM " " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
︙ | ︙ |
Changes to test/shell1.test.
︙ | ︙ | |||
296 297 298 299 300 301 302 | set res [catchcmd "test.db" ".dump FOO"] list [regexp {BEGIN TRANSACTION;} $res] \ [regexp {COMMIT;} $res] } {1 1} do_test shell1-3.4.3 { # too many arguments catchcmd "test.db" ".dump FOO BAD" | | | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | set res [catchcmd "test.db" ".dump FOO"] list [regexp {BEGIN TRANSACTION;} $res] \ [regexp {COMMIT;} $res] } {1 1} do_test shell1-3.4.3 { # too many arguments catchcmd "test.db" ".dump FOO BAD" } {1 {Usage: .dump ?--preserve-rowids? ?LIKE-PATTERN?}} # .echo ON|OFF Turn command echo on or off do_test shell1-3.5.1 { catchcmd "test.db" ".echo" } {1 {Usage: .echo on|off}} do_test shell1-3.5.2 { catchcmd "test.db" ".echo ON" |
︙ | ︙ | |||
741 742 743 744 745 746 747 | BEGIN TRANSACTION; CREATE TABLE t1(x); INSERT INTO "t1" VALUES(NULL); INSERT INTO "t1" VALUES(''); INSERT INTO "t1" VALUES(1); INSERT INTO "t1" VALUES(2.25); INSERT INTO "t1" VALUES('hello'); | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 | BEGIN TRANSACTION; CREATE TABLE t1(x); INSERT INTO "t1" VALUES(NULL); INSERT INTO "t1" VALUES(''); INSERT INTO "t1" VALUES(1); INSERT INTO "t1" VALUES(2.25); INSERT INTO "t1" VALUES('hello'); INSERT INTO "t1" VALUES(X'807f'); CREATE TABLE t3(x,y); INSERT INTO "t3" VALUES(1,NULL); INSERT INTO "t3" VALUES(2,''); INSERT INTO "t3" VALUES(3,1); INSERT INTO "t3" VALUES(4,2.25); INSERT INTO "t3" VALUES(5,'hello'); INSERT INTO "t3" VALUES(6,X'807f'); COMMIT;}} do_test shell1-4.1.1 { catchcmd test.db {.dump --preserve-rowids} } {0 {PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE t1(x); INSERT INTO "t1"(rowid,"x") VALUES(1,NULL); INSERT INTO "t1"(rowid,"x") VALUES(2,''); INSERT INTO "t1"(rowid,"x") VALUES(3,1); INSERT INTO "t1"(rowid,"x") VALUES(4,2.25); INSERT INTO "t1"(rowid,"x") VALUES(5,'hello'); INSERT INTO "t1"(rowid,"x") VALUES(6,X'807f'); CREATE TABLE t3(x,y); INSERT INTO "t3"(rowid,"x","y") VALUES(1,1,NULL); INSERT INTO "t3"(rowid,"x","y") VALUES(2,2,''); INSERT INTO "t3"(rowid,"x","y") VALUES(3,3,1); INSERT INTO "t3"(rowid,"x","y") VALUES(4,4,2.25); INSERT INTO "t3"(rowid,"x","y") VALUES(5,5,'hello'); INSERT INTO "t3"(rowid,"x","y") VALUES(6,6,X'807f'); COMMIT;}} do_test shell1-4.1.2 { db close forcedelete test2.db sqlite3 db test2.db db eval { CREATE TABLE t1(x INTEGER PRIMARY KEY, y); INSERT INTO t1 VALUES(1,null), (2,''), (3,1), (4,2.25), (5,'hello'), (6,x'807f'); } catchcmd test2.db {.dump --preserve-rowids} } {0 {PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE t1(x INTEGER PRIMARY KEY, y); INSERT INTO "t1" VALUES(1,NULL); INSERT INTO "t1" VALUES(2,''); INSERT INTO "t1" VALUES(3,1); INSERT INTO "t1" VALUES(4,2.25); INSERT INTO "t1" VALUES(5,'hello'); INSERT INTO "t1" VALUES(6,X'807f'); COMMIT;}} # Test the output of ".mode insert" # do_test shell1-4.2.1 { catchcmd test.db ".mode insert t1\nselect * from t1;" } {0 {INSERT INTO t1 VALUES(NULL); INSERT INTO t1 VALUES(''); |
︙ | ︙ |