diff --git a/.gitmodules b/.gitmodules index 2bd5d3f4c..b344f3c0b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "libpg_query"] path = libpg_query url = https://github.com/pganalyze/libpg_query.git +[submodule "crates/tree_sitter_sql/tree-sitter-sql"] + path = crates/tree_sitter_sql/tree-sitter-sql + url = https://github.com/DerekStride/tree-sitter-sql + branch = gh-pages diff --git a/Cargo.lock b/Cargo.lock index bfe3534e7..60439ca7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2586,6 +2586,24 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tree-sitter" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e747b1f9b7b931ed39a548c1fae149101497de3c1fc8d9e18c62c1a66c683d3d" +dependencies = [ + "cc", + "regex", +] + +[[package]] +name = "tree_sitter_sql" +version = "0.0.0" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "triomphe" version = "0.1.11" diff --git a/Cargo.toml b/Cargo.toml index eb2c414d8..6e6fb923a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ resolver = "2" rust-version = "1.71" [workspace.dependencies] +tree_sitter_sql = { path = "./crates/tree_sitter_sql", version = "0.0.0" } schema_cache = { path = "./crates/schema_cache", version = "0.0.0" } parser = { path = "./crates/parser", version = "0.0.0" } codegen = { path = "./crates/codegen", version = "0.0.0" } diff --git a/crates/schema_cache/src/lib.rs b/crates/schema_cache/src/lib.rs index 985f0eeca..bcf13ed1a 100644 --- a/crates/schema_cache/src/lib.rs +++ b/crates/schema_cache/src/lib.rs @@ -7,9 +7,10 @@ mod schema_cache; mod schemas; mod tables; -use schema_cache::SchemaCache; use sqlx::postgres::PgPool; +pub use schema_cache::SchemaCache; + #[derive(Debug, Clone)] struct SchemaCacheManager { pub cache: SchemaCache, diff --git a/crates/tree_sitter_sql/Cargo.toml b/crates/tree_sitter_sql/Cargo.toml new file mode 100644 index 000000000..a8ca0181d --- /dev/null +++ b/crates/tree_sitter_sql/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "tree_sitter_sql" +version = "0.0.0" +edition = "2021" + +build = "build.rs" + +[build-dependencies] +cc="*" + +[dependencies] +tree-sitter = "0.20.10" + +[lib] +doctest = false diff --git a/crates/tree_sitter_sql/build.rs b/crates/tree_sitter_sql/build.rs new file mode 100644 index 000000000..81fe8d939 --- /dev/null +++ b/crates/tree_sitter_sql/build.rs @@ -0,0 +1,16 @@ +fn main() { + let src_dir = std::path::Path::new("./tree-sitter-sql/src"); + let mut config = cc::Build::new(); + config.include(&src_dir); + config + .flag_if_supported("-Wno-unused-parameter") + .flag_if_supported("-Wno-unused-but-set-variable") + .flag_if_supported("-Wno-trigraphs"); + let parser_path = src_dir.join("parser.c"); + let scanner_path = src_dir.join("scanner.c"); + println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); + println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); + config.file(&parser_path); + config.file(&scanner_path); + config.compile("parser-scanner"); +} diff --git a/crates/tree_sitter_sql/src/lib.rs b/crates/tree_sitter_sql/src/lib.rs new file mode 100644 index 000000000..1575afc08 --- /dev/null +++ b/crates/tree_sitter_sql/src/lib.rs @@ -0,0 +1,47 @@ +use tree_sitter::Language; + +extern "C" { + fn tree_sitter_sql() -> Language; +} + +pub fn language() -> Language { + unsafe { tree_sitter_sql() } +} + +#[cfg(test)] +mod tests { + use tree_sitter::{Query, QueryCursor}; + + #[test] + fn test_can_load_grammar() { + let mut parser = tree_sitter::Parser::new(); + parser + .set_language(super::language()) + .expect("Error loading sql language"); + let source_code = "SELECT 1 FROM public.table where id = 4"; + + let query = Query::new( + parser.language().unwrap(), + "( + relation ( + ( + object_reference + schema: (identifier) + name: (identifier) + ) @reference + ) +) +", + ) + .unwrap(); + + let tree = parser.parse(source_code, None).unwrap(); + + let mut cursor = QueryCursor::new(); + + let mut captures = cursor.captures(&query, tree.root_node(), source_code.as_bytes()); + let (match_, idx) = captures.next().unwrap(); + let capture = match_.captures[idx]; + assert_eq!(capture.node.kind(), "object_reference"); + } +} diff --git a/crates/tree_sitter_sql/tree-sitter-sql b/crates/tree_sitter_sql/tree-sitter-sql new file mode 160000 index 000000000..da2d1eff4 --- /dev/null +++ b/crates/tree_sitter_sql/tree-sitter-sql @@ -0,0 +1 @@ +Subproject commit da2d1eff425b146d3c8cab7be8dfa98b11d896dc diff --git a/libpg_query b/libpg_query index 9b21e3295..db39825bc 160000 --- a/libpg_query +++ b/libpg_query @@ -1 +1 @@ -Subproject commit 9b21e3295402a0d0ee9a50c468d426c2dbb73ee6 +Subproject commit db39825bc7c1ddd45962ec6a626d740b7f8f027a