Skip to content

Commit

Permalink
v1.0.191
Browse files Browse the repository at this point in the history
  • Loading branch information
yy0931 committed Sep 1, 2024
1 parent 7939173 commit dbbcf5d
Show file tree
Hide file tree
Showing 11 changed files with 410 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sqlite3-editor"
version = "1.0.190"
version = "1.0.191"
edition = "2021"

[features]
Expand Down
20 changes: 18 additions & 2 deletions src/code_lens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use sqlparser::keywords::Keyword;
use sqlparser::tokenizer::{Token, Word};

use crate::keywords::START_OF_STATEMENT_KEYWORDS_UNSUPPORTED_BY_SQLPARSER;
use crate::list_placeholders::{list_placeholders, Placeholder};
use crate::parse_cte::parse_cte;
use crate::split_statements::{get_text_range, split_sqlite_statements};
use crate::sqlite3::escape_sql_identifier;
Expand All @@ -24,6 +25,8 @@ pub struct CodeLens {
pub start: ZeroIndexedLocation,
pub end: ZeroIndexedLocation,
pub stmt_executed: String,
pub cte_identifier: Option<String>,
pub placeholders: Vec<Placeholder>,
}

/// Returns a list of code lenses for the given SQL input.
Expand All @@ -43,22 +46,33 @@ pub fn code_lens(sql: &str) -> Vec<CodeLens> {
if let Some(cte) = cte {
for entry in cte.entries {
let with_clause = get_text_range(&lines, &stmt.real_start, &cte.body_start);
let cte_ident = escape_sql_identifier(&get_text_range(&lines, &entry.ident_start, &entry.ident_end));
let select_stmt = format!(
"{}SELECT * FROM {}",
if with_clause.ends_with(' ') { "" } else { " " },
escape_sql_identifier(&get_text_range(&lines, &entry.ident_start, &entry.ident_end))
cte_ident.clone()
);
let stmt_executed = with_clause + &select_stmt;
let Ok((cte_stmt, _)) = split_sqlite_statements(&stmt_executed) else {
continue;
};
let Some(cte_stmt) = cte_stmt.first() else {
continue;
};
code_lens.push(CodeLens {
kind: CodeLensKind::Select,
stmt_executed: with_clause + &select_stmt,
placeholders: list_placeholders(cte_stmt),
stmt_executed,
start: entry.ident_start,
end: entry.ident_end,
cte_identifier: Some(cte_ident),
})
}
cte_end = cte.body_start;
}

let mut kind: Option<CodeLensKind> = None;
let placeholders = list_placeholders(&stmt);
for token in stmt.real_tokens {
if token.start < cte_end {
continue;
Expand Down Expand Up @@ -120,6 +134,8 @@ pub fn code_lens(sql: &str) -> Vec<CodeLens> {
start: stmt.real_start,
end: stmt.real_end,
stmt_executed: stmt.real_text,
cte_identifier: None,
placeholders,
})
}
}
Expand Down
85 changes: 85 additions & 0 deletions src/code_lens_test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
code_lens::{code_lens, CodeLens, CodeLensKind},
list_placeholders::{Placeholder, PlaceholderRange},
tokenize::ZeroIndexedLocation,
};

Expand All @@ -13,18 +14,24 @@ fn test_select() {
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 9),
stmt_executed: "SELECT 1;".to_owned(),
cte_identifier: None,
placeholders: vec![],
},
CodeLens {
kind: CodeLensKind::Select,
start: ZeroIndexedLocation::new(0, 10),
end: ZeroIndexedLocation::new(0, 19),
stmt_executed: "SELECT 2;".to_owned(),
cte_identifier: None,
placeholders: vec![],
},
CodeLens {
kind: CodeLensKind::Select,
start: ZeroIndexedLocation::new(0, 20),
end: ZeroIndexedLocation::new(0, 30),
stmt_executed: "VALUES(3);".to_owned(),
cte_identifier: None,
placeholders: vec![],
},
]
);
Expand All @@ -40,12 +47,16 @@ fn test_with_clause() {
start: ZeroIndexedLocation::new(0, 5),
end: ZeroIndexedLocation::new(0, 6),
stmt_executed: "WITH a AS (SELECT 1) SELECT * FROM `a`".to_owned(),
cte_identifier: Some("`a`".to_owned()),
placeholders: vec![],
},
CodeLens {
kind: CodeLensKind::Select,
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 30),
stmt_executed: "WITH a AS (SELECT 1) SELECT 2;".to_owned(),
cte_identifier: None,
placeholders: vec![],
},
]
);
Expand All @@ -66,12 +77,16 @@ fn test_other() {
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 13),
stmt_executed: "DROP TABLE t;".to_owned(),
cte_identifier: None,
placeholders: vec![],
},
CodeLens {
kind: CodeLensKind::Other,
start: ZeroIndexedLocation::new(0, 14),
end: ZeroIndexedLocation::new(0, 31),
stmt_executed: "ATTACH 'db' as db".to_owned(),
cte_identifier: None,
placeholders: vec![],
}
]
);
Expand All @@ -86,6 +101,8 @@ fn test_begin_end() {
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 31),
stmt_executed: "BEGIN; SELECT 1; SELECT 2; END;".to_owned(),
cte_identifier: None,
placeholders: vec![],
}]
);
}
Expand All @@ -99,6 +116,8 @@ fn test_pragma() {
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 22),
stmt_executed: "PRAGMA analysis_limit;".to_owned(),
cte_identifier: None,
placeholders: vec![],
}]
);
}
Expand All @@ -112,6 +131,8 @@ fn test_vacuum() {
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 7),
stmt_executed: "VACUUM;".to_owned(),
cte_identifier: None,
placeholders: vec![],
}]
);
}
Expand All @@ -126,13 +147,77 @@ fn test_with_update() {
start: ZeroIndexedLocation::new(0, 5),
end: ZeroIndexedLocation::new(0, 6),
stmt_executed: "WITH x AS (SELECT 1) SELECT * FROM `x`".to_owned(),
cte_identifier: Some("`x`".to_owned()),
placeholders: vec![],
},
CodeLens {
kind: CodeLensKind::Other,
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 40),
stmt_executed: "WITH x AS (SELECT 1) UPDATE t SET a = 1;".to_owned(),
cte_identifier: None,
placeholders: vec![],
}
]
);
}

#[test]
fn test_placeholders() {
assert_eq!(
code_lens("SELECT ?, :a;"),
[CodeLens {
kind: CodeLensKind::Select,
start: ZeroIndexedLocation::new(0, 0),
end: ZeroIndexedLocation::new(0, 13),
stmt_executed: "SELECT ?, :a;".to_owned(),
cte_identifier: None,
placeholders: vec![
Placeholder {
name: None,
ranges_relative_to_stmt: vec![PlaceholderRange {
start: ZeroIndexedLocation::new(0, 7),
end: ZeroIndexedLocation::new(0, 8),
}],
},
Placeholder {
name: Some(":a".to_owned()),
ranges_relative_to_stmt: vec![PlaceholderRange {
start: ZeroIndexedLocation::new(0, 10),
end: ZeroIndexedLocation::new(0, 12),
}]
}
],
},]
);
}

#[test]
fn test_placeholders_with_prefix() {
assert_eq!(
code_lens("-- comment\n SELECT ?, :a;"),
[CodeLens {
kind: CodeLensKind::Select,
start: ZeroIndexedLocation::new(1, 1),
end: ZeroIndexedLocation::new(1, 14),
stmt_executed: "SELECT ?, :a;".to_owned(),
cte_identifier: None,
placeholders: vec![
Placeholder {
name: None,
ranges_relative_to_stmt: vec![PlaceholderRange {
start: ZeroIndexedLocation::new(0, 7),
end: ZeroIndexedLocation::new(0, 8),
}],
},
Placeholder {
name: Some(":a".to_owned()),
ranges_relative_to_stmt: vec![PlaceholderRange {
start: ZeroIndexedLocation::new(0, 10),
end: ZeroIndexedLocation::new(0, 12),
}]
}
],
},]
);
}
22 changes: 22 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ pub enum Error {
query: String,
params: Vec<Literal>,
},
InvalidNumberOfParameters {
query: String,
placeholders: Vec<Option<String>>,
params: Vec<Literal>,
},
Other {
message: String,
query: Option<String>,
Expand Down Expand Up @@ -166,6 +171,23 @@ impl std::fmt::Display for Error {
)
}
}
Self::InvalidNumberOfParameters {
query,
placeholders,
params,
} => {
write!(
f,
"Invalid number of parameters.\n{}\nParameters: {}\nPlaceholders: [{}]",
Self::format_query(query),
Self::format_params(params),
placeholders
.iter()
.map(|v| v.clone().unwrap_or("?".to_owned()))
.collect::<Vec<_>>()
.join(", ")
)
}
Self::Other { message, query, params } => {
write!(
f,
Expand Down
Loading

0 comments on commit dbbcf5d

Please sign in to comment.