[error] leverage sqlite3_error_offset

pull/824/merge
Timothy Stack 2 years ago
parent 8b3b8a6e3c
commit f3934c742d

@ -1,6 +1,6 @@
# aminclude_static.am generated automatically by Autoconf
# from AX_AM_MACROS_STATIC on Sat Jun 4 14:05:13 PDT 2022
# from AX_AM_MACROS_STATIC on Fri Jul 8 09:28:15 PDT 2022
# Code coverage

@ -97,6 +97,14 @@ AC_DEFUN([LNAV_WITH_SQLITE3],
AC_SUBST(HAVE_SQLITE3_VALUE_SUBTYPE)
AC_CHECK_FUNC(sqlite3_error_offset,
AC_DEFINE([HAVE_SQLITE3_ERROR_OFFSET], [],
[Have the sqlite3_error_offset function]
)
)
AC_SUBST(HAVE_SQLITE3_ERROR_OFFSET)
AS_VAR_SET(CFLAGS, $saved_CFLAGS)
AS_VAR_SET(CPPFLAGS, $saved_CPPFLAGS)
AS_VAR_SET(LDFLAGS, $saved_LDFLAGS)

@ -38,9 +38,8 @@ if test ! -f "configure"; then
./autogen.sh
rm -rf ~/github/lbuild
mkdir -p ~/github/lbuild
cd ~/github/lbuild
fi
cd ~/github/lbuild
TARGET_FILE='/vagrant/lnav-linux.zip'
if test x"${OS}" != x"FreeBSD"; then

@ -37,6 +37,9 @@
namespace lnav {
namespace pid {
bool in_child = false;
Result<auto_pid<process_state::running>, std::string>
from_fork()
{
@ -49,9 +52,12 @@ from_fork()
if (pid != 0) {
log_debug("started child: %d", pid);
} else {
in_child = true;
}
return Ok(auto_pid<process_state::running>(pid));
}
} // namespace pid
} // namespace lnav

@ -165,6 +165,9 @@ private:
namespace lnav {
namespace pid {
extern bool in_child;
Result<auto_pid<process_state::running>, std::string> from_fork();
} // namespace pid
} // namespace lnav

@ -35,6 +35,7 @@
#include <string>
#include <vector>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
@ -172,6 +173,50 @@ struct string_fragment {
return nonstd::nullopt;
}
template<typename P>
string_fragment find_left_boundary(size_t start, P&& predicate) const
{
assert(start < this->length());
while (start > 0) {
if (predicate(this->data()[start])) {
start += 1;
break;
}
start -= 1;
}
return string_fragment{
this->sf_string,
(int) start,
this->sf_end,
};
}
template<typename P>
string_fragment find_right_boundary(size_t start, P&& predicate) const
{
while (start < this->length()) {
if (predicate(this->data()[start])) {
break;
}
start += 1;
}
return string_fragment{
this->sf_string,
this->sf_begin,
this->sf_begin + (int) start,
};
}
template<typename P>
string_fragment find_boundaries_around(size_t start, P&& predicate) const
{
return this->template find_left_boundary(start, predicate)
.find_right_boundary(0, predicate);
}
template<typename P>
nonstd::optional<string_fragment> consume(P predicate) const
{
@ -216,7 +261,7 @@ struct string_fragment {
= nonstd::optional<std::pair<string_fragment, string_fragment>>;
template<typename P>
split_result split_while(P& predicate) const
split_result split_while(P&& predicate) const
{
int consumed = 0;
while (consumed < this->length()) {

@ -110,3 +110,35 @@ TEST_CASE("consume")
CHECK(empty.has_value());
CHECK(empty->empty());
}
TEST_CASE("find_left_boundary")
{
std::string in1 = "Hello,\nWorld!\n";
{
auto sf = string_fragment{in1};
auto world_sf = sf.find_left_boundary(
in1.length() - 3, [](auto ch) { return ch == '\n'; });
CHECK(world_sf.to_string() == "World!\n");
auto full_sf
= sf.find_left_boundary(3, [](auto ch) { return ch == '\n'; });
CHECK(full_sf.to_string() == in1);
}
}
TEST_CASE("find_right_boundary")
{
std::string in1 = "Hello,\nWorld!\n";
{
auto sf = string_fragment{in1};
auto world_sf = sf.find_right_boundary(
in1.length() - 3, [](auto ch) { return ch == '\n'; });
CHECK(world_sf.to_string() == "Hello,\nWorld!");
auto hello_sf
= sf.find_right_boundary(3, [](auto ch) { return ch == '\n'; });
CHECK(hello_sf.to_string() == "Hello,");
}
}

@ -324,7 +324,8 @@ println(FILE* file, const attr_line_t& al)
switch (role) {
case role_t::VCR_ERROR:
line_style |= fmt::fg(fmt::terminal_color::red);
line_style |= fmt::fg(fmt::terminal_color::red)
| fmt::emphasis::bold;
break;
case role_t::VCR_WARNING:
case role_t::VCR_RE_REPEAT:
@ -349,6 +350,9 @@ println(FILE* file, const attr_line_t& al)
line_style |= fmt::emphasis::bold
| fmt::fg(fmt::terminal_color::cyan);
break;
case role_t::VCR_STRING:
line_style |= fmt::fg(fmt::terminal_color::magenta);
break;
case role_t::VCR_VARIABLE:
line_style |= fmt::emphasis::underline;
break;

@ -20,6 +20,10 @@
#define HAVE_SQLITE3_STMT_READONLY
#define HAVE_SQLITE3_VALUE_SUBTYPE
#define HAVE_SQLITE3_ERROR_OFFSET
#define _XOPEN_SOURCE_EXTENDED 1
#define PACKAGE_BUGREPORT "lnav@googlegroups.com"

@ -39,6 +39,7 @@
#include <sys/wait.h>
#include <unistd.h>
#include "base/auto_pid.hh"
#include "base/lnav_log.hh"
#include "base/opt_util.hh"
#include "base/string_util.hh"
@ -137,6 +138,7 @@ grep_proc<LineType>::start()
}
/* In the child... */
lnav::pid::in_child = true;
/*
* Restore the default signal handlers so we don't hang around
@ -355,6 +357,8 @@ grep_proc<LineType>::check_poll_set(const std::vector<struct pollfd>& pollfds)
= this->gp_line_buffer.load_next_line(this->gp_pipe_range);
if (load_result.isErr()) {
log_error("failed to read from grep_proc child: %s",
load_result.unwrapErr().c_str());
break;
}
@ -417,7 +421,7 @@ grep_proc<LineType>::update_poll_set(std::vector<struct pollfd>& pollfds)
pollfds.push_back(
(struct pollfd){this->gp_line_buffer.get_fd(), POLLIN, 0});
}
if (this->gp_err_pipe != -1) {
if (this->gp_err_pipe.get() != -1) {
pollfds.push_back((struct pollfd){this->gp_err_pipe, POLLIN, 0});
}
}

@ -48,6 +48,7 @@
# include "simdutf8check.h"
#endif
#include "base/auto_pid.hh"
#include "base/injector.bind.hh"
#include "base/injector.hh"
#include "base/is_utf8.hh"
@ -683,7 +684,7 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
this->lb_file_offset,
this->lb_buffer.size());
#endif
if (this->lb_loader_future.valid()
if (!lnav::pid::in_child && this->lb_loader_future.valid()
&& start >= this->lb_loader_file_offset.value())
{
#if 0
@ -718,8 +719,9 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
if (this->in_range(start) && this->in_range(start + max_length - 1)) {
/* Cache already has the data, nothing to do. */
retval = true;
if (this->lb_seekable && this->lb_buffer.full()
&& !this->lb_loader_file_offset) {
if (!lnav::pid::in_child && this->lb_seekable && this->lb_buffer.full()
&& !this->lb_loader_file_offset)
{
// log_debug("loader available start=%d", start);
auto last_lf_iter = std::find(
this->lb_buffer.rbegin(), this->lb_buffer.rend(), '\n');
@ -900,8 +902,9 @@ line_buffer::fill_range(file_off_t start, ssize_t max_length)
break;
}
if (this->lb_seekable && this->lb_buffer.full()
&& !this->lb_loader_file_offset) {
if (!lnav::pid::in_child && this->lb_seekable && this->lb_buffer.full()
&& !this->lb_loader_file_offset)
{
// log_debug("loader available2 start=%d", start);
auto last_lf_iter = std::find(
this->lb_buffer.rbegin(), this->lb_buffer.rend(), '\n');

@ -1497,6 +1497,9 @@ vt_best_index(sqlite3_vtab* tab, sqlite3_index_info* p_info)
p_info->idxStr = static_cast<char*>(storage);
p_info->needToFreeIdxStr = 1;
p_info->estimatedCost = 10.0;
} else {
p_info->idxStr = "fullscan";
p_info->estimatedCost = 1000000000.0;
}
return SQLITE_OK;

@ -33,6 +33,8 @@
#include "lnav.hh"
#include "logfile_sub_source.hh"
using namespace lnav::roles::literals;
class filtered_sub_source
: public text_sub_source
, public text_time_translator {
@ -331,13 +333,12 @@ db_spectro_value_source::update_stats()
if (!dls.has_log_time_column()) {
if (dls.dls_time_column_invalidated_at) {
static const auto order_by_help
= attr_line_t()
.append(lnav::roles::keyword("ORDER BY"))
.append(" ")
.append(lnav::roles::variable("log_time"))
.append(" ")
.append(lnav::roles::keyword("ASC"));
static const auto order_by_help = attr_line_t()
.append("ORDER BY"_keyword)
.append(" ")
.append("log_time"_variable)
.append(" ")
.append("ASC"_keyword);
this->dsvs_error_msg
= lnav::console::user_message::error(
@ -345,7 +346,7 @@ db_spectro_value_source::update_stats()
.with_reason(
attr_line_t()
.append("The ")
.append_quoted(lnav::roles::variable("log_time"))
.append_quoted("log_time"_variable)
.appendf(
FMT_STRING(" column is not in ascending "
"order between rows {} and {}"),
@ -354,13 +355,13 @@ db_spectro_value_source::update_stats()
dls.dls_time_column_invalidated_at.value()))
.with_note(
attr_line_t("An ascending ")
.append_quoted(lnav::roles::variable("log_time"))
.append_quoted("log_time"_variable)
.append(
" column is needed to render a spectrogram"))
.with_help(attr_line_t("Add an ")
.append_quoted(order_by_help)
.append(" clause to your ")
.append(lnav::roles::keyword("SELECT"))
.append("SELECT"_keyword)
.append(" statement"));
} else {
this->dsvs_error_msg
@ -369,19 +370,19 @@ db_spectro_value_source::update_stats()
.with_reason(
attr_line_t()
.append("No ")
.append_quoted(lnav::roles::variable("log_time"))
.append_quoted("log_time"_variable)
.append(" column found in the result set"))
.with_note(
attr_line_t("An ascending ")
.append_quoted(lnav::roles::variable("log_time"))
.append_quoted("log_time"_variable)
.append(
" column is needed to render a spectrogram"))
.with_help(
attr_line_t("Include a ")
.append_quoted(lnav::roles::variable("log_time"))
.append_quoted("log_time"_variable)
.append(" column in your ")
.append(" statement. Use an ")
.append(lnav::roles::keyword("AS"))
.append("AS"_keyword)
.append(
" directive to alias a computed timestamp"));
}

@ -52,6 +52,8 @@
#include "sql_help.hh"
#include "sqlite-extension-func.hh"
using namespace lnav::roles::literals;
/**
* Copied from -- http://www.sqlite.org/lang_keywords.html
*/
@ -702,17 +704,51 @@ sql_compile_script(sqlite3* db,
log_debug("retcode %d %p %p", retcode, script, tail);
if (retcode != SQLITE_OK) {
const char* errmsg = sqlite3_errmsg(db);
int erroff = -1;
attr_line_t sql_content;
#if defined(HAVE_SQLITE3_ERROR_OFFSET)
erroff = sqlite3_error_offset(db);
#endif
if (tail != nullptr) {
const auto* tail_lf = strchr(tail, '\n');
if (tail_lf == nullptr) {
tail = tail + strlen(tail);
} else {
tail = tail_lf;
}
sql_content.append(
string_fragment{script, 0, (int) (tail - script)});
} else {
sql_content.append(script);
}
if (erroff >= sql_content.length()) {
erroff -= 1;
}
if (erroff != -1 && !endswith(sql_content.get_string(), "\n")) {
sql_content.append("\n");
}
sql_content.with_attr_for_all(
VC_ROLE.value(role_t::VCR_QUOTED_CODE));
readline_sqlite_highlighter(sql_content, sql_content.length());
if (erroff != -1) {
auto line_with_error
= string_fragment(sql_content.get_string())
.find_boundaries_around(erroff,
string_fragment::tag1{'\n'});
auto erroff_in_line = erroff - line_with_error.sf_begin;
attr_line_t pointer;
pointer.append(erroff_in_line, ' ')
.append("^ "_snippet_border)
.append(lnav::roles::error(errmsg))
.append("\n");
sql_content.insert(line_with_error.sf_end + 1, pointer).rtrim();
}
errors.emplace_back(
lnav::console::user_message::error(
"failed to compile SQL statement")

@ -326,58 +326,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 \

@ -1,7 +1,7 @@
✘ error: invalid value for “-c” option
✘ error: invalid value for “-c” option
 --> command-line argument
 |  -c foo 
 |  ^ command type prefix is missing
 |  ^ command type prefix is missing
 = help: command arguments must start with one of the following symbols to denote the type of command:
: - an lnav command (e.g. :goto 42)
; - an SQL statement (e.g. ;SELECT * FROM syslog_log)

@ -1,4 +1,4 @@
✘ error: no log files loaded
✘ error: no log files loaded
 --> command-option:2
 | :close 
 = help: :close

@ -1,6 +1,6 @@
✘ error: filter expression failed with: unable to parse time slice value: bad -- Unrecognized input
✘ error: filter expression failed with: unable to parse time slice value: bad -- Unrecognized input
 --> command-option:1
 | :filter-expr timeslice(:log_time_msecs, 'bad') is not null
 | :filter-expr timeslice(:log_time_msecs, 'bad') is not null
 = help: :filter-expr expr
══════════════════════════════════════════════════════════════════════
Set the filter expression

@ -1,4 +1,4 @@
✘ error: highlight does not exist -- foobar
✘ error: highlight does not exist -- foobar
 --> command-option:1
 | :clear-highlight foobar 
 = help: :clear-highlight pattern

@ -1,4 +1,4 @@
✘ error: expecting file name or '-' to write to the terminal
✘ error: expecting file name or '-' to write to the terminal
 --> command-option:1
 | :write-to 
 = help: :write-to path

@ -1,4 +1,4 @@
✘ error: invalid filter expression: :sc_bytes # ff
reason: unrecognized token: "#"
✘ error: invalid filter expression: :sc_bytes # ff
reason: unrecognized token: "#"
 --> command-option:1
 | :filter-expr :sc_bytes # ff 

@ -1,5 +1,5 @@
✘ error: cannot open file: /non-existent
reason: No such file or directory
✘ error: cannot open file: /non-existent
reason: No such file or directory
 --> command-option:2
 | :open /non-existent 
 = help: make sure the file exists and is accessible

@ -1,4 +1,4 @@
✘ error: unknown bookmark type: foobar
✘ error: unknown bookmark type: foobar
 --> command-option:2
 | :next-mark foobar 
 = help: available types: error, warning, file, user, user-expr, search, meta

@ -1,4 +1,4 @@
✘ error: expecting file name to open
✘ error: expecting file name to open
 --> command-option:1
 | :open 
 = help: :open path1 [... pathN]

@ -1,4 +1,4 @@
✘ error: invalid zoom level: bad
✘ error: invalid zoom level: bad
 --> command-option:1
 | :zoom-to bad 
 = help: available levels: 1-second, 30-second, 1-minute, 5-minute, 15-minute, 1-hour, 4-hour, 8-hour, 1-day, 1-week

@ -1,4 +1,4 @@
✘ error: expecting an SQL expression
✘ error: expecting an SQL expression
 --> command-option:1
 | :mark-expr 
 = help: :mark-expr expr

@ -1,4 +1,4 @@
✘ error: expecting a unix time value
✘ error: expecting a unix time value
 --> command-option:1
 | :unix-time 
 = help: :unix-time seconds

@ -1,3 +1,3 @@
✘ error: unknown script -- nonexistent.lnav -- file not found
✘ error: unknown script -- nonexistent.lnav -- file not found
 --> command-option:1
 | |nonexistent.lnav 

@ -1,4 +1,4 @@
✘ error: write-json-to -- unavailable in secure mode
✘ error: write-json-to -- unavailable in secure mode
 --> command-option:2
 | :write-json-to - 
 = help: :write-json-to path

@ -1,4 +1,4 @@
✘ error: unknown configuration option -- /bad/option
✘ error: unknown configuration option -- /bad/option
 --> command-option:1
 | :config /bad/option 
 = help: :config option [value]

@ -1,4 +1,4 @@
✘ error: filter limit reached, try combining filters with a pipe symbol (e.g. foo|bar)
✘ error: filter limit reached, try combining filters with a pipe symbol (e.g. foo|bar)
 --> command-option:32
 | :filter-out 32 
 = help: :filter-out pattern

@ -544,7 +544,7 @@ you can attach another database and create tables in that database.
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; 
;ATTACH DATABASE '/tmp/topten.db' AS topten; 
;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; 
@ -621,16 +621,16 @@ Access to lnav's environment variables is also available via the
read and written to using SQL SELECT, INSERT, UPDATE, and DELETE
statements. For example, to set the "FOO" variable to the value "BAR":
;INSERT INTO environ SELECT 'FOO', 'BAR'; 
;INSERT INTO environ SELECT 'FOO', 'BAR'; 
As a more complex example, you can set the variable "LAST" to the last
syslog line number by doing:
;INSERT INTO environ SELECT 'LAST', (SELECT max(log_line) FROM syslog_log); 
;INSERT INTO environ SELECT 'LAST', (SELECT max(log_line) FROM syslog_log); 
A delete will unset the environment variable:
;DELETE FROM environ WHERE name='LAST'; 
;DELETE FROM environ WHERE name='LAST'; 
The table allows you to easily use the results of a SQL query in lnav
commands, which is especially useful when scripting lnav.
@ -966,12 +966,12 @@ lnav@googlegroups.com[1] support@lnav.org[2]
:hide-lines-before, :hide-unmarked-lines, :toggle-filtering
Examples
#1 To set a filter expression that matched syslog messages from 'syslogd':
:filter-expr :log_procname = 'syslogd' 
:filter-expr :log_procname = 'syslogd' 
#2 To set a filter expression that matches log messages where 'id' is followed by a
number and contains the string 'foo':
:filter-expr :log_body REGEXP 'id\d+' AND :log_body REGEXP 'foo'
:filter-expr :log_body REGEXP 'id\d+' AND :log_body REGEXP 'foo'
@ -1140,7 +1140,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
:clear-mark-expr, :hide-unmarked-lines, :mark, :next-mark, :prev-mark
Example
#1 To mark lines from 'dhclient' that mention 'eth0':
:mark-expr :log_procname = 'dhclient' AND :log_body LIKE '%eth0%'
:mark-expr :log_procname = 'dhclient' AND :log_body LIKE '%eth0%'
@ -1904,27 +1904,27 @@ lnav@googlegroups.com[1] support@lnav.org[2]
dirname(), joinpath(), readlink(), realpath()
Examples
#1 To get the base of a plain file name:
;SELECT basename('foobar') 
;SELECT basename('foobar') 
#2 To get the base of a path:
;SELECT basename('foo/bar') 
;SELECT basename('foo/bar') 
#3 To get the base of a directory:
;SELECT basename('foo/bar/') 
;SELECT basename('foo/bar/') 
#4 To get the base of an empty string:
;SELECT basename('') 
;SELECT basename('') 
#5 To get the base of a Windows path:
;SELECT basename('foo\bar') 
;SELECT basename('foo\bar') 
#6 To get the base of the root directory:
;SELECT basename('/') 
;SELECT basename('/') 
@ -1990,11 +1990,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To search for the string 'abc' within 'abcabc' and starting at position 2:
;SELECT charindex('abc', 'abcabc', 2) 
;SELECT charindex('abc', 'abcabc', 2) 
#2 To search for the string 'abc' within 'abcdef' and starting at position 2:
;SELECT charindex('abc', 'abcdef', 2) 
;SELECT charindex('abc', 'abcdef', 2) 
@ -2047,15 +2047,15 @@ lnav@googlegroups.com[1] support@lnav.org[2]
datetime(), julianday(), strftime(), time(), timediff(), timeslice()
Examples
#1 To get the date portion of the timestamp '2017-01-02T03:04:05':
;SELECT date('2017-01-02T03:04:05') 
;SELECT date('2017-01-02T03:04:05') 
#2 To get the date portion of the timestamp '2017-01-02T03:04:05' plus one day:
;SELECT date('2017-01-02T03:04:05', '+1 day') 
;SELECT date('2017-01-02T03:04:05', '+1 day') 
#3 To get the date portion of the epoch timestamp 1491341842:
;SELECT date(1491341842, 'unixepoch') 
;SELECT date(1491341842, 'unixepoch') 
@ -2070,16 +2070,16 @@ lnav@googlegroups.com[1] support@lnav.org[2]
date(), julianday(), strftime(), time(), timediff(), timeslice()
Examples
#1 To get the date and time portion of the timestamp '2017-01-02T03:04:05':
;SELECT datetime('2017-01-02T03:04:05') 
;SELECT datetime('2017-01-02T03:04:05') 
#2 To get the date and time portion of the timestamp '2017-01-02T03:04:05' plus one
minute:
;SELECT datetime('2017-01-02T03:04:05', '+1 minute')
;SELECT datetime('2017-01-02T03:04:05', '+1 minute')
#3 To get the date and time portion of the epoch timestamp 1491341842:
;SELECT datetime(1491341842, 'unixepoch') 
;SELECT datetime(1491341842, 'unixepoch') 
@ -2115,23 +2115,23 @@ lnav@googlegroups.com[1] support@lnav.org[2]
basename(), joinpath(), readlink(), realpath()
Examples
#1 To get the directory of a relative file path:
;SELECT dirname('foo/bar') 
;SELECT dirname('foo/bar') 
#2 To get the directory of an absolute file path:
;SELECT dirname('/foo/bar') 
;SELECT dirname('/foo/bar') 
#3 To get the directory of a file in the root directory:
;SELECT dirname('/bar') 
;SELECT dirname('/bar') 
#4 To get the directory of a Windows path:
;SELECT dirname('foo\bar') 
;SELECT dirname('foo\bar') 
#5 To get the directory of an empty path:
;SELECT dirname('') 
;SELECT dirname('') 
@ -2151,11 +2151,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To test if the string 'notbad.jpg' ends with '.jpg':
;SELECT endswith('notbad.jpg', '.jpg') 
;SELECT endswith('notbad.jpg', '.jpg') 
#2 To test if the string 'notbad.png' starts with '.jpg':
;SELECT endswith('notbad.png', '.jpg') 
;SELECT endswith('notbad.png', '.jpg') 
@ -2190,11 +2190,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To extract key/value pairs from a string:
;SELECT extract('foo=1 bar=2 name="Rolo Tomassi"') 
;SELECT extract('foo=1 bar=2 name="Rolo Tomassi"') 
#2 To extract columnar data from a string:
;SELECT extract('1.0 abc 2.0') 
;SELECT extract('1.0 abc 2.0') 
@ -2257,7 +2257,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
gethostbyname()
Example
#1 To get the hostname for the IP '127.0.0.1':
;SELECT gethostbyaddr('127.0.0.1') 
;SELECT gethostbyaddr('127.0.0.1') 
@ -2270,7 +2270,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
gethostbyaddr()
Example
#1 To get the IP address for 'localhost':
;SELECT gethostbyname('localhost') 
;SELECT gethostbyname('localhost') 
@ -2283,7 +2283,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Example
#1 To test if the string 'abc' matches the glob 'a*':
;SELECT glob('a*', 'abc') 
;SELECT glob('a*', 'abc') 
@ -2309,7 +2309,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
#2 To join the values of the column 'ex_procname' using the string ', ':
;SELECT group_concat(ex_procname, ', ') FROM lnav_example_log
;SELECT group_concat(ex_procname, ', ') FROM lnav_example_log
#3 To concatenate the distinct values of the column 'ex_procname' from the table
@ -2333,7 +2333,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
substr(), trim(), unicode(), upper(), xpath()
Example
#1 To produce a hash of all of the values of 'column1':
;SELECT group_spooky_hash(column1) FROM (VALUES ('abc'), ('123'))
;SELECT group_spooky_hash(column1) FROM (VALUES ('abc'), ('123'))
@ -2375,7 +2375,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Example
#1 To get the hexadecimal rendering of the string 'abc':
;SELECT hex('abc') 
;SELECT hex('abc') 
@ -2430,7 +2430,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To test get the position of 'b' in the string 'abc':
;SELECT instr('abc', 'b') 
;SELECT instr('abc', 'b') 
@ -2446,15 +2446,15 @@ lnav@googlegroups.com[1] support@lnav.org[2]
json_group_object()
Examples
#1 To get the root of a JSON value:
;SELECT jget('1', '') 
;SELECT jget('1', '') 
#2 To get the property named 'b' in a JSON object:
;SELECT jget('{ "a": 1, "b": 2 }', '/b') 
;SELECT jget('{ "a": 1, "b": 2 }', '/b') 
#3 To get the 'msg' property and return a default if it does not exist:
;SELECT jget(null, '/msg', 'Hello') 
;SELECT jget(null, '/msg', 'Hello') 
@ -2470,19 +2470,19 @@ lnav@googlegroups.com[1] support@lnav.org[2]
basename(), dirname(), readlink(), realpath()
Examples
#1 To join a directory and file name into a relative path:
;SELECT joinpath('foo', 'bar') 
;SELECT joinpath('foo', 'bar') 
#2 To join an empty component with other names into a relative path:
;SELECT joinpath('', 'foo', 'bar') 
;SELECT joinpath('', 'foo', 'bar') 
#3 To create an absolute path with two path components:
;SELECT joinpath('/', 'foo', 'bar') 
;SELECT joinpath('/', 'foo', 'bar') 
#4 To create an absolute path from a path component that starts with a forward slash:
;SELECT joinpath('/', 'foo', '/bar') 
;SELECT joinpath('/', 'foo', '/bar') 
@ -2505,11 +2505,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
#2 To append 4 and 5 to the array [1, 2, 3]:
;SELECT json_concat('[1, 2, 3]', 4, 5) 
;SELECT json_concat('[1, 2, 3]', 4, 5) 
#3 To concatenate two arrays together:
;SELECT json_concat('[1, 2, 3]', json('[4, 5]')) 
;SELECT json_concat('[1, 2, 3]', json('[4, 5]')) 
@ -2523,11 +2523,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
jget(), json_concat(), json_group_array(), json_group_object()
Examples
#1 To test if a JSON array contains the number 4:
;SELECT json_contains('[1, 2, 3]', 4) 
;SELECT json_contains('[1, 2, 3]', 4) 
#2 To test if a JSON array contains the string 'def':
;SELECT json_contains('["abc", "def"]', 'def') 
;SELECT json_contains('["abc", "def"]', 'def') 
@ -2540,7 +2540,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
jget(), json_concat(), json_contains(), json_group_object()
Examples
#1 To create an array from arguments:
;SELECT json_group_array('one', 2, 3.4) 
;SELECT json_group_array('one', 2, 3.4) 
#2 To create an array from a column of values:
@ -2558,11 +2558,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
jget(), json_concat(), json_contains(), json_group_array()
Examples
#1 To create an object from arguments:
;SELECT json_group_object('a', 1, 'b', 2) 
;SELECT json_group_object('a', 1, 'b', 2) 
#2 To create an object from a pair of columns:
;SELECT json_group_object(column1, column2) FROM (VALUES ('a', 1), ('b', 2))
;SELECT json_group_object(column1, column2) FROM (VALUES ('a', 1), ('b', 2))
@ -2578,15 +2578,15 @@ lnav@googlegroups.com[1] support@lnav.org[2]
date(), datetime(), strftime(), time(), timediff(), timeslice()
Examples
#1 To get the julian day from the timestamp '2017-01-02T03:04:05':
;SELECT julianday('2017-01-02T03:04:05') 
;SELECT julianday('2017-01-02T03:04:05') 
#2 To get the julian day from the timestamp '2017-01-02T03:04:05' plus one minute:
;SELECT julianday('2017-01-02T03:04:05', '+1 minute')
;SELECT julianday('2017-01-02T03:04:05', '+1 minute')
#3 To get the julian day from the timestamp 1491341842:
;SELECT julianday(1491341842, 'unixepoch') 
;SELECT julianday(1491341842, 'unixepoch') 
@ -2649,11 +2649,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To get the first character of the string 'abc':
;SELECT leftstr('abc', 1) 
;SELECT leftstr('abc', 1) 
#2 To get the first ten characters of a string, regardless of size:
;SELECT leftstr('abc', 10) 
;SELECT leftstr('abc', 10) 
@ -2673,7 +2673,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To get the length of the string 'abc':
;SELECT length('abc') 
;SELECT length('abc') 
@ -2690,11 +2690,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Examples
#1 To test if the string 'aabcc' contains the letter 'b':
;SELECT like('%b%', 'aabcc') 
;SELECT like('%b%', 'aabcc') 
#2 To test if the string 'aab%' ends with 'b%':
;SELECT like('%b:%', 'aab%', ':') 
;SELECT like('%b:%', 'aab%', ':') 
@ -2792,7 +2792,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To extract key/value pairs from a log message:
;SELECT logfmt2json('foo=1 bar=2 name="Rolo Tomassi"')
;SELECT logfmt2json('foo=1 bar=2 name="Rolo Tomassi"')
@ -2812,7 +2812,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To lowercase the string 'AbC':
;SELECT lower('AbC') 
;SELECT lower('AbC') 
@ -2833,11 +2833,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To trim the leading whitespace from the string ' abc':
;SELECT ltrim(' abc') 
;SELECT ltrim(' abc') 
#2 To trim the characters 'a' or 'b' from the left side of the string 'aaaabbbc':
;SELECT ltrim('aaaabbbc', 'ab') 
;SELECT ltrim('aaaabbbc', 'ab') 
@ -2940,11 +2940,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To pad the string 'abc' to a length of six characters:
;SELECT padc('abc', 6) || 'def' 
;SELECT padc('abc', 6) || 'def' 
#2 To pad the string 'abcdef' to a length of eight characters:
;SELECT padc('abcdef', 8) || 'ghi' 
;SELECT padc('abcdef', 8) || 'ghi' 
@ -2965,11 +2965,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To pad the string 'abc' to a length of six characters:
;SELECT padl('abc', 6) 
;SELECT padl('abc', 6) 
#2 To pad the string 'abcdef' to a length of four characters:
;SELECT padl('abcdef', 4) 
;SELECT padl('abcdef', 4) 
@ -2990,11 +2990,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To pad the string 'abc' to a length of six characters:
;SELECT padr('abc', 6) || 'def' 
;SELECT padr('abc', 6) || 'def' 
#2 To pad the string 'abcdef' to a length of four characters:
;SELECT padr('abcdef', 4) || 'ghi' 
;SELECT padr('abcdef', 4) || 'ghi' 
@ -3055,15 +3055,15 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To substitute 'World' into the string 'Hello, %s!':
;SELECT printf('Hello, %s!', 'World') 
;SELECT printf('Hello, %s!', 'World') 
#2 To right-align 'small' in the string 'align:' with a column width of 10:
;SELECT printf('align: % 10s', 'small') 
;SELECT printf('align: % 10s', 'small') 
#3 To format 11 with a width of five characters and leading zeroes:
;SELECT printf('value: %05d', 11) 
;SELECT printf('value: %05d', 11) 
@ -3082,7 +3082,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To capitalize the words in the string 'hello, world!':
;SELECT proper('hello, world!') 
;SELECT proper('hello, world!') 
@ -3095,11 +3095,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Examples
#1 To quote the string 'abc':
;SELECT quote('abc') 
;SELECT quote('abc') 
#2 To quote the string 'abc'123':
;SELECT quote('abc''123') 
;SELECT quote('abc''123') 
@ -3204,7 +3204,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
substr(), trim(), unicode(), upper(), xpath()
Example
#1 To extract the key/value pairs 'a'/1 and 'b'/2 from the string 'a=1; b=2':
;SELECT * FROM regexp_capture('a=1; b=2', '(\w+)=(\d+)')
;SELECT * FROM regexp_capture('a=1; b=2', '(\w+)=(\d+)')
@ -3232,7 +3232,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
substr(), trim(), unicode(), upper(), xpath()
Example
#1 To extract the key/value pairs 'a'/1 and 'b'/2 from the string 'a=1; b=2':
;SELECT * FROM regexp_capture_into_json('a=1; b=2', '(\w+)=(\d+)')
;SELECT * FROM regexp_capture_into_json('a=1; b=2', '(\w+)=(\d+)')
@ -3254,17 +3254,17 @@ lnav@googlegroups.com[1] support@lnav.org[2]
upper(), xpath()
Examples
#1 To capture the digits from the string '123':
;SELECT regexp_match('(\d+)', '123') 
;SELECT regexp_match('(\d+)', '123') 
#2 To capture a number and word into a JSON object with the properties 'col_0' and
'col_1':
;SELECT regexp_match('(\d+) (\w+)', '123 four') 
;SELECT regexp_match('(\d+) (\w+)', '123 four') 
#3 To capture a number and word into a JSON object with the named properties 'num' and
'str':
;SELECT regexp_match('(?<num>\d+) (?<str>\w+)', '123 four')
;SELECT regexp_match('(?<num>\d+) (?<str>\w+)', '123 four')
@ -3288,11 +3288,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
upper(), xpath()
Examples
#1 To replace the word at the start of the string 'Hello, World!' with 'Goodbye':
;SELECT regexp_replace('Hello, World!', '^(\w+)', 'Goodbye')
;SELECT regexp_replace('Hello, World!', '^(\w+)', 'Goodbye')
#2 To wrap alphanumeric words with angle brackets:
;SELECT regexp_replace('123 abc', '(\w+)', '<\1>') 
;SELECT regexp_replace('123 abc', '(\w+)', '<\1>') 
@ -3316,11 +3316,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
upper(), xpath()
Examples
#1 To replace the string 'x' with 'z' in 'abc':
;SELECT replace('abc', 'x', 'z') 
;SELECT replace('abc', 'x', 'z') 
#2 To replace the string 'a' with 'z' in 'abc':
;SELECT replace('abc', 'a', 'z') 
;SELECT replace('abc', 'a', 'z') 
@ -3341,7 +3341,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Example
#1 To repeat the string 'abc' three times:
;SELECT replicate('abc', 3) 
;SELECT replicate('abc', 3) 
@ -3361,7 +3361,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
upper(), xpath()
Example
#1 To reverse the string 'abc':
;SELECT reverse('abc') 
;SELECT reverse('abc') 
@ -3383,11 +3383,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Examples
#1 To get the last character of the string 'abc':
;SELECT rightstr('abc', 1) 
;SELECT rightstr('abc', 1) 
#2 To get the last ten characters of a string, regardless of size:
;SELECT rightstr('abc', 10) 
;SELECT rightstr('abc', 10) 
@ -3450,11 +3450,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
upper(), xpath()
Examples
#1 To trim the whitespace from the end of the string 'abc ':
;SELECT rtrim('abc ') 
;SELECT rtrim('abc ') 
#2 To trim the characters 'b' and 'c' from the string 'abbbbcccc':
;SELECT rtrim('abbbbcccc', 'bc') 
;SELECT rtrim('abbbbcccc', 'bc') 
@ -3508,7 +3508,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
#2 To chart the values in a JSON array:
;SELECT sparkline(value) FROM json_each('[0, 1, 2, 3, 4, 5, 6, 7, 8]')
;SELECT sparkline(value) FROM json_each('[0, 1, 2, 3, 4, 5, 6, 7, 8]')
@ -3528,19 +3528,19 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Examples
#1 To produce a hash for the string 'Hello, World!':
;SELECT spooky_hash('Hello, World!') 
;SELECT spooky_hash('Hello, World!') 
#2 To produce a hash for the parameters where one is NULL:
;SELECT spooky_hash('Hello, World!', NULL) 
;SELECT spooky_hash('Hello, World!', NULL) 
#3 To produce a hash for the parameters where one is an empty string:
;SELECT spooky_hash('Hello, World!', '') 
;SELECT spooky_hash('Hello, World!', '') 
#4 To produce a hash for the parameters where one is a number:
;SELECT spooky_hash('Hello, World!', 123) 
;SELECT spooky_hash('Hello, World!', 123) 
@ -3561,7 +3561,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Example
#1 To check if the SQLite library was compiled with ENABLE_FTS3:
;SELECT sqlite_compileoption_used('ENABLE_FTS3') 
;SELECT sqlite_compileoption_used('ENABLE_FTS3') 
@ -3609,11 +3609,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Examples
#1 To test if the string 'foobar' starts with 'foo':
;SELECT startswith('foobar', 'foo') 
;SELECT startswith('foobar', 'foo') 
#2 To test if the string 'foobar' starts with 'bar':
;SELECT startswith('foobar', 'bar') 
;SELECT startswith('foobar', 'bar') 
@ -3635,7 +3635,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Example
#1 To get the 'b', 'c', and 'd' characters from the string 'abcabc':
;SELECT strfilter('abcabc', 'bcd') 
;SELECT strfilter('abcabc', 'bcd') 
@ -3653,16 +3653,16 @@ lnav@googlegroups.com[1] support@lnav.org[2]
date(), datetime(), julianday(), time(), timediff(), timeslice()
Examples
#1 To get the year from the timestamp '2017-01-02T03:04:05':
;SELECT strftime('%Y', '2017-01-02T03:04:05') 
;SELECT strftime('%Y', '2017-01-02T03:04:05') 
#2 To create a string with the time from the timestamp '2017-01-02T03:04:05' plus one
minute:
;SELECT strftime('The time is: %H:%M:%S', '2017-01-02T03:04:05', '+1 minute')
;SELECT strftime('The time is: %H:%M:%S', '2017-01-02T03:04:05', '+1 minute')
#3 To create a string with the Julian day from the epoch timestamp 1491341842:
;SELECT strftime('Julian day: %J', 1491341842, 'unixepoch')
;SELECT strftime('Julian day: %J', 1491341842, 'unixepoch')
@ -3692,22 +3692,22 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Examples
#1 To get the substring starting at the second character until the end of the string
'abc':
;SELECT substr('abc', 2) 
;SELECT substr('abc', 2) 
#2 To get the substring of size one starting at the second character of the string
'abc':
;SELECT substr('abc', 2, 1) 
;SELECT substr('abc', 2, 1) 
#3 To get the substring starting at the last character until the end of the string
'abc':
;SELECT substr('abc', -1) 
;SELECT substr('abc', -1) 
#4 To get the substring starting at the last character and going backwards one step of
the string 'abc':
;SELECT substr('abc', -1, -1) 
;SELECT substr('abc', -1, -1) 
@ -3739,15 +3739,15 @@ lnav@googlegroups.com[1] support@lnav.org[2]
date(), datetime(), julianday(), strftime(), timediff(), timeslice()
Examples
#1 To get the time portion of the timestamp '2017-01-02T03:04:05':
;SELECT time('2017-01-02T03:04:05') 
;SELECT time('2017-01-02T03:04:05') 
#2 To get the time portion of the timestamp '2017-01-02T03:04:05' plus one minute:
;SELECT time('2017-01-02T03:04:05', '+1 minute') 
;SELECT time('2017-01-02T03:04:05', '+1 minute') 
#3 To get the time portion of the epoch timestamp 1491341842:
;SELECT time(1491341842, 'unixepoch') 
;SELECT time(1491341842, 'unixepoch') 
@ -3761,11 +3761,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
date(), datetime(), julianday(), strftime(), time(), timeslice()
Examples
#1 To get the difference between two timestamps:
;SELECT timediff('2017-02-03T04:05:06', '2017-02-03T04:05:00')
;SELECT timediff('2017-02-03T04:05:06', '2017-02-03T04:05:00')
#2 To get the difference between relative timestamps:
;SELECT timediff('today', 'yesterday') 
;SELECT timediff('today', 'yesterday') 
@ -3780,16 +3780,16 @@ lnav@googlegroups.com[1] support@lnav.org[2]
date(), datetime(), julianday(), strftime(), time(), timediff()
Examples
#1 To get the timestamp rounded down to the start of the ten minute slice:
;SELECT timeslice('2017-01-01T05:05:00', '10m') 
;SELECT timeslice('2017-01-01T05:05:00', '10m') 
#2 To group log messages into five minute buckets and count them:
;SELECT timeslice(log_time_msecs, '5m') AS slice, count(1)
;SELECT timeslice(log_time_msecs, '5m') AS slice, count(1)
  FROM lnav_example_log GROUP BY slice
#3 To group log messages by those before 4:30am and after:
;SELECT timeslice(log_time_msecs, 'before 4:30am') AS slice, count(1) FROM
;SELECT timeslice(log_time_msecs, 'before 4:30am') AS slice, count(1) FROM
 lnav_example_log GROUP BY slice
@ -3837,11 +3837,11 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Examples
#1 To trim whitespace from the start and end of the string ' abc ':
;SELECT trim(' abc ') 
;SELECT trim(' abc ') 
#2 To trim the characters '-' and '+' from the string '-+abc+-':
;SELECT trim('-+abc+-', '-+') 
;SELECT trim('-+abc+-', '-+') 
@ -3858,7 +3858,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
#2 To get the type of the string 'abc':
;SELECT typeof('abc') 
;SELECT typeof('abc') 
@ -3879,7 +3879,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Example
#1 To get the unicode code point for the first character of 'abc':
;SELECT unicode('abc') 
;SELECT unicode('abc') 
@ -3907,7 +3907,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
xpath()
Example
#1 To uppercase the string 'aBc':
;SELECT upper('aBc') 
;SELECT upper('aBc') 
@ -3936,15 +3936,15 @@ lnav@googlegroups.com[1] support@lnav.org[2]
upper()
Examples
#1 To select the XML nodes on the path '/abc/def':
;SELECT * FROM xpath('/abc/def', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
;SELECT * FROM xpath('/abc/def', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
#2 To select all 'a' attributes on the path '/abc/def':
;SELECT * FROM xpath('/abc/def/@a', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
;SELECT * FROM xpath('/abc/def/@a', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
#3 To select the text nodes on the path '/abc/def':
;SELECT * FROM xpath('/abc/def/text()', '<abc><def a="b">Hello &#x2605;</def></abc>')
;SELECT * FROM xpath('/abc/def/text()', '<abc><def a="b">Hello &#x2605;</def></abc>')
@ -3964,7 +3964,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Example
#1 To attach the database file '/tmp/customers.db' with the name customers:
;ATTACH DATABASE '/tmp/customers.db' AS customers 
;ATTACH DATABASE '/tmp/customers.db' AS customers 
@ -3983,7 +3983,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Example
#1 To evaluate the number one and return the string 'one':
;SELECT CASE 1 WHEN 0 THEN 'zero' WHEN 1 THEN 'one' END
;SELECT CASE 1 WHEN 0 THEN 'zero' WHEN 1 THEN 'one' END
@ -4033,7 +4033,7 @@ lnav@googlegroups.com[1] support@lnav.org[2]
Example
#1 To insert the pair containing 'MSG' and 'HELLO, WORLD!' into the
'environ' table:
;INSERT INTO environ VALUES ('MSG', 'HELLO, WORLD!')
;INSERT INTO environ VALUES ('MSG', 'HELLO, WORLD!')

@ -1,5 +1,5 @@
✘ error: invalid argument: invalid
reason: expecting line number/percentage, timestamp, or relative time
✘ error: invalid argument: invalid
reason: expecting line number/percentage, timestamp, or relative time
 --> command-option:1
 | :goto invalid 
 = help: :goto line#|N%|timestamp

@ -1,4 +1,4 @@
✘ error: invalid unix time -- abc
✘ error: invalid unix time -- abc
 --> command-option:1
 | :unix-time abc 
 = help: :unix-time seconds

@ -1,5 +1,5 @@
✘ error: invalid timestamp: 2022-06-16Tabc
reason: the leading part of the timestamp was matched, however, the trailing text “Tabc” was not
✘ error: invalid timestamp: 2022-06-16Tabc
reason: the leading part of the timestamp was matched, however, the trailing text “Tabc” was not
 --> command-option:1
 | :goto 2022-06-16Tabc 
 |  ^--^ unrecognized input 

@ -1,4 +1,4 @@
✘ error: unknown field(s) -- foobar
✘ error: unknown field(s) -- foobar
 --> command-option:1
 | :hide-fields foobar 
 = help: :hide-fields field-name1 [... field-nameN]

@ -1,4 +1,4 @@
✘ error: invalid mark expression: :log_procname lik
reason: near "lik": syntax error
✘ error: invalid mark expression: :log_procname lik
reason: near "lik": syntax error
 --> command-option:1
 | :mark-expr :log_procname lik 

@ -1,4 +1,4 @@
✘ error: expecting an integer, found: abc
✘ error: expecting an integer, found: abc
 --> command-option:1
 | :config /tuning/archive-manager/min-free-space abc
 = help: :config option [value]

@ -1,4 +1,4 @@
✘ error: 'bad' is not a supported configuration $schema version
✘ error: 'bad' is not a supported configuration $schema version
 --> {test_dir}/bad-config2/formats/invalid-config/config.bad-schema.json:2
 |  "$schema": "bad" 
 = note: expecting one of the following $schema values:
@ -18,7 +18,7 @@
ui/
log/
global/
✘ error: invalid JSON
✘ error: invalid JSON
 --> {test_dir}/bad-config2/formats/invalid-config/config.malformed.json:3
 | parse error: object key and value must be separated by a colon (':')
 |  "ui": "theme", "abc", "def": "" }
@ -33,6 +33,6 @@
ui/
log/
global/
✘ error: invalid JSON
reason: parse error: premature EOF
✘ error: invalid JSON
reason: parse error: premature EOF
 --> {test_dir}/bad-config2/formats/invalid-config/config.truncated.json:3

@ -1,4 +1,4 @@
✘ error: unknown configuration option -- /bad/path
✘ error: unknown configuration option -- /bad/path
 --> command-option:1
 | :reset-config /bad/path 
 = help: :reset-config option

@ -1,6 +1,6 @@
✘ error: invalid value for property “/ui/theme-defs/default/styles/text/color”
reason: invalid color -- “#f”
 |  reason: Could not parse color: #f
✘ error: invalid value for property “/ui/theme-defs/default/styles/text/color”
reason: invalid color -- “#f”
 |  reason: Could not parse color: #f
 --> command-option:1
 = help: Property Synopsis
/ui/theme-defs/default/styles/text/color #hex|color_name

@ -1,6 +1,6 @@
✘ error: invalid value for property “/ui/theme”
reason: unknown theme -- “baddy”
 |   = help: The available themes are: default, eldar, grayscale, monocai, night-owl, solarized-dark, solarized-light
✘ error: invalid value for property “/ui/theme”
reason: unknown theme -- “baddy”
 |   = help: The available themes are: default, eldar, grayscale, monocai, night-owl, solarized-dark, solarized-light
 --> command-option:1
 = help: Property Synopsis
/ui/theme theme_name

@ -1,8 +1,8 @@
✘ error: invalid value for property “/log/watch-expressions/http-errors/expr”
reason: SQL expression is invalid
 |  reason: no such column: sc_status
 |   --> /log/watch-expressions/http-errors/expr
 |   | sc_status >= 400 AND bad 
✘ error: invalid value for property “/log/watch-expressions/http-errors/expr”
reason: SQL expression is invalid
 |  reason: no such column: sc_status
 |   --> /log/watch-expressions/http-errors/expr
 |   | sc_status >= 400 AND bad 
 --> command-option:1
 = help: Property Synopsis
/log/watch-expressions/http-errors/expr <SQL-expression>

@ -1,48 +1,48 @@
✘ error: “abc(def” is not a valid regular expression for property “/invalid_props_log/search-table/bad_table_regex/pattern”
reason: missing )
✘ error: “abc(def” is not a valid regular expression for property “/invalid_props_log/search-table/bad_table_regex/pattern”
reason: missing )
 --> {test_dir}/bad-config/formats/invalid-properties/format.json:24
 |  "pattern": "abc(def" 
 --> /invalid_props_log/search-table/bad_table_regex/pattern
 | abc(def
 |  ^ missing )
 |  ^ missing )
 = help: Property Synopsis
/invalid_props_log/search-table/bad_table_regex/pattern <regex>
Description
The regular expression for this search table.
✘ error: “^(?<timestamp>\d+: (?<body>.*)$” is not a valid regular expression for property “/bad_regex_log/regex/std/pattern”
reason: missing )
✘ error: “^(?<timestamp>\d+: (?<body>.*)$” is not a valid regular expression for property “/bad_regex_log/regex/std/pattern”
reason: missing )
 --> {test_dir}/bad-config/formats/invalid-regex/format.json:6
 |  "pattern": "^(?<timestamp>\\d+: (?<body>.*)$"
 --> /bad_regex_log/regex/std/pattern
 | ^(?<timestamp>\d+: (?<body>.*)$
 |  ^ missing )
 |  ^ missing )
 = help: Property Synopsis
/bad_regex_log/regex/std/pattern <message-regex>
Description
The regular expression to match a log message and capture fields.
✘ error: “(foo” is not a valid regular expression for property “/bad_regex_log/level/error”
reason: missing )
✘ error: “(foo” is not a valid regular expression for property “/bad_regex_log/level/error”
reason: missing )
 --> {test_dir}/bad-config/formats/invalid-regex/format.json:10
 |  "error" : "(foo" 
 --> /bad_regex_log/level/error
 | (foo
 |  ^ missing )
 |  ^ missing )
 = help: Property Synopsis
/bad_regex_log/level/error <pattern|integer>
Description
The regular expression used to match the log text for this level. For JSON logs with numeric levels, this should be the number for the corresponding level.
✘ error: “abc(” is not a valid regular expression for property “/bad_regex_log/highlights/foobar/pattern”
reason: missing )
✘ error: “abc(” is not a valid regular expression for property “/bad_regex_log/highlights/foobar/pattern”
reason: missing )
 --> {test_dir}/bad-config/formats/invalid-regex/format.json:22
 |  "pattern": "abc(" 
 --> /bad_regex_log/highlights/foobar/pattern
 | abc(
 |  ^ missing )
 |  ^ missing )
 = help: Property Synopsis
/bad_regex_log/highlights/foobar/pattern <regex>
Description
A regular expression to highlight in logs of this format.
✘ error: “foo” is not a valid value for option “/bad_sample_log/value/pid/kind”
✘ error: “foo” is not a valid value for option “/bad_sample_log/value/pid/kind”
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:24
 |  "kind": "foo" 
 = help: Property Synopsis
@ -51,7 +51,7 @@
The type of data in the field
Allowed Values
string, integer, float, boolean, json, struct, quoted, xml
✘ error: 'bad' is not a supported log format $schema version
✘ error: 'bad' is not a supported log format $schema version
 --> {test_dir}/bad-config/formats/invalid-schema/format.json:2
 |  "$schema": "bad" 
 = note: expecting one of the following $schema values:
@ -60,22 +60,22 @@
/$schema The URI of the schema for this file
Description
Specifies the type of this file
✘ error: invalid sample log message: "abc: foo"
reason: unrecognized timestamp -- abc
✘ error: invalid sample log message: "abc: foo"
reason: unrecognized timestamp -- abc
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:30
 = note: the following custom formats were tried:
abc
^ “%i” matched up to here
 = help: If the timestamp format is not supported by default, you can add a custom format with the “timestamp-format” property
✘ error: invalid sample log message: "1428634687123| debug hello"
reason: “debug” does not match the expected level of “info”
✘ error: invalid sample log message: "1428634687123| debug hello"
reason: “debug” does not match the expected level of “info”
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:33
✘ error: invalid pattern: “with-level”
reason: pattern does not match entire multiline message
✘ error: invalid pattern: “with-level”
reason: pattern does not match entire multiline message
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:37
 = help: using “.*” when capturing the body will match new-lines
✘ error: invalid sample log message: "1428634687123; foo bar"
reason: sample does not match any patterns
✘ error: invalid sample log message: "1428634687123; foo bar"
reason: sample does not match any patterns
 --> {test_dir}/bad-config/formats/invalid-sample/format.json:41
 = note: the following shows how each pattern matched this sample:
1428634687123; foo bar
@ -88,33 +88,34 @@
std  = “^(?<timestamp>\d+): (?<pid>\w+) (?<body>.*)$”
with-level = “^(?<timestamp>\d+)\| (?<level>\w+) (?<body>\w+)$”
✘ error: invalid value for property “/invalid_props_log/timestamp-field”
reason: “ts” was not found in the pattern at /invalid_props_log/regex/std
✘ error: invalid value for property “/invalid_props_log/timestamp-field”
reason: “ts” was not found in the pattern at /invalid_props_log/regex/std
 --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
 = note: the following captures are available:
body, pid, timestamp
✘ error: “not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/color”
reason: Unknown color: 'not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
✘ error: “not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/color”
reason: Unknown color: 'not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
 --> {test_dir}/bad-config/formats/invalid-properties/format.json:18
✘ error: “also not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/background-color”
reason: Unknown color: 'also not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
✘ error: “also not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/background-color”
reason: Unknown color: 'also not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
 --> {test_dir}/bad-config/formats/invalid-properties/format.json:19
✘ error: “no_regexes_log” is not a valid log format
reason: no regexes specified
✘ error: “no_regexes_log” is not a valid log format
reason: no regexes specified
 --> {test_dir}/bad-config/formats/no-regexes/format.json:4
✘ error: “no_regexes_log” is not a valid log format
reason: log message samples must be included in a format definition
✘ error: “no_regexes_log” is not a valid log format
reason: log message samples must be included in a format definition
 --> {test_dir}/bad-config/formats/no-regexes/format.json:4
✘ error: “no_sample_log” is not a valid log format
reason: log message samples must be included in a format definition
✘ error: “no_sample_log” is not a valid log format
reason: log message samples must be included in a format definition
 --> {test_dir}/bad-config/formats/no-samples/format.json:4
✘ error: failed to compile SQL statement
reason: near "TALE": syntax error
✘ error: failed to compile SQL statement
reason: near "TALE": syntax error
 --> {test_dir}/bad-config/formats/invalid-sql/init.sql:4
 | -- comment test 
 | CREATE TALE 
✘ error: failed to execute SQL statement
reason: missing )
 | CREATE TALE invalid (x y z); 
 |  ^ near "TALE": syntax error 
✘ error: failed to execute SQL statement
reason: missing )
 --> {test_dir}/bad-config/formats/invalid-sql/init2.sql
 | SELECT regexp_match('abc(', '123') 
 | SELECT regexp_match('abc(', '123') 
 | FROM sqlite_master; 

@ -1,27 +1,27 @@
✘ error: invalid JSON
✘ error: invalid JSON
 --> {test_dir}/bad-config-json/formats/invalid-json/format.json:4
 | parse error: object key and value must be separated by a colon (':')
 |  ar_log": { "abc" } }
 |  (right here) ------^
 | 
✘ error: “abc(” is not a valid regular expression for property “/invalid_key_log/level-pointer”
reason: missing )
✘ error: “abc(” is not a valid regular expression for property “/invalid_key_log/level-pointer”
reason: missing )
 --> {test_dir}/bad-config-json/formats/invalid-key/format.json:4
 |  "level-pointer": "abc(", 
 --> /invalid_key_log/level-pointer
 | abc(
 |  ^ missing )
 |  ^ missing )
 = help: Property Synopsis
/invalid_key_log/level-pointer
Description
A regular-expression that matches the JSON-pointer of the level property
✘ error: “def[ghi” is not a valid regular expression for property “/invalid_key_log/file-pattern”
reason: missing terminating ] for character class
✘ error: “def[ghi” is not a valid regular expression for property “/invalid_key_log/file-pattern”
reason: missing terminating ] for character class
 --> {test_dir}/bad-config-json/formats/invalid-key/format.json:5
 |  "file-pattern": "def[ghi", 
 --> /invalid_key_log/file-pattern
 | def[ghi
 |  ^ missing terminating ] for character class
 |  ^ missing terminating ] for character class
 = help: Property Synopsis
/invalid_key_log/file-pattern
Description
@ -39,23 +39,23 @@
action-list <string>
rewriter <command>
description <string>
✘ error: “-1.2” is not a valid value for “/invalid_key_log/timestamp-divisor”
reason: value cannot be less than or equal to zero
✘ error: “-1.2” is not a valid value for “/invalid_key_log/timestamp-divisor”
reason: value cannot be less than or equal to zero
 --> {test_dir}/bad-config-json/formats/invalid-key/format.json:25
 |  "timestamp-divisor": -1.2 
 = help: Property Synopsis
/invalid_key_log/timestamp-divisor <number>
Description
The value to divide a numeric timestamp by in a JSON log.
✘ error: “foobar_log” is not a valid log format
reason: no regexes specified
✘ error: “foobar_log” is not a valid log format
reason: no regexes specified
 --> {test_dir}/bad-config-json/formats/invalid-json/format.json:3
✘ error: “foobar_log” is not a valid log format
reason: log message samples must be included in a format definition
✘ error: “foobar_log” is not a valid log format
reason: log message samples must be included in a format definition
 --> {test_dir}/bad-config-json/formats/invalid-json/format.json:3
✘ error: “invalid_key_log” is not a valid log format
reason: structured logs cannot have regexes
✘ error: “invalid_key_log” is not a valid log format
reason: structured logs cannot have regexes
 --> {test_dir}/bad-config-json/formats/invalid-key/format.json:4
✘ error: invalid line format element “/invalid_key_log/line-format/0/field”
reason: “non-existent” is not a defined value
✘ error: invalid line format element “/invalid_key_log/line-format/0/field”
reason: “non-existent” is not a defined value
 --> {test_dir}/bad-config-json/formats/invalid-key/format.json:22

@ -1,7 +1,7 @@
✘ error: invalid value for “log_tags” column of table “access_log”
reason: unexpected JSON value
 |   --> access_log.log_tags:1
 |   | 1 
 |   = help: expecting an array of tag values
✘ error: invalid value for “log_tags” column of table “access_log”
reason: unexpected JSON value
 |   --> access_log.log_tags:1
 |   | 1 
 |   = help: expecting an array of tag values
 --> command-option:1
 | ;UPDATE access_log SET log_tags = 1 WHERE log_line = 1

@ -1,11 +1,11 @@
✘ error: invalid value for “log_tags” column of table “access_log”
reason: “foo” is not a valid value for option “/#”
 |  reason: value does not match pattern: ^#[^\s]+$
 |   --> access_log.log_tags:1
 |   | ["foo"] 
 |   = help: Property Synopsis
 |  /# tag
 |  Description
 |  A tag for the log line
✘ error: invalid value for “log_tags” column of table “access_log”
reason: “foo” is not a valid value for option “/#”
 |  reason: value does not match pattern: ^#[^\s]+$
 |   --> access_log.log_tags:1
 |   | ["foo"] 
 |   = help: Property Synopsis
 |  /# tag
 |  Description
 |  A tag for the log line
 --> command-option:1
 | ;UPDATE access_log SET log_tags = json_array('foo') WHERE log_line = 1
 | ;UPDATE access_log SET log_tags = json_array('foo') WHERE log_line = 1

@ -1,3 +1,3 @@
✘ error: no such table: nonexistent_table
✘ error: no such table: nonexistent_table
 --> command-option:1
 | ;select * from nonexistent_table 

@ -1,3 +1,3 @@
✘ error: the stop parameter is required
✘ error: the stop parameter is required
 --> command-option:1
 | ;SELECT * FROM generate_series(1) 

@ -1,5 +1,5 @@
✘ error: invalid regular expression
reason: missing )
✘ error: invalid regular expression
reason: missing )
 --> command-option:1
 | :create-search-table search_test1 bad( 
 |  ^ missing )

@ -1,5 +1,5 @@
✘ error: Cannot generate spectrogram for database results
reason: No “log_time” column found in the result set
✘ error: Cannot generate spectrogram for database results
reason: No “log_time” column found in the result set
 --> command-option:2
 | :spectrogram sc_bytes 
 = note: An ascending “log_time” column is needed to render a spectrogram

@ -1,3 +1,3 @@
✘ error: Only the top view in the stack can be deleted
✘ error: Only the top view in the stack can be deleted
 --> command-option:2
 | ;DELETE FROM lnav_view_stack WHERE name = 'log'
 | ;DELETE FROM lnav_view_stack WHERE name = 'log'

@ -1,3 +1,3 @@
✘ error: not authorized
✘ error: not authorized
 --> command-option:1
 | ;attach database '/tmp/memdb' as 'db' 
 | ;attach database '/tmp/memdb' as 'db' 

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

@ -1,3 +1,3 @@
✘ error: not authorized
✘ error: not authorized
 --> command-option:1
 | ;attach database 'simple-db.db' as 'db' 
 | ;attach database 'simple-db.db' as 'db' 

@ -1,3 +1,3 @@
✘ error: not authorized
✘ error: not authorized
 --> command-option:1
 | ;attach database ':memdb:' as 'db' 
 | ;attach database ':memdb:' as 'db' 

@ -1,5 +1,5 @@
✘ error: Cannot generate spectrogram for database results
reason: unknown column -- “sc_byes”
✘ error: Cannot generate spectrogram for database results
reason: unknown column -- “sc_byes”
 --> command-option:2
 | :spectrogram sc_byes 
 = help: Expecting a numeric column to visualize

@ -1,3 +1,3 @@
✘ error: A non-empty name and value must be provided when inserting an environment variable
✘ error: A non-empty name and value must be provided when inserting an environment variable
 --> command-option:1
 | ;INSERT INTO environ (name) VALUES (null)

@ -1,3 +1,3 @@
✘ error: An environment variable with the name 'SQL_ENV_VALUE' already exists
✘ error: An environment variable with the name 'SQL_ENV_VALUE' already exists
 --> command-option:1
 | ;INSERT INTO environ (name, value) VALUES ("SQL_ENV_VALUE", "bar")

@ -1,3 +1,3 @@
✘ error: Environment variable names cannot contain an equals sign (=)
✘ error: Environment variable names cannot contain an equals sign (=)
 --> command-option:1
 | ;INSERT INTO environ (name, value) VALUES ("foo=bar", "bar")

@ -1,5 +1,5 @@
✘ error: Cannot generate spectrogram for database results
reason: “c_ip” is not a numeric column
✘ error: Cannot generate spectrogram for database results
reason: “c_ip” is not a numeric column
 --> command-option:2
 | :spectrogram c_ip 
 = help: Only numeric columns can be visualized

@ -1,6 +1,6 @@
✘ error: no data was redirected to lnav's standard-input
✘ error: no data was redirected to lnav's standard-input
 --> command-option:1
 | |rename-stdin foo 
 --> ../test/.lnav/formats/default/rename-stdin.lnav:7
 | ;SELECT raise_error('no data was redirected to lnav''s standard-input') 
 |  WHERE (SELECT count(1) FROM lnav_file WHERE filepath='stdin') = 0
 | ;SELECT raise_error('no data was redirected to lnav''s standard-input') 
 |  WHERE (SELECT count(1) FROM lnav_file WHERE filepath='stdin') = 0

@ -1,3 +1,3 @@
✘ error: A non-empty name and value must be provided when inserting an environment variable
✘ error: 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)

@ -1,4 +1,4 @@
✘ error: unable to read script file: nonexistent-file -- No such file or directory
✘ error: unable to read script file: nonexistent-file -- No such file or directory
 --> command-option:1
 | ;.read nonexistent-file 
 = help: ;.read path

@ -1,4 +1,4 @@
✘ error: unknown search table -- search_test1
✘ error: unknown search table -- search_test1
 --> command-option:1
 | :delete-search-table search_test1 
 = help: :delete-search-table table-name

@ -1,3 +1,3 @@
✘ error: Expecting a non-empty pattern value
✘ error: Expecting a non-empty pattern value
 --> command-option:1
 | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', '')
 | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', '')

@ -1,5 +1,5 @@
✘ error: expecting the new name for stdin as the first argument
✘ error: expecting the new name for stdin as the first argument
 --> command-option:1
 | |rename-stdin 
 --> ../test/.lnav/formats/default/rename-stdin.lnav:6
 | ;SELECT raise_error('expecting the new name for stdin as the first argument') WHERE $1 IS NULL
 | ;SELECT raise_error('expecting the new name for stdin as the first argument') WHERE $1 IS NULL

@ -1,3 +1,3 @@
✘ error: Expecting an lnav view name for column number 0
✘ error: Expecting an lnav view name for column number 0
 --> command-option:1
 | ;INSERT INTO lnav_view_filters VALUES ('bad', 0, 1, 'out', 'regex', 'abc')
 | ;INSERT INTO lnav_view_filters VALUES ('bad', 0, 1, 'out', 'regex', 'abc')

@ -1,4 +1,4 @@
✘ error: unknown search table -- search_test1
✘ error: unknown search table -- search_test1
 --> command-option:2
 | :delete-search-table search_test1 
 = help: :delete-search-table table-name

@ -1,5 +1,5 @@
✘ error: Cannot generate spectrogram for database results
reason: The “log_time” column is not in ascending order between rows 1 and 2
✘ error: Cannot generate spectrogram for database results
reason: The “log_time” column is not in ascending order between rows 1 and 2
 --> command-option:2
 | :spectrogram sc_bytes 
 = note: An ascending “log_time” column is needed to render a spectrogram

@ -1,3 +1,3 @@
✘ error: real file paths cannot be updated, only symbolic ones
✘ error: real file paths cannot be updated, only symbolic ones
 --> command-option:1
 | ;UPDATE lnav_file SET filepath='foo' WHERE endswith(filepath, '_log.0')
 | ;UPDATE lnav_file SET filepath='foo' WHERE endswith(filepath, '_log.0')

@ -1,3 +1,3 @@
✘ error: attempt to write a readonly database
✘ error: attempt to write a readonly database
 --> command-option:1
 | ;delete from access_log 

@ -1,3 +1,3 @@
✘ error: The lnav_view_stack table cannot be updated
✘ error: The lnav_view_stack table cannot be updated
 --> command-option:1
 | ;UPDATE lnav_view_stack SET name = 'foo'
 | ;UPDATE lnav_view_stack SET name = 'foo'

@ -1,3 +1,3 @@
✘ error: Invalid regular expression for pattern: missing ) at offset 4
✘ error: Invalid regular expression for pattern: missing ) at offset 4
 --> command-option:1
 | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', 'abc(')
 | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', 'abc(')

@ -1,3 +1,3 @@
✘ error: the start parameter is required
✘ error: the start parameter is required
 --> command-option:1
 | ;SELECT * FROM generate_series() 

@ -1,3 +1,3 @@
✘ error: A non-empty name and value must be provided when inserting an environment variable
✘ error: A non-empty name and value must be provided when inserting an environment variable
 --> command-option:1
 | ;INSERT INTO environ (name, value) VALUES ("", null)

@ -1,3 +1,3 @@
✘ error: not authorized
✘ error: not authorized
 --> command-option:1
 | ;attach database 'file:memdb?cache=shared' as 'db'
 | ;attach database 'file:memdb?cache=shared' as 'db'

@ -1,3 +1,3 @@
✘ error: Invalid time: bad-time
✘ error: Invalid time: bad-time
 --> command-option:1
 | ;UPDATE lnav_views SET top_time = 'bad-time' WHERE name = 'log'
 | ;UPDATE lnav_views SET top_time = 'bad-time' WHERE name = 'log'

@ -1,3 +1,3 @@
✘ error: Expecting an lnav view name for column number 0
✘ error: Expecting an lnav view name for column number 0
 --> command-option:1
 | ;INSERT INTO lnav_view_filters VALUES (NULL, 0, 1, 'out', 'regex', 'abc')
 | ;INSERT INTO lnav_view_filters VALUES (NULL, 0, 1, 'out', 'regex', 'abc')

@ -1,3 +1,3 @@
✘ error: Expecting an value of 'in' or 'out' for column number 3
✘ error: 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')
 | ;INSERT INTO lnav_view_filters VALUES ('log', 0 , 1, 'bad', 'regex', 'abc')

Loading…
Cancel
Save