Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Sqlite support for sub-queries and CTE's #1816

Merged
merged 21 commits into from Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4584534
reproduce incorrect nullability for materialized views
tyrelr Apr 18, 2022
8fdcf47
split ephemeral/index-only table handling from real table handling
tyrelr Apr 17, 2022
3204363
add test for literal null, expect nullability to be identified from t…
tyrelr Apr 17, 2022
5bc371a
gather interpreter state into a struct, no change in behaviour
tyrelr Apr 17, 2022
4acddcc
prevent infinite loops that could arise once branching is supported
tyrelr Apr 17, 2022
4e83284
track nullability alongside the datatype instead of in a separate lookup
tyrelr Apr 18, 2022
e5a5e36
implement basic comprehension of branching opcodes
tyrelr Apr 17, 2022
67aadbd
fix datatype calculation of aggregates which are never 'stepped' through
tyrelr Apr 17, 2022
f0fdd3e
implement coroutine and return operations, including tracking of 'act…
tyrelr Apr 17, 2022
5dbf994
strip unnecessary history field out
tyrelr Apr 18, 2022
3ed1e15
Modify variable test to expect bind-variable outputs to be nullable, …
tyrelr Apr 18, 2022
94707af
add partially commented-out union tests, simplify code to satisfy sim…
tyrelr Apr 18, 2022
76818ae
fix unit test incorrectly expecting primary keys to be implicitly not…
tyrelr Apr 19, 2022
d7ad52e
add failing test for recursive tables
tyrelr May 15, 2022
5360798
add logging of query explain plan
tyrelr May 15, 2022
dce9c06
track explain plan execution history
tyrelr May 23, 2022
c2aa41d
broken RowData implementation (doesn't alias)
tyrelr May 23, 2022
dd14670
Implement OpenPseudo tables as an alias of a register value
tyrelr May 23, 2022
4f5fe36
fix comment
tyrelr May 28, 2022
22a54be
clean up logging code warnings
tyrelr May 29, 2022
8e817a3
use cfg to omit QueryPlanLogger unless sqlite feature is used
tyrelr Jun 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 80 additions & 0 deletions sqlx-core/src/logger.rs
@@ -1,4 +1,7 @@
use crate::connection::LogSettings;
use std::collections::HashSet;
use std::fmt::Debug;
use std::hash::Hash;
use std::time::Instant;

pub(crate) struct QueryLogger<'q> {
Expand Down Expand Up @@ -78,6 +81,83 @@ impl<'q> Drop for QueryLogger<'q> {
}
}

pub(crate) struct QueryPlanLogger<'q, O: Debug + Hash + Eq, R: Debug + Hash + Eq, P: Debug> {
sql: &'q str,
unknown_operations: HashSet<O>,
results: HashSet<R>,
program: Vec<P>,
settings: LogSettings,
}

impl<'q, O: Debug + Hash + Eq, R: Debug + Hash + Eq, P: Debug> QueryPlanLogger<'q, O, R, P> {
pub(crate) fn new(sql: &'q str, settings: LogSettings) -> Self {
tyrelr marked this conversation as resolved.
Show resolved Hide resolved
Self {
sql,
unknown_operations: HashSet::new(),
results: HashSet::new(),
program: Vec::new(),
settings,
}
}

pub(crate) fn add_result(&mut self, result: R) {
self.results.insert(result);
}

pub(crate) fn add_program(&mut self, program: Vec<P>) {
self.program = program;
}

pub(crate) fn add_unknown_operation(&mut self, operation: O) {
self.unknown_operations.insert(operation);
}

pub(crate) fn finish(&self) {
let lvl = self.settings.statements_level;

if let Some(lvl) = lvl
.to_level()
.filter(|lvl| log::log_enabled!(target: "sqlx::explain", *lvl))
{
let mut summary = parse_query_summary(&self.sql);

let sql = if summary != self.sql {
summary.push_str(" …");
format!(
"\n\n{}\n",
sqlformat::format(
&self.sql,
&sqlformat::QueryParams::None,
sqlformat::FormatOptions::default()
)
)
} else {
String::new()
};

log::logger().log(
&log::Record::builder()
.args(format_args!(
"{}; program:{:?}, unknown_operations:{:?}, results: {:?}{}",
summary, self.program, self.unknown_operations, self.results, sql
))
.level(lvl)
.module_path_static(Some("sqlx::explain"))
.target("sqlx::explain")
.build(),
);
}
}
}

impl<'q, O: Debug + Hash + Eq, R: Debug + Hash + Eq, P: Debug> Drop
for QueryPlanLogger<'q, O, R, P>
{
fn drop(&mut self) {
self.finish();
}
}

fn parse_query_summary(sql: &str) -> String {
// For now, just take the first 4 words
sql.split_whitespace()
Expand Down