[sql] jget() is not returning values with the right sqlite type

This commit is contained in:
Timothy Stack 2021-09-09 22:22:52 -07:00
parent 7252e5fc0f
commit f6e245c04a
5 changed files with 70 additions and 8 deletions

1
NEWS
View File

@ -24,6 +24,7 @@ lnav v0.10.1:
* The tab for the "Files" panel will be highlighted in red if there
is an issue opening a file.
* Overwritten files should be reloaded again.
* The "jget()" SQL function now returns numbers with the correct type.
lnav v0.10.0:
Features:

View File

@ -1,6 +1,6 @@
# aminclude_static.am generated automatically by Autoconf
# from AX_AM_MACROS_STATIC on Wed Sep 8 14:08:11 PDT 2021
# from AX_AM_MACROS_STATIC on Thu Sep 9 16:09:09 PDT 2021
# Code coverage

View File

@ -681,16 +681,15 @@ bool handle_paging_key(int ch)
case 'I':
{
auto &hs = lnav_data.ld_hist_source2;
auto &hist_tc = lnav_data.ld_views[LNV_HISTOGRAM];
if (toggle_view(&hist_tc)) {
auto *src_view = dynamic_cast<text_time_translator *>(tc->get_sub_source());
if (src_view != nullptr) {
src_view->time_for_row(tc->get_top()) | [&hs, &hist_tc](auto log_top) {
hs.row_for_time(log_top) | [&hist_tc](auto row) {
hist_tc.set_top(row);
src_view->time_for_row(tc->get_top()) | [](auto log_top) {
lnav_data.ld_hist_source2.row_for_time(log_top) | [](auto row) {
lnav_data.ld_views[LNV_HISTOGRAM].set_top(row);
};
};
}
@ -700,6 +699,7 @@ bool handle_paging_key(int ch)
auto *dst_view = dynamic_cast<text_time_translator *>(top_tc->get_sub_source());
if (dst_view != nullptr) {
auto& hs = lnav_data.ld_hist_source2;
auto hist_top_time_opt = hs.time_for_row(hist_tc.get_top());
auto curr_top_time_opt = dst_view->time_for_row(top_tc->get_top());
if (hist_top_time_opt && curr_top_time_opt &&

View File

@ -43,6 +43,7 @@
#include "vtab_module.hh"
#include "vtab_module_json.hh"
#include "lnav_util.hh"
#include "yajl/api/yajl_gen.h"
#include "sqlite-extension-func.hh"
@ -53,11 +54,12 @@ using namespace mapbox;
class sql_json_op : public json_op {
public:
sql_json_op(json_ptr &ptr) : json_op(ptr), sjo_type(-1), sjo_int(0) { };
sql_json_op(json_ptr &ptr) : json_op(ptr) { };
int sjo_type;
int sjo_type{-1};
string sjo_str;
int sjo_int;
int64_t sjo_int{0};
double sjo_float{0.0};
};
static void null_or_default(sqlite3_context *context, int argc, sqlite3_value **argv)
@ -172,6 +174,28 @@ static int gen_handle_string(void *ctx, const unsigned char * stringVal, size_t
return sjo->jo_ptr_error_code == yajl_gen_status_ok;
}
static int gen_handle_number(void *ctx, const char *numval, size_t numlen)
{
sql_json_op *sjo = (sql_json_op *)ctx;
yajl_gen gen = (yajl_gen)sjo->jo_ptr_data;
if (sjo->jo_ptr.jp_state == json_ptr::MS_DONE) {
if (strtonum(sjo->sjo_int, numval, numlen) == numlen) {
sjo->sjo_type = SQLITE_INTEGER;
} else {
auto numstr = std::string(numval, numlen);
sjo->sjo_float = std::stod(numstr);
sjo->sjo_type = SQLITE_FLOAT;
}
}
else {
sjo->jo_ptr_error_code = yajl_gen_number(gen, numval, numlen);
}
return sjo->jo_ptr_error_code == yajl_gen_status_ok;
}
static void sql_jget(sqlite3_context *context,
int argc, sqlite3_value **argv)
{
@ -205,6 +229,7 @@ static void sql_jget(sqlite3_context *context,
jo.jo_ptr_callbacks.yajl_null = gen_handle_null;
jo.jo_ptr_callbacks.yajl_boolean = gen_handle_boolean;
jo.jo_ptr_callbacks.yajl_string = gen_handle_string;
jo.jo_ptr_callbacks.yajl_number = gen_handle_number;
jo.jo_ptr_data = gen.get_handle();
handle.reset(yajl_alloc(&json_op::ptr_callbacks, nullptr, &jo));
@ -258,6 +283,9 @@ static void sql_jget(sqlite3_context *context,
case SQLITE_INTEGER:
sqlite3_result_int(context, jo.sjo_int);
return;
case SQLITE_FLOAT:
sqlite3_result_double(context, jo.sjo_float);
return;
}
string_fragment result = gen.to_string_fragment();
@ -268,6 +296,9 @@ static void sql_jget(sqlite3_context *context,
}
sqlite3_result_text(context, result.data(), result.length(), SQLITE_TRANSIENT);
#ifdef HAVE_SQLITE3_VALUE_SUBTYPE
sqlite3_result_subtype(context, JSON_SUBTYPE);
#endif
}
struct concat_context {

View File

@ -104,6 +104,16 @@ Row 0:
Column jget('[null, true, 20, 30, 40]', '/3'): 30
EOF
run_test ./drive_sql "select typeof(jget('[null, true, 20, 30, 40]', '/3'))"
check_error_output "" <<EOF
EOF
check_output "jget null does not work" <<EOF
Row 0:
Column typeof(jget('[null, true, 20, 30, 40]', '/3')): integer
EOF
run_test ./drive_sql "select jget('[null, true, 20, 30, 40, {\"msg\": \"Hello\"}]', '/5')"
check_error_output "" <<EOF
@ -124,6 +134,16 @@ Row 0:
Column jget('[null, true, 20, 30, 40, {"msg": "Hello"}]', '/5/msg'): Hello
EOF
run_test ./drive_sql "select jget('[null, true, 20, 30, 40, {\"msg\": \"Hello\"}]', '')"
check_error_output "" <<EOF
EOF
check_output "jget null does not work" <<EOF
Row 0:
Column jget('[null, true, 20, 30, 40, {"msg": "Hello"}]', ''): [null,true,20,30,40,{"msg":"Hello"}]
EOF
run_test ./drive_sql "select jget('[null, true, 20, 30, 40]', '/abc')"
check_error_output "" <<EOF
@ -174,6 +194,16 @@ Row 0:
Column jget('[null, true, 20, 30, 4.0]', '/4'): 4.0
EOF
run_test ./drive_sql "select typeof(jget('[null, true, 20, 30, 4.0]', '/4'))"
check_error_output "" <<EOF
EOF
check_output "jget for array does not work" <<EOF
Row 0:
Column typeof(jget('[null, true, 20, 30, 4.0]', '/4')): real
EOF
run_test ./drive_sql "select jget('[null, true, 20, 30, 40', '/0/foo')"
check_error_output "" <<EOF