From: drh Date: Wed, 10 Jan 2018 16:50:18 +0000 (+0000) Subject: Implement the ".ar --create" command using a single X-Git-Tag: version-3.22.0~60^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=634c70fa1586565fe08a8f208691061cd36602dc;p=thirdparty%2Fsqlite.git Implement the ".ar --create" command using a single "REPLACE INTO sqlar SELECT ... FROM fsdir();" statement. Add the shell_putsnl() SQL function for providing --verbose output. FossilOrigin-Name: 28ab930436fea33c79073e84f39d9e381fa60b4702a5dcbfaaed72baeeae8431 --- diff --git a/manifest b/manifest index 2de51ed59b..dcc5c90bb1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"filetype()"\sSQL\sfunction\sfor\sinterpreting\sfile\smodes\sto\sthe\nfileio.c\sextension. -D 2018-01-10T15:53:06.284 +C Implement\sthe\s".ar\s--create"\scommand\susing\sa\ssingle\s\n"REPLACE\sINTO\ssqlar\sSELECT\s...\sFROM\sfsdir();"\sstatement.\s\sAdd\sthe\nshell_putsnl()\sSQL\sfunction\sfor\sproviding\s--verbose\soutput. +D 2018-01-10T16:50:18.954 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 12b6daa4bdb03fa87da27cbc205ff88ace645475b5be79414a3038b68ade14cb @@ -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 7d49ed78c6d8298d38d4733c3cc24f3a4230cd2f151564b7c11ab2e280007f9c +F src/shell.c.in f8ae3a792ba5ae09d6ad89845fc1cae75eb5b467f8534f654b8107b54e4aa81e F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 @@ -1697,7 +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 430d1a7daa823ae53606b7a158af4e7c16f62ff9b072b90606524e7c3f6131df -R 54a0e19016ae7cc0ce7d6a9a20dca28f +P 58c0c74c407d93f48930a4964b6cc48f008b522d193a62a559de0e6a319a8bd0 +R 6861922f8b8e02d4e242f42a1464e5df U drh -Z d67640218b4e3095d4e0ccc9365f61ee +Z dfee26c5de1e816e5523347d081a1560 diff --git a/manifest.uuid b/manifest.uuid index 91f7e865d7..398fb8a627 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -58c0c74c407d93f48930a4964b6cc48f008b522d193a62a559de0e6a319a8bd0 \ No newline at end of file +28ab930436fea33c79073e84f39d9e381fa60b4702a5dcbfaaed72baeeae8431 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 83b21b1663..80ca7305ec 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1135,6 +1135,22 @@ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ fflush(p->pLog); } +/* +** SQL function: shell_putsnl(X) +** +** Write the text X to the screen (or whatever output is being directed) +** adding a newline at the end, and then return X. +*/ +static void shellPutsFunc( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + ShellState *p = (ShellState*)sqlite3_user_data(pCtx); + utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); + sqlite3_result_value(pCtx, apVal[0]); +} + /* ** Output the given string as a hex-encoded blob (eg. X'1234' ) */ @@ -3307,6 +3323,8 @@ static void open_db(ShellState *p, int keepAlive){ shellAddSchemaName, 0, 0); sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, shellModuleSchema, 0, 0); + sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, + shellPutsFunc, 0, 0); if( p->openMode==SHELL_OPEN_ZIPFILE ){ char *zSql = sqlite3_mprintf( "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename); @@ -5008,7 +5026,6 @@ static int arCreateOrUpdateCommand( ArCommand *pAr, /* Command arguments and options */ int bUpdate /* true for a --create. false for --update */ ){ - const char *zSql = "SELECT name, mode, mtime, data FROM fsdir($name, $dir)"; const char *zCreate = "CREATE TABLE IF NOT EXISTS sqlar(\n" " name TEXT PRIMARY KEY, -- name of the file\n" @@ -5018,86 +5035,41 @@ static int arCreateOrUpdateCommand( " data BLOB -- compressed content\n" ")"; const char *zDrop = "DROP TABLE IF EXISTS sqlar"; - const char *zInsert = "REPLACE INTO sqlar VALUES(?,?,?,?,sqlar_compress(?))"; - - sqlite3_stmt *pStmt = 0; /* Directory traverser */ - sqlite3_stmt *pInsert = 0; /* Compilation of zInsert */ + const char *zInsertFmt = + "REPLACE INTO sqlar(name,mode,mtime,sz,data)\n" + " SELECT\n" + " %s,\n" + " mode,\n" + " mtime,\n" + " CASE filetype(mode)\n" + " WHEN 'file' THEN length(data)\n" + " WHEN 'directory' THEN 0\n" + " ELSE -1 END,\n" + " CASE WHEN filetype(mode)<>'directory' THEN data ELSE NULL END\n" + " FROM fsdir(%Q,%Q)\n" + " WHERE filetype(mode)<>'unknown'"; int i; /* For iterating through azFile[] */ - int j; /* Parameter index */ int rc; /* Return code */ - assert( pAr->bZip==0 ); - rc = arExecSql(pAr, "SAVEPOINT ar;"); if( rc!=SQLITE_OK ) return rc; - if( bUpdate==0 ){ rc = arExecSql(pAr, zDrop); if( rc!=SQLITE_OK ) return rc; } - rc = arExecSql(pAr, zCreate); - if( !pAr->bDryRun ){ - shellPrepare(pAr->db, &rc, zInsert, &pInsert); - } - shellPrepare(pAr->db, &rc, zSql, &pStmt); - j = sqlite3_bind_parameter_index(pStmt, "$dir"); - sqlite3_bind_text(pStmt, j, pAr->zDir, -1, SQLITE_STATIC); - if( pAr->bDryRun ){ - utf8_printf(pAr->p->out, "%s;\n", sqlite3_sql(pStmt)); - } - for(i=0; inArg && rc==SQLITE_OK; i++){ - j = sqlite3_bind_parameter_index(pStmt, "$name"); - sqlite3_bind_text(pStmt, j, pAr->azArg[i], -1, SQLITE_STATIC); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - int sz; - const char *zName = (const char*)sqlite3_column_text(pStmt, 0); - int mode = sqlite3_column_int(pStmt, 1); - unsigned int mtime = sqlite3_column_int(pStmt, 2); - - if( pAr->bVerbose ){ - utf8_printf(pAr->p->out, "%s\n", zName); - } - if( pAr->bDryRun ){ - utf8_printf(pAr->p->out, "%s;\n", zInsert); - continue; - } - - sqlite3_bind_text(pInsert, 1, zName, -1, SQLITE_STATIC); - sqlite3_bind_int(pInsert, 2, mode); - sqlite3_bind_int64(pInsert, 3, (sqlite3_int64)mtime); - - if( S_ISDIR(mode) ){ - sz = 0; - sqlite3_bind_null(pInsert, 5); - }else{ - sqlite3_bind_value(pInsert, 5, sqlite3_column_value(pStmt, 3)); - if( S_ISLNK(mode) ){ - sz = -1; - }else{ - sz = sqlite3_column_bytes(pStmt, 3); - } - } - - sqlite3_bind_int(pInsert, 4, sz); - if( pAr->bDryRun ){ - utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pInsert)); - }else{ - sqlite3_step(pInsert); - } - rc = sqlite3_reset(pInsert); - } - shellReset(&rc, pStmt); + char *zSql = sqlite3_mprintf(zInsertFmt, + pAr->bVerbose ? "shell_putsnl(name)" : "name", + pAr->azArg[i], pAr->zDir); + rc = arExecSql(pAr, zSql); + sqlite3_free(zSql); } - if( rc!=SQLITE_OK ){ arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;"); }else{ rc = arExecSql(pAr, "RELEASE ar;"); } - shellFinalize(&rc, pStmt); - shellFinalize(&rc, pInsert); return rc; } @@ -5161,7 +5133,9 @@ static int arDotCommand( #endif } if( cmd.zSrcTable==0 ){ - if( sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) ){ + if( cmd.eCmd!=AR_CMD_CREATE + && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) + ){ utf8_printf(stderr, "database does not contain an 'sqlar' table\n"); rc = SQLITE_ERROR; goto end_ar_command;