mirror of https://github.com/tstack/lnav.git
[sql] some more error improvements
This commit is contained in:
parent
dde6d88430
commit
4c20b0039c
|
@ -49,6 +49,7 @@
|
|||
#include "service_tags.hh"
|
||||
#include "shlex.hh"
|
||||
#include "sql_util.hh"
|
||||
#include "vtab_module.hh"
|
||||
#include "yajlpp/json_ptr.hh"
|
||||
|
||||
exec_context INIT_EXEC_CONTEXT;
|
||||
|
@ -125,7 +126,15 @@ execute_command(exec_context& ec, const std::string& cmdline)
|
|||
|
||||
ec.ec_current_help = &iter->second->c_help;
|
||||
auto retval = iter->second->c_func(ec, cmdline, args);
|
||||
if (retval.isErr()) {
|
||||
auto um = retval.unwrapErr();
|
||||
|
||||
ec.add_error_context(um);
|
||||
ec.ec_current_help = nullptr;
|
||||
return Err(um);
|
||||
}
|
||||
ec.ec_current_help = nullptr;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -310,39 +319,25 @@ execute_sql(exec_context& ec, const std::string& sql, std::string& alt_msg)
|
|||
break;
|
||||
|
||||
default: {
|
||||
const char* errmsg;
|
||||
attr_line_t bound_note;
|
||||
|
||||
if (!bound_values.empty()) {
|
||||
bound_note.append(
|
||||
"the bound parameters are set as follows:\n");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
log_error("sqlite3_step error code: %d", retcode);
|
||||
errmsg = sqlite3_errmsg(lnav_data.ld_db);
|
||||
if (startswith(errmsg, "lnav-error:")) {
|
||||
auto from_res
|
||||
= lnav::from_json<lnav::console::user_message>(
|
||||
&errmsg[11]);
|
||||
|
||||
if (from_res.isOk()) {
|
||||
return Err(from_res.unwrap());
|
||||
}
|
||||
|
||||
return ec.make_error(
|
||||
"internal error: {}",
|
||||
from_res.unwrapErr()[0].um_message.get_string());
|
||||
}
|
||||
|
||||
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)
|
||||
auto um = sqlite3_error_to_user_message(lnav_data.ld_db)
|
||||
.with_snippets(ec.ec_source)
|
||||
.with_note(bound_note);
|
||||
|
||||
|
@ -956,12 +951,17 @@ exec_context::execute(const std::string& cmdline)
|
|||
void
|
||||
exec_context::add_error_context(lnav::console::user_message& um)
|
||||
{
|
||||
um.with_snippets(this->ec_source);
|
||||
if (um.um_snippets.empty()) {
|
||||
um.with_snippets(this->ec_source);
|
||||
}
|
||||
|
||||
if (this->ec_current_help != nullptr) {
|
||||
if (this->ec_current_help != nullptr && um.um_help.empty()) {
|
||||
attr_line_t help;
|
||||
|
||||
format_help_text_for_term(*this->ec_current_help, 70, help, true);
|
||||
format_help_text_for_term(*this->ec_current_help,
|
||||
70,
|
||||
help,
|
||||
help_text_content::synopsis_and_summary);
|
||||
um.with_help(help);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -479,7 +479,11 @@ filter_sub_source::rl_change(readline_curses* rc)
|
|||
|
||||
if (set_res.isErr()) {
|
||||
lnav_data.ld_filter_help_status_source.fss_error.set_value(
|
||||
"error: %s", set_res.unwrapErr().c_str());
|
||||
"error: %s",
|
||||
set_res.unwrapErr()
|
||||
.to_attr_line()
|
||||
.get_string()
|
||||
.c_str());
|
||||
} else {
|
||||
top_view->set_needs_update();
|
||||
lnav_data.ld_filter_help_status_source.fss_error.clear();
|
||||
|
|
|
@ -82,7 +82,7 @@ void
|
|||
format_help_text_for_term(const help_text& ht,
|
||||
size_t width,
|
||||
attr_line_t& out,
|
||||
bool synopsis_only)
|
||||
help_text_content htc)
|
||||
{
|
||||
static const size_t body_indent = 2;
|
||||
|
||||
|
@ -120,14 +120,16 @@ format_help_text_for_term(const help_text& ht,
|
|||
line_range{(int) line_start, (int) out.get_string().length()},
|
||||
VC_ROLE.value(role_t::VCR_H3),
|
||||
});
|
||||
alb.append("\n")
|
||||
.append(
|
||||
lnav::roles::table_border(repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent)
|
||||
.append(attr_line_t::from_ansi_str(ht.ht_summary),
|
||||
&tws.with_indent(body_indent))
|
||||
.append("\n");
|
||||
if (htc != help_text_content::synopsis) {
|
||||
alb.append("\n")
|
||||
.append(lnav::roles::table_border(
|
||||
repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent)
|
||||
.append(attr_line_t::from_ansi_str(ht.ht_summary),
|
||||
&tws.with_indent(body_indent))
|
||||
.append("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case help_context_t::HC_SQL_FUNCTION:
|
||||
|
@ -174,22 +176,24 @@ format_help_text_for_term(const help_text& ht,
|
|||
line_range{(int) line_start, (int) out.get_string().length()},
|
||||
VC_ROLE.value(role_t::VCR_H3),
|
||||
});
|
||||
if (break_all) {
|
||||
alb.append("\n")
|
||||
.append(lnav::roles::table_border(
|
||||
repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent + strlen(ht.ht_name) + 1);
|
||||
} else {
|
||||
alb.append("\n")
|
||||
.append(lnav::roles::table_border(
|
||||
repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent);
|
||||
if (htc != help_text_content::synopsis) {
|
||||
if (break_all) {
|
||||
alb.append("\n")
|
||||
.append(lnav::roles::table_border(
|
||||
repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent + strlen(ht.ht_name) + 1);
|
||||
} else {
|
||||
alb.append("\n")
|
||||
.append(lnav::roles::table_border(
|
||||
repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent);
|
||||
}
|
||||
out.append(attr_line_t::from_ansi_str(ht.ht_summary),
|
||||
&tws.with_indent(body_indent))
|
||||
.append("\n");
|
||||
}
|
||||
out.append(attr_line_t::from_ansi_str(ht.ht_summary),
|
||||
&tws.with_indent(body_indent))
|
||||
.append("\n");
|
||||
break;
|
||||
}
|
||||
case help_context_t::HC_SQL_COMMAND: {
|
||||
|
@ -219,14 +223,16 @@ format_help_text_for_term(const help_text& ht,
|
|||
line_range{(int) line_start, (int) out.get_string().length()},
|
||||
VC_ROLE.value(role_t::VCR_H3),
|
||||
});
|
||||
alb.append("\n")
|
||||
.append(
|
||||
lnav::roles::table_border(repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent)
|
||||
.append(attr_line_t::from_ansi_str(ht.ht_summary),
|
||||
&tws.with_indent(body_indent + 2))
|
||||
.append("\n");
|
||||
if (htc != help_text_content::synopsis) {
|
||||
alb.append("\n")
|
||||
.append(lnav::roles::table_border(
|
||||
repeat("\u2550", tws.tws_width)))
|
||||
.append("\n")
|
||||
.indent(body_indent)
|
||||
.append(attr_line_t::from_ansi_str(ht.ht_summary),
|
||||
&tws.with_indent(body_indent + 2))
|
||||
.append("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case help_context_t::HC_SQL_INFIX:
|
||||
|
@ -332,9 +338,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
line_range{(int) line_start, (int) out.get_string().length()},
|
||||
VC_ROLE.value(role_t::VCR_H3),
|
||||
});
|
||||
if (synopsis_only) {
|
||||
out.append("\n");
|
||||
} else {
|
||||
if (htc != help_text_content::synopsis) {
|
||||
alb.append("\n")
|
||||
.append(lnav::roles::table_border(
|
||||
repeat("\u2550", tws.tws_width)))
|
||||
|
@ -349,7 +353,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!synopsis_only && !ht.ht_parameters.empty()) {
|
||||
if (htc == help_text_content::full && !ht.ht_parameters.empty()) {
|
||||
size_t max_param_name_width = 0;
|
||||
|
||||
for (const auto& param : ht.ht_parameters) {
|
||||
|
@ -375,7 +379,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
.append("\n");
|
||||
}
|
||||
}
|
||||
if (!synopsis_only && !ht.ht_results.empty()) {
|
||||
if (htc == help_text_content::full && !ht.ht_results.empty()) {
|
||||
size_t max_result_name_width = 0;
|
||||
|
||||
for (const auto& result : ht.ht_results) {
|
||||
|
@ -400,7 +404,7 @@ format_help_text_for_term(const help_text& ht,
|
|||
.append("\n");
|
||||
}
|
||||
}
|
||||
if (!synopsis_only && !ht.ht_tags.empty()) {
|
||||
if (htc == help_text_content::full && !ht.ht_tags.empty()) {
|
||||
auto related_help = get_related(ht);
|
||||
auto related_refs = std::vector<std::string>();
|
||||
|
||||
|
|
|
@ -38,10 +38,16 @@
|
|||
using help_example_to_attr_line_fun_t
|
||||
= std::function<attr_line_t(const help_text&, const help_example&)>;
|
||||
|
||||
enum class help_text_content {
|
||||
synopsis,
|
||||
synopsis_and_summary,
|
||||
full,
|
||||
};
|
||||
|
||||
void format_help_text_for_term(const help_text& ht,
|
||||
size_t width,
|
||||
attr_line_t& out,
|
||||
bool synopsis_only = false);
|
||||
help_text_content htc = help_text_content::full);
|
||||
|
||||
void format_example_text_for_term(const help_text& ht,
|
||||
help_example_to_attr_line_fun_t eval,
|
||||
|
|
|
@ -706,6 +706,7 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
|
|||
}
|
||||
// log_debug("got preload");
|
||||
this->lb_loader_future = {};
|
||||
this->lb_share_manager.invalidate_refs();
|
||||
this->lb_file_offset = this->lb_loader_file_offset.value();
|
||||
this->lb_loader_file_offset = nonstd::nullopt;
|
||||
this->lb_buffer.swap(this->lb_alt_buffer.value());
|
||||
|
|
|
@ -628,8 +628,7 @@ com_mark_expr(exec_context& ec,
|
|||
auto set_res = lss.set_preview_sql_filter(stmt.release());
|
||||
|
||||
if (set_res.isErr()) {
|
||||
return ec.make_error("mark expression failed with: {}",
|
||||
set_res.unwrapErr());
|
||||
return Err(set_res.unwrapErr());
|
||||
}
|
||||
lnav_data.ld_preview_status_source.get_description().set_value(
|
||||
"Matches are highlighted in the text view");
|
||||
|
@ -637,8 +636,7 @@ com_mark_expr(exec_context& ec,
|
|||
auto set_res = lss.set_sql_marker(expr, stmt.release());
|
||||
|
||||
if (set_res.isErr()) {
|
||||
return ec.make_error("mark expression failed with: {}",
|
||||
set_res.unwrapErr());
|
||||
return Err(set_res.unwrapErr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1992,8 +1990,7 @@ com_filter_expr(exec_context& ec,
|
|||
stmt.release());
|
||||
|
||||
if (set_res.isErr()) {
|
||||
return ec.make_error("filter expression failed with: {}",
|
||||
set_res.unwrapErr());
|
||||
return Err(set_res.unwrapErr());
|
||||
}
|
||||
lnav_data.ld_preview_status_source.get_description().set_value(
|
||||
"Matches are highlighted in the text view");
|
||||
|
@ -2003,8 +2000,7 @@ com_filter_expr(exec_context& ec,
|
|||
= lnav_data.ld_log_source.set_sql_filter(expr, stmt.release());
|
||||
|
||||
if (set_res.isErr()) {
|
||||
return ec.make_error("filter expression failed with: {}",
|
||||
set_res.unwrapErr());
|
||||
return Err(set_res.unwrapErr());
|
||||
}
|
||||
}
|
||||
lnav_data.ld_log_source.text_filters_changed();
|
||||
|
|
|
@ -256,6 +256,8 @@ read_string_attr_type(yajlpp_parse_context* ypc,
|
|||
|
||||
if (type == "role") {
|
||||
sa->sa_type = &VC_ROLE;
|
||||
} else if (type == "preformatted") {
|
||||
sa->sa_type = &SA_PREFORMATTED;
|
||||
} else {
|
||||
ensure(false);
|
||||
}
|
||||
|
|
|
@ -1839,10 +1839,7 @@ vt_update(sqlite3_vtab* tab,
|
|||
.append(" column of table ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
vt->vi->get_name().to_string())))
|
||||
.with_reason(errors[0].to_attr_line({}))
|
||||
.with_snippet(lnav::console::snippet::from(
|
||||
log_vtab_data.lvd_location,
|
||||
log_vtab_data.lvd_content));
|
||||
.with_reason(errors[0].to_attr_line({}));
|
||||
auto json_error = lnav::to_json(top_error);
|
||||
tab->zErrMsg
|
||||
= sqlite3_mprintf("lnav-error:%s", json_error.c_str());
|
||||
|
|
|
@ -732,6 +732,7 @@ logfile::read_full_message(logfile::const_iterator ll,
|
|||
{
|
||||
require(ll->get_sub_offset() == 0);
|
||||
|
||||
msg_out.disown();
|
||||
try {
|
||||
auto read_result
|
||||
= this->lf_line_buffer.read_range(this->get_file_range(ll));
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "readline_highlighters.hh"
|
||||
#include "relative_time.hh"
|
||||
#include "sql_util.hh"
|
||||
#include "vtab_module.hh"
|
||||
#include "yajlpp/yajlpp.hh"
|
||||
|
||||
const bookmark_type_t logfile_sub_source::BM_ERRORS("error");
|
||||
|
@ -574,8 +575,10 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
this->lss_token_line);
|
||||
if (eval_res.isErr()) {
|
||||
color = COLOR_YELLOW;
|
||||
value_out.emplace_back(line_range{0, -1},
|
||||
SA_ERROR.value(eval_res.unwrapErr()));
|
||||
value_out.emplace_back(
|
||||
line_range{0, -1},
|
||||
SA_ERROR.value(
|
||||
eval_res.unwrapErr().to_attr_line().get_string()));
|
||||
} else {
|
||||
auto matched = eval_res.unwrap();
|
||||
|
||||
|
@ -601,7 +604,7 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
|
|||
auto msg = fmt::format(
|
||||
FMT_STRING(
|
||||
"filter expression evaluation failed with -- {}"),
|
||||
eval_res.unwrapErr());
|
||||
eval_res.unwrapErr().to_attr_line().get_string());
|
||||
auto color = COLOR_YELLOW;
|
||||
value_out.emplace_back(line_range{0, -1}, SA_ERROR.value(msg));
|
||||
value_out.emplace_back(line_range{0, 1},
|
||||
|
@ -1251,7 +1254,7 @@ logfile_sub_source::insert_file(const std::shared_ptr<logfile>& lf)
|
|||
return true;
|
||||
}
|
||||
|
||||
Result<void, std::string>
|
||||
Result<void, lnav::console::user_message>
|
||||
logfile_sub_source::set_sql_filter(std::string stmt_str, sqlite3_stmt* stmt)
|
||||
{
|
||||
for (auto& filt : this->tss_filters) {
|
||||
|
@ -1294,7 +1297,7 @@ logfile_sub_source::set_sql_filter(std::string stmt_str, sqlite3_stmt* stmt)
|
|||
return Ok();
|
||||
}
|
||||
|
||||
Result<void, std::string>
|
||||
Result<void, lnav::console::user_message>
|
||||
logfile_sub_source::set_sql_marker(std::string stmt_str, sqlite3_stmt* stmt)
|
||||
{
|
||||
if (stmt != nullptr && !this->lss_filtered_index.empty()) {
|
||||
|
@ -1351,7 +1354,7 @@ logfile_sub_source::set_sql_marker(std::string stmt_str, sqlite3_stmt* stmt)
|
|||
return Ok();
|
||||
}
|
||||
|
||||
Result<void, std::string>
|
||||
Result<void, lnav::console::user_message>
|
||||
logfile_sub_source::set_preview_sql_filter(sqlite3_stmt* stmt)
|
||||
{
|
||||
if (stmt != nullptr && !this->lss_filtered_index.empty()) {
|
||||
|
@ -1371,7 +1374,7 @@ logfile_sub_source::set_preview_sql_filter(sqlite3_stmt* stmt)
|
|||
return Ok();
|
||||
}
|
||||
|
||||
Result<bool, std::string>
|
||||
Result<bool, lnav::console::user_message>
|
||||
logfile_sub_source::eval_sql_filter(sqlite3_stmt* stmt,
|
||||
iterator ld,
|
||||
logfile::const_iterator ll)
|
||||
|
@ -1592,7 +1595,7 @@ logfile_sub_source::eval_sql_filter(sqlite3_stmt* stmt,
|
|||
case SQLITE_ROW:
|
||||
return Ok(true);
|
||||
default:
|
||||
return Err(std::string(sqlite3_errmsg(sqlite3_db_handle(stmt))));
|
||||
return Err(sqlite3_error_to_user_message(sqlite3_db_handle(stmt)));
|
||||
}
|
||||
|
||||
return Ok(true);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
#include "base/lnav.console.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/time_util.hh"
|
||||
#include "big_array.hh"
|
||||
|
@ -496,13 +497,14 @@ public:
|
|||
return retval;
|
||||
}
|
||||
|
||||
Result<void, std::string> set_sql_filter(std::string stmt_str,
|
||||
sqlite3_stmt* stmt);
|
||||
Result<void, lnav::console::user_message> set_sql_filter(
|
||||
std::string stmt_str, sqlite3_stmt* stmt);
|
||||
|
||||
Result<void, std::string> set_sql_marker(std::string stmt_str,
|
||||
sqlite3_stmt* stmt);
|
||||
Result<void, lnav::console::user_message> set_sql_marker(
|
||||
std::string stmt_str, sqlite3_stmt* stmt);
|
||||
|
||||
Result<void, std::string> set_preview_sql_filter(sqlite3_stmt* stmt);
|
||||
Result<void, lnav::console::user_message> set_preview_sql_filter(
|
||||
sqlite3_stmt* stmt);
|
||||
|
||||
std::string get_sql_filter_text()
|
||||
{
|
||||
|
@ -794,9 +796,8 @@ public:
|
|||
|
||||
void text_crumbs_for_line(int line, std::vector<breadcrumb::crumb>& crumbs);
|
||||
|
||||
Result<bool, std::string> eval_sql_filter(sqlite3_stmt* stmt,
|
||||
iterator ld,
|
||||
logfile::const_iterator ll);
|
||||
Result<bool, lnav::console::user_message> eval_sql_filter(
|
||||
sqlite3_stmt* stmt, iterator ld, logfile::const_iterator ll);
|
||||
|
||||
void invalidate_sql_filter();
|
||||
|
||||
|
|
|
@ -177,11 +177,17 @@ rl_sql_help(readline_curses* rc)
|
|||
etc.get_dimensions(ex_height, ex_width);
|
||||
|
||||
for (const auto& ht : avail_help) {
|
||||
format_help_text_for_term(
|
||||
*ht, std::min(70UL, doc_width), doc_al, help_count > 1);
|
||||
format_help_text_for_term(*ht,
|
||||
std::min(70UL, doc_width),
|
||||
doc_al,
|
||||
help_count > 1
|
||||
? help_text_content::synopsis
|
||||
: help_text_content::full);
|
||||
if (help_count == 1) {
|
||||
format_example_text_for_term(
|
||||
*ht, eval_example, std::min(70UL, ex_width), ex_al);
|
||||
} else {
|
||||
doc_al.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,6 +610,9 @@ rl_callback_int(readline_curses* rc, bool is_alt)
|
|||
rc->set_alt_value("");
|
||||
ec.ec_source.back().s_content
|
||||
= fmt::format(FMT_STRING(":{}"), rc->get_value().get_string());
|
||||
readline_lnav_highlighter(ec.ec_source.back().s_content, -1);
|
||||
ec.ec_source.back().s_content.with_attr_for_all(
|
||||
VC_ROLE.value(role_t::VCR_QUOTED_CODE));
|
||||
auto exec_res = execute_command(ec, rc->get_value().get_string());
|
||||
if (exec_res.isOk()) {
|
||||
rc->set_value(exec_res.unwrap());
|
||||
|
@ -679,7 +688,11 @@ rl_callback_int(readline_curses* rc, bool is_alt)
|
|||
break;
|
||||
|
||||
case ln_mode_t::SQL: {
|
||||
ec.ec_source.back().s_content = rc->get_value();
|
||||
ec.ec_source.back().s_content
|
||||
= fmt::format(FMT_STRING(";{}"), rc->get_value().get_string());
|
||||
readline_lnav_highlighter(ec.ec_source.back().s_content, -1);
|
||||
ec.ec_source.back().s_content.with_attr_for_all(
|
||||
VC_ROLE.value(role_t::VCR_QUOTED_CODE));
|
||||
auto result
|
||||
= execute_sql(ec, rc->get_value().get_string(), alt_msg);
|
||||
db_label_source& dls = lnav_data.ld_db_row_source;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "base/opt_util.hh"
|
||||
#include "config.h"
|
||||
#include "lnav.hh"
|
||||
#include "lnav_util.hh"
|
||||
#include "sql_util.hh"
|
||||
#include "view_curses.hh"
|
||||
#include "vtab_module_json.hh"
|
||||
|
@ -690,8 +691,11 @@ CREATE TABLE lnav_view_filters (
|
|||
auto set_res = lnav_data.ld_log_source.set_sql_filter(
|
||||
clause, stmt.release());
|
||||
if (set_res.isErr()) {
|
||||
throw sqlite_func_error("filter expression failed with: {}",
|
||||
set_res.unwrapErr());
|
||||
tab->zErrMsg = sqlite3_mprintf(
|
||||
"%s%s",
|
||||
LNAV_SQLITE_ERROR_PREFIX,
|
||||
lnav::to_json(set_res.unwrapErr()).c_str());
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
tf = lnav_data.ld_log_source.get_sql_filter().value();
|
||||
break;
|
||||
|
@ -787,8 +791,11 @@ CREATE TABLE lnav_view_filters (
|
|||
auto set_res = lnav_data.ld_log_source.set_sql_filter(
|
||||
clause, stmt.release());
|
||||
if (set_res.isErr()) {
|
||||
throw sqlite_func_error("filter expression failed with: {}",
|
||||
set_res.unwrapErr());
|
||||
tab->zErrMsg = sqlite3_mprintf(
|
||||
"%s%s",
|
||||
LNAV_SQLITE_ERROR_PREFIX,
|
||||
lnav::to_json(set_res.unwrapErr()).c_str());
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
*iter = lnav_data.ld_log_source.get_sql_filter().value();
|
||||
} else {
|
||||
|
|
|
@ -30,7 +30,39 @@
|
|||
#include "vtab_module.hh"
|
||||
|
||||
#include "config.h"
|
||||
#include "lnav_util.hh"
|
||||
|
||||
std::string vtab_module_schemas;
|
||||
|
||||
std::map<intern_string_t, std::string> vtab_module_ddls;
|
||||
|
||||
const char* LNAV_SQLITE_ERROR_PREFIX = "lnav-error:";
|
||||
|
||||
void
|
||||
to_sqlite(sqlite3_context* ctx, const lnav::console::user_message& um)
|
||||
{
|
||||
auto errmsg = fmt::format(
|
||||
FMT_STRING("{}{}"), LNAV_SQLITE_ERROR_PREFIX, lnav::to_json(um));
|
||||
|
||||
sqlite3_result_error(ctx, errmsg.c_str(), errmsg.size());
|
||||
}
|
||||
|
||||
lnav::console::user_message
|
||||
sqlite3_error_to_user_message(sqlite3* db)
|
||||
{
|
||||
const auto* errmsg = sqlite3_errmsg(db);
|
||||
if (startswith(errmsg, LNAV_SQLITE_ERROR_PREFIX)) {
|
||||
auto from_res = lnav::from_json<lnav::console::user_message>(
|
||||
&errmsg[strlen(LNAV_SQLITE_ERROR_PREFIX)]);
|
||||
|
||||
if (from_res.isOk()) {
|
||||
return from_res.unwrap();
|
||||
}
|
||||
|
||||
return lnav::console::user_message::error("internal error")
|
||||
.with_reason(from_res.unwrapErr()[0].um_message.get_string());
|
||||
}
|
||||
|
||||
return lnav::console::user_message::error("SQL statement failed")
|
||||
.with_reason(errmsg);
|
||||
}
|
||||
|
|
|
@ -38,13 +38,19 @@
|
|||
|
||||
#include "base/auto_mem.hh"
|
||||
#include "base/intern_string.hh"
|
||||
#include "base/lnav.console.hh"
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "fmt/format.h"
|
||||
#include "help_text_formatter.hh"
|
||||
#include "mapbox/variant.hpp"
|
||||
#include "optional.hpp"
|
||||
#include "sqlite-extension-func.hh"
|
||||
|
||||
extern const char* LNAV_SQLITE_ERROR_PREFIX;
|
||||
|
||||
lnav::console::user_message sqlite3_error_to_user_message(sqlite3*);
|
||||
|
||||
struct from_sqlite_conversion_error : std::exception {
|
||||
from_sqlite_conversion_error(const char* type, int argi)
|
||||
: e_type(type), e_argi(argi)
|
||||
|
@ -218,6 +224,8 @@ struct from_sqlite<vtab_types::nullable<T>> {
|
|||
}
|
||||
};
|
||||
|
||||
void to_sqlite(sqlite3_context* ctx, const lnav::console::user_message& um);
|
||||
|
||||
inline void
|
||||
to_sqlite(sqlite3_context* ctx, const char* str)
|
||||
{
|
||||
|
@ -408,7 +416,16 @@ struct sqlite_func_adapter<Return (*)(Args...), f> {
|
|||
e.e_argi);
|
||||
sqlite3_result_error(context, buffer, -1);
|
||||
} catch (const std::exception& e) {
|
||||
sqlite3_result_error(context, e.what(), -1);
|
||||
const auto* fd = (const FuncDef*) sqlite3_user_data(context);
|
||||
attr_line_t error_al;
|
||||
error_al.append("call to ");
|
||||
format_help_text_for_term(
|
||||
fd->fd_help, 40, error_al, help_text_content::synopsis);
|
||||
error_al.append(" failed");
|
||||
auto um = lnav::console::user_message::error(error_al).with_reason(
|
||||
e.what());
|
||||
|
||||
to_sqlite(context, um);
|
||||
} catch (...) {
|
||||
sqlite3_result_error(
|
||||
context, "Function threw an unexpected exception", -1);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[1m[31m✘ error[0m: filter expression failed with: unable to parse time slice value: bad -- Unrecognized input
|
||||
[1m[31m✘ error[0m: call to [1m[4mtimeslice[0m[4m([0m[4mtime[0m[4m, [0m[4mslice[0m[4m)[0m failed
|
||||
[1m[31mreason[0m: unable to parse time slice value: bad -- Unrecognized input
|
||||
[36m --> [0m[1mcommand-option[0m:1
|
||||
[36m | [0m[37m[40m:[0m[1m[36m[40mfilter-expr[0m[37m[40m [0m[1m[37m[40mtimeslice[0m[37m[40m([0m[37m[40m:log_time_msecs[0m[37m[40m, [0m[35m[40m'bad'[0m[37m[40m) [0m[1m[36m[40mis[0m[37m[40m [0m[1m[36m[40mnot[0m[37m[40m [0m[1m[36m[40mnull[0m
|
||||
[36m =[0m [36mhelp[0m: [4m:[0m[1m[4mfilter-expr[0m[4m [0m[4mexpr[0m
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
[1m[31mreason[0m: unrecognized token: "#"
|
||||
[36m --> [0m[1mcommand-option[0m:1
|
||||
[36m | [0m[37m[40m:[0m[1m[36m[40mfilter-expr[0m[37m[40m [0m[37m[40m:sc_bytes[0m[37m[40m # [0m[37m[40mff[0m[37m[40m [0m
|
||||
[36m =[0m [36mhelp[0m: [4m:[0m[1m[4mfilter-expr[0m[4m [0m[4mexpr[0m
|
||||
══════════════════════════════════════════════════════════════════════
|
||||
Set the filter expression
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
[1m[31mreason[0m: near "lik": syntax error
|
||||
[36m --> [0m[1mcommand-option[0m:1
|
||||
[36m | [0m[37m[40m:[0m[1m[36m[40mmark-expr[0m[37m[40m [0m[37m[40m:log_procname[0m[37m[40m [0m[37m[40mlik[0m[37m[40m [0m
|
||||
[36m =[0m [36mhelp[0m: [4m:[0m[1m[4mmark-expr[0m[4m [0m[4mexpr[0m
|
||||
══════════════════════════════════════════════════════════════════════
|
||||
Set the bookmark expression
|
||||
|
|
|
@ -3,3 +3,6 @@
|
|||
[36m --> [0m[1mcommand-option[0m:1
|
||||
[36m | [0m[37m[40m:[0m[1m[36m[40mcreate-search-table[0m[37m[40m search_test1 bad[0m[1m[32m[40m([0m[37m[40m [0m
|
||||
[36m | [0m[37m[40m [0m[32m[40m^ [0m[32m[40mmissing )[0m
|
||||
[36m =[0m [36mhelp[0m: [4m:[0m[1m[4mcreate-search-table[0m[4m [0m[4mtable-name[0m[4m [[0m[4mpattern[0m[4m][0m
|
||||
══════════════════════════════════════════════════════════════════════
|
||||
Create an SQL table based on a regex search
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[1m[31m✘ error[0m: SQL statement failed
|
||||
[1m[31m✘ error[0m: call to [1m[4mraise_error[0m[4m([0m[4mmsg[0m[4m)[0m failed
|
||||
[1m[31mreason[0m: oops!
|
||||
[36m --> [0m[1mcommand-option[0m:1
|
||||
[36m | [0m[37m[40m;[0m[1m[36m[40mSELECT[0m[37m[40m [0m[1m[37m[40mraise_error[0m[37m[40m([0m[35m[40m'oops!'[0m[37m[40m) [0m
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[1m[31m✘ error[0m: SQL statement failed
|
||||
[1m[31m✘ error[0m: call to [1m[4mraise_error[0m[4m([0m[4mmsg[0m[4m)[0m failed
|
||||
[1m[31mreason[0m: no data was redirected to lnav's standard-input
|
||||
[36m --> [0m[1mcommand-option[0m:1
|
||||
[36m | [0m[37m[40m|rename-stdin foo [0m
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[1m[31m✘ error[0m: SQL statement failed
|
||||
[1m[31m✘ error[0m: call to [1m[4mraise_error[0m[4m([0m[4mmsg[0m[4m)[0m failed
|
||||
[1m[31mreason[0m: expecting the new name for stdin as the first argument
|
||||
[36m --> [0m[1mcommand-option[0m:1
|
||||
[36m | [0m[37m[40m|rename-stdin [0m
|
||||
|
|
|
@ -1 +1 @@
|
|||
error: sqlite3_exec failed -- unable to stat path: non-existent-link -- No such file or directory
|
||||
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to readlink(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":44},{"start":17,"end":21,"type":"role","value":43},{"start":8,"end":22,"type":"role","value":57}]},"reason":{"str":"unable to stat path: non-existent-link -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
|
||||
|
|
|
@ -1 +1 @@
|
|||
error: sqlite3_exec failed -- Could not get real path for non-existent-path -- No such file or directory
|
||||
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to realpath(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":44},{"start":17,"end":21,"type":"role","value":43},{"start":8,"end":22,"type":"role","value":57}]},"reason":{"str":"Could not get real path for non-existent-path -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
error: sqlite3_exec failed -- parse error: premature EOF
|
||||
["hi", "bye", "solong]
|
||||
(right here) ------^
|
||||
|
||||
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to json_contains(json, value) failed","attrs":[{"start":8,"end":21,"type":"role","value":44},{"start":22,"end":26,"type":"role","value":43},{"start":28,"end":33,"type":"role","value":43},{"start":8,"end":34,"type":"role","value":57}]},"reason":{"str":"parse error: premature EOF\n [\"hi\", \"bye\", \"solong]\n (right here) ------^","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
|
||||
|
|
|
@ -1 +1 @@
|
|||
error: sqlite3_exec failed -- regular expression does not have any captures
|
||||
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to regexp_match(re, str) failed","attrs":[{"start":8,"end":20,"type":"role","value":44},{"start":21,"end":23,"type":"role","value":43},{"start":25,"end":28,"type":"role","value":43},{"start":8,"end":29,"type":"role","value":57}]},"reason":{"str":"regular expression does not have any captures","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
|
||||
|
|
|
@ -1 +1 @@
|
|||
error: sqlite3_exec failed -- unable to parse time slice value: blah -- Unrecognized input
|
||||
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":44},{"start":18,"end":22,"type":"role","value":43},{"start":24,"end":29,"type":"role","value":43},{"start":8,"end":30,"type":"role","value":57}]},"reason":{"str":"unable to parse time slice value: blah -- Unrecognized input","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
|
||||
|
|
|
@ -1 +1 @@
|
|||
error: sqlite3_exec failed -- no time slice value given
|
||||
error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":44},{"start":18,"end":22,"type":"role","value":43},{"start":24,"end":29,"type":"role","value":43},{"start":8,"end":30,"type":"role","value":57}]},"reason":{"str":"no time slice value given","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
|
||||
|
|
Loading…
Reference in New Issue