diff --git a/src/base/string_util.cc b/src/base/string_util.cc index f6a1a69e..1a3c5159 100644 --- a/src/base/string_util.cc +++ b/src/base/string_util.cc @@ -261,6 +261,37 @@ is_blank(const std::string& str) str.begin(), str.end(), [](const auto ch) { return isspace(ch); }); } +std::string +scrub_ws(const char* in) +{ + static const std::string TAB_SYMBOL = "\u21e5"; + static const std::string LF_SYMBOL = "\u240a"; + static const std::string CR_SYMBOL = "\u240d"; + + std::string retval; + + for (size_t lpc = 0; in[lpc]; lpc++) { + auto ch = in[lpc]; + + switch (ch) { + case '\t': + retval.append(TAB_SYMBOL); + break; + case '\n': + retval.append(LF_SYMBOL); + break; + case '\r': + retval.append(CR_SYMBOL); + break; + default: + retval.append(1, ch); + break; + } + } + + return retval; +} + template size_t strtonum(long long& num_out, const char* string, size_t len); diff --git a/src/base/string_util.hh b/src/base/string_util.hh index 8b682004..9211f05d 100644 --- a/src/base/string_util.hh +++ b/src/base/string_util.hh @@ -92,6 +92,8 @@ endswith(const std::string& str, const char (&suffix)[N]) void truncate_to(std::string& str, size_t max_char_len); +std::string scrub_ws(const char* in); + inline std::string trim(const std::string& str) { diff --git a/src/command_executor.cc b/src/command_executor.cc index 8018d9e4..e61aa3c1 100644 --- a/src/command_executor.cc +++ b/src/command_executor.cc @@ -187,6 +187,7 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg) alt_msg = ""; return ec.make_error("No statement given"); } + std::map bound_values; #ifdef HAVE_SQLITE3_STMT_READONLY if (ec.is_read_only() && !sqlite3_stmt_readonly(stmt.in())) { return ec.make_error( @@ -233,17 +234,20 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg) sqlite3_bind_text(stmt.in(), lpc + 1, local_var->second.c_str(), - -1, + local_var->second.length(), SQLITE_TRANSIENT); + bound_values[name] = local_var->second; } else if ((global_var = gvars.find(&name[1])) != gvars.end()) { sqlite3_bind_text(stmt.in(), lpc + 1, global_var->second.c_str(), - -1, + global_var->second.length(), SQLITE_TRANSIENT); + bound_values[name] = global_var->second; } else if ((env_value = getenv(&name[1])) != nullptr) { sqlite3_bind_text( stmt.in(), lpc + 1, env_value, -1, SQLITE_STATIC); + bound_values[name] = env_value; } } else if (name[0] == ':' && ec.ec_line_values != nullptr) { for (auto& lv : *ec.ec_line_values) { @@ -254,17 +258,21 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg) case value_kind_t::VALUE_BOOLEAN: sqlite3_bind_int64( stmt.in(), lpc + 1, lv.lv_value.i); + bound_values[name] = fmt::to_string(lv.lv_value.i); break; case value_kind_t::VALUE_FLOAT: sqlite3_bind_double( stmt.in(), lpc + 1, lv.lv_value.d); + bound_values[name] = fmt::to_string(lv.lv_value.d); break; case value_kind_t::VALUE_INTEGER: sqlite3_bind_int64( stmt.in(), lpc + 1, lv.lv_value.i); + bound_values[name] = fmt::to_string(lv.lv_value.i); break; case value_kind_t::VALUE_NULL: sqlite3_bind_null(stmt.in(), lpc + 1); + bound_values[name] = db_label_source::NULL_STR; break; default: sqlite3_bind_text(stmt.in(), @@ -272,12 +280,14 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg) lv.text_value(), lv.text_length(), SQLITE_TRANSIENT); + bound_values[name] = lv.to_string(); break; } } } else { sqlite3_bind_null(stmt.in(), lpc + 1); log_warning("Could not bind variable: %s", name); + bound_values[name] = db_label_source::NULL_STR; } } @@ -317,7 +327,26 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg) "internal error: {}", from_res.unwrapErr()[0].um_message.get_string()); } - return ec.make_error("{}", errmsg); + + attr_line_t bound_note; + for (const auto& bval : bound_values) { + auto scrubbed_val = scrub_ws(bval.second.c_str()); + + truncate_to(scrubbed_val, 40); + bound_note.append(" ") + .append(lnav::roles::variable(bval.first)) + .append(" = ") + .append_quoted(scrubbed_val) + .append("\n"); + } + + auto um = lnav::console::user_message::error( + "SQL statement failed") + .with_reason(errmsg) + .with_snippets(ec.ec_source) + .with_note(bound_note); + + return Err(um); } } } @@ -824,35 +853,33 @@ pipe_callback(exec_context& ec, const std::string& cmdline, auto_fd& fd) return std::string(); }); - } else { - auto tmp_fd - = lnav::filesystem::open_temp_file( - ghc::filesystem::temp_directory_path() / "lnav.out.XXXXXX") - .map([](auto pair) { - ghc::filesystem::remove(pair.first); - - return std::move(pair.second); - }) - .expect("Cannot create temporary file for callback"); - auto pp = std::make_shared( - std::move(fd), false, std::move(tmp_fd)); - static int exec_count = 0; - - lnav_data.ld_pipers.push_back(pp); - auto desc = fmt::format( - FMT_STRING("[{}] Output of {}"), exec_count++, cmdline); - lnav_data.ld_active_files.fc_file_names[desc] - .with_fd(pp->get_fd()) - .with_include_in_session(false) - .with_detect_format(false); - lnav_data.ld_files_to_front.emplace_back(desc, 0); - if (lnav_data.ld_rl_view != nullptr) { - lnav_data.ld_rl_view->set_alt_value( - HELP_MSG_1(X, "to close the file")); - } - - return lnav::futures::make_ready_future(std::string()); } + auto tmp_fd + = lnav::filesystem::open_temp_file( + ghc::filesystem::temp_directory_path() / "lnav.out.XXXXXX") + .map([](auto pair) { + ghc::filesystem::remove(pair.first); + + return std::move(pair.second); + }) + .expect("Cannot create temporary file for callback"); + auto pp + = std::make_shared(std::move(fd), false, std::move(tmp_fd)); + static int exec_count = 0; + + lnav_data.ld_pipers.push_back(pp); + auto desc + = fmt::format(FMT_STRING("[{}] Output of {}"), exec_count++, cmdline); + lnav_data.ld_active_files.fc_file_names[desc] + .with_fd(pp->get_fd()) + .with_include_in_session(false) + .with_detect_format(false); + lnav_data.ld_files_to_front.emplace_back(desc, 0); + if (lnav_data.ld_rl_view != nullptr) { + lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1(X, "to close the file")); + } + + return lnav::futures::make_ready_future(std::string()); } void diff --git a/src/db_sub_source.cc b/src/db_sub_source.cc index 3b070e5e..1b5f2ce9 100644 --- a/src/db_sub_source.cc +++ b/src/db_sub_source.cc @@ -48,9 +48,6 @@ db_label_source::text_value_for_line(textview_curses& tc, std::string& label_out, text_sub_source::line_flags_t flags) { - static const std::string TAB_SYMBOL = "\u21e5"; - static const std::string LF_SYMBOL = "\u240a"; - static const std::string CR_SYMBOL = "\u240d"; /* * start_value is the result rowid, each bucket type is a column value @@ -64,25 +61,7 @@ db_label_source::text_value_for_line(textview_curses& tc, for (int lpc = 0; lpc < (int) this->dls_rows[row].size(); lpc++) { auto actual_col_size = std::min(MAX_COLUMN_WIDTH, this->dls_headers[lpc].hm_column_size); - auto raw_cell_str = std::string(this->dls_rows[row][lpc]); - std::string cell_str; - - for (const auto ch : raw_cell_str) { - switch (ch) { - case '\t': - cell_str.append(TAB_SYMBOL); - break; - case '\n': - cell_str.append(LF_SYMBOL); - break; - case '\r': - cell_str.append(CR_SYMBOL); - break; - default: - cell_str.append(1, ch); - break; - } - } + auto cell_str = scrub_ws(this->dls_rows[row][lpc]); truncate_to(cell_str, MAX_COLUMN_WIDTH); diff --git a/src/json-extension-functions.cc b/src/json-extension-functions.cc index 2294e7dc..27b82733 100644 --- a/src/json-extension-functions.cc +++ b/src/json-extension-functions.cc @@ -604,7 +604,6 @@ sql_json_group_object_step(sqlite3_context* context, } for (int lpc = 0; (lpc + 1) < argc; lpc += 2) { - log_debug("arg type %d", sqlite3_value_type(argv[lpc])); if (sqlite3_value_type(argv[lpc]) == SQLITE_NULL) { continue; } diff --git a/src/readline_callbacks.cc b/src/readline_callbacks.cc index 678409ab..5dc23530 100644 --- a/src/readline_callbacks.cc +++ b/src/readline_callbacks.cc @@ -384,7 +384,7 @@ rl_change(readline_curses* rc) lnav_data.ld_bottom_source.set_prompt( "Enter a script to execute: " ABORT_MSG); } else { - struct script_metadata& meta = iter->second[0]; + auto& meta = iter->second[0]; char help_text[1024]; snprintf(help_text, @@ -728,15 +728,20 @@ rl_callback_int(readline_curses* rc, bool is_alt) exec_context::output_guard og( ec, "tmp", std::make_pair(tmpout.release(), fclose)); - auto result = execute_file(ec, path_and_args.get_string()) - .map(ok_prefix) - .orElse(err_to_ok) - .unwrap(); - auto lf_index = result.find('\n'); - if (lf_index != std::string::npos) { - result = result.substr(0, lf_index); + auto exec_res + = execute_file(ec, path_and_args.get_string()); + if (exec_res.isOk()) { + rc->set_value(exec_res.unwrap()); + } else { + auto um = exec_res.unwrapErr(); + + lnav_data.ld_user_message_source.replace_with( + um.to_attr_line().rtrim()); + lnav_data.ld_user_message_view.reload_data(); + lnav_data.ld_user_message_expiration + = std::chrono::steady_clock::now() + 20s; + rc->set_value(""); } - rc->set_value(result); } struct stat st; diff --git a/src/sql_util.cc b/src/sql_util.cc index bdb71fd5..3db34857 100644 --- a/src/sql_util.cc +++ b/src/sql_util.cc @@ -982,7 +982,6 @@ annotate_sql_statement(attr_line_t& al) pcrepp re; string_attr_type* type; } PATTERNS[] = { - {pcrepp{R"(^(\.\w+))"}, &SQL_COMMAND_ATTR}, {pcrepp{R"(\A,)"}, &SQL_COMMA_ATTR}, {pcrepp{R"(\A\(|\A\))"}, &SQL_PAREN_ATTR}, {pcrepp{keyword_re_str, PCRE_CASELESS}, &SQL_KEYWORD_ATTR}, @@ -999,6 +998,7 @@ annotate_sql_statement(attr_line_t& al) {pcrepp{R"(\A.)"}, &SQL_GARBAGE_ATTR}, }; + static const pcrepp cmd_pattern{R"(^(\.\w+))"}; static const pcrepp ws_pattern(R"(\A\s+)"); pcre_context_static<30> pc; @@ -1006,6 +1006,13 @@ annotate_sql_statement(attr_line_t& al) auto& line = al.get_string(); auto& sa = al.get_attrs(); + if (cmd_pattern.match(pc, pi, PCRE_ANCHORED)) { + auto* cap = pc.all(); + sa.emplace_back(line_range(cap->c_begin, cap->c_end), + SQL_COMMAND_ATTR.value()); + return; + } + while (pi.pi_next_offset < line.length()) { if (ws_pattern.match(pc, pi, PCRE_ANCHORED)) { continue; diff --git a/test/expected/expected.am b/test/expected/expected.am index ba28baa9..59d04b19 100644 --- a/test/expected/expected.am +++ b/test/expected/expected.am @@ -232,8 +232,6 @@ EXPECTED_FILES = \ $(srcdir)/%reldir%/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out \ $(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err \ $(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out \ - $(srcdir)/%reldir%/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.err \ - $(srcdir)/%reldir%/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.out \ $(srcdir)/%reldir%/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.err \ $(srcdir)/%reldir%/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.out \ $(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err \ @@ -326,58 +324,6 @@ EXPECTED_FILES = \ $(srcdir)/%reldir%/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.out \ $(srcdir)/%reldir%/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.err \ $(srcdir)/%reldir%/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.out \ - $(srcdir)/%reldir%/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.err \ - $(srcdir)/%reldir%/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.out \ - $(srcdir)/%reldir%/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.err \ - $(srcdir)/%reldir%/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.out \ - $(srcdir)/%reldir%/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.err \ - $(srcdir)/%reldir%/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.out \ - $(srcdir)/%reldir%/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.err \ - $(srcdir)/%reldir%/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.out \ - $(srcdir)/%reldir%/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.err \ - $(srcdir)/%reldir%/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.out \ - $(srcdir)/%reldir%/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.err \ - $(srcdir)/%reldir%/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.out \ - $(srcdir)/%reldir%/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.err \ - $(srcdir)/%reldir%/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.out \ - $(srcdir)/%reldir%/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.err \ - $(srcdir)/%reldir%/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.out \ - $(srcdir)/%reldir%/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.err \ - $(srcdir)/%reldir%/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.out \ - $(srcdir)/%reldir%/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.err \ - $(srcdir)/%reldir%/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.out \ - $(srcdir)/%reldir%/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.err \ - $(srcdir)/%reldir%/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.out \ - $(srcdir)/%reldir%/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.err \ - $(srcdir)/%reldir%/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.out \ - $(srcdir)/%reldir%/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.err \ - $(srcdir)/%reldir%/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.out \ - $(srcdir)/%reldir%/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.err \ - $(srcdir)/%reldir%/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.out \ - $(srcdir)/%reldir%/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.err \ - $(srcdir)/%reldir%/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.out \ - $(srcdir)/%reldir%/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.err \ - $(srcdir)/%reldir%/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.out \ - $(srcdir)/%reldir%/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.err \ - $(srcdir)/%reldir%/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.out \ - $(srcdir)/%reldir%/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.err \ - $(srcdir)/%reldir%/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.out \ - $(srcdir)/%reldir%/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.err \ - $(srcdir)/%reldir%/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.out \ - $(srcdir)/%reldir%/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.err \ - $(srcdir)/%reldir%/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.out \ - $(srcdir)/%reldir%/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.err \ - $(srcdir)/%reldir%/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.out \ - $(srcdir)/%reldir%/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.err \ - $(srcdir)/%reldir%/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.out \ - $(srcdir)/%reldir%/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.err \ - $(srcdir)/%reldir%/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.out \ - $(srcdir)/%reldir%/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.err \ - $(srcdir)/%reldir%/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.out \ - $(srcdir)/%reldir%/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.err \ - $(srcdir)/%reldir%/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.out \ - $(srcdir)/%reldir%/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.err \ - $(srcdir)/%reldir%/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.out \ $(srcdir)/%reldir%/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.err \ $(srcdir)/%reldir%/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.out \ $(srcdir)/%reldir%/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err \ @@ -564,6 +510,8 @@ EXPECTED_FILES = \ $(srcdir)/%reldir%/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.out \ $(srcdir)/%reldir%/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.err \ $(srcdir)/%reldir%/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.out \ + $(srcdir)/%reldir%/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err \ + $(srcdir)/%reldir%/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out \ $(srcdir)/%reldir%/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.err \ $(srcdir)/%reldir%/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.out \ $(srcdir)/%reldir%/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.err \ diff --git a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out index e62d9f2f..cb4778a3 100644 --- a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out +++ b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out @@ -545,7 +545,7 @@ For example, if you wanted to save the results from the earlier example of a top ten query into the "/tmp/topten.db" file, you can do: ▌;ATTACH DATABASE '/tmp/topten.db' AS topten;  - ▌;CREATE TABLE topten.foo AS SELECT cs_uri_stem, count(*) AS total  + ▌;CREATE TABLE topten.foo AS SELECT cs_uri_stem, count(*) AS total  ▌ FROM access_log GROUP BY cs_uri_stem ORDER BY total DESC  ▌ LIMIT 10;  diff --git a/test/expected/test_sql.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err b/test/expected/test_sql.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err index 6e4f929c..65683311 100644 --- a/test/expected/test_sql.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err +++ b/test/expected/test_sql.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err @@ -1,3 +1,4 @@ -✘ error: Only the top view in the stack can be deleted +✘ error: SQL statement failed + reason: Only the top view in the stack can be deleted  --> command-option:2  | ;DELETE FROM lnav_view_stack WHERE name = 'log' diff --git a/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err b/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err index 782fe5ee..4be21b09 100644 --- a/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err +++ b/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err @@ -1,3 +1,4 @@ -✘ error: oops! +✘ error: SQL statement failed + reason: oops!  --> command-option:1  | ;SELECT raise_error('oops!')  diff --git a/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err b/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err index c019770a..0c1c0593 100644 --- a/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err +++ b/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err @@ -1,3 +1,4 @@ -✘ error: A non-empty name and value must be provided when inserting an environment variable +✘ error: SQL statement failed + reason: A non-empty name and value must be provided when inserting an environment variable  --> command-option:1  | ;INSERT INTO environ (name) VALUES (null) diff --git a/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err b/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err index a62e0ba9..89f156fc 100644 --- a/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err +++ b/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err @@ -1,3 +1,4 @@ -✘ error: An environment variable with the name 'SQL_ENV_VALUE' already exists +✘ error: SQL statement failed + reason: An environment variable with the name 'SQL_ENV_VALUE' already exists  --> command-option:1  | ;INSERT INTO environ (name, value) VALUES ("SQL_ENV_VALUE", "bar") diff --git a/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err b/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err index 9ba05c1c..b15f6ce7 100644 --- a/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err +++ b/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err @@ -1,3 +1,4 @@ -✘ error: Environment variable names cannot contain an equals sign (=) +✘ error: SQL statement failed + reason: Environment variable names cannot contain an equals sign (=)  --> command-option:1  | ;INSERT INTO environ (name, value) VALUES ("foo=bar", "bar") diff --git a/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err b/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err index 979055d2..4fb5ccf8 100644 --- a/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err +++ b/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err @@ -1,4 +1,5 @@ -✘ error: no data was redirected to lnav's standard-input +✘ error: SQL statement failed + reason: no data was redirected to lnav's standard-input  --> command-option:1  | |rename-stdin foo   --> ../test/.lnav/formats/default/rename-stdin.lnav:7 diff --git a/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err b/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err index a4595bd2..3ced6be5 100644 --- a/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err +++ b/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err @@ -1,3 +1,4 @@ -✘ error: A non-empty name and value must be provided when inserting an environment variable +✘ error: SQL statement failed + reason: A non-empty name and value must be provided when inserting an environment variable  --> command-option:1  | ;INSERT INTO environ (name, value) VALUES (null, null) diff --git a/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err b/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err index 5736eba2..cdb21401 100644 --- a/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err +++ b/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err @@ -1,6 +1,6 @@ ✘ error: unable to read script file: nonexistent-file -- No such file or directory  --> command-option:1 - | ;.read nonexistent-file  + | ;.read nonexistent-file   = help: ;.read path ══════════════════════════════════════════════════════════════════════ Execute the SQLite statements in the given file diff --git a/test/expected/test_sql.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err b/test/expected/test_sql.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err index 8bdc2a07..482241e7 100644 --- a/test/expected/test_sql.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err +++ b/test/expected/test_sql.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err @@ -1,3 +1,4 @@ -✘ error: Expecting a non-empty pattern value +✘ error: SQL statement failed + reason: Expecting a non-empty pattern value  --> command-option:1  | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', '') diff --git a/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err b/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err index d0680566..0c18d01a 100644 --- a/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err +++ b/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err @@ -1,4 +1,5 @@ -✘ error: expecting the new name for stdin as the first argument +✘ error: SQL statement failed + reason: expecting the new name for stdin as the first argument  --> command-option:1  | |rename-stdin   --> ../test/.lnav/formats/default/rename-stdin.lnav:6 diff --git a/test/expected/test_sql.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err b/test/expected/test_sql.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err index 0c0a6e87..609aacba 100644 --- a/test/expected/test_sql.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err +++ b/test/expected/test_sql.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err @@ -1,3 +1,4 @@ -✘ error: Expecting an lnav view name for column number 0 +✘ error: SQL statement failed + reason: Expecting an lnav view name for column number 0  --> command-option:1  | ;INSERT INTO lnav_view_filters VALUES ('bad', 0, 1, 'out', 'regex', 'abc') diff --git a/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err b/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err index 1d04a437..d3d1a0a8 100644 --- a/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err +++ b/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err @@ -1,3 +1,4 @@ -✘ error: real file paths cannot be updated, only symbolic ones +✘ error: SQL statement failed + reason: real file paths cannot be updated, only symbolic ones  --> command-option:1  | ;UPDATE lnav_file SET filepath='foo' WHERE endswith(filepath, '_log.0') diff --git a/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err b/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err index 590b1919..8dd63fac 100644 --- a/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err +++ b/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err @@ -1,3 +1,4 @@ -✘ error: attempt to write a readonly database +✘ error: SQL statement failed + reason: attempt to write a readonly database  --> command-option:1  | ;delete from access_log  diff --git a/test/expected/test_sql.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err b/test/expected/test_sql.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err index 180df81a..66b8e6ad 100644 --- a/test/expected/test_sql.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err +++ b/test/expected/test_sql.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err @@ -1,3 +1,4 @@ -✘ error: The lnav_view_stack table cannot be updated +✘ error: SQL statement failed + reason: The lnav_view_stack table cannot be updated  --> command-option:1  | ;UPDATE lnav_view_stack SET name = 'foo' diff --git a/test/expected/test_sql.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err b/test/expected/test_sql.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err index 82f33db3..b97c051c 100644 --- a/test/expected/test_sql.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err +++ b/test/expected/test_sql.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err @@ -1,3 +1,4 @@ -✘ error: Invalid regular expression for pattern: missing ) at offset 4 +✘ error: SQL statement failed + reason: Invalid regular expression for pattern: missing ) at offset 4  --> command-option:1  | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', 'abc(') diff --git a/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err b/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err index d1252712..da8dff56 100644 --- a/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err +++ b/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err @@ -1,3 +1,4 @@ -✘ error: A non-empty name and value must be provided when inserting an environment variable +✘ error: SQL statement failed + reason: A non-empty name and value must be provided when inserting an environment variable  --> command-option:1  | ;INSERT INTO environ (name, value) VALUES ("", null) diff --git a/test/expected/test_sql.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err b/test/expected/test_sql.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err index a264da54..4276af6d 100644 --- a/test/expected/test_sql.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err +++ b/test/expected/test_sql.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err @@ -1,3 +1,4 @@ -✘ error: Invalid time: bad-time +✘ error: SQL statement failed + reason: Invalid time: bad-time  --> command-option:1  | ;UPDATE lnav_views SET top_time = 'bad-time' WHERE name = 'log' diff --git a/test/expected/test_sql.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err b/test/expected/test_sql.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err index bf408af5..aab37c6e 100644 --- a/test/expected/test_sql.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err +++ b/test/expected/test_sql.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err @@ -1,3 +1,4 @@ -✘ error: Expecting an lnav view name for column number 0 +✘ error: SQL statement failed + reason: Expecting an lnav view name for column number 0  --> command-option:1  | ;INSERT INTO lnav_view_filters VALUES (NULL, 0, 1, 'out', 'regex', 'abc') diff --git a/test/expected/test_sql.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err b/test/expected/test_sql.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err index 81f993d0..8a477fcc 100644 --- a/test/expected/test_sql.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err +++ b/test/expected/test_sql.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err @@ -1,3 +1,4 @@ -✘ error: Expecting an value of 'in' or 'out' for column number 3 +✘ error: SQL statement failed + reason: Expecting an value of 'in' or 'out' for column number 3  --> command-option:1  | ;INSERT INTO lnav_view_filters VALUES ('log', 0 , 1, 'bad', 'regex', 'abc') diff --git a/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err b/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out b/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out new file mode 100644 index 00000000..9498d4bc --- /dev/null +++ b/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out @@ -0,0 +1,7 @@ + SELECT * FROM foo.bar + sql_keyword ------ + sql_oper - + sql_keyword ---- + sql_ident --- + sql_garbage - + sql_ident --- diff --git a/test/test_sql_anno.sh b/test/test_sql_anno.sh index 9aa41cc1..e09c3125 100644 --- a/test/test_sql_anno.sh +++ b/test/test_sql_anno.sh @@ -46,3 +46,5 @@ run_cap_test ./drive_sql_anno "SELECT * FROM (SELECT foo, bar FROM baz)" run_cap_test ./drive_sql_anno \ "SELECT * from vmw_log, regexp_capture(log_body, '--> /SessionStats/SessionPool/Session/(?[abc]+)')" + +run_cap_test ./drive_sql_anno "SELECT * FROM foo.bar"