# HG changeset patch # User František Kučera # Date 1571753096 -7200 # Node ID 0b38339b871b9e13dc9b0cbd9199c4063e936120 # Parent ccf19c7e7adfcd37fd7d5e8b3aa8355f4330f05f improve --keep-file option: default is auto = file will be kept, if it was present before the transformation diff -r ccf19c7e7adf -r 0b38339b871b src/CLIParser.h --- a/src/CLIParser.h Tue Oct 22 16:04:23 2019 +0200 +++ b/src/CLIParser.h Tue Oct 22 16:04:56 2019 +0200 @@ -70,7 +70,11 @@ } else if (option == OPTION_FILE) { c.file = readNext(arguments, i); } else if (option == OPTION_KEEP_FILE) { - c.keepFile = true; + string_t value = readNext(arguments, i); + if (value == L"auto") c.keepFile = KeepFile::Automatic; + else if (value == L"true") c.keepFile = KeepFile::Always; + else if (value == L"false") c.keepFile = KeepFile::Never; + else throw relpipe::cli::RelpipeCLIException(L"Unsupported keep-file value: " + value + L" Expecting: true, false, auto", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); } else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); } addQuery(c, currentQuery); // last relation diff -r ccf19c7e7adf -r 0b38339b871b src/Configuration.h --- a/src/Configuration.h Tue Oct 22 16:04:23 2019 +0200 +++ b/src/Configuration.h Tue Oct 22 16:04:56 2019 +0200 @@ -49,6 +49,15 @@ std::vector parameters; }; +enum class KeepFile { + /** The file will be kept even if it was created during this transformation, so all the input data will stay on the disk. */ + Always, + /** The file will be deleted at the end of this transformation – even if the file already existed. This is potentially dangerous, because we can unintentionally delete a database file. */ + Never, + /** The file will be kept only if it was already present before the transformation. */ + Automatic +}; + class Configuration { public: @@ -61,9 +70,9 @@ relpipe::writer::string_t file; /** - * If true, the file (if any was created) will not be deleted when this transformation finishes. + * see KeepFile documentation */ - relpipe::writer::boolean_t keepFile = false; + KeepFile keepFile = KeepFile::Automatic; std::vector statements; diff -r ccf19c7e7adf -r 0b38339b871b src/SqlHandler.h --- a/src/SqlHandler.h Tue Oct 22 16:04:23 2019 +0200 +++ b/src/SqlHandler.h Tue Oct 22 16:04:56 2019 +0200 @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -140,6 +141,7 @@ class SqlHandler : public RelationalReaderValueHandler { private: Configuration configuration; + boolean_t fileAlreadyExisted = false; writer::RelationalWriter* relationalWriter; std::wstring_convert> convertor; // TODO: support also other encodings vector currentReaderMetadata; @@ -186,7 +188,17 @@ public: SqlHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration) : relationalWriter(relationalWriter), configuration(configuration) { - std::string file = configuration.file.size() ? convertor.to_bytes(configuration.file) : ":memory:"; + std::string file; + if (configuration.file.size()) { + file = convertor.to_bytes(configuration.file); + + // in C++17 we can use: std::filesystem::exists() + struct stat fileStat; + fileAlreadyExisted = (stat(file.c_str(), &fileStat) == 0); + } else { + file = ":memory:"; + } + connection.reset(new Connection(file.c_str())); } @@ -255,7 +267,7 @@ default: throw SqlException(L"Unsupported type in attribute()"); } - + if (currentAttributeIndex % currentReaderMetadata.size() == 0) { currentInsert->next(); currentInsert->reset(); @@ -264,12 +276,17 @@ } void endOfPipe() { + // run the transformation – process all statements: for (const Statement& statement : configuration.statements) processStatement(statement); - if (configuration.file.size() && !configuration.keepFile) { - int result = unlink(convertor.to_bytes(configuration.file).c_str()); - if (result) throw SqlException(L"Unable to delete SQLite file."); - } + // delete or keep the file: + if (configuration.file.size()) { + if (configuration.keepFile == KeepFile::Never || (configuration.keepFile == KeepFile::Automatic && !fileAlreadyExisted)) { + std::wcerr << L"will unlink file" << std::endl; + int result = unlink(convertor.to_bytes(configuration.file).c_str()); + if (result) throw SqlException(L"Unable to delete SQLite file."); + } + } // else: we had no file, everything was in memory } };