]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the built-in edit(VALUE) and edit(VALUE,EDITOR) function to the CLI.
authordrh <drh@noemail.net>
Thu, 11 Jan 2018 00:04:00 +0000 (00:04 +0000)
committerdrh <drh@noemail.net>
Thu, 11 Jan 2018 00:04:00 +0000 (00:04 +0000)
FossilOrigin-Name: ef823c47a0ac4f3b001e6c89c38354b45b5229d872cfc69a29c82e99414b89c8

manifest
manifest.uuid
src/shell.c.in

index 18f1e54d50bc774c979b1c145d39dadba8d284e2..f1234ab3408ccd0a73138686574ad9b7fe3a03e7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\s".once\s-e"\sand\s".once\s-x"\scommands\sto\sthe\sCLI,\sand\sthe\s".excel"\scommand\nthat\sis\san\salias\sfor\s".once\s-x".
-D 2018-01-10T23:29:42.447
+C Add\sthe\sbuilt-in\sedit(VALUE)\sand\sedit(VALUE,EDITOR)\sfunction\sto\sthe\sCLI.
+D 2018-01-11T00:04:00.842
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
@@ -484,7 +484,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
-F src/shell.c.in 0baa3d017e3e46ed935413f7e8d09b8c77a8f870c84cf8b2d8b81528517bf485
+F src/shell.c.in 52aef9f2f61915c9226d6ff87444102b744a48e7b001e50d88d262fed3526030
 F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
@@ -1697,8 +1697,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 60c694c1ab26a7a096f17ccea5a93ecda0f9f2113ab5fdc8b17dbffc787724fc fbf5e43c07e7c012cb39b33a74b3fab9e46ba946c48497fbd990110692125f57
-R cbc8182064251451cd032585a1a8098f
-T +closed fbf5e43c07e7c012cb39b33a74b3fab9e46ba946c48497fbd990110692125f57
+P a6ed5ab9bc9741267fd1207e63b4c49d074291085c7e3f25e9f62a82f916a656
+R 178e506824f095711305ed729320460e
 U drh
-Z c9d5887fceb0e0e24e4f6ea11d33b5eb
+Z c1ee7e4e075a7abb60497a235dd7f461
index ff97541f24744e2ebe7c0ef76fb53ea5f1f6ef2c..07d9f13bed64a4e27e36e817e83811952c92990c 100644 (file)
@@ -1 +1 @@
-a6ed5ab9bc9741267fd1207e63b4c49d074291085c7e3f25e9f62a82f916a656
\ No newline at end of file
+ef823c47a0ac4f3b001e6c89c38354b45b5229d872cfc69a29c82e99414b89c8
\ No newline at end of file
index e9c268e42ab05771057fba90dd34109e983d8c7b..e03eebd0427dfe0e325104b550a3dd6f64710fd6 100644 (file)
@@ -1156,6 +1156,132 @@ static void shellPutsFunc(
   sqlite3_result_value(pCtx, apVal[0]);
 }
 
+/*
+** SQL function:   edit(VALUE)
+**                 edit(VALUE,EDITOR)
+**
+** These steps:
+**
+**     (1) Write VALUE into a temporary file.
+**     (2) Run program EDITOR on that temporary file.
+**     (3) Read the temporary file back and return its content as the result.
+**     (4) Delete the temporary file
+**
+** If the EDITOR argument is omitted, use the value in the VISUAL
+** environment variable.  If still there is no EDITOR, through an error.
+**
+** Also throw an error if the EDITOR program returns a non-zero exit code.
+*/
+static void editFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zEditor;
+  char *zTempFile = 0;
+  sqlite3 *db;
+  char *zCmd = 0;
+  int bBin;
+  int rc;
+  FILE *f = 0;
+  sqlite3_int64 sz;
+  sqlite3_int64 x;
+  unsigned char *p = 0;
+
+  if( argc==2 ){
+    zEditor = (const char*)sqlite3_value_text(argv[1]);
+  }else{
+    zEditor = getenv("VISUAL");
+  }
+  if( zEditor==0 ){
+    sqlite3_result_error(context, "no editor for edit()", -1);
+    return;
+  }
+  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
+    sqlite3_result_error(context, "NULL input to edit()", -1);
+    return;
+  }
+  db = sqlite3_context_db_handle(context);
+  zTempFile = 0;
+  sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
+  if( zTempFile==0 ){
+    sqlite3_uint64 r = 0;
+    sqlite3_randomness(sizeof(r), &r);
+    zTempFile = sqlite3_mprintf("temp%llx", r);
+    if( zTempFile==0 ){
+      sqlite3_result_error_nomem(context);
+      return;
+    }
+  }
+  bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
+  f = fopen(zTempFile, bBin ? "wb" : "w");
+  if( f==0 ){
+    sqlite3_result_error(context, "edit() cannot open temp file", -1);
+    goto edit_func_end;
+  }
+  sz = sqlite3_value_bytes(argv[0]);
+  if( bBin ){
+    x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);
+  }else{
+    x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);
+  }
+  fclose(f);
+  f = 0;
+  if( x!=sz ){
+    sqlite3_result_error(context, "edit() could not write the whole file", -1);
+    goto edit_func_end;
+  }
+  zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
+  if( zCmd==0 ){
+    sqlite3_result_error_nomem(context);
+    goto edit_func_end;
+  }
+  rc = system(zCmd);
+  sqlite3_free(zCmd);
+  if( rc ){
+    sqlite3_result_error(context, "EDITOR returned non-zero", -1);
+    goto edit_func_end;
+  }
+  f = fopen(zTempFile, bBin ? "rb" : "r");
+  if( f==0 ){
+    sqlite3_result_error(context,
+      "edit() cannot reopen temp file after edit", -1);
+    goto edit_func_end;
+  }
+  fseek(f, 0, SEEK_END);
+  sz = ftell(f);
+  rewind(f);
+  p = sqlite3_malloc64( sz+(bBin==0) );
+  if( p==0 ){
+    sqlite3_result_error_nomem(context);
+    goto edit_func_end;
+  }
+  if( bBin ){
+    x = fread(p, 1, sz, f);
+  }else{
+    x = fread(p, 1, sz, f);
+    p[sz] = 0;
+  }
+  fclose(f);
+  f = 0;
+  if( x!=sz ){
+    sqlite3_result_error(context, "could not read back the whole file", -1);
+    goto edit_func_end;
+  }
+  if( bBin ){
+    sqlite3_result_blob(context, p, sz, sqlite3_free);
+  }else{
+    sqlite3_result_text(context, (const char*)p, sz, sqlite3_free);
+  }
+  p = 0;
+
+edit_func_end:
+  if( f ) fclose(f);
+  unlink(zTempFile);
+  sqlite3_free(zTempFile);
+  sqlite3_free(p);
+}
+
 /*
 ** Save or restore the current output mode
 */
@@ -3345,6 +3471,10 @@ static void open_db(ShellState *p, int keepAlive){
                             shellModuleSchema, 0, 0);
     sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
                             shellPutsFunc, 0, 0);
+    sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
+                            editFunc, 0, 0);
+    sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
+                            editFunc, 0, 0);
     if( p->openMode==SHELL_OPEN_ZIPFILE ){
       char *zSql = sqlite3_mprintf(
          "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);