[rewriter] capture rewriter command output

Also, SQL statements should populate variables.

Related to #1218
This commit is contained in:
Tim Stack 2024-01-02 21:41:32 -08:00
parent 9f800bcd4e
commit 57467edea7
4 changed files with 72 additions and 9 deletions

View File

@ -1269,14 +1269,14 @@ json_write_row(yajl_gen handle,
default:
obj_map.gen(anonymize
? ta.next(string_fragment::from_c_str(
dls.dls_rows[row][col]))
dls.dls_rows[row][col]))
: dls.dls_rows[row][col]);
break;
}
break;
default:
obj_map.gen(anonymize ? ta.next(string_fragment::from_c_str(
dls.dls_rows[row][col]))
dls.dls_rows[row][col]))
: dls.dls_rows[row][col]);
break;
}

View File

@ -1761,11 +1761,35 @@ external_log_format::rewrite(exec_context& ec,
vd_iter->second->vd_rewrite_src_name, 1, vd.vd_rewriter);
std::string field_value;
auto exec_res = execute_any(ec, vd.vd_rewriter);
if (exec_res.isOk()) {
field_value = exec_res.unwrap();
} else {
field_value = exec_res.unwrapErr().to_attr_line().get_string();
auto_mem<FILE> tmpout(fclose);
tmpout = std::tmpfile();
if (!tmpout) {
log_error("unable to create temporary file");
return;
}
fcntl(fileno(tmpout), F_SETFD, FD_CLOEXEC);
auto fd_copy = auto_fd::dup_of(fileno(tmpout));
fd_copy.close_on_exec();
auto ec_out = std::make_pair(tmpout.release(), fclose);
{
exec_context::output_guard og(ec, "tmp", ec_out);
auto exec_res = execute_any(ec, vd.vd_rewriter);
if (exec_res.isOk()) {
field_value = exec_res.unwrap();
} else {
field_value = exec_res.unwrapErr().to_attr_line().get_string();
}
}
struct stat st;
fstat(fd_copy.get(), &st);
if (st.st_size > 0) {
auto buf = auto_buffer::alloc(st.st_size);
buf.resize(st.st_size);
pread(fd_copy.get(), buf.in(), st.st_size, 0);
field_value = buf.to_string();
}
value_out.erase(iter->lv_origin.lr_start, iter->lv_origin.length());

View File

@ -63,7 +63,7 @@ pretty_sql_callback(exec_context& ec, sqlite3_stmt* stmt)
return 0;
}
int ncols = sqlite3_column_count(stmt);
const auto ncols = sqlite3_column_count(stmt);
for (int lpc = 0; lpc < ncols; lpc++) {
if (!ec.ec_accumulator->empty()) {
@ -78,6 +78,44 @@ pretty_sql_callback(exec_context& ec, sqlite3_stmt* stmt)
ec.ec_accumulator->append(res);
}
for (int lpc = 0; lpc < ncols; lpc++) {
const auto* colname = sqlite3_column_name(stmt, lpc);
auto* raw_value = sqlite3_column_value(stmt, lpc);
auto value_type = sqlite3_value_type(raw_value);
scoped_value_t value;
switch (value_type) {
case SQLITE_INTEGER:
value = (int64_t) sqlite3_value_int64(raw_value);
break;
case SQLITE_FLOAT:
value = sqlite3_value_double(raw_value);
break;
case SQLITE_NULL:
value = null_value_t{};
break;
default:
value = string_fragment::from_bytes(
sqlite3_value_text(raw_value),
sqlite3_value_bytes(raw_value));
break;
}
if (!ec.ec_local_vars.empty() && !ec.ec_dry_run) {
if (sql_ident_needs_quote(colname)) {
continue;
}
auto& vars = ec.ec_local_vars.top();
if (vars.find(colname) != vars.end()) {
continue;
}
if (value.is<string_fragment>()) {
value = value.get<string_fragment>().to_string();
}
vars[colname] = value;
}
}
return 0;
}

View File

@ -1,2 +1,3 @@
;SELECT 'mailto:' || :user
;SELECT 'mailto:' || :user AS mt
:echo $mt