[exec] fix reporting of errors in scripts

This commit is contained in:
Timothy Stack 2022-07-12 22:52:40 -07:00
parent e669f6ca55
commit dde6d88430
31 changed files with 163 additions and 138 deletions

View File

@ -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>(long long& num_out,
const char* string,
size_t len);

View File

@ -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)
{

View File

@ -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<std::string, std::string> 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<piper_proc>(
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<piper_proc>(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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -982,7 +982,6 @@ annotate_sql_statement(attr_line_t& al)
pcrepp re;
string_attr_type<void>* 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;

View File

@ -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 \

View File

@ -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; 

View File

@ -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'

View File

@ -1,3 +1,4 @@
✘ error: oops!
✘ error: SQL statement failed
reason: oops!
 --> command-option:1
 | ;SELECT raise_error('oops!') 

View File

@ -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)

View File

@ -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")

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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', '')

View File

@ -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

View File

@ -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')

View File

@ -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')

View File

@ -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 

View File

@ -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'

View File

@ -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(')

View File

@ -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)

View File

@ -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'

View File

@ -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')

View File

@ -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')

View File

@ -0,0 +1,7 @@
SELECT * FROM foo.bar
sql_keyword ------
sql_oper -
sql_keyword ----
sql_ident ---
sql_garbage -
sql_ident ---

View File

@ -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/(?<line>[abc]+)')"
run_cap_test ./drive_sql_anno "SELECT * FROM foo.bar"