]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the ".import" command in the CLI so that it works correctly with tables
authordrh <>
Mon, 11 Mar 2024 11:26:20 +0000 (11:26 +0000)
committerdrh <>
Mon, 11 Mar 2024 11:26:20 +0000 (11:26 +0000)
that contain computed columns.

FossilOrigin-Name: b26f24441f84a30deb9a562ab6c6de7543fbc3b3b93c34277964c9c21d734153

manifest
manifest.uuid
src/shell.c.in
test/shell5.test

index 20415c74564c7354af9b850a2168a848527dfa00..ad892d5099f992b5987fe508aea088a111fc63c8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Reenable\sthe\suse\sof\sSQLITE_OMIT_VIRTUALTABLE\sby\sfixing\na\smisplaced\s#endif\scaused\sby\sthe\smerge\sat\s[c080560c2d0d753c].
-D 2024-03-09T13:17:12.892
+C Fix\sthe\s".import"\scommand\sin\sthe\sCLI\sso\sthat\sit\sworks\scorrectly\swith\stables\nthat\scontain\scomputed\scolumns.
+D 2024-03-11T11:26:20.409
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -739,7 +739,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 446bcb8ebf0ea7066c2ca99e5336f0dbc9230ac76f80fafd1bfa82fe7871af2d
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c f1a81ff4f8e9e76c224e2ab3a4baa799add0db22158c7fcede65d8cc4a6fa2da
-F src/shell.c.in c7e7e4812515403e5236c199859d9d87e8d4d25a65516eaede9f522726d16ce0
+F src/shell.c.in f7cc8711aee604bc078a93d777ad7246980485c57fa3047408b0f842ba03c14d
 F src/sqlite.h.in 020d7b7307dda51420dc48b47e5334eaface77baba6bd9818375d392eb3ab5b5
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
@@ -1587,7 +1587,7 @@ F test/shell1.test c7127a5e780ffc9e14c476773127fdf292c6db226529c44c1676f37b37931
 F test/shell2.test 35226c070a8c7f64fd016dfac2a0db2a40f709b3131f61daacd9dad61536c9cb
 F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
 F test/shell4.test 947029e5a9efae9054d424b309fc0311439c0c3a0866ebfa3b8a771120708220
-F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
+F test/shell5.test 263bfd6a49049295277e3f5bdc221390dc5e72f39954b23d43204ed81993304f
 F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
 F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
 F test/shell8.test 3fd093d481aaa94dc77fb73f1044c1f19c7efe3477a395cc4f7450133bc54915
@@ -2160,8 +2160,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 111b3d8270db4f61efd9f4c02636f50e44bd9547261d1d922de2708bc7a07151
-R 28a2f964bc69438d93f9129c1b7b165e
+P 71120ea83783ee04c6dd9ef260f6ec528935b5ea3baf2348c6d5ec258093271b
+Q +95a9c88b258f18ac671a4c712603931167cc8bd0b86e41481b200c08043338b5
+R 7ba5ef65daab2c3aa274d6b8c040cb14
 U drh
-Z 2fb59d7cf4bcc6ddaf8b976ecd57985d
+Z a93afaa14e992589b98ee64c5f704190
 # Remove this line to create a well-formed Fossil manifest.
index cfce0a2531e8df7c6763fbd7fc674c0a7f2c75b4..3a60248f8bc1b87777aebdccca7b558501996d33 100644 (file)
@@ -1 +1 @@
-71120ea83783ee04c6dd9ef260f6ec528935b5ea3baf2348c6d5ec258093271b
\ No newline at end of file
+b26f24441f84a30deb9a562ab6c6de7543fbc3b3b93c34277964c9c21d734153
\ No newline at end of file
index 861e60997cbf363089947a494fbbdc5defa8a074..8ee0dd2e72f7628cead7510df1939f78aab634d6 100644 (file)
@@ -8698,16 +8698,15 @@ static int do_meta_command(char *zLine, ShellState *p){
 #ifndef SQLITE_SHELL_FIDDLE
   if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
     char *zTable = 0;           /* Insert data into this table */
-    char *zSchema = 0;          /* within this schema (may default to "main") */
+    char *zSchema = 0;          /* Schema of zTable */
     char *zFile = 0;            /* Name of file to extra content from */
     sqlite3_stmt *pStmt = NULL; /* A statement */
     int nCol;                   /* Number of columns in the table */
-    int nByte;                  /* Number of bytes in an SQL string */
+    i64 nByte;                  /* Number of bytes in an SQL string */
     int i, j;                   /* Loop counters */
     int needCommit;             /* True to COMMIT or ROLLBACK at end */
     int nSep;                   /* Number of bytes in p->colSeparator[] */
-    char *zSql;                 /* An SQL statement */
-    char *zFullTabName;         /* Table name with schema if applicable */
+    char *zSql = 0;             /* An SQL statement */
     ImportCtx sCtx;             /* Reader context */
     char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
     int eVerbose = 0;           /* Larger for more console output */
@@ -8841,24 +8840,14 @@ static int do_meta_command(char *zLine, ShellState *p){
     while( (nSkip--)>0 ){
       while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
     }
-    if( zSchema!=0 ){
-      zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
-    }else{
-      zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
-    }
-    zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
-    if( zSql==0 || zFullTabName==0 ){
-      import_cleanup(&sCtx);
-      shell_out_of_memory();
-    }
-    nByte = strlen30(zSql);
-    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
-    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
+    if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) ){
+      /* Table does not exist.  Create it. */
       sqlite3 *dbCols = 0;
       char *zRenames = 0;
       char *zColDefs;
-      zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
+      zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", 
+                    zSchema ? zSchema : "main", zTable);
       while( xRead(&sCtx) ){
         zAutoColumn(sCtx.z, &dbCols, 0);
         if( sCtx.cTerm!=sCtx.cColSep ) break;
@@ -8873,34 +8862,50 @@ static int do_meta_command(char *zLine, ShellState *p){
       assert(dbCols==0);
       if( zColDefs==0 ){
         eputf("%s: empty file\n", sCtx.zFile);
-      import_fail:
-        sqlite3_free(zCreate);
-        sqlite3_free(zSql);
-        sqlite3_free(zFullTabName);
         import_cleanup(&sCtx);
         rc = 1;
         goto meta_command_exit;
       }
       zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
+      if( zCreate==0 ){
+        import_cleanup(&sCtx);
+        shell_out_of_memory();
+      }
       if( eVerbose>=1 ){
         oputf("%s\n", zCreate);
       }
       rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
+      sqlite3_free(zCreate);
+      zCreate = 0;
       if( rc ){
         eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
-        goto import_fail;
+        import_cleanup(&sCtx);
+        rc = 1;
+        goto meta_command_exit;
       }
-      sqlite3_free(zCreate);
-      zCreate = 0;
-      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     }
+    zSql = sqlite3_mprintf("SELECT count(*) FROM pragma_table_info(%Q,%Q);",
+                           zTable, zSchema);
+    if( zSql==0 ){
+      import_cleanup(&sCtx);
+      shell_out_of_memory();
+    }
+    nByte = strlen(zSql);    
+    rc =  sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+    sqlite3_free(zSql);
+    zSql = 0;
     if( rc ){
       if (pStmt) sqlite3_finalize(pStmt);
       eputf("Error: %s\n", sqlite3_errmsg(p->db));
-      goto import_fail;
+      import_cleanup(&sCtx);
+      rc = 1;
+      goto meta_command_exit;
+    }
+    if( sqlite3_step(pStmt)==SQLITE_ROW ){
+      nCol = sqlite3_column_int(pStmt, 0);
+    }else{
+      nCol = 0;
     }
-    sqlite3_free(zSql);
-    nCol = sqlite3_column_count(pStmt);
     sqlite3_finalize(pStmt);
     pStmt = 0;
     if( nCol==0 ) return 0; /* no columns, no error */
@@ -8909,7 +8914,12 @@ static int do_meta_command(char *zLine, ShellState *p){
       import_cleanup(&sCtx);
       shell_out_of_memory();
     }
-    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
+    if( zSchema ){
+      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?", 
+                       zSchema, zTable);
+    }else{
+      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
+    }
     j = strlen30(zSql);
     for(i=1; i<nCol; i++){
       zSql[j++] = ',';
@@ -8921,13 +8931,15 @@ static int do_meta_command(char *zLine, ShellState *p){
       oputf("Insert using: %s\n", zSql);
     }
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+    sqlite3_free(zSql);
+    zSql = 0;
     if( rc ){
       eputf("Error: %s\n", sqlite3_errmsg(p->db));
       if (pStmt) sqlite3_finalize(pStmt);
-      goto import_fail;
+      import_cleanup(&sCtx);
+      rc = 1;
+      goto meta_command_exit;
     }
-    sqlite3_free(zSql);
-    sqlite3_free(zFullTabName);
     needCommit = sqlite3_get_autocommit(p->db);
     if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
     do{
index 39018a0ce9bc7f38324848ad6cf690f16d540b52..20f2ba219d4ded5289c3432a882a4f4541926eb3 100644 (file)
@@ -570,4 +570,18 @@ SELECT * FROM t1;}
 } {0 {    1 = あい
     2 = うえお}}
 
+# 2024-03-11 https://sqlite.org/forum/forumpost/ca014d7358
+# Import into a table that contains computed columns.
+#
+do_test shell5-7.1 {
+  set out [open shell5.csv w]
+  fconfigure $out -translation lf
+  puts $out {aaa|bbb}
+  close $out
+  forcedelete test.db
+  catchcmd :memory: {CREATE TABLE t1(a TEXT, b TEXT, c AS (a||b));
+.import shell5.csv t1
+SELECT * FROM t1;}
+} {0 aaa|bbb|aaabbb}
+
 finish_test