mirror of https://github.com/tstack/lnav.git
[docs] add report generation to cookbook
This commit is contained in:
parent
4d2691fa99
commit
d45d7d6c58
13
NEWS
13
NEWS
|
@ -33,6 +33,13 @@ lnav v0.9.1:
|
|||
* Themes can now include definitions for text highlights under:
|
||||
/ui/theme-defs/<theme_name>/highlights
|
||||
* Added a "grayscale" theme that isn't so colorful.
|
||||
* Added the humanize_file_size() SQL function that converts a numeric size
|
||||
to a human-friendly string.
|
||||
* Added the sparkline() SQL function that returns a "sparkline" bar made
|
||||
out of unicode characters. It can be used with a single value or as
|
||||
an aggregator.
|
||||
* Added a "log_time_msecs" hidden column to the log tables that returns
|
||||
the timestamp as the number of milliseconds from the epoch.
|
||||
|
||||
Interface Changes:
|
||||
* When copying log lines, the file name and time offset will be included
|
||||
|
@ -42,9 +49,15 @@ lnav v0.9.1:
|
|||
* The range_start and range_stop values of the regexp_capture() results
|
||||
now start at 1 instead of zero to match with what the other SQL string
|
||||
functions expect.
|
||||
* The ":write-cols-to" command has been renamed to ":write-table-to".
|
||||
* The DB view will limit the maximum column width to 120 characters.
|
||||
* The ":echo" command now evaluates its message to do variable
|
||||
substitution.
|
||||
|
||||
Fixes:
|
||||
* Unicode text can now be entered in prompts.
|
||||
* The replicate() SQL function would cause a crash if the number of
|
||||
replications was zero.
|
||||
|
||||
lnav v0.9.0:
|
||||
Features:
|
||||
|
|
|
@ -41,6 +41,7 @@ class CustSqliteLexer(RegexLexer):
|
|||
'root': [
|
||||
(r'\s+', Text),
|
||||
(r'--.*\n?', Comment.Single),
|
||||
(r'#.*\n?', Comment.Single),
|
||||
(r'/\*', Comment.Multiline, 'multiline-comments'),
|
||||
(words((
|
||||
'ABORT',
|
||||
|
|
|
@ -19,6 +19,40 @@ Defining a New Format
|
|||
|
||||
TBD
|
||||
|
||||
|
||||
Annotating Logs
|
||||
---------------
|
||||
|
||||
Log messages can be annotated in a couple of different ways in **lnav** to help
|
||||
you get organized.
|
||||
|
||||
Create partitions for Linux boots
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When digging through logs that can be broken up into multiple sections,
|
||||
**lnav**'s :ref:`partitioning feature<taking_notes>` can be used to keep track
|
||||
of which section you are in. For example, if a collection of Linux logs
|
||||
covered multiple boots, the following script could be used to create partitions
|
||||
for each boot. After the partition name is set for the log messages, the
|
||||
current name will show up in the top status bar next to the current time.
|
||||
|
||||
.. literalinclude:: ../../src/scripts/partition-by-boot.lnav
|
||||
:language: custsqlite
|
||||
:caption: partition-by-boot.lnav
|
||||
:linenos:
|
||||
|
||||
Tagging SSH log messages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Log messages can be tagged interactively with the :ref:`:tag<tag>` command or
|
||||
programmatically using the :ref:`sql-ext`. This example uses a script to
|
||||
search for interesting SSH messages and automatically adds an appropriate tag.
|
||||
|
||||
.. literalinclude:: ../../example-scripts/tag-ssh-msgs.lnav
|
||||
:language: custsqlite
|
||||
:caption: tag-ssh-msgs.lnav
|
||||
:linenos:
|
||||
|
||||
Log Analysis
|
||||
------------
|
||||
|
||||
|
@ -50,3 +84,21 @@ between 10,000 and 40,000 bytes like so:
|
|||
.. code-block:: custsqlite
|
||||
|
||||
:filter-expr :sc_bytes BETWEEN 10000 AND 40000
|
||||
|
||||
|
||||
Generating a Report
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Reports can be generated by writing an **lnav** :ref:`script<scripts>` that
|
||||
uses SQL queries and commands to format a document. A basic script can simply
|
||||
execute a SQL query that is shown in the DB view. More sophisticated scripts
|
||||
can use the following commands to generate customized output for a report:
|
||||
|
||||
* The :ref:`:echo<echo>` command to write plain text
|
||||
* :ref:`SQL queries<sql-ext>` followed by a "write" command, like
|
||||
:ref:`:write-table-to<write_table_to>`.
|
||||
|
||||
.. literalinclude:: ../../example-scripts/report-demo.lnav
|
||||
:language: custsqlite
|
||||
:caption: report-demo.lnav
|
||||
:linenos:
|
||||
|
|
|
@ -333,9 +333,25 @@ can have a mix of SQL and **lnav** commands, as well as include other scripts.
|
|||
The type of statement to execute is determined by the leading character on a
|
||||
line: a semi-colon begins a SQL statement; a colon starts an **lnav** command;
|
||||
and a pipe (|) denotes another script to be executed. Lines beginning with a
|
||||
hash are treated as comments. Any arguments passed to a script can be
|
||||
referenced using '$N' where 'N' is the index of the argument. Remember that
|
||||
you need to use the :ref:`:eval<eval>` command when referencing
|
||||
hash are treated as comments. The following variables are defined in a script:
|
||||
|
||||
.. envvar:: #
|
||||
|
||||
The number of arguments passed to the script.
|
||||
|
||||
.. envvar:: __all__
|
||||
|
||||
A string containing all the arguments joined by a single space.
|
||||
|
||||
.. envvar:: 0
|
||||
|
||||
The path to the script being executed.
|
||||
|
||||
.. envvar:: 1-N
|
||||
|
||||
The arguments passed to the script.
|
||||
|
||||
Remember that you need to use the :ref:`:eval<eval>` command when referencing
|
||||
variables in most **lnav** commands. Scripts can provide help text to be
|
||||
displayed during interactive usage by adding the following tags in a comment
|
||||
header:
|
||||
|
@ -350,6 +366,17 @@ header:
|
|||
# @description: Say hello to the given names.
|
||||
|
||||
|
||||
|
||||
.. tip::
|
||||
|
||||
The :ref:`:eval<eval>` command can be used to do variable substitution for
|
||||
commands that do not natively support it. For example, to substitute the
|
||||
variable, :code:`pattern`, in a :ref:`:filter-out<filter_out>` command:
|
||||
|
||||
.. code-block:: lnav
|
||||
|
||||
:eval :filter-out ${pattern}
|
||||
|
||||
Installing Formats
|
||||
------------------
|
||||
|
||||
|
|
|
@ -84,69 +84,6 @@ the `sqlite.org <http://sqlite.org>`_ web site.
|
|||
**lnav**'s interface to perform queries. The database will be attached with
|
||||
a name based on the database file name.
|
||||
|
||||
Taking Notes
|
||||
------------
|
||||
|
||||
A few of the columns in the log tables can be updated on a row-by-row basis to
|
||||
allow you to take notes. The majority of the columns in a log table are
|
||||
read-only since they are backed by the log files themselves. However, the
|
||||
following columns can be changed by an :code:`UPDATE` statement:
|
||||
|
||||
* **log_part** - The "partition" the log message belongs to. This column can
|
||||
also be changed by the :ref:`:partition-name<partition_name>` command.
|
||||
* **log_mark** - Indicates whether the line has been bookmarked.
|
||||
* **log_comment** - A free-form text field for storing commentary. This
|
||||
column can also be changed by the :ref:`:comment<comment>` command.
|
||||
* **log_tags** - A JSON list of tags associated with the log message. This
|
||||
column can also be changed by the :ref:`:tag<tag>` command.
|
||||
|
||||
While these columns can be updated by through other means, using the SQL
|
||||
interface allows you to make changes automatically and en masse. For example,
|
||||
to bookmark all lines that have the text "something interesting" in the log
|
||||
message body, you can execute:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;UPDATE all_logs SET log_mark = 1 WHERE log_body LIKE '%something interesting%'
|
||||
|
||||
As a more advanced example of the power afforded by SQL and **lnav**'s virtual
|
||||
tables, we will tag log messages where the IP address bound by dhclient has
|
||||
changed. For example, if dhclient reports "bound to 10.0.0.1" initially and
|
||||
then reports "bound to 10.0.0.2", we want to tag only the messages where the
|
||||
IP address was different from the previous message. While this can be done
|
||||
with a single SQL statement [#]_, we will break things down into a few steps for
|
||||
this example. First, we will use the :ref:`:create-search-table<create_search_table>`
|
||||
command to match the dhclient message and extract the IP address:
|
||||
|
||||
.. code-block:: lnav
|
||||
|
||||
:create-search-table dhclient_ip bound to (?<ip>[^ ]+)
|
||||
|
||||
The above command will create a new table named :code:`dhclient_ip` with the
|
||||
standard log columns and an :code:`ip` column that contains the IP address.
|
||||
Next, we will create a view over the :code:`dhclient_ip` table that returns
|
||||
the log message line number, the IP address from the current row and the IP
|
||||
address from the previous row:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;CREATE VIEW IF NOT EXISTS dhclient_ip_changes AS SELECT log_line, ip, lag(ip) OVER (ORDER BY log_line) AS prev_ip FROM dhclient_ip
|
||||
|
||||
Finally, the following :code:`UPDATE` statement will concatenate the tag
|
||||
"#ipchanged" onto the :code:`log_tags` column for any rows in the view where
|
||||
the current IP is different from the previous IP:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;UPDATE syslog_log SET log_tags = json_concat(log_tags, '#ipchanged') WHERE log_line IN (SELECT log_line FROM dhclient_ip_changes WHERE ip != prev_ip)
|
||||
|
||||
Since the above can be a lot to type out interactively, you can put these
|
||||
commands into a :ref:`script<scripts>` and execute that script with the
|
||||
:kbd:`\|` hotkey.
|
||||
|
||||
.. [#] The expression :code:`regexp_match('bound to ([^ ]+)', log_body) as ip`
|
||||
can be used to extract the IP address from the log message body.
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
|
|
|
@ -132,4 +132,70 @@ To hide messages below a certain log level, you can use the
|
|||
Search Tables
|
||||
-------------
|
||||
|
||||
TBD
|
||||
TBD
|
||||
|
||||
|
||||
.. _taking_notes:
|
||||
|
||||
Taking Notes
|
||||
------------
|
||||
|
||||
A few of the columns in the log tables can be updated on a row-by-row basis to
|
||||
allow you to take notes. The majority of the columns in a log table are
|
||||
read-only since they are backed by the log files themselves. However, the
|
||||
following columns can be changed by an :code:`UPDATE` statement:
|
||||
|
||||
* **log_part** - The "partition" the log message belongs to. This column can
|
||||
also be changed by the :ref:`:partition-name<partition_name>` command.
|
||||
* **log_mark** - Indicates whether the line has been bookmarked.
|
||||
* **log_comment** - A free-form text field for storing commentary. This
|
||||
column can also be changed by the :ref:`:comment<comment>` command.
|
||||
* **log_tags** - A JSON list of tags associated with the log message. This
|
||||
column can also be changed by the :ref:`:tag<tag>` command.
|
||||
|
||||
While these columns can be updated by through other means, using the SQL
|
||||
interface allows you to make changes automatically and en masse. For example,
|
||||
to bookmark all lines that have the text "something interesting" in the log
|
||||
message body, you can execute:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;UPDATE all_logs SET log_mark = 1 WHERE log_body LIKE '%something interesting%'
|
||||
|
||||
As a more advanced example of the power afforded by SQL and **lnav**'s virtual
|
||||
tables, we will tag log messages where the IP address bound by dhclient has
|
||||
changed. For example, if dhclient reports "bound to 10.0.0.1" initially and
|
||||
then reports "bound to 10.0.0.2", we want to tag only the messages where the
|
||||
IP address was different from the previous message. While this can be done
|
||||
with a single SQL statement [#]_, we will break things down into a few steps for
|
||||
this example. First, we will use the :ref:`:create-search-table<create_search_table>`
|
||||
command to match the dhclient message and extract the IP address:
|
||||
|
||||
.. code-block:: lnav
|
||||
|
||||
:create-search-table dhclient_ip bound to (?<ip>[^ ]+)
|
||||
|
||||
The above command will create a new table named :code:`dhclient_ip` with the
|
||||
standard log columns and an :code:`ip` column that contains the IP address.
|
||||
Next, we will create a view over the :code:`dhclient_ip` table that returns
|
||||
the log message line number, the IP address from the current row and the IP
|
||||
address from the previous row:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;CREATE VIEW IF NOT EXISTS dhclient_ip_changes AS SELECT log_line, ip, lag(ip) OVER (ORDER BY log_line) AS prev_ip FROM dhclient_ip
|
||||
|
||||
Finally, the following :code:`UPDATE` statement will concatenate the tag
|
||||
"#ipchanged" onto the :code:`log_tags` column for any rows in the view where
|
||||
the current IP is different from the previous IP:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;UPDATE syslog_log SET log_tags = json_concat(log_tags, '#ipchanged') WHERE log_line IN (SELECT log_line FROM dhclient_ip_changes WHERE ip != prev_ip)
|
||||
|
||||
Since the above can be a lot to type out interactively, you can put these
|
||||
commands into a :ref:`script<scripts>` and execute that script with the
|
||||
:kbd:`\|` hotkey.
|
||||
|
||||
.. [#] The expression :code:`regexp_match('bound to ([^ ]+)', log_body) as ip`
|
||||
can be used to extract the IP address from the log message body.
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
#
|
||||
# @synopsis: report-demo [<output-path>]
|
||||
# @description: Generate a report for requests in access_log files
|
||||
#
|
||||
|
||||
# Figure out the file path where the report should be written to, default is
|
||||
# stdout
|
||||
;SELECT CASE
|
||||
WHEN $1 IS NULL THEN '-'
|
||||
ELSE $1
|
||||
END AS out_path
|
||||
|
||||
# Redirect output from commands to $out_path
|
||||
:redirect-to $out_path
|
||||
|
||||
# Print an introductory message
|
||||
;SELECT printf('\n%d total requests', count(1)) AS msg FROM access_log
|
||||
:echo $msg
|
||||
|
||||
;WITH top_paths AS (
|
||||
SELECT
|
||||
cs_uri_stem,
|
||||
count(1) AS total_hits,
|
||||
sum(sc_bytes) as bytes,
|
||||
count(distinct c_ip) as visitors
|
||||
FROM access_log
|
||||
WHERE sc_status BETWEEN 200 AND 300
|
||||
GROUP BY cs_uri_stem
|
||||
ORDER BY total_hits DESC
|
||||
LIMIT 50),
|
||||
weekly_hits_with_gaps AS (
|
||||
SELECT timeslice(log_time_msecs, '1w') AS week,
|
||||
cs_uri_stem,
|
||||
count(1) AS weekly_hits
|
||||
FROM access_log
|
||||
WHERE cs_uri_stem IN (SELECT cs_uri_stem FROM top_paths) AND
|
||||
sc_status BETWEEN 200 AND 300
|
||||
GROUP BY week, cs_uri_stem),
|
||||
all_weeks AS (
|
||||
SELECT week
|
||||
FROM weekly_hits_with_gaps
|
||||
GROUP BY week
|
||||
ORDER BY week ASC),
|
||||
weekly_hits AS (
|
||||
SELECT all_weeks.week,
|
||||
top_paths.cs_uri_stem,
|
||||
ifnull(weekly_hits, 0) AS hits
|
||||
FROM all_weeks
|
||||
CROSS JOIN top_paths
|
||||
LEFT JOIN weekly_hits_with_gaps
|
||||
ON all_weeks.week = weekly_hits_with_gaps.week AND
|
||||
top_paths.cs_uri_stem = weekly_hits_with_gaps.cs_uri_stem)
|
||||
SELECT weekly_hits.cs_uri_stem AS Path,
|
||||
printf('%,9d', total_hits) AS Hits,
|
||||
printf('%,9d', visitors) AS Visitors,
|
||||
printf('%9s', humanize_file_size(bytes)) as Amount,
|
||||
sparkline(hits) AS Weeks
|
||||
FROM weekly_hits
|
||||
LEFT JOIN top_paths ON top_paths.cs_uri_stem = weekly_hits.cs_uri_stem
|
||||
GROUP BY weekly_hits.cs_uri_stem
|
||||
ORDER BY Hits DESC
|
||||
LIMIT 10
|
||||
|
||||
:write-table-to -
|
||||
|
||||
:echo
|
||||
:echo Failed Requests
|
||||
:echo
|
||||
|
||||
;SELECT printf('%,9d', count(1)) AS Hits,
|
||||
printf('%,9d', count(distinct c_ip)) AS Visitors,
|
||||
sc_status AS Status,
|
||||
cs_method AS Method,
|
||||
group_concat(distinct cs_version) AS Versions,
|
||||
cs_uri_stem AS Path,
|
||||
replicate('|', (cast(count(1) AS REAL) / $total_requests) * 100.0) AS "% of Requests"
|
||||
FROM access_log
|
||||
WHERE sc_status >= 400
|
||||
GROUP BY cs_method, cs_uri_stem
|
||||
ORDER BY Hits DESC
|
||||
LIMIT 10
|
||||
|
||||
:write-table-to -
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# @synopsis: tag-ssh-msgs
|
||||
# @description: Tag interesting SSH log messages
|
||||
#
|
||||
|
||||
;UPDATE all_logs
|
||||
SET log_tags = json_concat(log_tags, '#ssh.invalid-user')
|
||||
WHERE log_text LIKE '%Invalid user from%'
|
||||
|
||||
;SELECT 'Tagged ' || changes() || ' messages';
|
|
@ -89,6 +89,22 @@ public:
|
|||
auto_fd lh_fd;
|
||||
};
|
||||
|
||||
#if HAVE_ARCHIVE_H
|
||||
/**
|
||||
* Enables a subset of the supported archive formats to speed up detection,
|
||||
* since some formats, like xar are unlikely to be used.
|
||||
*/
|
||||
static void enable_desired_archive_formats(archive *arc)
|
||||
{
|
||||
archive_read_support_format_7zip(arc);
|
||||
archive_read_support_format_cpio(arc);
|
||||
archive_read_support_format_lha(arc);
|
||||
archive_read_support_format_rar(arc);
|
||||
archive_read_support_format_tar(arc);
|
||||
archive_read_support_format_zip(arc);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_archive(const fs::path& filename)
|
||||
{
|
||||
#if HAVE_ARCHIVE_H
|
||||
|
@ -97,7 +113,7 @@ bool is_archive(const fs::path& filename)
|
|||
arc = archive_read_new();
|
||||
|
||||
archive_read_support_filter_all(arc);
|
||||
archive_read_support_format_all(arc);
|
||||
enable_desired_archive_formats(arc);
|
||||
archive_read_support_format_raw(arc);
|
||||
log_debug("read open %s", filename.c_str());
|
||||
auto r = archive_read_open_filename(arc, filename.c_str(), 128 * 1024);
|
||||
|
@ -254,7 +270,7 @@ static walk_result_t extract(const std::string &filename, const extract_cb &cb)
|
|||
auto_mem<archive> ext(archive_free);
|
||||
|
||||
arc = archive_read_new();
|
||||
archive_read_support_format_all(arc);
|
||||
enable_desired_archive_formats(arc);
|
||||
archive_read_support_format_raw(arc);
|
||||
archive_read_support_filter_all(arc);
|
||||
ext = archive_write_disk_new();
|
||||
|
|
|
@ -72,6 +72,26 @@ public:
|
|||
return retval;
|
||||
};
|
||||
|
||||
/**
|
||||
* dup(2) the given file descriptor and wrap it in an auto_fd.
|
||||
*
|
||||
* @param fd The file descriptor to duplicate.
|
||||
* @return A new auto_fd that contains the duplicated file descriptor.
|
||||
*/
|
||||
static auto_fd dup_of(int fd) {
|
||||
if (fd == -1) {
|
||||
return auto_fd{};
|
||||
}
|
||||
|
||||
auto new_fd = dup(fd);
|
||||
|
||||
if (new_fd == -1) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
return auto_fd(new_fd);
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct an auto_fd to manage the given file descriptor.
|
||||
*
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
namespace humanize {
|
||||
|
||||
std::string file_size(ssize_t value)
|
||||
std::string file_size(file_ssize_t value)
|
||||
{
|
||||
static const double LN1024 = log(1024.0);
|
||||
static const std::vector<const char *> UNITS = {
|
||||
|
@ -61,4 +61,34 @@ std::string file_size(ssize_t value)
|
|||
UNITS[exp]);
|
||||
}
|
||||
|
||||
const std::string& sparkline(double value, nonstd::optional<double> upper_opt)
|
||||
{
|
||||
static const std::string ZERO = " ";
|
||||
static const std::string BARS[] = {
|
||||
"\u2581",
|
||||
"\u2582",
|
||||
"\u2583",
|
||||
"\u2584",
|
||||
"\u2585",
|
||||
"\u2586",
|
||||
"\u2587",
|
||||
"\u2588",
|
||||
};
|
||||
static const double BARS_COUNT = std::distance(begin(BARS), end(BARS));
|
||||
|
||||
if (value <= 0.0) {
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
auto upper = upper_opt.value_or(100.0);
|
||||
|
||||
if (value >= upper) {
|
||||
return BARS[(size_t) BARS_COUNT - 1];
|
||||
}
|
||||
|
||||
size_t index = ceil((value / upper) * BARS_COUNT) - 1;
|
||||
|
||||
return BARS[index];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "file_range.hh"
|
||||
|
||||
namespace humanize {
|
||||
|
||||
/**
|
||||
|
@ -42,7 +44,9 @@ namespace humanize {
|
|||
* @param value The value to format.
|
||||
* @return The formatted string.
|
||||
*/
|
||||
std::string file_size(ssize_t value);
|
||||
std::string file_size(file_ssize_t value);
|
||||
|
||||
const std::string& sparkline(double value, nonstd::optional<double> upper);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,11 @@ size_t unquote_w3c(char *dst, const char *str, size_t len)
|
|||
void truncate_to(std::string &str, size_t max_char_len)
|
||||
{
|
||||
static const std::string ELLIPSIS = "\u22ef";
|
||||
|
||||
if (str.length() < max_char_len) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto str_char_len_res = utf8_string_length(str);
|
||||
|
||||
if (str_char_len_res.isErr()) {
|
||||
|
@ -130,12 +135,16 @@ void truncate_to(std::string &str, size_t max_char_len)
|
|||
return;
|
||||
}
|
||||
|
||||
auto to_remove = (str_char_len - max_char_len) + 1;
|
||||
auto chars_to_remove = (str_char_len - max_char_len) + 1;
|
||||
auto midpoint = str_char_len / 2;
|
||||
auto to_keep_at_front = midpoint - (to_remove / 2);
|
||||
|
||||
str.erase(to_keep_at_front, to_remove);
|
||||
str.insert(to_keep_at_front, ELLIPSIS);
|
||||
auto chars_to_keep_at_front = midpoint - (chars_to_remove / 2);
|
||||
auto bytes_to_keep_at_front =
|
||||
utf8_char_to_byte_index(str, chars_to_keep_at_front);
|
||||
auto remove_up_to_bytes =
|
||||
utf8_char_to_byte_index(str, chars_to_keep_at_front + chars_to_remove);
|
||||
auto bytes_to_remove = remove_up_to_bytes - bytes_to_keep_at_front;
|
||||
str.erase(bytes_to_keep_at_front, bytes_to_remove);
|
||||
str.insert(bytes_to_keep_at_front, ELLIPSIS);
|
||||
}
|
||||
|
||||
bool is_url(const char *fn)
|
||||
|
@ -190,3 +199,20 @@ std::string repeat(const std::string& input, size_t num)
|
|||
std::fill_n(std::ostream_iterator<std::string>(os), num, input);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string center_str(const std::string &subject, size_t width)
|
||||
{
|
||||
std::string retval = subject;
|
||||
|
||||
truncate_to(retval, width);
|
||||
|
||||
auto retval_length = utf8_string_length(retval).unwrapOr(retval.length());
|
||||
auto total_fill = width - retval_length;
|
||||
auto before = total_fill / 2;
|
||||
auto after = total_fill - before;
|
||||
|
||||
retval.insert(0, before, ' ');
|
||||
retval.append(after, ' ');
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -137,13 +137,17 @@ inline ssize_t utf8_char_to_byte_index(const std::string &str, ssize_t ch_index)
|
|||
return retval;
|
||||
}
|
||||
|
||||
inline Result<size_t, const char *> utf8_string_length(const std::string &str)
|
||||
inline Result<size_t, const char *> utf8_string_length(const char *str, ssize_t len = -1)
|
||||
{
|
||||
size_t retval = 0;
|
||||
|
||||
for (size_t byte_index = 0; byte_index < str.length();) {
|
||||
auto ch_size = TRY(ww898::utf::utf8::char_size([&str, byte_index]() {
|
||||
return std::make_pair(str[byte_index], str.length() - byte_index);
|
||||
if (len == -1) {
|
||||
len = strlen(str);
|
||||
}
|
||||
|
||||
for (ssize_t byte_index = 0; byte_index < len;) {
|
||||
auto ch_size = TRY(ww898::utf::utf8::char_size([str, len, byte_index]() {
|
||||
return std::make_pair(str[byte_index], len - byte_index);
|
||||
}));
|
||||
byte_index += ch_size;
|
||||
retval += 1;
|
||||
|
@ -152,6 +156,11 @@ inline Result<size_t, const char *> utf8_string_length(const std::string &str)
|
|||
return Ok(retval);
|
||||
}
|
||||
|
||||
inline Result<size_t, const char *> utf8_string_length(const std::string& str)
|
||||
{
|
||||
return utf8_string_length(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
bool is_url(const char *fn);
|
||||
|
||||
size_t abbreviate_str(char *str, size_t len, size_t max_len);
|
||||
|
@ -160,4 +169,6 @@ void split_ws(const std::string &str, std::vector<std::string> &toks_out);
|
|||
|
||||
std::string repeat(const std::string& input, size_t num);
|
||||
|
||||
std::string center_str(const std::string& subject, size_t width);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -84,11 +84,10 @@ std::string column_namer::add_column(const std::string &in_name)
|
|||
|
||||
while (this->existing_name(retval)) {
|
||||
if (num == 0) {
|
||||
log_debug("existing!");
|
||||
this->cn_name_counters[retval] = num;
|
||||
}
|
||||
|
||||
log_debug("dup %s", retval.c_str());
|
||||
log_debug("column name already exists: %s", retval.c_str());
|
||||
snprintf(buffer, buf_size, "%s_%d", base_name.c_str(), num);
|
||||
retval = buffer;
|
||||
num += 1;
|
||||
|
|
|
@ -424,7 +424,7 @@ static Result<string, string> execute_file_contents(exec_context &ec, const ghc:
|
|||
char mode = '\0';
|
||||
|
||||
ec.ec_path_stack.emplace_back(path.parent_path());
|
||||
ec.ec_output_stack.emplace_back(nonstd::nullopt);
|
||||
exec_context::output_guard og(ec);
|
||||
while ((line_size = getline(line.out(), &line_max_size, file)) != -1) {
|
||||
line_number += 1;
|
||||
|
||||
|
@ -471,7 +471,6 @@ static Result<string, string> execute_file_contents(exec_context &ec, const ghc:
|
|||
} else {
|
||||
fclose(file);
|
||||
}
|
||||
ec.ec_output_stack.pop_back();
|
||||
ec.ec_path_stack.pop_back();
|
||||
|
||||
return Ok(retval);
|
||||
|
@ -846,3 +845,41 @@ std::string exec_context::get_error_prefix()
|
|||
|
||||
return fmt::format("{}:{}: error: ", source.first, source.second);
|
||||
}
|
||||
|
||||
void exec_context::set_output(const string &name, FILE *file)
|
||||
{
|
||||
log_info("redirecting command output to: %s", name.c_str());
|
||||
this->ec_output_stack.back().second | [](auto file) {
|
||||
if (file != stdout) {
|
||||
fclose(file);
|
||||
}
|
||||
};
|
||||
this->ec_output_stack.back() = std::make_pair(name, file);
|
||||
}
|
||||
|
||||
void exec_context::clear_output()
|
||||
{
|
||||
log_info("redirecting command output to screen");
|
||||
this->ec_output_stack.back().second | [](auto file) {
|
||||
if (file != stdout) {
|
||||
fclose(file);
|
||||
}
|
||||
};
|
||||
this->ec_output_stack.back() = std::make_pair("default", nonstd::nullopt);
|
||||
}
|
||||
|
||||
exec_context::output_guard::output_guard(exec_context &context,
|
||||
std::string name,
|
||||
const nonstd::optional<FILE *> &file)
|
||||
: sg_context(context) {
|
||||
if (file) {
|
||||
log_info("redirecting command output to: %s", name.c_str());
|
||||
}
|
||||
context.ec_output_stack.emplace_back(std::move(name), file);
|
||||
}
|
||||
|
||||
exec_context::output_guard::~output_guard()
|
||||
{
|
||||
this->sg_context.clear_output();
|
||||
this->sg_context.ec_output_stack.pop_back();
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ struct exec_context {
|
|||
this->ec_local_vars.push(std::map<std::string, std::string>());
|
||||
this->ec_path_stack.emplace_back(".");
|
||||
this->ec_source.emplace("command", 1);
|
||||
this->ec_output_stack.emplace_back(nonstd::nullopt);
|
||||
this->ec_output_stack.emplace_back("screen", nonstd::nullopt);
|
||||
}
|
||||
|
||||
std::string get_error_prefix();
|
||||
|
@ -79,14 +79,18 @@ struct exec_context {
|
|||
for (auto iter = this->ec_output_stack.rbegin();
|
||||
iter != this->ec_output_stack.rend();
|
||||
++iter) {
|
||||
if (*iter) {
|
||||
return *iter;
|
||||
if (iter->second && *iter->second) {
|
||||
return *iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return nonstd::nullopt;
|
||||
}
|
||||
|
||||
void set_output(const std::string& name, FILE *file);
|
||||
|
||||
void clear_output();
|
||||
|
||||
struct source_guard {
|
||||
source_guard(exec_context &context) : sg_context(context) {
|
||||
|
||||
|
@ -99,6 +103,16 @@ struct exec_context {
|
|||
exec_context &sg_context;
|
||||
};
|
||||
|
||||
struct output_guard {
|
||||
explicit output_guard(exec_context &context,
|
||||
std::string name = "default",
|
||||
const nonstd::optional<FILE *>& file = nonstd::nullopt);
|
||||
|
||||
~output_guard();
|
||||
|
||||
exec_context &sg_context;
|
||||
};
|
||||
|
||||
source_guard enter_source(const std::string& path, int line_number) {
|
||||
this->ec_source.emplace(path, line_number);
|
||||
return source_guard(*this);
|
||||
|
@ -120,7 +134,7 @@ struct exec_context {
|
|||
std::map<std::string, std::string> ec_global_vars;
|
||||
std::vector<ghc::filesystem::path> ec_path_stack;
|
||||
std::stack<std::pair<std::string, int>> ec_source;
|
||||
std::vector<nonstd::optional<FILE *>> ec_output_stack;
|
||||
std::vector<std::pair<std::string, nonstd::optional<FILE *>>> ec_output_stack;
|
||||
|
||||
attr_line_t ec_accumulator;
|
||||
|
||||
|
|
|
@ -356,8 +356,7 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
|
|||
struct element blank;
|
||||
|
||||
blank.e_capture.c_begin = blank.e_capture.c_end =
|
||||
free_row.front().e_capture.
|
||||
c_begin;
|
||||
free_row.front().e_capture.c_begin;
|
||||
blank.e_token = DNT_KEY;
|
||||
pair_subs.PUSH_BACK(blank);
|
||||
pair_subs.PUSH_BACK(free_row.front());
|
||||
|
@ -445,8 +444,8 @@ void data_parser::discover_format()
|
|||
|
||||
elem.e_capture = *pc_iter;
|
||||
|
||||
require(elem.e_capture.c_begin != -1);
|
||||
require(elem.e_capture.c_end != -1);
|
||||
require(elem.e_capture.c_begin >= 0);
|
||||
require(elem.e_capture.c_end >= 0);
|
||||
|
||||
state_stack.top().update_for_element(elem);
|
||||
switch (elem.e_token) {
|
||||
|
|
|
@ -257,6 +257,7 @@ public:
|
|||
{
|
||||
ELEMENT_TRACE;
|
||||
|
||||
require(elem.e_capture.c_end >= -1);
|
||||
this->std::list<element>::push_front(elem);
|
||||
};
|
||||
|
||||
|
@ -264,6 +265,7 @@ public:
|
|||
{
|
||||
ELEMENT_TRACE;
|
||||
|
||||
require(elem.e_capture.c_end >= -1);
|
||||
this->std::list<element>::push_back(elem);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Generated by re2c 2.0.3 on Sat Feb 13 21:35:28 2021 */
|
||||
#line 1 "../../lnav/src/data_scanner_re.re"
|
||||
/* Generated by re2c 2.0.3 on Thu Feb 25 11:01:38 2021 */
|
||||
#line 1 "../../lnav2/src/data_scanner_re.re"
|
||||
/**
|
||||
* Copyright (c) 2015, Timothy Stack
|
||||
*
|
||||
|
@ -41,7 +41,11 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
|||
{
|
||||
# define YYCTYPE unsigned char
|
||||
# define CAPTURE(tok) { \
|
||||
pi.pi_next_offset = YYCURSOR.val - (const unsigned char *) pi.get_string(); \
|
||||
if (YYCURSOR.val == EMPTY) { \
|
||||
pi.pi_next_offset = pi.pi_length; \
|
||||
} else { \
|
||||
pi.pi_next_offset = YYCURSOR.val - (const unsigned char *) pi.get_string(); \
|
||||
} \
|
||||
cap[0].c_end = pi.pi_next_offset; \
|
||||
cap[1].c_end = pi.pi_next_offset; \
|
||||
token_out = tok; \
|
||||
|
@ -102,10 +106,12 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
|||
|
||||
pc.set_count(2);
|
||||
cap[0].c_begin = pi.pi_next_offset;
|
||||
cap[0].c_end = pi.pi_next_offset;
|
||||
cap[1].c_begin = pi.pi_next_offset;
|
||||
cap[1].c_end = pi.pi_next_offset;
|
||||
|
||||
|
||||
#line 109 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 115 "../../lnav2/src/data_scanner_re.cc"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
unsigned int yyaccept = 0;
|
||||
|
@ -360,9 +366,9 @@ yy2:
|
|||
}
|
||||
yy3:
|
||||
++YYCURSOR;
|
||||
#line 132 "../../lnav/src/data_scanner_re.re"
|
||||
#line 138 "../../lnav2/src/data_scanner_re.re"
|
||||
{ return false; }
|
||||
#line 366 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 372 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy5:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -520,11 +526,11 @@ yy6:
|
|||
default: goto yy7;
|
||||
}
|
||||
yy7:
|
||||
#line 226 "../../lnav/src/data_scanner_re.re"
|
||||
#line 232 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
RET(DT_SYMBOL);
|
||||
}
|
||||
#line 528 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 534 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy8:
|
||||
yyaccept = 1;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -543,14 +549,14 @@ yy8:
|
|||
default: goto yy74;
|
||||
}
|
||||
yy9:
|
||||
#line 231 "../../lnav/src/data_scanner_re.re"
|
||||
#line 237 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_WHITE); }
|
||||
#line 549 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 555 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy10:
|
||||
++YYCURSOR;
|
||||
#line 230 "../../lnav/src/data_scanner_re.re"
|
||||
#line 236 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_LINE); }
|
||||
#line 554 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 560 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy12:
|
||||
yyaccept = 1;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -572,9 +578,9 @@ yy12:
|
|||
yy13:
|
||||
++YYCURSOR;
|
||||
yy14:
|
||||
#line 233 "../../lnav/src/data_scanner_re.re"
|
||||
#line 239 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_GARBAGE); }
|
||||
#line 578 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 584 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy15:
|
||||
yyaccept = 2;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -1024,19 +1030,19 @@ yy18:
|
|||
default: goto yy19;
|
||||
}
|
||||
yy19:
|
||||
#line 198 "../../lnav/src/data_scanner_re.re"
|
||||
#line 204 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_LPAREN); }
|
||||
#line 1030 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 1036 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy20:
|
||||
++YYCURSOR;
|
||||
#line 199 "../../lnav/src/data_scanner_re.re"
|
||||
#line 205 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_RPAREN); }
|
||||
#line 1035 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 1041 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy22:
|
||||
++YYCURSOR;
|
||||
#line 191 "../../lnav/src/data_scanner_re.re"
|
||||
#line 197 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_COMMA); }
|
||||
#line 1040 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 1046 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy24:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -1351,9 +1357,9 @@ yy26:
|
|||
default: goto yy28;
|
||||
}
|
||||
yy28:
|
||||
#line 162 "../../lnav/src/data_scanner_re.re"
|
||||
#line 168 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_PATH); }
|
||||
#line 1357 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 1363 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy29:
|
||||
yyaccept = 4;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -1513,9 +1519,9 @@ yy29:
|
|||
default: goto yy30;
|
||||
}
|
||||
yy30:
|
||||
#line 217 "../../lnav/src/data_scanner_re.re"
|
||||
#line 223 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_NUMBER); }
|
||||
#line 1519 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 1525 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy31:
|
||||
yyaccept = 4;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -1998,14 +2004,14 @@ yy34:
|
|||
default: goto yy35;
|
||||
}
|
||||
yy35:
|
||||
#line 189 "../../lnav/src/data_scanner_re.re"
|
||||
#line 195 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_COLON); }
|
||||
#line 2004 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 2010 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy36:
|
||||
++YYCURSOR;
|
||||
#line 192 "../../lnav/src/data_scanner_re.re"
|
||||
#line 198 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_SEMI); }
|
||||
#line 2009 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 2015 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy38:
|
||||
yyaccept = 6;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -2080,19 +2086,19 @@ yy38:
|
|||
default: goto yy39;
|
||||
}
|
||||
yy39:
|
||||
#line 200 "../../lnav/src/data_scanner_re.re"
|
||||
#line 206 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_LANGLE); }
|
||||
#line 2086 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 2092 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy40:
|
||||
++YYCURSOR;
|
||||
#line 190 "../../lnav/src/data_scanner_re.re"
|
||||
#line 196 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_EQUALS); }
|
||||
#line 2091 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 2097 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy42:
|
||||
++YYCURSOR;
|
||||
#line 201 "../../lnav/src/data_scanner_re.re"
|
||||
#line 207 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_RANGLE); }
|
||||
#line 2096 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 2102 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy44:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -2556,9 +2562,9 @@ yy50:
|
|||
default: goto yy51;
|
||||
}
|
||||
yy51:
|
||||
#line 196 "../../lnav/src/data_scanner_re.re"
|
||||
#line 202 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_LSQUARE); }
|
||||
#line 2562 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 2568 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy52:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -2567,9 +2573,9 @@ yy52:
|
|||
}
|
||||
yy53:
|
||||
++YYCURSOR;
|
||||
#line 197 "../../lnav/src/data_scanner_re.re"
|
||||
#line 203 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_RSQUARE); }
|
||||
#line 2573 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 2579 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy55:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -3116,14 +3122,14 @@ yy62:
|
|||
default: goto yy63;
|
||||
}
|
||||
yy63:
|
||||
#line 194 "../../lnav/src/data_scanner_re.re"
|
||||
#line 200 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_LCURLY); }
|
||||
#line 3122 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 3128 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy64:
|
||||
++YYCURSOR;
|
||||
#line 195 "../../lnav/src/data_scanner_re.re"
|
||||
#line 201 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_RCURLY); }
|
||||
#line 3127 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 3133 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy66:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -3670,7 +3676,7 @@ yy79:
|
|||
default: goto yy80;
|
||||
}
|
||||
yy80:
|
||||
#line 134 "../../lnav/src/data_scanner_re.re"
|
||||
#line 140 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
CAPTURE(DT_QUOTED_STRING);
|
||||
switch (pi.get_string()[cap[1].c_begin]) {
|
||||
|
@ -3683,7 +3689,7 @@ yy80:
|
|||
cap[1].c_end -= 1;
|
||||
return true;
|
||||
}
|
||||
#line 3687 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 3693 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy81:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -5152,9 +5158,9 @@ yy102:
|
|||
}
|
||||
yy103:
|
||||
++YYCURSOR;
|
||||
#line 193 "../../lnav/src/data_scanner_re.re"
|
||||
#line 199 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_EMPTY_CONTAINER); }
|
||||
#line 5158 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 5164 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy105:
|
||||
yyaccept = 4;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -5780,9 +5786,9 @@ yy114:
|
|||
default: goto yy115;
|
||||
}
|
||||
yy115:
|
||||
#line 216 "../../lnav/src/data_scanner_re.re"
|
||||
#line 222 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_PERCENTAGE); }
|
||||
#line 5786 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 5792 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy116:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -6016,9 +6022,9 @@ yy117:
|
|||
default: goto yy118;
|
||||
}
|
||||
yy118:
|
||||
#line 215 "../../lnav/src/data_scanner_re.re"
|
||||
#line 221 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_OCTAL_NUMBER); }
|
||||
#line 6022 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 6028 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy119:
|
||||
yyaccept = 4;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -6364,9 +6370,9 @@ yy121:
|
|||
default: goto yy122;
|
||||
}
|
||||
yy122:
|
||||
#line 218 "../../lnav/src/data_scanner_re.re"
|
||||
#line 224 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_HEX_NUMBER); }
|
||||
#line 6370 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 6376 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy123:
|
||||
yyaccept = 10;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -7489,11 +7495,11 @@ yy133:
|
|||
default: goto yy134;
|
||||
}
|
||||
yy134:
|
||||
#line 146 "../../lnav/src/data_scanner_re.re"
|
||||
#line 152 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
CAPTURE(DT_WORD);
|
||||
}
|
||||
#line 7497 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 7503 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy135:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -9296,7 +9302,7 @@ yy160:
|
|||
yyt1 = yyt2;
|
||||
yy161:
|
||||
YYCURSOR = yyt1;
|
||||
#line 149 "../../lnav/src/data_scanner_re.re"
|
||||
#line 155 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
CAPTURE(DT_QUOTED_STRING);
|
||||
switch (pi.get_string()[cap[1].c_begin]) {
|
||||
|
@ -9309,7 +9315,7 @@ yy161:
|
|||
cap[1].c_end -= 1;
|
||||
return true;
|
||||
}
|
||||
#line 9313 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 9319 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy162:
|
||||
yyaccept = 12;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -12758,9 +12764,9 @@ yy200:
|
|||
++YYCURSOR;
|
||||
yy201:
|
||||
YYCURSOR = yyt2;
|
||||
#line 175 "../../lnav/src/data_scanner_re.re"
|
||||
#line 181 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_IPV6_ADDRESS); }
|
||||
#line 12764 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 12770 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy202:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -14038,11 +14044,11 @@ yy217:
|
|||
yy218:
|
||||
++YYCURSOR;
|
||||
yy219:
|
||||
#line 181 "../../lnav/src/data_scanner_re.re"
|
||||
#line 187 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
RET(DT_XML_OPEN_TAG);
|
||||
}
|
||||
#line 14046 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 14052 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy220:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -14191,9 +14197,9 @@ yy223:
|
|||
yyt3 = yyt4;
|
||||
yy224:
|
||||
YYCURSOR = yyt3;
|
||||
#line 224 "../../lnav/src/data_scanner_re.re"
|
||||
#line 230 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_WORD); }
|
||||
#line 14197 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 14203 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy225:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -21698,11 +21704,11 @@ yy310:
|
|||
yy311:
|
||||
++YYCURSOR;
|
||||
yy312:
|
||||
#line 177 "../../lnav/src/data_scanner_re.re"
|
||||
#line 183 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
RET(DT_XML_EMPTY_TAG);
|
||||
}
|
||||
#line 21706 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 21712 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy313:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -21714,11 +21720,11 @@ yy313:
|
|||
}
|
||||
yy315:
|
||||
++YYCURSOR;
|
||||
#line 185 "../../lnav/src/data_scanner_re.re"
|
||||
#line 191 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
RET(DT_XML_CLOSE_TAG);
|
||||
}
|
||||
#line 21722 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 21728 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy317:
|
||||
yych = *++YYCURSOR;
|
||||
yy318:
|
||||
|
@ -22883,9 +22889,9 @@ yy332:
|
|||
default: goto yy334;
|
||||
}
|
||||
yy334:
|
||||
#line 220 "../../lnav/src/data_scanner_re.re"
|
||||
#line 226 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_EMAIL); }
|
||||
#line 22889 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 22895 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy335:
|
||||
yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -23273,11 +23279,11 @@ yy338:
|
|||
default: goto yy340;
|
||||
}
|
||||
yy340:
|
||||
#line 211 "../../lnav/src/data_scanner_re.re"
|
||||
#line 217 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
RET(DT_VERSION_NUMBER);
|
||||
}
|
||||
#line 23281 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 23287 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy341:
|
||||
yyaccept = 18;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -25711,7 +25717,7 @@ yy362:
|
|||
default: goto yy363;
|
||||
}
|
||||
yy363:
|
||||
#line 165 "../../lnav/src/data_scanner_re.re"
|
||||
#line 171 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
if ((YYCURSOR - (const unsigned char *) pi.get_string()) == 17) {
|
||||
RET(DT_MAC_ADDRESS);
|
||||
|
@ -25719,7 +25725,7 @@ yy363:
|
|||
RET(DT_HEX_DUMP);
|
||||
}
|
||||
}
|
||||
#line 25723 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 25729 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy364:
|
||||
yyaccept = 19;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -29755,9 +29761,9 @@ yy414:
|
|||
++YYCURSOR;
|
||||
yy415:
|
||||
YYCURSOR = yyt1;
|
||||
#line 222 "../../lnav/src/data_scanner_re.re"
|
||||
#line 228 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_CONSTANT); }
|
||||
#line 29761 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 29767 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy416:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -30086,9 +30092,9 @@ yy422:
|
|||
++YYCURSOR;
|
||||
yy423:
|
||||
YYCURSOR = yyt1;
|
||||
#line 163 "../../lnav/src/data_scanner_re.re"
|
||||
#line 169 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_TIME); }
|
||||
#line 30092 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 30098 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy424:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -31042,9 +31048,9 @@ yy436:
|
|||
default: goto yy438;
|
||||
}
|
||||
yy438:
|
||||
#line 209 "../../lnav/src/data_scanner_re.re"
|
||||
#line 215 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_NUMBER); }
|
||||
#line 31048 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 31054 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy439:
|
||||
yyaccept = 21;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -32454,9 +32460,9 @@ yy453:
|
|||
default: goto yy455;
|
||||
}
|
||||
yy455:
|
||||
#line 161 "../../lnav/src/data_scanner_re.re"
|
||||
#line 167 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_URL); }
|
||||
#line 32460 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 32466 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy456:
|
||||
yych = *++YYCURSOR;
|
||||
switch (yych) {
|
||||
|
@ -46940,9 +46946,9 @@ yy625:
|
|||
yyt1 = yyt2;
|
||||
yy626:
|
||||
YYCURSOR = yyt1;
|
||||
#line 164 "../../lnav/src/data_scanner_re.re"
|
||||
#line 170 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_TIME); }
|
||||
#line 46946 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 46952 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy627:
|
||||
yyaccept = 26;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -47282,11 +47288,11 @@ yy634:
|
|||
++YYCURSOR;
|
||||
yy635:
|
||||
YYCURSOR = yyt1;
|
||||
#line 203 "../../lnav/src/data_scanner_re.re"
|
||||
#line 209 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
RET(DT_IPV4_ADDRESS);
|
||||
}
|
||||
#line 47290 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 47296 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy636:
|
||||
yyaccept = 27;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -49067,11 +49073,11 @@ yy652:
|
|||
default: goto yy653;
|
||||
}
|
||||
yy653:
|
||||
#line 172 "../../lnav/src/data_scanner_re.re"
|
||||
#line 178 "../../lnav2/src/data_scanner_re.re"
|
||||
{
|
||||
RET(DT_DATE);
|
||||
}
|
||||
#line 49075 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 49081 "../../lnav2/src/data_scanner_re.cc"
|
||||
yy654:
|
||||
yyaccept = 28;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
|
@ -82935,10 +82941,10 @@ yy990:
|
|||
default: goto yy991;
|
||||
}
|
||||
yy991:
|
||||
#line 207 "../../lnav/src/data_scanner_re.re"
|
||||
#line 213 "../../lnav2/src/data_scanner_re.re"
|
||||
{ RET(DT_UUID); }
|
||||
#line 82941 "../../lnav/src/data_scanner_re.cc"
|
||||
#line 82947 "../../lnav2/src/data_scanner_re.cc"
|
||||
}
|
||||
#line 235 "../../lnav/src/data_scanner_re.re"
|
||||
#line 241 "../../lnav2/src/data_scanner_re.re"
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,11 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
|||
{
|
||||
# define YYCTYPE unsigned char
|
||||
# define CAPTURE(tok) { \
|
||||
pi.pi_next_offset = YYCURSOR.val - (const unsigned char *) pi.get_string(); \
|
||||
if (YYCURSOR.val == EMPTY) { \
|
||||
pi.pi_next_offset = pi.pi_length; \
|
||||
} else { \
|
||||
pi.pi_next_offset = YYCURSOR.val - (const unsigned char *) pi.get_string(); \
|
||||
} \
|
||||
cap[0].c_end = pi.pi_next_offset; \
|
||||
cap[1].c_end = pi.pi_next_offset; \
|
||||
token_out = tok; \
|
||||
|
@ -100,7 +104,9 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
|||
|
||||
pc.set_count(2);
|
||||
cap[0].c_begin = pi.pi_next_offset;
|
||||
cap[0].c_end = pi.pi_next_offset;
|
||||
cap[1].c_begin = pi.pi_next_offset;
|
||||
cap[1].c_end = pi.pi_next_offset;
|
||||
|
||||
/*!re2c
|
||||
re2c:yyfill:enable = 0;
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
const char *db_label_source::NULL_STR = "<NULL>";
|
||||
|
||||
constexpr size_t MAX_COLUMN_WIDTH = 120;
|
||||
|
||||
void db_label_source::text_value_for_line(textview_curses &tc, int row,
|
||||
std::string &label_out,
|
||||
text_sub_source::line_flags_t flags)
|
||||
|
@ -51,14 +53,20 @@ void db_label_source::text_value_for_line(textview_curses &tc, int row,
|
|||
return;
|
||||
}
|
||||
for (int lpc = 0; lpc < (int)this->dls_rows[row].size(); lpc++) {
|
||||
int padding = (this->dls_headers[lpc].hm_column_size -
|
||||
strlen(this->dls_rows[row][lpc]) -
|
||||
1);
|
||||
auto actual_col_size = std::min(MAX_COLUMN_WIDTH,
|
||||
this->dls_headers[lpc].hm_column_size);
|
||||
auto cell_str = std::string(this->dls_rows[row][lpc]);
|
||||
|
||||
truncate_to(cell_str, MAX_COLUMN_WIDTH);
|
||||
|
||||
auto cell_length = utf8_string_length(cell_str)
|
||||
.unwrapOr(MAX_COLUMN_WIDTH);
|
||||
auto padding = actual_col_size - cell_length;
|
||||
this->dls_cell_width[lpc] = cell_str.length() + padding;
|
||||
if (this->dls_headers[lpc].hm_column_type != SQLITE3_TEXT) {
|
||||
label_out.append(padding, ' ');
|
||||
}
|
||||
label_out.append(this->dls_rows[row][lpc]);
|
||||
label_out.append(cell_str);
|
||||
if (this->dls_headers[lpc].hm_column_type == SQLITE3_TEXT) {
|
||||
label_out.append(padding, ' ');
|
||||
}
|
||||
|
@ -79,7 +87,7 @@ void db_label_source::text_attrs_for_line(textview_curses &tc, int row,
|
|||
if (row % 2 == 0) {
|
||||
sa.emplace_back(lr2, &view_curses::VC_STYLE, A_BOLD);
|
||||
}
|
||||
lr.lr_start += this->dls_headers[lpc].hm_column_size - 1;
|
||||
lr.lr_start += this->dls_cell_width[lpc];
|
||||
lr.lr_end = lr.lr_start + 1;
|
||||
sa.emplace_back(lr, &view_curses::VC_GRAPHIC, ACS_VLINE);
|
||||
lr.lr_start += 1;
|
||||
|
@ -122,10 +130,11 @@ void db_label_source::push_header(const std::string &colstr, int type,
|
|||
bool graphable)
|
||||
{
|
||||
this->dls_headers.emplace_back(colstr);
|
||||
this->dls_cell_width.push_back(0);
|
||||
|
||||
header_meta &hm = this->dls_headers.back();
|
||||
|
||||
hm.hm_column_size = colstr.length() + 1;
|
||||
hm.hm_column_size = utf8_string_length(colstr).unwrapOr(colstr.length());
|
||||
hm.hm_column_type = type;
|
||||
hm.hm_graphable = graphable;
|
||||
if (colstr == "log_time") {
|
||||
|
@ -140,12 +149,6 @@ void db_label_source::push_column(const char *colstr)
|
|||
double num_value = 0.0;
|
||||
size_t value_len;
|
||||
|
||||
if (colstr == nullptr) {
|
||||
value_len = 0;
|
||||
}
|
||||
else {
|
||||
value_len = strlen(colstr);
|
||||
}
|
||||
if (colstr == nullptr) {
|
||||
colstr = NULL_STR;
|
||||
}
|
||||
|
@ -155,6 +158,7 @@ void db_label_source::push_column(const char *colstr)
|
|||
throw "out of memory";
|
||||
}
|
||||
}
|
||||
value_len = strlen(colstr);
|
||||
|
||||
if (index == this->dls_time_column_index) {
|
||||
date_time_scanner dts;
|
||||
|
@ -175,7 +179,8 @@ void db_label_source::push_column(const char *colstr)
|
|||
|
||||
this->dls_rows.back().push_back(colstr);
|
||||
this->dls_headers[index].hm_column_size =
|
||||
std::max(this->dls_headers[index].hm_column_size, strlen(colstr) + 1);
|
||||
std::max(this->dls_headers[index].hm_column_size,
|
||||
utf8_string_length(colstr, value_len).unwrapOr(value_len));
|
||||
|
||||
if (colstr != nullptr && this->dls_headers[index].hm_graphable) {
|
||||
if (sscanf(colstr, "%lf", &num_value) != 1) {
|
||||
|
@ -215,6 +220,7 @@ void db_label_source::clear()
|
|||
}
|
||||
this->dls_rows.clear();
|
||||
this->dls_time_column.clear();
|
||||
this->dls_cell_width.clear();
|
||||
}
|
||||
|
||||
long db_label_source::column_name_to_index(const std::string &name) const
|
||||
|
@ -365,13 +371,25 @@ bool db_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
|
|||
for (size_t lpc = 0;
|
||||
lpc < this->dos_labels->dls_headers.size();
|
||||
lpc++) {
|
||||
int before, total_fill =
|
||||
dls->dls_headers[lpc].hm_column_size -
|
||||
dls->dls_headers[lpc].hm_name.length();
|
||||
auto actual_col_size = std::min(
|
||||
MAX_COLUMN_WIDTH, dls->dls_headers[lpc].hm_column_size);
|
||||
std::string cell_title = dls->dls_headers[lpc].hm_name;
|
||||
|
||||
struct line_range header_range(line.length(),
|
||||
line.length() +
|
||||
dls->dls_headers[lpc].hm_column_size);
|
||||
truncate_to(cell_title, MAX_COLUMN_WIDTH);
|
||||
|
||||
auto cell_length = utf8_string_length(cell_title)
|
||||
.unwrapOr(actual_col_size);
|
||||
int before, total_fill = actual_col_size - cell_length;
|
||||
auto line_len_before = line.length();
|
||||
|
||||
before = total_fill / 2;
|
||||
total_fill -= before;
|
||||
line.append(before, ' ');
|
||||
line.append(cell_title);
|
||||
line.append(total_fill, ' ');
|
||||
line.append(1, ' ');
|
||||
|
||||
struct line_range header_range(line_len_before, line.length());
|
||||
|
||||
int attrs =
|
||||
vc.attrs_for_ident(dls->dls_headers[lpc].hm_name) | A_REVERSE;
|
||||
|
@ -379,12 +397,6 @@ bool db_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
|
|||
attrs = A_UNDERLINE;
|
||||
}
|
||||
sa.emplace_back(header_range, &view_curses::VC_STYLE, attrs);
|
||||
|
||||
before = total_fill / 2;
|
||||
total_fill -= before;
|
||||
line.append(before, ' ');
|
||||
line.append(dls->dls_headers[lpc].hm_name);
|
||||
line.append(total_fill, ' ');
|
||||
}
|
||||
|
||||
struct line_range lr(0);
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
size_t retval = 0;
|
||||
|
||||
for (auto &dls_header : this->dls_headers) {
|
||||
retval += dls_header.hm_column_size;
|
||||
retval += dls_header.hm_column_size + 1;
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
|
@ -75,8 +75,6 @@ public:
|
|||
|
||||
void push_header(const std::string &colstr, int type, bool graphable);
|
||||
|
||||
/* TODO: add support for left and right justification... numbers should */
|
||||
/* be right justified and strings should be left. */
|
||||
void push_column(const char *colstr);
|
||||
|
||||
void clear();
|
||||
|
@ -117,8 +115,9 @@ public:
|
|||
|
||||
stacked_bar_chart<std::string> dls_chart;
|
||||
std::vector<header_meta> dls_headers;
|
||||
std::vector<std::vector<const char *> > dls_rows;
|
||||
std::vector<std::vector<const char *>> dls_rows;
|
||||
std::vector<struct timeval> dls_time_column;
|
||||
std::vector<size_t> dls_cell_width;
|
||||
int dls_time_column_index{-1};
|
||||
|
||||
static const char *NULL_STR;
|
||||
|
|
|
@ -669,8 +669,8 @@ static void floorFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
|||
** string that constains s contatenated n times
|
||||
*/
|
||||
static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
unsigned char *z; /* input string */
|
||||
unsigned char *zo; /* result string */
|
||||
static const char *EMPTY = "";
|
||||
unsigned char *z; /* result string */
|
||||
i64 iCount; /* times to repeat */
|
||||
i64 nLen; /* length of the input string (no multibyte considerations) */
|
||||
i64 nTLen; /* length of the result string (no multibyte considerations) */
|
||||
|
@ -683,28 +683,29 @@ static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **ar
|
|||
|
||||
if( iCount<0 ){
|
||||
sqlite3_result_error(context, "domain error", -1);
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
|
||||
if (iCount == 0) {
|
||||
sqlite3_result_text(context, EMPTY, 0, SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
|
||||
nLen = sqlite3_value_bytes(argv[0]);
|
||||
nTLen = nLen*iCount;
|
||||
z= (unsigned char *) sqlite3_malloc(nTLen + 1);
|
||||
zo= (unsigned char *) sqlite3_malloc(nLen + 1);
|
||||
if (!z || !zo){
|
||||
if (!z){
|
||||
sqlite3_result_error_nomem(context);
|
||||
if (z) sqlite3_free(z);
|
||||
if (zo) sqlite3_free(zo);
|
||||
return;
|
||||
}
|
||||
strcpy((char*)zo, (char*)sqlite3_value_text(argv[0]));
|
||||
auto zo = sqlite3_value_text(argv[0]);
|
||||
|
||||
for(i=0; i<iCount; ++i){
|
||||
strcpy((char*)(z+i*nLen), (char*)zo);
|
||||
}
|
||||
|
||||
sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_free(z);
|
||||
sqlite3_free(zo);
|
||||
}
|
||||
sqlite3_result_text(context, (char*)z, -1, sqlite3_free);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -45,6 +45,11 @@ enum class help_context_t {
|
|||
HC_SQL_TABLE_VALUED_FUNCTION,
|
||||
};
|
||||
|
||||
enum class help_function_type_t {
|
||||
HFT_REGULAR,
|
||||
HFT_AGGREGATE,
|
||||
};
|
||||
|
||||
enum class help_nargs_t {
|
||||
HN_REQUIRED,
|
||||
HN_OPTIONAL,
|
||||
|
@ -82,6 +87,8 @@ struct help_text {
|
|||
std::vector<const char *> ht_enum_values;
|
||||
std::vector<const char *> ht_tags;
|
||||
std::vector<const char *> ht_opposites;
|
||||
help_function_type_t ht_function_type{help_function_type_t::HFT_REGULAR};
|
||||
void *ht_impl{nullptr};
|
||||
|
||||
help_text() = default;
|
||||
|
||||
|
@ -104,6 +111,12 @@ struct help_text {
|
|||
return *this;
|
||||
};
|
||||
|
||||
help_text &sql_agg_function() noexcept {
|
||||
this->ht_context = help_context_t::HC_SQL_FUNCTION;
|
||||
this->ht_function_type = help_function_type_t::HFT_AGGREGATE;
|
||||
return *this;
|
||||
};
|
||||
|
||||
help_text &sql_table_valued_function() noexcept {
|
||||
this->ht_context = help_context_t::HC_SQL_TABLE_VALUED_FUNCTION;
|
||||
return *this;
|
||||
|
@ -171,6 +184,12 @@ struct help_text {
|
|||
|
||||
help_text &with_opposites(const std::initializer_list<const char*> &opps) noexcept;
|
||||
|
||||
template<typename F>
|
||||
help_text &with_impl(F impl) {
|
||||
this->ht_impl = (void *) impl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void index_tags();
|
||||
|
||||
static std::multimap<std::string, help_text *> TAGGED;
|
||||
|
|
|
@ -466,6 +466,9 @@ static std::string link_name(const help_text &ht)
|
|||
} else {
|
||||
scrubbed_name = ht.ht_name;
|
||||
}
|
||||
if (ht.ht_function_type == help_function_type_t::HFT_AGGREGATE) {
|
||||
scrubbed_name += "_agg";
|
||||
}
|
||||
for (auto ¶m : ht.ht_parameters) {
|
||||
if (!is_sql_infix && param.ht_name[0]) {
|
||||
continue;
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
:alt-msg Press t to switch to the text view
|
||||
|
||||
**See Also**
|
||||
:ref:`echo`, :ref:`eval`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to`
|
||||
:ref:`echo`, :ref:`eval`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -67,7 +67,7 @@
|
|||
:append-to /tmp/interesting-lines.txt
|
||||
|
||||
**See Also**
|
||||
:ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to`
|
||||
:ref:`echo`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -214,7 +214,7 @@
|
|||
:create-logline-table task_durations
|
||||
|
||||
**See Also**
|
||||
:ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`
|
||||
:ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -238,7 +238,7 @@
|
|||
:create-search-table task_durations duration=(?<duration>\d+)
|
||||
|
||||
**See Also**
|
||||
:ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`delete_search_table`, :ref:`delete_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`
|
||||
:ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`delete_search_table`, :ref:`delete_search_table`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -295,7 +295,7 @@
|
|||
:delete-logline-table task_durations
|
||||
|
||||
**See Also**
|
||||
:ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`
|
||||
:ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -318,7 +318,7 @@
|
|||
:delete-search-table task_durations
|
||||
|
||||
**See Also**
|
||||
:ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`
|
||||
:ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -387,7 +387,7 @@
|
|||
:echo *msg*
|
||||
^^^^^^^^^^^
|
||||
|
||||
Echo the given message
|
||||
Echo the given message to the screen or, if :redirect-to has been called, to output file specified in the redirect. Variable substitution is performed on the message. Use a backslash to escape any special characters, like '$'
|
||||
|
||||
**Parameters**
|
||||
* **msg\*** --- The message to display
|
||||
|
@ -400,7 +400,7 @@
|
|||
:echo Hello, World!
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`eval`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -452,12 +452,6 @@
|
|||
* **command\*** --- The command or query to perform substitution on.
|
||||
|
||||
**Examples**
|
||||
To output the user's home directory:
|
||||
|
||||
.. code-block:: lnav
|
||||
|
||||
:eval :echo $HOME
|
||||
|
||||
To substitute the table name from a variable:
|
||||
|
||||
.. code-block:: lnav
|
||||
|
@ -465,7 +459,7 @@
|
|||
:eval ;SELECT * FROM ${table}
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`echo`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`echo`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -848,7 +842,7 @@
|
|||
:pipe-line-to sed -e 's/foo/bar/g'
|
||||
|
||||
**See Also**
|
||||
:ref:`append_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to`
|
||||
:ref:`append_to`, :ref:`echo`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -871,7 +865,7 @@
|
|||
:pipe-to sed -e s/foo/bar/g
|
||||
|
||||
**See Also**
|
||||
:ref:`append_to`, :ref:`pipe_line_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to`
|
||||
:ref:`append_to`, :ref:`echo`, :ref:`pipe_line_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -980,7 +974,7 @@
|
|||
:redirect-to *\[path\]*
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Redirect the output of commands to the given file
|
||||
Redirect the output of commands that write to stdout to the given file
|
||||
|
||||
**Parameters**
|
||||
* **path** --- The path to the file to write. If not specified, the current redirect will be cleared
|
||||
|
@ -993,7 +987,7 @@
|
|||
:redirect-to /tmp/script-output.txt
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1352,12 +1346,12 @@
|
|||
----
|
||||
|
||||
|
||||
.. _write_cols_to:
|
||||
.. _write_table_to:
|
||||
|
||||
:write-cols-to *path*
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
:write-table-to *path*
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Write SQL results to the given file in a columnar format
|
||||
Write SQL results to the given file in a tabular format
|
||||
|
||||
**Parameters**
|
||||
* **path\*** --- The path to the file to write
|
||||
|
@ -1367,10 +1361,10 @@
|
|||
|
||||
.. code-block:: lnav
|
||||
|
||||
:write-cols-to /tmp/table.txt
|
||||
:write-table-to /tmp/table.txt
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1393,7 +1387,7 @@
|
|||
:write-csv-to /tmp/table.csv
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1416,7 +1410,7 @@
|
|||
:write-json-to /tmp/table.json
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1439,7 +1433,7 @@
|
|||
:write-jsonlines-to /tmp/table.json
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1462,7 +1456,7 @@
|
|||
:write-raw-to /tmp/table.txt
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1485,7 +1479,7 @@
|
|||
:write-screen-to /tmp/table.txt
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_to`, :ref:`write_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_table_to`, :ref:`write_to`, :ref:`write_to`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1508,7 +1502,7 @@
|
|||
:write-to /tmp/interesting-lines.txt
|
||||
|
||||
**See Also**
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`
|
||||
:ref:`alt_msg`, :ref:`append_to`, :ref:`echo`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_table_to`, :ref:`write_table_to`
|
||||
|
||||
----
|
||||
|
||||
|
|
|
@ -771,7 +771,7 @@ char(*X*)
|
|||
HI
|
||||
|
||||
**See Also**
|
||||
:ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -804,7 +804,7 @@ charindex(*needle*, *haystack*, *\[start\]*)
|
|||
0
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1068,7 +1068,7 @@ endswith(*str*, *suffix*)
|
|||
0
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1123,7 +1123,7 @@ extract(*str*)
|
|||
{"col_0":1.0,"col_1":2.0}
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1273,12 +1273,12 @@ group_concat(*X*, *\[sep\]*)
|
|||
hw,gw
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
||||
.. _group_spooky_hash:
|
||||
.. _group_spooky_hash_agg:
|
||||
|
||||
group_spooky_hash(*str*)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1297,7 +1297,7 @@ group_spooky_hash(*str*)
|
|||
4e7a190aead058cb123c94290f29c34a
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1324,6 +1324,30 @@ hex(*X*)
|
|||
----
|
||||
|
||||
|
||||
.. _humanize_file_size:
|
||||
|
||||
humanize_file_size(*value*)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Format the given file size as a human-friendly string
|
||||
|
||||
**Parameters**
|
||||
* **value\*** --- The file size to format
|
||||
|
||||
**Examples**
|
||||
To format an amount:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT humanize_file_size(10 * 1024 * 1024)
|
||||
10.0MB
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
||||
.. _ifnull:
|
||||
|
||||
ifnull(*X*, *Y*)
|
||||
|
@ -1367,7 +1391,7 @@ instr(*haystack*, *needle*)
|
|||
2
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1720,7 +1744,7 @@ leftstr(*str*, *N*)
|
|||
abc
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1744,7 +1768,7 @@ length(*str*)
|
|||
3
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1912,7 +1936,7 @@ lower(*str*)
|
|||
abc
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -1944,7 +1968,7 @@ ltrim(*str*, *\[chars\]*)
|
|||
c
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2101,7 +2125,7 @@ padc(*str*, *len*)
|
|||
abcdef ghi
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2133,7 +2157,7 @@ padl(*str*, *len*)
|
|||
abcdef
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2165,7 +2189,7 @@ padr(*str*, *len*)
|
|||
abcdefghi
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2263,7 +2287,7 @@ printf(*format*, *X*)
|
|||
value: 00011
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2287,7 +2311,7 @@ proper(*str*)
|
|||
Hello, World!
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2470,7 +2494,7 @@ regexp_capture(*string*, *pattern*)
|
|||
1 2 3 8 9 2
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2509,7 +2533,7 @@ regexp_match(*re*, *str*)
|
|||
{"num":123,"str":"four"}
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_replace`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_replace`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2542,7 +2566,7 @@ regexp_replace(*str*, *re*, *repl*)
|
|||
<123> <abc>
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_match`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_match`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2575,7 +2599,7 @@ replace(*str*, *old*, *replacement*)
|
|||
zbc
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2600,7 +2624,7 @@ replicate(*str*, *N*)
|
|||
abcabcabc
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2624,7 +2648,7 @@ reverse(*str*)
|
|||
cba
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2656,7 +2680,7 @@ rightstr(*str*, *N*)
|
|||
abc
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2713,7 +2737,7 @@ row_number()
|
|||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT row_number() OVER (PARTITION BY ex_procname ORDER BY log_line) AS msg_num, ex_procname, log_body FROM lnav_example_log
|
||||
msg_num ex_procname log_body
|
||||
msg_num ex_procname log_body
|
||||
1 gw Goodbye, World!
|
||||
2 gw Goodbye, World!
|
||||
3 gw Goodbye, World!
|
||||
|
@ -2752,7 +2776,7 @@ rtrim(*str*, *\[chars\]*)
|
|||
a
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2795,6 +2819,56 @@ sign(*num*)
|
|||
----
|
||||
|
||||
|
||||
.. _sparkline:
|
||||
|
||||
sparkline(*value*, *\[upper\]*)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Converts a numeric value on a range to a bar chart character
|
||||
|
||||
**Parameters**
|
||||
* **value\*** --- The numeric value to convert
|
||||
* **upper** --- The upper bound of the numeric range (default: 100)
|
||||
|
||||
**Examples**
|
||||
To get the unicode block element for the value 32 in the range of 0-128:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT sparkline(32, 128)
|
||||
▂
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
||||
.. _sparkline_agg:
|
||||
|
||||
sparkline(*value*, *\[upper\]*)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
An aggregate function to convert numeric values to a sparkline bar chart
|
||||
|
||||
**Parameters**
|
||||
* **value\*** --- The numeric values to chart
|
||||
* **upper** --- The upper bound of the numeric range. If not provided, the default is derived from all of the provided values
|
||||
|
||||
**Examples**
|
||||
To chart the values in a JSON array:
|
||||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT sparkline(value) FROM json_each('[0, 1, 2, 3, 4, 5, 6, 7, 8]')
|
||||
▁▂▃▄▅▆▇█
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
||||
.. _spooky_hash:
|
||||
|
||||
spooky_hash(*str*)
|
||||
|
@ -2835,7 +2909,7 @@ spooky_hash(*str*)
|
|||
f96b3d9c1a19f4394c97a1b79b1880df
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2949,7 +3023,7 @@ startswith(*str*, *prefix*)
|
|||
0
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -2974,7 +3048,7 @@ strfilter(*source*, *include*)
|
|||
bcbc
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -3061,7 +3135,7 @@ substr(*str*, *start*, *\[size\]*)
|
|||
b
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -3184,11 +3258,8 @@ timeslice(*time*, *slice*)
|
|||
|
||||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT timeslice(log_time, '5m') AS slice, count(*) FROM lnav_example_log GROUP BY slice
|
||||
slice count(*)
|
||||
2017-02-03 04:05:00.000 2
|
||||
2017-02-03 04:25:00.000 1
|
||||
2017-02-03 04:55:00.000 1
|
||||
;SELECT timeslice(log_time_msecs, '5m') AS slice, count(*) FROM lnav_example_log GROUP BY slice
|
||||
2017-01-01 05:00:00.000
|
||||
|
||||
**See Also**
|
||||
:ref:`date`, :ref:`datetime`, :ref:`julianday`, :ref:`strftime`, :ref:`time`, :ref:`timediff`
|
||||
|
@ -3258,7 +3329,7 @@ trim(*str*, *\[chars\]*)
|
|||
abc
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -3311,7 +3382,7 @@ unicode(*X*)
|
|||
97
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`upper`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`upper`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -3349,7 +3420,7 @@ upper(*str*)
|
|||
ABC
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`xpath`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`xpath`
|
||||
|
||||
----
|
||||
|
||||
|
@ -3371,7 +3442,7 @@ xpath(*xpath*, *xmldoc*)
|
|||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT * FROM xpath('/abc/def', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
|
||||
result node_path node_attr node_text
|
||||
result node_path node_attr node_text
|
||||
<def a="b">Hello</def> /abc/def[1] {"a":"b"} Hello
|
||||
<def>Bye</def> /abc/def[2] {} Bye
|
||||
|
||||
|
@ -3380,7 +3451,7 @@ xpath(*xpath*, *xmldoc*)
|
|||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT * FROM xpath('/abc/def/@a', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
|
||||
result node_path node_attr node_text
|
||||
result node_path node_attr node_text
|
||||
b /abc/def[1]/@a {"a":"b"} Hello
|
||||
|
||||
To select the text nodes on the path '/abc/def':
|
||||
|
@ -3388,11 +3459,11 @@ xpath(*xpath*, *xmldoc*)
|
|||
.. code-block:: custsqlite
|
||||
|
||||
;SELECT * FROM xpath('/abc/def/text()', '<abc><def a="b">Hello ★</def></abc>')
|
||||
result node_path node_attr node_text
|
||||
Hello ★ /abc/def/text() {} Hello ★
|
||||
result node_path node_attr node_text
|
||||
Hello ★ /abc/def/text() {} Hello ★
|
||||
|
||||
**See Also**
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`
|
||||
:ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline_agg`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`
|
||||
|
||||
----
|
||||
|
||||
|
|
|
@ -256,6 +256,7 @@ bool setup_logline_table(exec_context &ec)
|
|||
{
|
||||
// Hidden columns don't show up in the table_info pragma.
|
||||
static const char *hidden_table_columns[] = {
|
||||
"log_time_msecs",
|
||||
"log_path",
|
||||
"log_text",
|
||||
"log_body",
|
||||
|
@ -2617,7 +2618,7 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
init_session();
|
||||
lnav_data.ld_exec_context.ec_output_stack.back() = stdout;
|
||||
lnav_data.ld_exec_context.set_output("stdout", stdout);
|
||||
alerter::singleton().enabled(false);
|
||||
|
||||
log_tc = &lnav_data.ld_views[LNV_LOG];
|
||||
|
|
|
@ -666,12 +666,8 @@ static Result<string, string> com_save_to(exec_context &ec, string cmdline, vect
|
|||
|
||||
vector<string> split_args;
|
||||
shlex lexer(fn);
|
||||
scoped_resolver scopes = {
|
||||
&ec.ec_local_vars.top(),
|
||||
&ec.ec_global_vars,
|
||||
};
|
||||
|
||||
if (!lexer.split(split_args, scopes)) {
|
||||
if (!lexer.split(split_args, ec.create_resolver())) {
|
||||
return ec.make_error("unable to parse arguments");
|
||||
}
|
||||
if (split_args.size() > 1) {
|
||||
|
@ -685,16 +681,15 @@ static Result<string, string> com_save_to(exec_context &ec, string cmdline, vect
|
|||
mode = "w";
|
||||
}
|
||||
|
||||
textview_curses * tc = *lnav_data.ld_view_stack.top();
|
||||
bookmark_vector<vis_line_t> &bv =
|
||||
tc->get_bookmarks()[&textview_curses::BM_USER];
|
||||
db_label_source &dls = lnav_data.ld_db_row_source;
|
||||
db_overlay_source &dos = lnav_data.ld_db_overlay;
|
||||
auto *tc = *lnav_data.ld_view_stack.top();
|
||||
auto &bv = tc->get_bookmarks()[&textview_curses::BM_USER];
|
||||
auto &dls = lnav_data.ld_db_row_source;
|
||||
|
||||
if (args[0] == "write-csv-to" ||
|
||||
args[0] == "write-json-to" ||
|
||||
args[0] == "write-jsonlines-to" ||
|
||||
args[0] == "write-cols-to") {
|
||||
args[0] == "write-cols-to" ||
|
||||
args[0] == "write-table-to") {
|
||||
if (dls.dls_headers.empty()) {
|
||||
return ec.make_error("no query result to write, use ';' to execute a query");
|
||||
}
|
||||
|
@ -791,26 +786,84 @@ static Result<string, string> com_save_to(exec_context &ec, string cmdline, vect
|
|||
line_count += 1;
|
||||
}
|
||||
}
|
||||
else if (args[0] == "write-cols-to") {
|
||||
attr_line_t header_line;
|
||||
else if (args[0] == "write-cols-to" || args[0] == "write-table-to") {
|
||||
bool first = true;
|
||||
|
||||
dos.list_value_for_overlay(lnav_data.ld_views[LNV_DB], 0, 1, 0_vl, header_line);
|
||||
fputs(header_line.get_string().c_str(), outfile);
|
||||
fputc('\n', outfile);
|
||||
for (size_t lpc = 0; lpc < dls.text_line_count(); lpc++) {
|
||||
if (ec.ec_dry_run && lpc > 10) {
|
||||
fprintf(outfile, "\u250f");
|
||||
for (const auto& hdr : dls.dls_headers) {
|
||||
auto cell_line = repeat("\u2501", hdr.hm_column_size);
|
||||
|
||||
if (!first) {
|
||||
fprintf(outfile, "\u2533");
|
||||
}
|
||||
fprintf(outfile, "%s", cell_line.c_str());
|
||||
first = false;
|
||||
}
|
||||
fprintf(outfile, "\u2513\n");
|
||||
|
||||
for (const auto& hdr : dls.dls_headers) {
|
||||
auto centered_hdr = center_str(hdr.hm_name, hdr.hm_column_size);
|
||||
|
||||
fprintf(outfile, "\u2503");
|
||||
fprintf(outfile, "%s", centered_hdr.c_str());
|
||||
}
|
||||
fprintf(outfile, "\u2503\n");
|
||||
|
||||
first = true;
|
||||
fprintf(outfile, "\u2521");
|
||||
for (const auto& hdr : dls.dls_headers) {
|
||||
auto cell_line = repeat("\u2501", hdr.hm_column_size);
|
||||
|
||||
if (!first) {
|
||||
fprintf(outfile, "\u2547");
|
||||
}
|
||||
fprintf(outfile, "%s", cell_line.c_str());
|
||||
first = false;
|
||||
}
|
||||
fprintf(outfile, "\u2529\n");
|
||||
|
||||
for (size_t row = 0; row < dls.text_line_count(); row++) {
|
||||
if (ec.ec_dry_run && row > 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
string line;
|
||||
for (size_t col = 0; col < dls.dls_headers.size(); col++) {
|
||||
const auto& hdr = dls.dls_headers[col];
|
||||
|
||||
dls.text_value_for_line(lnav_data.ld_views[LNV_DB], lpc, line,
|
||||
text_sub_source::RF_RAW);
|
||||
fputs(line.c_str(), outfile);
|
||||
fputc('\n', outfile);
|
||||
fprintf(outfile, "\u2502");
|
||||
|
||||
auto cell = dls.dls_rows[row][col];
|
||||
auto cell_byte_len = strlen(cell);
|
||||
auto cell_length = utf8_string_length(cell, cell_byte_len)
|
||||
.unwrapOr(cell_byte_len);
|
||||
auto padding = hdr.hm_column_size - cell_length;
|
||||
|
||||
if (hdr.hm_column_type != SQLITE3_TEXT) {
|
||||
fprintf(outfile, "%s", std::string(padding, ' ').c_str());
|
||||
}
|
||||
fprintf(outfile, "%s", cell);
|
||||
if (hdr.hm_column_type == SQLITE3_TEXT) {
|
||||
fprintf(outfile, "%s", std::string(padding, ' ').c_str());
|
||||
}
|
||||
}
|
||||
fprintf(outfile, "\u2502\n");
|
||||
|
||||
line_count += 1;
|
||||
}
|
||||
|
||||
first = true;
|
||||
fprintf(outfile, "\u2514");
|
||||
for (const auto& hdr : dls.dls_headers) {
|
||||
auto cell_line = repeat("\u2501", hdr.hm_column_size);
|
||||
|
||||
if (!first) {
|
||||
fprintf(outfile, "\u2534");
|
||||
}
|
||||
fprintf(outfile, "%s", cell_line.c_str());
|
||||
first = false;
|
||||
}
|
||||
fprintf(outfile, "\u2518\n");
|
||||
|
||||
}
|
||||
else if (args[0] == "write-json-to") {
|
||||
yajlpp_gen gen;
|
||||
|
@ -1123,7 +1176,7 @@ static Result<string, string> com_redirect_to(exec_context &ec, string cmdline,
|
|||
return Ok(string("info: redirect will be cleared"));
|
||||
}
|
||||
|
||||
ec.ec_output_stack.back() = nonstd::nullopt;
|
||||
ec.clear_output();
|
||||
return Ok(string("info: cleared redirect"));
|
||||
}
|
||||
|
||||
|
@ -1146,14 +1199,19 @@ static Result<string, string> com_redirect_to(exec_context &ec, string cmdline,
|
|||
return Ok("info: output will be redirected to -- " + split_args[0]);
|
||||
}
|
||||
|
||||
FILE *file = fopen(split_args[0].c_str(), "w");
|
||||
nonstd::optional<FILE *> file;
|
||||
|
||||
if (file == nullptr) {
|
||||
return ec.make_error("unable to open file -- {}", split_args[0]);
|
||||
if (split_args[0] == "-") {
|
||||
ec.clear_output();
|
||||
} else {
|
||||
FILE *file = fopen(split_args[0].c_str(), "w");
|
||||
if (file == nullptr) {
|
||||
return ec.make_error("unable to open file -- {}", split_args[0]);
|
||||
}
|
||||
|
||||
ec.set_output(split_args[0], file);
|
||||
}
|
||||
|
||||
ec.ec_output_stack.back() = file;
|
||||
|
||||
return Ok("info: redirecting output to file -- " + split_args[0]);
|
||||
}
|
||||
|
||||
|
@ -3396,20 +3454,24 @@ static Result<string, string> com_echo(exec_context &ec, string cmdline, vector<
|
|||
}
|
||||
else if (args.size() >= 1) {
|
||||
bool lf = true;
|
||||
string src;
|
||||
|
||||
if (args.size() > 2 && args[1] == "-n") {
|
||||
string::size_type index_in_cmdline = cmdline.find(args[1]);
|
||||
|
||||
lf = false;
|
||||
retval = cmdline.substr(index_in_cmdline + args[1].length() + 1);
|
||||
src = cmdline.substr(index_in_cmdline + args[1].length() + 1);
|
||||
}
|
||||
else if (args.size() >= 2) {
|
||||
retval = cmdline.substr(args[0].length() + 1);
|
||||
src = cmdline.substr(args[0].length() + 1);
|
||||
}
|
||||
else {
|
||||
retval = "";
|
||||
src = "";
|
||||
}
|
||||
|
||||
auto lexer = shlex(src);
|
||||
lexer.eval(retval, ec.create_resolver());
|
||||
|
||||
auto ec_out = ec.get_output();
|
||||
if (ec.ec_dry_run) {
|
||||
lnav_data.ld_preview_status_source.get_description()
|
||||
|
@ -4804,11 +4866,11 @@ readline_context::command_t STD_COMMANDS[] = {
|
|||
})
|
||||
},
|
||||
{
|
||||
"write-cols-to",
|
||||
"write-table-to",
|
||||
com_save_to,
|
||||
|
||||
help_text(":write-cols-to")
|
||||
.with_summary("Write SQL results to the given file in a columnar format")
|
||||
help_text(":write-table-to")
|
||||
.with_summary("Write SQL results to the given file in a tabular format")
|
||||
.with_parameter(help_text("path", "The path to the file to write"))
|
||||
.with_tags({"io", "scripting", "sql"})
|
||||
.with_example({
|
||||
|
@ -4873,7 +4935,8 @@ readline_context::command_t STD_COMMANDS[] = {
|
|||
com_redirect_to,
|
||||
|
||||
help_text(":redirect-to")
|
||||
.with_summary("Redirect the output of commands to the given file")
|
||||
.with_summary("Redirect the output of commands that write to "
|
||||
"stdout to the given file")
|
||||
.with_parameter(help_text(
|
||||
"path", "The path to the file to write."
|
||||
" If not specified, the current redirect will be cleared")
|
||||
|
@ -5256,9 +5319,13 @@ readline_context::command_t STD_COMMANDS[] = {
|
|||
com_echo,
|
||||
|
||||
help_text(":echo")
|
||||
.with_summary("Echo the given message")
|
||||
.with_summary(
|
||||
"Echo the given message to the screen or, if :redirect-to has "
|
||||
"been called, to output file specified in the redirect. "
|
||||
"Variable substitution is performed on the message. Use a "
|
||||
"backslash to escape any special characters, like '$'")
|
||||
.with_parameter(help_text("msg", "The message to display"))
|
||||
.with_tags({"scripting"})
|
||||
.with_tags({"io", "scripting"})
|
||||
.with_example({
|
||||
"To output 'Hello, World!'",
|
||||
"Hello, World!"
|
||||
|
@ -5289,10 +5356,6 @@ readline_context::command_t STD_COMMANDS[] = {
|
|||
.with_tags({"scripting"})
|
||||
.with_examples(
|
||||
{
|
||||
{
|
||||
"To output the user's home directory",
|
||||
":echo $HOME"
|
||||
},
|
||||
{
|
||||
"To substitute the table name from a variable",
|
||||
";SELECT * FROM ${table}"
|
||||
|
@ -5354,6 +5417,7 @@ readline_context::command_t STD_COMMANDS[] = {
|
|||
|
||||
static unordered_map<char const *, vector<char const *>> aliases = {
|
||||
{ "quit", { "q", "q!" } },
|
||||
{ "write-table-to", { "write-cols-to", }}
|
||||
};
|
||||
|
||||
void init_lnav_commands(readline_context::command_map_t &cmd_map)
|
||||
|
|
|
@ -2099,7 +2099,7 @@ public:
|
|||
|
||||
virtual bool next(log_cursor &lc, logfile_sub_source &lss)
|
||||
{
|
||||
lc.lc_curr_line = lc.lc_curr_line + vis_line_t(1);
|
||||
lc.lc_curr_line = lc.lc_curr_line + 1_vl;
|
||||
lc.lc_sub_index = 0;
|
||||
|
||||
if (lc.is_eof()) {
|
||||
|
@ -2107,7 +2107,7 @@ public:
|
|||
}
|
||||
|
||||
content_line_t cl(lss.at(lc.lc_curr_line));
|
||||
shared_ptr<logfile> lf = lss.find(cl);
|
||||
auto lf = lss.find_file_ptr(cl);
|
||||
auto lf_iter = lf->begin() + cl;
|
||||
uint8_t mod_id = lf_iter->get_module_id();
|
||||
|
||||
|
@ -2115,12 +2115,12 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
auto format = lf->get_format();
|
||||
|
||||
this->elt_module_format.mf_mod_format = nullptr;
|
||||
if (format->get_name() == this->lfvi_format.get_name()) {
|
||||
if (lf->get_format_name() == this->lfvi_format.get_name()) {
|
||||
return true;
|
||||
} else if (mod_id && mod_id == this->lfvi_format.lf_mod_index) {
|
||||
auto format = lf->get_format();
|
||||
|
||||
return lf->read_line(lf_iter).map([this, format, cl](auto line) {
|
||||
std::vector<logline_value> values;
|
||||
shared_buffer_ref body_ref;
|
||||
|
|
|
@ -60,6 +60,7 @@ static const char *LOG_COLUMNS = R"( (
|
|||
|
||||
static const char *LOG_FOOTER_COLUMNS = R"(
|
||||
-- END Format-specific fields
|
||||
log_time_msecs INTEGER HIDDEN, -- The adjusted timestamp for the log message as the number of milliseconds from the epoch
|
||||
log_path TEXT HIDDEN COLLATE naturalnocase, -- The path to the log file this message is from
|
||||
log_text TEXT HIDDEN, -- The full text of the log message
|
||||
log_body TEXT HIDDEN -- The body of the log message
|
||||
|
@ -518,6 +519,10 @@ static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
|
|||
|
||||
switch (post_col_number) {
|
||||
case 0: {
|
||||
sqlite3_result_int64(ctx, ll->get_time_in_millis());
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
const string &fn = lf->get_filename();
|
||||
|
||||
sqlite3_result_text(ctx,
|
||||
|
@ -526,7 +531,7 @@ static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
|
|||
SQLITE_STATIC);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
case 2: {
|
||||
shared_buffer_ref line;
|
||||
|
||||
lf->read_full_message(ll, line);
|
||||
|
@ -536,7 +541,7 @@ static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
|
|||
SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
case 3: {
|
||||
if (vc->line_values.empty()) {
|
||||
lf->read_full_message(ll, vc->log_msg);
|
||||
vt->vi->extract(lf, line_number, vc->log_msg, vc->line_values);
|
||||
|
|
|
@ -137,6 +137,7 @@ public:
|
|||
keys_inout.emplace_back("log_line");
|
||||
keys_inout.emplace_back("min(log_line)");
|
||||
keys_inout.emplace_back("log_mark");
|
||||
keys_inout.emplace_back("log_time_msecs");
|
||||
};
|
||||
|
||||
virtual void extract(std::shared_ptr<logfile> lf,
|
||||
|
|
|
@ -651,3 +651,12 @@ logfile::read_raw_message(logfile::const_iterator ll)
|
|||
|
||||
return this->lf_line_buffer.read_range(this->get_file_range(ll));
|
||||
}
|
||||
|
||||
intern_string_t logfile::get_format_name() const
|
||||
{
|
||||
if (this->lf_format) {
|
||||
return this->lf_format->get_name();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -164,6 +164,8 @@ public:
|
|||
*/
|
||||
std::shared_ptr<log_format> get_format() const { return this->lf_format; };
|
||||
|
||||
intern_string_t get_format_name() const;
|
||||
|
||||
text_format_t get_text_format() const {
|
||||
return this->lf_text_format;
|
||||
}
|
||||
|
|
|
@ -1068,6 +1068,10 @@ bool logfile_sub_source::eval_sql_filter(sqlite3_stmt *stmt, iterator ld, logfil
|
|||
SQLITE_STATIC);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(name, ":log_time_msecs") == 0) {
|
||||
sqlite3_bind_int64(stmt, lpc + 1, ll->get_time_in_millis());
|
||||
continue;
|
||||
}
|
||||
if (strcmp(name, ":log_mark") == 0) {
|
||||
sqlite3_bind_int(stmt, lpc + 1, ll->is_marked());
|
||||
continue;
|
||||
|
|
|
@ -501,6 +501,14 @@ public:
|
|||
return retval;
|
||||
};
|
||||
|
||||
logfile *find_file_ptr(content_line_t &line)
|
||||
{
|
||||
auto retval = this->lss_files[line / MAX_LINES_PER_FILE]->get_file_ptr();
|
||||
line = content_line_t(line % MAX_LINES_PER_FILE);
|
||||
|
||||
return retval;
|
||||
};
|
||||
|
||||
logline *find_line(content_line_t line)
|
||||
{
|
||||
logline *retval = nullptr;
|
||||
|
@ -599,7 +607,7 @@ public:
|
|||
{
|
||||
this->ld_filter_state.lfo_filter_state.clear();
|
||||
};
|
||||
\
|
||||
|
||||
void set_file(const std::shared_ptr<logfile> &lf) {
|
||||
this->ld_filter_state.lfo_filter_state.tfs_logfile = lf;
|
||||
lf->set_logline_observer(&this->ld_filter_state);
|
||||
|
@ -609,6 +617,10 @@ public:
|
|||
return this->ld_filter_state.lfo_filter_state.tfs_logfile;
|
||||
};
|
||||
|
||||
logfile *get_file_ptr() const {
|
||||
return this->ld_filter_state.lfo_filter_state.tfs_logfile.get();
|
||||
};
|
||||
|
||||
bool is_visible() const {
|
||||
return this->ld_visible;
|
||||
}
|
||||
|
|
|
@ -200,7 +200,6 @@ bool rl_sql_help(readline_curses *rc)
|
|||
auto vtab_module_iter = vtab_module_ddls.find(intern_ident);
|
||||
string ddl;
|
||||
|
||||
log_debug("ident %s", ident.c_str());
|
||||
if (vtab != nullptr) {
|
||||
ddl = trim(vtab->get_table_statement());
|
||||
} else if (vtab_module_iter != vtab_module_ddls.end()) {
|
||||
|
@ -367,7 +366,6 @@ static void rl_search_internal(readline_curses *rc, ln_mode_t mode, bool complet
|
|||
lnav_data.ld_log_source.set_preview_sql_filter(nullptr);
|
||||
tc->reload_data();
|
||||
|
||||
log_debug("rl_search_int");
|
||||
switch (mode) {
|
||||
case LNM_SEARCH:
|
||||
case LNM_SEARCH_FILTERS:
|
||||
|
@ -633,22 +631,23 @@ static void rl_callback_int(readline_curses *rc, bool is_alt)
|
|||
rc->set_value("Unable to open temporary output file: " +
|
||||
string(strerror(errno)));
|
||||
} else {
|
||||
auto_fd fd(fileno(tmpout));
|
||||
auto_fd fd_copy((const auto_fd &) fd);
|
||||
auto fd_copy = auto_fd::dup_of(fileno(tmpout));
|
||||
char desc[256], timestamp[32];
|
||||
time_t current_time = time(NULL);
|
||||
time_t current_time = time(nullptr);
|
||||
string path_and_args = rc->get_value();
|
||||
|
||||
ec.ec_output_stack.back() = tmpout.in();
|
||||
string result = execute_file(ec, path_and_args)
|
||||
.map(ok_prefix)
|
||||
.orElse(err_to_ok).unwrap();
|
||||
string::size_type lf_index = result.find('\n');
|
||||
if (lf_index != string::npos) {
|
||||
result = result.substr(0, lf_index);
|
||||
{
|
||||
exec_context::output_guard og(ec, "tmp", tmpout.release());
|
||||
|
||||
string result = execute_file(ec, path_and_args)
|
||||
.map(ok_prefix)
|
||||
.orElse(err_to_ok).unwrap();
|
||||
string::size_type lf_index = result.find('\n');
|
||||
if (lf_index != string::npos) {
|
||||
result = result.substr(0, lf_index);
|
||||
}
|
||||
rc->set_value(result);
|
||||
}
|
||||
rc->set_value(result);
|
||||
ec.ec_output_stack.back() = nonstd::nullopt;
|
||||
|
||||
struct stat st;
|
||||
|
||||
|
@ -666,7 +665,7 @@ static void rl_callback_int(readline_curses *rc, bool is_alt)
|
|||
.with_detect_format(false);
|
||||
lnav_data.ld_files_to_front.emplace_back(desc, 0);
|
||||
|
||||
if (lnav_data.ld_rl_view != NULL) {
|
||||
if (lnav_data.ld_rl_view != nullptr) {
|
||||
lnav_data.ld_rl_view->set_alt_value(
|
||||
HELP_MSG_1(X, "to close the file"));
|
||||
}
|
||||
|
|
|
@ -223,6 +223,7 @@ void add_filter_expr_possibilities(readline_curses *rlc, int context, const std:
|
|||
static const char *BUILTIN_VARS[] = {
|
||||
":log_level",
|
||||
":log_time",
|
||||
":log_time_msecs",
|
||||
":log_mark",
|
||||
":log_comment",
|
||||
":log_tags",
|
||||
|
|
|
@ -274,7 +274,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
int64_t to_microseconds() {
|
||||
int64_t to_microseconds() const {
|
||||
int64_t retval;
|
||||
|
||||
retval = this->rt_field[RTF_YEARS].value * 12;
|
||||
|
|
|
@ -20,4 +20,4 @@
|
|||
(SELECT lt2.start_time AS end_time FROM lease_times AS lt2 WHERE lt1.start_time < lt2.start_time LIMIT 1) AS end_time,
|
||||
ip
|
||||
FROM lease_times AS lt1)
|
||||
:write-cols-to -
|
||||
:write-table-to -
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
# @description: Partition the log view based on boot messages from the Linux kernel.
|
||||
#
|
||||
|
||||
;UPDATE syslog_log SET log_part = 'Boot: ' || log_time WHERE log_text LIKE '%kernel: Linux version%';
|
||||
;UPDATE syslog_log
|
||||
SET log_part = 'Boot: ' || log_time
|
||||
WHERE log_text LIKE '%kernel:%Linux version%';
|
||||
|
||||
;SELECT 'Created ' || changes() || ' partitions(s)';
|
||||
|
|
19
src/shlex.cc
19
src/shlex.cc
|
@ -193,3 +193,22 @@ void shlex::scan_variable_ref(pcre_context::capture_t &cap_out,
|
|||
token_out = shlex_token_t::ST_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void shlex::resolve_home_dir(std::string &result,
|
||||
const pcre_context::capture_t cap) const
|
||||
{
|
||||
if (cap.length() == 1) {
|
||||
result.append(getenv_opt("HOME").value_or("~"));
|
||||
} else {
|
||||
auto username = (char *) alloca(cap.length());
|
||||
|
||||
memcpy(username, &this->s_str[cap.c_begin + 1], cap.length() - 1);
|
||||
username[cap.length() - 1] = '\0';
|
||||
auto pw = getpwnam(username);
|
||||
if (pw != nullptr) {
|
||||
result.append(pw->pw_dir);
|
||||
} else {
|
||||
result.append(&this->s_str[cap.c_begin], cap.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
25
src/shlex.hh
25
src/shlex.hh
|
@ -141,6 +141,14 @@ public:
|
|||
case shlex_token_t::ST_TILDE:
|
||||
this->resolve_home_dir(result, cap);
|
||||
break;
|
||||
case shlex_token_t::ST_DOUBLE_QUOTE_START:
|
||||
case shlex_token_t::ST_DOUBLE_QUOTE_END:
|
||||
result.append("\"");
|
||||
break;
|
||||
case shlex_token_t::ST_SINGLE_QUOTE_START:
|
||||
case shlex_token_t::ST_SINGLE_QUOTE_END:
|
||||
result.append("'");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -220,22 +228,7 @@ public:
|
|||
|
||||
void scan_variable_ref(pcre_context::capture_t &cap_out, shlex_token_t &token_out);
|
||||
|
||||
void resolve_home_dir(std::string& result, const pcre_context::capture_t cap) const {
|
||||
if (cap.length() == 1) {
|
||||
result.append(getenv_opt("HOME").value_or("~"));
|
||||
} else {
|
||||
auto username = (char *) alloca(cap.length());
|
||||
|
||||
memcpy(username, &this->s_str[cap.c_begin + 1], cap.length() - 1);
|
||||
username[cap.length() - 1] = '\0';
|
||||
auto pw = getpwnam(username);
|
||||
if (pw != nullptr) {
|
||||
result.append(pw->pw_dir);
|
||||
} else {
|
||||
result.append(&this->s_str[cap.c_begin], cap.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
void resolve_home_dir(std::string& result, const pcre_context::capture_t cap) const;
|
||||
|
||||
enum class state_t {
|
||||
STATE_NORMAL,
|
||||
|
|
|
@ -98,7 +98,7 @@ int register_sqlite_funcs(sqlite3 *db, sqlite_registration_func_t *reg_funcs)
|
|||
agg_funcs[i].nArg,
|
||||
SQLITE_UTF8,
|
||||
(void *) &agg_funcs[i],
|
||||
0,
|
||||
nullptr,
|
||||
agg_funcs[i].xStep,
|
||||
agg_funcs[i].xFinalize);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "pcrepp/pcrepp.hh"
|
||||
|
||||
#include "base/humanize.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "yajlpp/yajlpp.hh"
|
||||
#include "column_namer.hh"
|
||||
|
@ -248,6 +249,60 @@ static void sql_spooky_hash_final(sqlite3_context *context)
|
|||
}
|
||||
}
|
||||
|
||||
struct sparkline_context {
|
||||
bool sc_initialized{true};
|
||||
double sc_max_value{0.0};
|
||||
std::vector<double> sc_values;
|
||||
};
|
||||
|
||||
static void sparkline_step(sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv)
|
||||
{
|
||||
auto *sc = (sparkline_context *)
|
||||
sqlite3_aggregate_context(context, sizeof(sparkline_context));
|
||||
|
||||
if (!sc->sc_initialized) {
|
||||
new (sc) sparkline_context;
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_values.push_back(sqlite3_value_double(argv[0]));
|
||||
sc->sc_max_value = std::max(sc->sc_max_value, sc->sc_values.back());
|
||||
|
||||
if (argc >= 2) {
|
||||
sc->sc_max_value = std::max(sc->sc_max_value,
|
||||
sqlite3_value_double(argv[1]));
|
||||
}
|
||||
}
|
||||
|
||||
static void sparkline_final(sqlite3_context *context)
|
||||
{
|
||||
auto *sc = (sparkline_context *)
|
||||
sqlite3_aggregate_context(context, sizeof(sparkline_context));
|
||||
|
||||
if (!sc->sc_initialized) {
|
||||
sqlite3_result_text(context, "", 0, SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
|
||||
auto retval = (char *) sqlite3_malloc(sc->sc_values.size() * 3 + 1);
|
||||
auto start = retval;
|
||||
|
||||
for (const auto& value : sc->sc_values) {
|
||||
auto bar = humanize::sparkline(value, sc->sc_max_value);
|
||||
|
||||
strcpy(start, bar.c_str());
|
||||
start += bar.length();
|
||||
}
|
||||
*start = '\0';
|
||||
|
||||
sqlite3_result_text(context, retval, -1, sqlite3_free);
|
||||
}
|
||||
|
||||
int string_extension_functions(struct FuncDef **basic_funcs,
|
||||
struct FuncDefAgg **agg_funcs)
|
||||
{
|
||||
|
@ -301,6 +356,34 @@ int string_extension_functions(struct FuncDef **basic_funcs,
|
|||
})
|
||||
),
|
||||
|
||||
sqlite_func_adapter<decltype(&humanize::file_size), humanize::file_size>::builder(
|
||||
help_text("humanize_file_size",
|
||||
"Format the given file size as a human-friendly string")
|
||||
.sql_function()
|
||||
.with_parameter({"value", "The file size to format"})
|
||||
.with_tags({"string"})
|
||||
.with_example({
|
||||
"To format an amount",
|
||||
"SELECT humanize_file_size(10 * 1024 * 1024)"
|
||||
})
|
||||
),
|
||||
|
||||
sqlite_func_adapter<decltype(&humanize::sparkline), humanize::sparkline>::builder(
|
||||
help_text("sparkline",
|
||||
"Converts a numeric value on a range to a bar chart character")
|
||||
.sql_function()
|
||||
.with_parameter({"value", "The numeric value to convert"})
|
||||
.with_parameter(help_text(
|
||||
"upper", "The upper bound of the numeric range (default: 100)")
|
||||
.optional())
|
||||
.with_tags({"string"})
|
||||
.with_example({
|
||||
"To get the unicode block element for the value 32 in the "
|
||||
"range of 0-128",
|
||||
"SELECT sparkline(32, 128)"
|
||||
})
|
||||
),
|
||||
|
||||
sqlite_func_adapter<decltype(&extract), extract>::builder(
|
||||
help_text("extract",
|
||||
"Automatically Parse and extract data from a string")
|
||||
|
@ -388,7 +471,7 @@ int string_extension_functions(struct FuncDef **basic_funcs,
|
|||
sql_spooky_hash_step, sql_spooky_hash_final,
|
||||
help_text("group_spooky_hash",
|
||||
"Compute the hash value for the given arguments")
|
||||
.sql_function()
|
||||
.sql_agg_function()
|
||||
.with_parameter(help_text("str", "The string to hash")
|
||||
.one_or_more())
|
||||
.with_tags({"string"})
|
||||
|
@ -398,6 +481,26 @@ int string_extension_functions(struct FuncDef **basic_funcs,
|
|||
})
|
||||
},
|
||||
|
||||
{
|
||||
"sparkline", -1, 0,
|
||||
sparkline_step, sparkline_final,
|
||||
help_text("sparkline",
|
||||
"An aggregate function to convert numeric values to a "
|
||||
"sparkline bar chart")
|
||||
.sql_agg_function()
|
||||
.with_parameter({"value", "The numeric values to chart"})
|
||||
.with_parameter(help_text(
|
||||
"upper", "The upper bound of the numeric range. "
|
||||
"If not provided, the default is derived from "
|
||||
"all of the provided values")
|
||||
.optional())
|
||||
.with_tags({"string"})
|
||||
.with_example({
|
||||
"To chart the values in a JSON array",
|
||||
"SELECT sparkline(value) FROM json_each('[0, 1, 2, 3, 4, 5, 6, 7, 8]')"
|
||||
})
|
||||
},
|
||||
|
||||
{nullptr}
|
||||
};
|
||||
|
||||
|
|
|
@ -234,15 +234,22 @@ void textview_curses::grep_begin(grep_proc<vis_line_t> &gp, vis_line_t start, vi
|
|||
this->tc_searching += 1;
|
||||
this->tc_search_action(this);
|
||||
|
||||
bookmark_vector<vis_line_t> &search_bv = this->tc_bookmarks[&BM_SEARCH];
|
||||
|
||||
if (start != -1) {
|
||||
auto pair = search_bv.equal_range(vis_line_t(start), vis_line_t(stop));
|
||||
if (start != -1_vl) {
|
||||
auto& search_bv = this->tc_bookmarks[&BM_SEARCH];
|
||||
auto pair = search_bv.equal_range(start, stop);
|
||||
|
||||
if (pair.first != pair.second) {
|
||||
this->set_needs_update();
|
||||
}
|
||||
for (auto mark_iter = pair.first;
|
||||
mark_iter != pair.second;
|
||||
++mark_iter) {
|
||||
this->set_user_mark(&BM_SEARCH, *mark_iter, false);
|
||||
if (this->tc_sub_source) {
|
||||
this->tc_sub_source->text_mark(&BM_SEARCH, *mark_iter, false);
|
||||
}
|
||||
}
|
||||
if (pair.first != pair.second) {
|
||||
search_bv.erase(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -652,6 +659,71 @@ textview_curses::horiz_shift(vis_line_t start, vis_line_t end, int off_start,
|
|||
range_out = std::make_pair(prev_hit, next_hit);
|
||||
}
|
||||
|
||||
void
|
||||
textview_curses::set_user_mark(bookmark_type_t *bm, vis_line_t vl, bool marked)
|
||||
{
|
||||
bookmark_vector<vis_line_t> &bv = this->tc_bookmarks[bm];
|
||||
bookmark_vector<vis_line_t>::iterator iter;
|
||||
|
||||
if (marked) {
|
||||
bv.insert_once(vl);
|
||||
}
|
||||
else {
|
||||
iter = std::lower_bound(bv.begin(), bv.end(), vl);
|
||||
if (iter != bv.end() && *iter == vl) {
|
||||
bv.erase(iter);
|
||||
}
|
||||
}
|
||||
if (this->tc_sub_source) {
|
||||
this->tc_sub_source->text_mark(bm, vl, marked);
|
||||
}
|
||||
|
||||
if (marked) {
|
||||
this->search_range(vl, vl + 1_vl);
|
||||
this->search_new_data();
|
||||
}
|
||||
this->set_needs_update();
|
||||
}
|
||||
|
||||
void
|
||||
textview_curses::toggle_user_mark(bookmark_type_t *bm, vis_line_t start_line,
|
||||
vis_line_t end_line)
|
||||
{
|
||||
if (end_line == -1) {
|
||||
end_line = start_line;
|
||||
}
|
||||
if (start_line > end_line) {
|
||||
std::swap(start_line, end_line);
|
||||
}
|
||||
|
||||
if (start_line >= this->get_inner_height()) {
|
||||
return;
|
||||
}
|
||||
if (end_line >= this->get_inner_height()) {
|
||||
end_line = vis_line_t(this->get_inner_height() - 1);
|
||||
}
|
||||
for (vis_line_t curr_line = start_line; curr_line <= end_line;
|
||||
++curr_line) {
|
||||
bookmark_vector<vis_line_t> &bv = this->tc_bookmarks[bm];
|
||||
bookmark_vector<vis_line_t>::iterator iter;
|
||||
bool added;
|
||||
|
||||
iter = bv.insert_once(curr_line);
|
||||
if (iter == bv.end()) {
|
||||
added = true;
|
||||
}
|
||||
else {
|
||||
bv.erase(iter);
|
||||
added = false;
|
||||
}
|
||||
if (this->tc_sub_source) {
|
||||
this->tc_sub_source->text_mark(bm, curr_line, added);
|
||||
}
|
||||
}
|
||||
this->search_range(start_line, end_line + 1_vl);
|
||||
this->search_new_data();
|
||||
}
|
||||
|
||||
void text_time_translator::scroll_invoked(textview_curses *tc)
|
||||
{
|
||||
if (tc->get_inner_height() > 0) {
|
||||
|
|
|
@ -635,64 +635,9 @@ public:
|
|||
|
||||
void toggle_user_mark(bookmark_type_t *bm,
|
||||
vis_line_t start_line,
|
||||
vis_line_t end_line = vis_line_t(-1))
|
||||
{
|
||||
if (end_line == -1) {
|
||||
end_line = start_line;
|
||||
}
|
||||
if (start_line > end_line) {
|
||||
std::swap(start_line, end_line);
|
||||
}
|
||||
vis_line_t end_line = vis_line_t(-1));;
|
||||
|
||||
if (start_line >= this->get_inner_height()) {
|
||||
return;
|
||||
}
|
||||
if (end_line >= this->get_inner_height()) {
|
||||
end_line = vis_line_t(this->get_inner_height() - 1);
|
||||
}
|
||||
for (vis_line_t curr_line = start_line; curr_line <= end_line;
|
||||
++curr_line) {
|
||||
bookmark_vector<vis_line_t> &bv = this->tc_bookmarks[bm];
|
||||
bookmark_vector<vis_line_t>::iterator iter;
|
||||
bool added;
|
||||
|
||||
iter = bv.insert_once(curr_line);
|
||||
if (iter == bv.end()) {
|
||||
added = true;
|
||||
}
|
||||
else {
|
||||
bv.erase(iter);
|
||||
added = false;
|
||||
}
|
||||
if (this->tc_sub_source) {
|
||||
this->tc_sub_source->text_mark(bm, curr_line, added);
|
||||
}
|
||||
}
|
||||
this->search_range(start_line, end_line + 1_vl);
|
||||
this->search_new_data();
|
||||
};
|
||||
|
||||
void set_user_mark(bookmark_type_t *bm, vis_line_t vl, bool marked) {
|
||||
bookmark_vector<vis_line_t> &bv = this->tc_bookmarks[bm];
|
||||
bookmark_vector<vis_line_t>::iterator iter;
|
||||
|
||||
if (marked) {
|
||||
bv.insert_once(vl);
|
||||
}
|
||||
else {
|
||||
iter = std::lower_bound(bv.begin(), bv.end(), vl);
|
||||
if (iter != bv.end() && *iter == vl) {
|
||||
bv.erase(iter);
|
||||
}
|
||||
}
|
||||
if (this->tc_sub_source) {
|
||||
this->tc_sub_source->text_mark(bm, vl, marked);
|
||||
}
|
||||
|
||||
this->search_range(vl, vl + 1_vl);
|
||||
this->search_new_data();
|
||||
this->set_needs_update();
|
||||
};
|
||||
void set_user_mark(bookmark_type_t *bm, vis_line_t vl, bool marked);;
|
||||
|
||||
textview_curses &set_sub_source(text_sub_source *src) {
|
||||
this->tc_sub_source = src;
|
||||
|
|
|
@ -36,8 +36,10 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/date_time_scanner.hh"
|
||||
#include "base/lrucache.hpp"
|
||||
#include "sql_util.hh"
|
||||
#include "relative_time.hh"
|
||||
|
||||
|
@ -45,47 +47,75 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static string timeslice(const char *time_in, nonstd::optional<const char *> slice_in_opt)
|
||||
static lnav::sqlite::text_buffer timeslice(sqlite3_value *time_in, nonstd::optional<const char *> slice_in_opt)
|
||||
{
|
||||
const char *slice_in = slice_in_opt.value_or("15m");
|
||||
auto parse_res = relative_time::from_str(slice_in, strlen(slice_in));
|
||||
date_time_scanner dts;
|
||||
time_t now;
|
||||
thread_local date_time_scanner dts;
|
||||
thread_local struct {
|
||||
std::string c_slice_str;
|
||||
relative_time c_rel_time;
|
||||
} cache;
|
||||
const auto slice_in = string_fragment(slice_in_opt.value_or("15m"));
|
||||
|
||||
time(&now);
|
||||
dts.set_base_time(now);
|
||||
|
||||
if (parse_res.isErr()) {
|
||||
throw sqlite_func_error("unable to parse time slice value: {} -- {}",
|
||||
slice_in, parse_res.unwrapErr().pe_msg);
|
||||
}
|
||||
|
||||
auto rt = parse_res.unwrap();
|
||||
if (rt.empty()) {
|
||||
if (slice_in.empty()) {
|
||||
throw sqlite_func_error("no time slice value given");
|
||||
}
|
||||
|
||||
if (rt.is_absolute()) {
|
||||
throw sqlite_func_error("absolute time slices are not valid");
|
||||
if (slice_in != cache.c_slice_str.c_str()) {
|
||||
auto parse_res = relative_time::from_str(slice_in.data());
|
||||
if (parse_res.isErr()) {
|
||||
throw sqlite_func_error("unable to parse time slice value: {} -- {}",
|
||||
slice_in, parse_res.unwrapErr().pe_msg);
|
||||
}
|
||||
|
||||
cache.c_rel_time = parse_res.unwrap();
|
||||
if (cache.c_rel_time.empty()) {
|
||||
throw sqlite_func_error("could not determine a time slice from: {}",
|
||||
slice_in);
|
||||
}
|
||||
|
||||
if (cache.c_rel_time.is_absolute()) {
|
||||
throw sqlite_func_error("absolute time slices are not valid");
|
||||
}
|
||||
|
||||
cache.c_slice_str = slice_in.to_string();
|
||||
}
|
||||
|
||||
struct exttm tm;
|
||||
int64_t us, remainder;
|
||||
struct timeval tv;
|
||||
|
||||
if (dts.scan(time_in, strlen(time_in), nullptr, &tm, tv) == nullptr) {
|
||||
throw sqlite_func_error("unable to parse time value -- {}", time_in);
|
||||
switch (sqlite3_value_type(time_in)) {
|
||||
case SQLITE3_TEXT: {
|
||||
const char *time_in_str = reinterpret_cast<const char *>(sqlite3_value_text(
|
||||
time_in));
|
||||
struct exttm tm;
|
||||
|
||||
if (dts.scan(time_in_str, strlen(time_in_str), nullptr, &tm, tv, false) == nullptr) {
|
||||
dts.unlock();
|
||||
if (dts.scan(time_in_str, strlen(time_in_str), nullptr, &tm, tv, false) == nullptr) {
|
||||
throw sqlite_func_error("unable to parse time value -- {}",
|
||||
time_in_str);
|
||||
}
|
||||
}
|
||||
|
||||
us = tv.tv_sec * 1000000LL + tv.tv_usec;
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
auto msecs = sqlite3_value_int64(time_in);
|
||||
|
||||
us = msecs * 1000LL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t us = tv.tv_sec * 1000000LL + tv.tv_usec, remainder;
|
||||
|
||||
remainder = us % rt.to_microseconds();
|
||||
remainder = us % cache.c_rel_time.to_microseconds();
|
||||
us -= remainder;
|
||||
|
||||
tv.tv_sec = us / (1000 * 1000);
|
||||
tv.tv_usec = us % (1000 * 1000);
|
||||
tv.tv_sec = us / (1000LL * 1000LL);
|
||||
tv.tv_usec = us % (1000LL * 1000LL);
|
||||
|
||||
char ts[64];
|
||||
sql_strftime(ts, sizeof(ts), tv);
|
||||
auto ts = lnav::sqlite::text_buffer::alloc(64);
|
||||
ts.tb_length = sql_strftime(ts.tb_value, ts.tb_length, tv);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
@ -132,7 +162,7 @@ int time_extension_functions(struct FuncDef **basic_funcs,
|
|||
})
|
||||
.with_example({
|
||||
"To group log messages into five minute buckets and count them",
|
||||
"SELECT timeslice(log_time, '5m') AS slice, count(*) FROM lnav_example_log GROUP BY slice"
|
||||
"SELECT timeslice(log_time_msecs, '5m') AS slice, count(*) FROM lnav_example_log GROUP BY slice"
|
||||
})
|
||||
),
|
||||
|
||||
|
|
|
@ -172,6 +172,27 @@ inline void to_sqlite(sqlite3_context *ctx, const char *str)
|
|||
}
|
||||
}
|
||||
|
||||
namespace lnav {
|
||||
namespace sqlite {
|
||||
struct text_buffer {
|
||||
static text_buffer alloc(size_t size) {
|
||||
return text_buffer {
|
||||
(char *) malloc(size),
|
||||
size,
|
||||
};
|
||||
}
|
||||
|
||||
char *tb_value;
|
||||
size_t tb_length;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_sqlite(sqlite3_context *ctx, const lnav::sqlite::text_buffer &str)
|
||||
{
|
||||
sqlite3_result_text(ctx, str.tb_value, str.tb_length, free);
|
||||
}
|
||||
|
||||
inline void to_sqlite(sqlite3_context *ctx, const std::string &str)
|
||||
{
|
||||
sqlite3_result_text(ctx, str.c_str(), str.length(), SQLITE_TRANSIENT);
|
||||
|
|
|
@ -1233,10 +1233,11 @@ Parameter
|
|||
X The unicode code point values
|
||||
See Also
|
||||
charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To get a string with the code points 0x48 and 0x49:
|
||||
;SELECT char(0x48, 0x49)
|
||||
|
@ -1252,11 +1253,12 @@ Parameters
|
|||
haystack The string to search within
|
||||
start The one-based index within the haystack to start the search
|
||||
See Also
|
||||
char(), endswith(), extract(), group_concat(), group_spooky_hash(), instr(),
|
||||
leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
char(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), 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)
|
||||
|
@ -1402,11 +1404,12 @@ Parameters
|
|||
str The string to test
|
||||
suffix The suffix to check in the string
|
||||
See Also
|
||||
char(), charindex(), extract(), group_concat(), group_spooky_hash(), instr(),
|
||||
leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
char(), charindex(), extract(), group_concat(), group_spooky_hash(),
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To test if the string 'notbad.jpg' ends with '.jpg':
|
||||
;SELECT endswith('notbad.jpg', '.jpg')
|
||||
|
@ -1436,11 +1439,12 @@ Synopsis
|
|||
Parameter
|
||||
str The string to parse
|
||||
See Also
|
||||
char(), charindex(), endswith(), group_concat(), group_spooky_hash(), instr(),
|
||||
leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
char(), charindex(), endswith(), group_concat(), group_spooky_hash(),
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To extract key/value pairs from a string:
|
||||
;SELECT extract('foo=1 bar=2 name="Rolo Tomassi"')
|
||||
|
@ -1518,11 +1522,12 @@ Parameters
|
|||
X The value to concatenate.
|
||||
sep The separator to place between the values.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_spooky_hash(), instr(),
|
||||
leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
char(), charindex(), endswith(), extract(), group_spooky_hash(),
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To concatenate the values of the column 'ex_procname' from the table 'lnav_example_log'
|
||||
:
|
||||
|
@ -1545,11 +1550,12 @@ Synopsis
|
|||
Parameter
|
||||
str The string to hash
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), instr(), leftstr(),
|
||||
length(), lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
|
||||
regexp_capture(), regexp_match(), regexp_replace(), replace(), replicate(),
|
||||
reverse(), rightstr(), rtrim(), spooky_hash(), startswith(), strfilter(),
|
||||
substr(), trim(), unicode(), upper(), xpath()
|
||||
char(), charindex(), endswith(), extract(), group_concat(),
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), 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'))
|
||||
|
@ -1568,6 +1574,24 @@ Example
|
|||
|
||||
|
||||
|
||||
Synopsis
|
||||
humanize_file_size(value) -- Format the given file size as a human-friendly
|
||||
string
|
||||
Parameter
|
||||
value The file size to format
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To format an amount:
|
||||
;SELECT humanize_file_size(10 * 1024 * 1024)
|
||||
|
||||
|
||||
|
||||
Synopsis
|
||||
ifnull(X, Y) -- Returns a copy of its first non-NULL argument, or NULL if
|
||||
both arguments are NULL
|
||||
|
@ -1590,10 +1614,11 @@ Parameters
|
|||
needle The string to look for in the haystack
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), leftstr(), length(), lower(), ltrim(), padc(), padl(),
|
||||
padr(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To test get the position of 'b' in the string 'abc':
|
||||
;SELECT instr('abc', 'b')
|
||||
|
@ -1795,10 +1820,11 @@ Parameters
|
|||
N The number of characters from the left side of the string to return.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), length(), lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
|
||||
regexp_capture(), regexp_match(), regexp_replace(), replace(), replicate(),
|
||||
reverse(), rightstr(), rtrim(), spooky_hash(), startswith(), strfilter(),
|
||||
substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), length(), lower(), ltrim(), padc(), padl(),
|
||||
padr(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To get the first character of the string 'abc':
|
||||
;SELECT leftstr('abc', 1)
|
||||
|
@ -1816,10 +1842,11 @@ Parameter
|
|||
str The string to determine the length of
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), lower(), ltrim(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), lower(), ltrim(), padc(), padl(),
|
||||
padr(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To get the length of the string 'abc':
|
||||
;SELECT length('abc')
|
||||
|
@ -1911,10 +1938,11 @@ Parameter
|
|||
str The string to convert.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), ltrim(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), ltrim(), padc(), padl(),
|
||||
padr(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To lowercase the string 'AbC':
|
||||
;SELECT lower('AbC')
|
||||
|
@ -1930,10 +1958,11 @@ Parameters
|
|||
chars The characters to trim. Defaults to spaces.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), padc(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), padc(), padl(),
|
||||
padr(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To trim the leading whitespace from the string ' abc':
|
||||
;SELECT ltrim(' abc')
|
||||
|
@ -2028,10 +2057,11 @@ Parameters
|
|||
len The minimum desired length of the output string
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padl(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padl(),
|
||||
padr(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To pad the string 'abc' to a length of six characters:
|
||||
;SELECT padc('abc', 6) || 'def'
|
||||
|
@ -2050,10 +2080,11 @@ Parameters
|
|||
len The minimum desired length of the output string
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padr(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padr(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To pad the string 'abc' to a length of six characters:
|
||||
;SELECT padl('abc', 6)
|
||||
|
@ -2072,10 +2103,11 @@ Parameters
|
|||
len The minimum desired length of the output string
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), printf(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To pad the string 'abc' to a length of six characters:
|
||||
;SELECT padr('abc', 6) || 'def'
|
||||
|
@ -2128,10 +2160,11 @@ Parameters
|
|||
X The argument to substitute at a given position in the format.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
proper(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To substitute 'World' into the string 'Hello, %s!':
|
||||
;SELECT printf('Hello, %s!', 'World')
|
||||
|
@ -2152,10 +2185,11 @@ Parameter
|
|||
str The string to capitalize.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), regexp_capture(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To capitalize the words in the string 'hello, world!':
|
||||
;SELECT proper('hello, world!')
|
||||
|
@ -2256,10 +2290,11 @@ Results
|
|||
content The captured value from the string.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_match(), regexp_replace(), replace(), replicate(),
|
||||
reverse(), rightstr(), rtrim(), spooky_hash(), startswith(), strfilter(),
|
||||
substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_match(), regexp_replace(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), sparkline(), sparkline(),
|
||||
spooky_hash(), startswith(), strfilter(), 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+)')
|
||||
|
@ -2274,10 +2309,11 @@ Parameters
|
|||
str The string to test against the regular expression
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_replace(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_replace(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To capture the digits from the string '123':
|
||||
;SELECT regexp_match('(\d+)', '123')
|
||||
|
@ -2304,10 +2340,11 @@ Parameters
|
|||
backslash followed by the number of the group, starting with 1.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_match(), replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_match(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), 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')
|
||||
|
@ -2328,10 +2365,11 @@ Parameters
|
|||
replacement The string to replace any occurrences of the old string with.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replicate(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To replace the string 'x' with 'z' in 'abc':
|
||||
;SELECT replace('abc', 'x', 'z')
|
||||
|
@ -2349,10 +2387,11 @@ Parameters
|
|||
N The number of times to replicate the string.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), reverse(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), reverse(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To repeat the string 'abc' three times:
|
||||
;SELECT replicate('abc', 3)
|
||||
|
@ -2365,10 +2404,11 @@ Parameter
|
|||
str The string to reverse.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), rightstr(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), rightstr(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To reverse the string 'abc':
|
||||
;SELECT reverse('abc')
|
||||
|
@ -2383,10 +2423,11 @@ Parameters
|
|||
N The number of characters from the right side of the string to return.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rtrim(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rtrim(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To get the last character of the string 'abc':
|
||||
;SELECT rightstr('abc', 1)
|
||||
|
@ -2443,10 +2484,11 @@ Parameters
|
|||
chars The characters to trim. Defaults to spaces.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), spooky_hash(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), sparkline(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To trim the whitespace from the end of the string 'abc ':
|
||||
;SELECT rtrim('abc ')
|
||||
|
@ -2479,16 +2521,37 @@ Examples
|
|||
|
||||
|
||||
|
||||
Synopsis
|
||||
sparkline(value, [upper]) -- An aggregate function to convert numeric values
|
||||
to a sparkline bar chart
|
||||
Parameters
|
||||
value The numeric values to chart
|
||||
upper The upper bound of the numeric range. If not provided, the default
|
||||
is derived from all of the provided values
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To chart the values in a JSON array:
|
||||
;SELECT sparkline(value) FROM json_each('[0, 1, 2, 3, 4, 5, 6, 7, 8]')
|
||||
|
||||
|
||||
|
||||
Synopsis
|
||||
spooky_hash(str, ...) -- Compute the hash value for the given arguments.
|
||||
Parameter
|
||||
str The string to hash
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), startswith(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), startswith(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To produce a hash for the string 'Hello, World!':
|
||||
;SELECT spooky_hash('Hello, World!')
|
||||
|
@ -2557,10 +2620,11 @@ Parameters
|
|||
prefix The prefix to check in the string
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
strfilter(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), strfilter(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To test if the string 'foobar' starts with 'foo':
|
||||
;SELECT startswith('foobar', 'foo')
|
||||
|
@ -2579,10 +2643,11 @@ Parameters
|
|||
include The characters to include in the result
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), substr(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), substr(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Example
|
||||
#1 To get the 'b', 'c', and 'd' characters from the string 'abcabc':
|
||||
;SELECT strfilter('abcabc', 'bcd')
|
||||
|
@ -2627,10 +2692,11 @@ Parameters
|
|||
the characters before the start are returned.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), strfilter(), trim(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), trim(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To get the substring starting at the second character until the end of the string 'abc'
|
||||
:
|
||||
|
@ -2719,8 +2785,8 @@ Examples
|
|||
|
||||
|
||||
#2 To group log messages into five minute buckets and count them:
|
||||
;SELECT timeslice(log_time, '5m') AS slice, count(*) FROM lnav_example_log GROUP BY
|
||||
slice
|
||||
;SELECT timeslice(log_time_msecs, '5m') AS slice, count(*) FROM lnav_example_log GROUP
|
||||
BY slice
|
||||
|
||||
|
||||
|
||||
|
@ -2753,10 +2819,11 @@ Parameters
|
|||
chars The characters to trim. Defaults to spaces.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), strfilter(), substr(), unicode(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
unicode(), upper(), xpath()
|
||||
Examples
|
||||
#1 To trim whitespace from the start and end of the string ' abc ':
|
||||
;SELECT trim(' abc ')
|
||||
|
@ -2790,10 +2857,11 @@ Parameter
|
|||
X The string to examine.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), strfilter(), substr(), trim(), upper(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), upper(), xpath()
|
||||
Example
|
||||
#1 To get the unicode code point for the first character of 'abc':
|
||||
;SELECT unicode('abc')
|
||||
|
@ -2813,10 +2881,11 @@ Parameter
|
|||
str The string to convert.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), strfilter(), substr(), trim(), unicode(), xpath()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), xpath()
|
||||
Example
|
||||
#1 To uppercase the string 'aBc':
|
||||
;SELECT upper('aBc')
|
||||
|
@ -2836,10 +2905,11 @@ Results
|
|||
node_text The node's text value.
|
||||
See Also
|
||||
char(), charindex(), endswith(), extract(), group_concat(), group_spooky_hash(),
|
||||
instr(), leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
|
||||
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
|
||||
replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
|
||||
startswith(), strfilter(), substr(), trim(), unicode(), upper()
|
||||
humanize_file_size(), instr(), leftstr(), length(), lower(), ltrim(), padc(),
|
||||
padl(), padr(), printf(), proper(), regexp_capture(), regexp_match(),
|
||||
regexp_replace(), replace(), replicate(), reverse(), rightstr(), rtrim(),
|
||||
sparkline(), sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
|
||||
trim(), unicode(), 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>')
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
;SELECT 'World' as name
|
||||
:eval :echo Hello, ${name}!
|
||||
:echo Hello, ${name}!
|
||||
Goodbye, ${name}!
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
|
||||
:eval :echo nested here $0 $1 $2
|
||||
:echo nested here $0 $1 $2
|
||||
|
|
|
@ -41,16 +41,43 @@ int main(int argc, char *argv[])
|
|||
int lpc, retval = EXIT_SUCCESS;
|
||||
bookmark_vector<vis_line_t> bv, bv_cp;
|
||||
|
||||
bv.insert_once(vis_line_t(1));
|
||||
bv.insert_once(vis_line_t(1));
|
||||
bv.insert_once(vis_line_t(2));
|
||||
bv.insert_once(vis_line_t(2));
|
||||
assert(bv.size() == 1);
|
||||
|
||||
bv.insert_once(vis_line_t(4));
|
||||
bv.insert_once(vis_line_t(3));
|
||||
bv.insert_once(vis_line_t(2));
|
||||
assert(bv[0] == 1);
|
||||
assert(bv[1] == 2);
|
||||
assert(bv[2] == 3);
|
||||
|
||||
assert(bv[0] == 2);
|
||||
assert(bv[1] == 3);
|
||||
assert(bv[2] == 4);
|
||||
|
||||
{
|
||||
auto range = bv.equal_range(0_vl, 5_vl);
|
||||
|
||||
assert(range.first != range.second);
|
||||
assert(*range.first == 2_vl);
|
||||
++range.first;
|
||||
assert(range.first != range.second);
|
||||
assert(*range.first == 3_vl);
|
||||
++range.first;
|
||||
assert(range.first != range.second);
|
||||
assert(*range.first == 4_vl);
|
||||
++range.first;
|
||||
assert(range.first == range.second);
|
||||
}
|
||||
|
||||
{
|
||||
auto range = bv.equal_range(0_vl, 1_vl);
|
||||
|
||||
assert(range.first == range.second);
|
||||
}
|
||||
|
||||
{
|
||||
auto range = bv.equal_range(10_vl, 10_vl);
|
||||
|
||||
assert(range.first == range.second);
|
||||
}
|
||||
|
||||
bv.clear();
|
||||
assert(bv.next(vis_line_t(0)) == -1);
|
||||
assert(bv.prev(vis_line_t(0)) == -1);
|
||||
|
|
|
@ -60,12 +60,15 @@ EOF
|
|||
|
||||
run_test ${lnav_test} -n -d /tmp/lnav.err \
|
||||
-c ";SELECT 1 AS c1, 'Hello, World!' AS c2" \
|
||||
-c ":write-cols-to -" \
|
||||
-c ":write-table-to -" \
|
||||
"${test_dir}/logfile_access_log.*"
|
||||
|
||||
check_output "writing columns does not work?" <<EOF
|
||||
c1 c2
|
||||
1 Hello, World!
|
||||
┏━━┳━━━━━━━━━━━━━┓
|
||||
┃c1┃ c2 ┃
|
||||
┡━━╇━━━━━━━━━━━━━┩
|
||||
│ 1│Hello, World!│
|
||||
└━━┴━━━━━━━━━━━━━┘
|
||||
EOF
|
||||
|
||||
|
||||
|
@ -1103,7 +1106,7 @@ EOF
|
|||
export XYZ="World"
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
-c ':echo Hello, $XYZ!' \
|
||||
-c ':echo Hello, \$XYZ!' \
|
||||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_output "echo hello" <<EOF
|
||||
|
@ -1123,7 +1126,7 @@ EOF
|
|||
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
-c ':eval :echo Hello, $XYZ!' \
|
||||
-c ':echo Hello, $XYZ!' \
|
||||
${test_dir}/logfile_access_log.0
|
||||
|
||||
check_output "eval echo hello" <<EOF
|
||||
|
|
|
@ -46,7 +46,7 @@ check_output_ws "single" <<EOF
|
|||
'abc'
|
||||
sst ^
|
||||
sen ^
|
||||
eval -- abc
|
||||
eval -- 'abc'
|
||||
split:
|
||||
0 -- abc
|
||||
EOF
|
||||
|
@ -57,7 +57,7 @@ check_output_ws "double" <<EOF
|
|||
"def"
|
||||
dst ^
|
||||
den ^
|
||||
eval -- def
|
||||
eval -- "def"
|
||||
split:
|
||||
0 -- def
|
||||
EOF
|
||||
|
@ -68,7 +68,7 @@ check_output_ws "double with single" <<EOF
|
|||
"'"
|
||||
dst ^
|
||||
den ^
|
||||
eval -- '
|
||||
eval -- "'"
|
||||
split:
|
||||
0 -- '
|
||||
EOF
|
||||
|
@ -79,7 +79,7 @@ check_output_ws "single with double" <<EOF
|
|||
'"'
|
||||
sst ^
|
||||
sen ^
|
||||
eval -- "
|
||||
eval -- '"'
|
||||
split:
|
||||
0 -- "
|
||||
EOF
|
||||
|
@ -91,7 +91,7 @@ check_output_ws "double w/ref" <<EOF
|
|||
dst ^
|
||||
ref ^--^
|
||||
den ^
|
||||
eval -- abc xyz 123
|
||||
eval -- "abc xyz 123"
|
||||
split:
|
||||
0 -- abc xyz 123
|
||||
EOF
|
||||
|
@ -103,7 +103,7 @@ check_output_ws "double w/quoted-ref" <<EOF
|
|||
dst ^
|
||||
qrf ^----^
|
||||
den ^
|
||||
eval -- abc xyz 123
|
||||
eval -- "abc xyz 123"
|
||||
split:
|
||||
0 -- abc xyz 123
|
||||
EOF
|
||||
|
@ -114,7 +114,7 @@ check_output_ws "single w/ref" <<EOF
|
|||
'abc \$DEF 123'
|
||||
sst ^
|
||||
sen ^
|
||||
eval -- abc \$DEF 123
|
||||
eval -- 'abc \$DEF 123'
|
||||
split:
|
||||
0 -- abc \$DEF 123
|
||||
EOF
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
lnav_test="${top_builddir}/src/lnav-test"
|
||||
|
||||
run_test ${lnav_test} -n \
|
||||
-c ";SELECT replicate('foobar', 120)" \
|
||||
${test_dir}/logfile_empty.0
|
||||
|
||||
check_output "long lines are not truncated?" <<EOF
|
||||
replicate('foobar', 120)
|
||||
foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar⋯oobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar
|
||||
EOF
|
||||
|
||||
cp ${srcdir}/logfile_syslog.2 logfile_syslog_test.2
|
||||
touch -t 201511030923 logfile_syslog_test.2
|
||||
run_test ${lnav_test} -n \
|
||||
|
|
|
@ -1,5 +1,30 @@
|
|||
#! /bin/bash
|
||||
|
||||
run_test ./drive_sql "select humanize_file_size()"
|
||||
|
||||
check_error_output "" <<EOF
|
||||
error: sqlite3_exec failed -- wrong number of arguments to function humanize_file_size()
|
||||
EOF
|
||||
|
||||
run_test ./drive_sql "select humanize_file_size('abc')"
|
||||
|
||||
check_error_output "" <<EOF
|
||||
error: sqlite3_exec failed -- Expecting an integer for argument number 0
|
||||
EOF
|
||||
|
||||
run_test ./drive_sql "select humanize_file_size(1, 2)"
|
||||
|
||||
check_error_output "" <<EOF
|
||||
error: sqlite3_exec failed -- wrong number of arguments to function humanize_file_size()
|
||||
EOF
|
||||
|
||||
run_test ./drive_sql "select humanize_file_size(10 * 1000 * 1000)"
|
||||
|
||||
check_output "" <<EOF
|
||||
Row 0:
|
||||
Column humanize_file_size(10 * 1000 * 1000): 9.5MB
|
||||
EOF
|
||||
|
||||
run_test ./drive_sql "select startswith('.foo', '.')"
|
||||
|
||||
check_output "" <<EOF
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
:eval :echo toplevel here $1 $2
|
||||
:echo toplevel here $1 $2
|
||||
|
||||
|nested.lnav abc $3
|
||||
|
|
|
@ -188,71 +188,6 @@ K 68
|
|||
S 24 ┋ h ┋
|
||||
A ····└ normal
|
||||
K 6f
|
||||
S 24 ┋ ┋
|
||||
A ····└ carriage-return
|
||||
S 14 ┋ Command Help :: ┋
|
||||
A └ fg(#c0c0c0), bg(#000080), bold
|
||||
A ··············└ normal, fg(#c0c0c0), bg(#000080)
|
||||
A ···············└ fg(#000080), bg(#c0c0c0)
|
||||
A ················└ fg(#000000), bg(#c0c0c0)
|
||||
S 15 ┋Synopsis ┋
|
||||
A └ normal, underline
|
||||
A ········└ normal
|
||||
CSI Erase to Right
|
||||
S 16 ┋ :echo msg - Echo the given message ┋
|
||||
A ···└ bold │
|
||||
A ·······└ normal
|
||||
A ········└ underline
|
||||
A ···········└ normal
|
||||
CSI Erase to Right
|
||||
S 16 ┋ ┋
|
||||
A ····································└ carriage-return
|
||||
S 17 ┋Parameter ┋
|
||||
A └ underline
|
||||
A ·········└ normal
|
||||
CSI Erase to Right
|
||||
S 17 ┋ ┋
|
||||
A ·········└ carriage-return
|
||||
S 18 ┋ msg The message to display ┋
|
||||
A ··└ fg(#008080), bold
|
||||
A ·····└ normal
|
||||
CSI Erase to Right
|
||||
S 18 ┋ ┋
|
||||
A ······························└ carriage-return
|
||||
S 19 ┋See Also ┋
|
||||
A └ underline
|
||||
A ········└ normal
|
||||
CSI Erase to Right
|
||||
S 20 ┋ :alt-msg, :eval, :redirect-to, :write-cols-to, :write-csv-to, ┋
|
||||
A ··└ bold │ │ │ │ │ │ │ │ │
|
||||
A ··········└ normal │ │ │ │ │ │
|
||||
A ············└ bold │ │ │ │ │ │
|
||||
A ·················└ normal │ │ │ │ │
|
||||
A ···················└ bold │ │ │ │ │
|
||||
A ·······························└ normal │ │ │
|
||||
A ·································└ bold │ │ │
|
||||
A ···············································└ normal │
|
||||
A ·················································└ bold │
|
||||
A ······························································└ normal
|
||||
CSI Erase to Right
|
||||
S 20 ┋ ┋
|
||||
A ·······························································└ carriage-return
|
||||
S 21 ┋ :write-json-to, :write-jsonlines-to, :write-raw-to, :write-screen-to, ┋
|
||||
A ··└ bold │ │ │ │ │ │ │
|
||||
A ················└ normal │ │ │ │ │
|
||||
A ··················└ bold │ │ │ │ │
|
||||
A ·····································└ normal │ │ │
|
||||
A ·······································└ bold │ │ │
|
||||
A ····················································└ normal │
|
||||
A ······················································└ bold │
|
||||
A ······································································└ normal
|
||||
CSI Erase to Right
|
||||
S 21 ┋ ┋
|
||||
A ·······································································└ carriage-return
|
||||
S 22 ┋ :write-to ┋
|
||||
A ··└ bold │
|
||||
A ···········└ normal
|
||||
CSI Erase to Right
|
||||
S 24 ┋ o ┋
|
||||
A ·····└ normal
|
||||
K 20
|
||||
|
@ -275,33 +210,6 @@ A ········└ carriage-return
|
|||
CSI Erase Below
|
||||
S 24 ┋ ┋
|
||||
A └ normal
|
||||
S 14 ┋hoped that these features will allow the user to quickly and x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 15 ┋efficiently zero in on problems. x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 16 ┋ x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 17 ┋ x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 18 ┋OPENING PATHS/URLs x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 19 ┋================== x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 20 ┋ x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 21 ┋The main arguments to lnav are the files, directories, glob patterns, x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 22 ┋or URLs to be viewed. If no arguments are given, the default syslog x┋
|
||||
A └┛ alt
|
||||
A ················································································└ normal
|
||||
S 23 ┋ L0 0% ┋
|
||||
A ·└ fg(#000000), bg(#c0c0c0)
|
||||
S 23 ┋ ?:View Help ┋
|
||||
|
|
Loading…
Reference in New Issue