Skip to content

Commit 175e1f1

Browse files
authored
impr (hql+core+cli+mcp): cleaning up cli, adding mcp aggregation methods, v from id/type (#438)
## Description <!-- Provide a brief description of the changes in this PR --> ## Related Issues <!-- Link to any related issues using #issue_number --> Closes #433 #436 #435 ## Checklist when merging to main <!-- Mark items with "x" when completed --> - [ ] No compiler warnings (if applicable) - [ ] Code is formatted with `rustfmt` - [ ] No useless or dead code (if applicable) - [ ] Code is easy to understand - [ ] Doc comments are used for all functions, enums, structs, and fields (where appropriate) - [ ] All tests pass - [ ] Performance has not regressed (assuming change was not to fix a bug) - [ ] Version number has been updated in `helix-cli/Cargo.toml` and `helixdb/Cargo.toml` ## Additional Notes <!-- Add any additional information that would be helpful for reviewers -->
2 parents ac639f4 + afec30e commit 175e1f1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1417
-171
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ other_data/
2424
!examples/rag_demo/**
2525
test-store/
2626
helixdb-cfg/
27-
27+
/test/

Cargo.lock

Lines changed: 27 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

helix-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "helix-cli"
3-
version = "1.0.136"
3+
version = "1.0.137"
44
edition = "2024"
55

66
[dependencies]

helix-cli/src/utils.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,15 @@ pub const DEFAULT_SCHEMA: &str = r#"// Start building your schema here.
6565
//
6666
// N::User {
6767
// Name: String,
68-
// Label: String,
69-
// Age: Integer,
68+
// Age: I32,
7069
// IsAdmin: Boolean,
7170
// }
7271
//
7372
// E::Knows {
7473
// From: User,
7574
// To: User,
7675
// Properties: {
77-
// Since: Integer,
76+
// Since: Date DEFAULT NOW,
7877
// }
7978
// }
8079
//
@@ -93,7 +92,7 @@ pub const DEFAULT_QUERIES: &str = r#"// Start writing your queries here.
9392
// RETURN {variable}
9493
//
9594
// Example:
96-
// QUERY GetUserFriends(user_id: String) =>
95+
// QUERY GetUserFriends(user_id: ID) =>
9796
// friends <- N<User>(user_id)::Out<Knows>
9897
// RETURN friends
9998
//
@@ -488,27 +487,34 @@ fn parse_content(content: &Content) -> Result<Source, String> {
488487

489488
/// Runs the static analyzer on the parsed source to catch errors and generate diagnostics if any.
490489
/// Otherwise returns the generated source object which is an IR used to transpile the queries to rust.
491-
fn analyze_source(source: Source) -> Result<GeneratedSource, String> {
492-
if source.schema.is_empty() {
490+
fn analyze_source(content: &Content) -> Result<GeneratedSource, String> {
491+
if content.source.schema.is_empty() {
493492
return Err("No schema definitions provided".to_string());
494493
}
495494

496-
let (diagnostics, source) = analyze(&source);
495+
let (diagnostics, analyzed_source) = analyze(&content.source);
497496
if !diagnostics.is_empty() {
498497
for diag in diagnostics {
499498
let filepath = diag.filepath.clone().unwrap_or("queries.hx".to_string());
500-
println!("{}", diag.render(&source.src, &filepath));
499+
500+
// Find the correct file content for this diagnostic
501+
let file_content = content.files.iter()
502+
.find(|f| f.name == filepath)
503+
.map(|f| &f.content)
504+
.unwrap_or(&analyzed_source.src);
505+
506+
println!("{}", diag.render(file_content, &filepath));
501507
}
502508
return Err("compilation failed!".to_string());
503509
}
504510

505-
Ok(source)
511+
Ok(analyzed_source)
506512
}
507513

508514
pub fn generate(files: &[DirEntry], path: &str) -> Result<(Content, GeneratedSource), String> {
509515
let mut content = generate_content(files)?;
510516
content.source = parse_content(&content)?;
511-
let mut analyzed_source = analyze_source(content.source.clone())?;
517+
let mut analyzed_source = analyze_source(&content)?;
512518
analyzed_source.config = read_config(path)?;
513519
Ok((content, analyzed_source))
514520
}

helix-container/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use helix_db::helix_gateway::{
1010
router::router::{HandlerFn, HandlerSubmission},
1111
};
1212
use std::{collections::HashMap, sync::Arc};
13-
use tracing::{Level, info};
13+
use tracing::{info, Level};
1414
use tracing_subscriber::util::SubscriberInitExt;
1515

1616
mod queries;

helix-db/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "helix-db"
3-
version = "1.0.136"
3+
version = "1.0.137"
44
edition = "2024"
55
description = "HelixDB is a powerful, open-source, graph-vector database built in Rust for intelligent data storage for RAG and AI."
66
license = "AGPL-3.0"
@@ -27,6 +27,8 @@ flume = { version = "0.11.1", default-features = false, features = ["async", "se
2727
itertools = "0.14.0"
2828
tempfile = "3.20.0"
2929
paste = "1.0.15"
30+
rayon = "1.11.0"
31+
mimalloc = "0.1.48"
3032

3133
# compiler dependencies
3234
pest = { version = "2.7", optional = true }

helix-db/src/grammar.pest

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ get_stmt = { identifier ~ "<-" ~ evaluates_to_anything }
6262
traversal = { (start_node | start_edge | search_vector | start_vector) ~ step* ~ last_step? }
6363
id_traversal = { identifier ~ ((step+ ~ last_step?) | last_step) }
6464
anonymous_traversal = { "_" ~ ((step+ ~ last_step?) | last_step)? }
65-
step = { "::" ~ (graph_step | order_by | where_step | closure_step | object_step | exclude_field | count | ID | range_step | AddE) }
65+
step = { "::" ~ (graph_step | order_by| aggregate | group_by | where_step | closure_step | object_step | exclude_field | count | ID | range_step | AddE) }
6666
last_step = { "::" ~ (bool_operations | update | first) }
6767
// change this for loop to be able to take traversals etc in the future.
6868
for_loop = { "FOR" ~ for_argument ~ "IN" ~ identifier ~ "{" ~ query_body ~ "}" }
@@ -92,6 +92,7 @@ evaluates_to_anything = {
9292
| search_vector
9393
| bm25_search
9494
| string_literal
95+
| array_literal
9596
| float
9697
| integer
9798
| boolean
@@ -195,6 +196,9 @@ update_field = { identifier ~ ":" ~ (evaluates_to_anything | anonymous_traversal
195196
update = { "UPDATE" ~ "(" ~ "{" ~ update_field ~ ("," ~ update_field)* ~ "}" ~ ")" }
196197
drop = { "DROP" ~ evaluates_to_anything }
197198
first = { "FIRST" }
199+
aggregate = { "AGGREGATE_BY" ~ "(" ~ (identifier ~ ("," ~ identifier)*) ~ ")" }
200+
group_by = { "GROUP_BY" ~ "(" ~ (identifier ~ ("," ~ identifier)*) ~ ")" }
201+
198202

199203
// ---------------------------------------------------------------------
200204
// Vector steps

helix-db/src/helix_engine/bm25/bm25.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,44 @@ impl HBM25Config {
109109
b: 0.75,
110110
})
111111
}
112+
113+
pub fn new_temp(graph_env: &Env, wtxn: &mut RwTxn, uuid: &str) -> Result<HBM25Config, GraphError> {
114+
let inverted_index_db: Database<Bytes, Bytes> = graph_env
115+
.database_options()
116+
.types::<Bytes, Bytes>()
117+
.flags(heed3::DatabaseFlags::DUP_SORT)
118+
.name(format!("{DB_BM25_INVERTED_INDEX}_{uuid}").as_str())
119+
.create(wtxn)?;
120+
121+
let doc_lengths_db: Database<U128<heed3::byteorder::BE>, U32<heed3::byteorder::BE>> =
122+
graph_env
123+
.database_options()
124+
.types::<U128<heed3::byteorder::BE>, U32<heed3::byteorder::BE>>()
125+
.name(format!("{DB_BM25_DOC_LENGTHS}_{uuid}").as_str())
126+
.create(wtxn)?;
127+
128+
let term_frequencies_db: Database<Bytes, U32<heed3::byteorder::BE>> = graph_env
129+
.database_options()
130+
.types::<Bytes, U32<heed3::byteorder::BE>>()
131+
.name(format!("{DB_BM25_TERM_FREQUENCIES}_{uuid}").as_str())
132+
.create(wtxn)?;
133+
134+
let metadata_db: Database<Bytes, Bytes> = graph_env
135+
.database_options()
136+
.types::<Bytes, Bytes>()
137+
.name(format!("{DB_BM25_METADATA}_{uuid}").as_str())
138+
.create(wtxn)?;
139+
140+
Ok(HBM25Config {
141+
graph_env: graph_env.clone(),
142+
inverted_index_db,
143+
doc_lengths_db,
144+
term_frequencies_db,
145+
metadata_db,
146+
k1: 1.2,
147+
b: 0.75,
148+
})
149+
}
112150
}
113151

114152
impl BM25 for HBM25Config {

helix-db/src/helix_engine/tests/traversal_tests/count_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::{
1313
n_from_id::NFromIdAdapter,
1414
n_from_type::NFromTypeAdapter,
1515
},
16-
util::{filter_ref::FilterRefAdapter, range::RangeAdapter},
16+
util::{count::CountAdapter, filter_ref::FilterRefAdapter, range::RangeAdapter},
1717
},
1818
traversal_value::Traversable,
1919
},

helix-db/src/helix_engine/traversal_core/ops/source/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ pub mod e_from_type;
66
pub mod n_from_id;
77
pub mod n_from_index;
88
pub mod n_from_type;
9-
pub mod v_from_id;
9+
pub mod v_from_id;
10+
pub mod v_from_type;

0 commit comments

Comments
 (0)