-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
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
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
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' )
*/
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);
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"
" 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; i<pAr->nArg && 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;
}
#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;