gqlite 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Cargo.toml +12 -6
  3. data/ext/db-index/Cargo.toml +29 -0
  4. data/ext/db-index/src/hnsw/error.rs +66 -0
  5. data/ext/db-index/src/hnsw/graph_store.rs +272 -0
  6. data/ext/db-index/src/hnsw/id.rs +36 -0
  7. data/ext/db-index/src/hnsw/implementation.rs +1517 -0
  8. data/ext/db-index/src/hnsw/kernels.rs +1228 -0
  9. data/ext/db-index/src/hnsw/metric.rs +244 -0
  10. data/ext/db-index/src/hnsw/scalar.rs +72 -0
  11. data/ext/db-index/src/hnsw/simple_store.rs +140 -0
  12. data/ext/db-index/src/hnsw/store.rs +472 -0
  13. data/ext/db-index/src/hnsw/vector.rs +105 -0
  14. data/ext/db-index/src/hnsw/vectors.rs +568 -0
  15. data/ext/db-index/src/hnsw.rs +42 -0
  16. data/ext/db-index/src/lib.rs +3 -0
  17. data/ext/gqlitedb/Cargo.toml +19 -8
  18. data/ext/gqlitedb/benches/common/pokec.rs +62 -2
  19. data/ext/gqlitedb/benches/pokec_divan.rs +66 -2
  20. data/ext/gqlitedb/benches/pokec_iai.rs +60 -3
  21. data/ext/gqlitedb/release.toml +2 -2
  22. data/ext/gqlitedb/src/aggregators/arithmetic.rs +3 -1
  23. data/ext/gqlitedb/src/aggregators/containers.rs +1 -1
  24. data/ext/gqlitedb/src/aggregators/stats.rs +21 -12
  25. data/ext/gqlitedb/src/capi.rs +20 -24
  26. data/ext/gqlitedb/src/compiler/expression_analyser.rs +28 -20
  27. data/ext/gqlitedb/src/compiler/variables_manager.rs +104 -38
  28. data/ext/gqlitedb/src/compiler.rs +506 -227
  29. data/ext/gqlitedb/src/connection.rs +151 -11
  30. data/ext/gqlitedb/src/consts.rs +1 -2
  31. data/ext/gqlitedb/src/error.rs +123 -61
  32. data/ext/gqlitedb/src/functions/common.rs +64 -0
  33. data/ext/gqlitedb/src/functions/containers.rs +2 -46
  34. data/ext/gqlitedb/src/functions/edge.rs +1 -1
  35. data/ext/gqlitedb/src/functions/math.rs +87 -15
  36. data/ext/gqlitedb/src/functions/node.rs +1 -1
  37. data/ext/gqlitedb/src/functions/path.rs +48 -11
  38. data/ext/gqlitedb/src/functions/scalar.rs +47 -4
  39. data/ext/gqlitedb/src/functions/string.rs +123 -1
  40. data/ext/gqlitedb/src/functions/value.rs +1 -1
  41. data/ext/gqlitedb/src/functions.rs +165 -28
  42. data/ext/gqlitedb/src/graph.rs +1 -9
  43. data/ext/gqlitedb/src/interpreter/evaluators.rs +968 -130
  44. data/ext/gqlitedb/src/interpreter/instructions.rs +39 -2
  45. data/ext/gqlitedb/src/lib.rs +5 -4
  46. data/ext/gqlitedb/src/parser/gql.pest +1 -1
  47. data/ext/gqlitedb/src/planner.rs +329 -0
  48. data/ext/gqlitedb/src/prelude.rs +3 -3
  49. data/ext/gqlitedb/src/store/pgrx.rs +1 -1
  50. data/ext/gqlitedb/src/store/postgres.rs +742 -16
  51. data/ext/gqlitedb/src/store/redb/hnsw_store.rs +702 -0
  52. data/ext/gqlitedb/src/store/redb/index.rs +274 -0
  53. data/ext/gqlitedb/src/store/redb.rs +1268 -113
  54. data/ext/gqlitedb/src/store/sqlbase/sqlmetadata.rs +28 -0
  55. data/ext/gqlitedb/src/store/sqlbase/sqlstore.rs +103 -0
  56. data/ext/gqlitedb/src/store/sqlbase.rs +146 -16
  57. data/ext/gqlitedb/src/store/sqlite.rs +576 -14
  58. data/ext/gqlitedb/src/store/vector_extract.rs +56 -0
  59. data/ext/gqlitedb/src/store.rs +140 -29
  60. data/ext/gqlitedb/src/tests/compiler.rs +207 -10
  61. data/ext/gqlitedb/src/tests/connection/postgres.rs +38 -3
  62. data/ext/gqlitedb/src/tests/connection/redb.rs +23 -0
  63. data/ext/gqlitedb/src/tests/connection/sqlite.rs +31 -0
  64. data/ext/gqlitedb/src/tests/connection.rs +61 -1
  65. data/ext/gqlitedb/src/tests/evaluators.rs +162 -7
  66. data/ext/gqlitedb/src/tests/parser.rs +54 -23
  67. data/ext/gqlitedb/src/tests/planner.rs +511 -0
  68. data/ext/gqlitedb/src/tests/store/postgres.rs +7 -0
  69. data/ext/gqlitedb/src/tests/store/redb.rs +8 -0
  70. data/ext/gqlitedb/src/tests/store/sqlite.rs +8 -0
  71. data/ext/gqlitedb/src/tests/store/vector_index/postgres.rs +182 -0
  72. data/ext/gqlitedb/src/tests/store/vector_index/redb.rs +386 -0
  73. data/ext/gqlitedb/src/tests/store/vector_index/sqlite.rs +166 -0
  74. data/ext/gqlitedb/src/tests/store/vector_index.rs +2313 -0
  75. data/ext/gqlitedb/src/tests/store.rs +78 -14
  76. data/ext/gqlitedb/src/tests/templates/ast.rs +92 -16
  77. data/ext/gqlitedb/src/tests/templates/programs.rs +14 -7
  78. data/ext/gqlitedb/src/tests.rs +15 -9
  79. data/ext/gqlitedb/src/utils.rs +6 -1
  80. data/ext/gqlitedb/src/value/compare.rs +61 -3
  81. data/ext/gqlitedb/src/value.rs +136 -7
  82. data/ext/gqlitedb/templates/sql/postgres/metadata_delete.sql +1 -0
  83. data/ext/gqlitedb/templates/sql/postgres/node_select.sql +1 -1
  84. data/ext/gqlitedb/templates/sql/sqlite/metadata_delete.sql +1 -0
  85. data/ext/gqliterb/src/lib.rs +53 -8
  86. data/ext/gqlparser/Cargo.toml +25 -0
  87. data/ext/gqlparser/README.MD +9 -0
  88. data/ext/gqlparser/benches/pokec_divan.rs +34 -0
  89. data/ext/gqlparser/src/common.rs +69 -0
  90. data/ext/gqlparser/src/gqls/ast.rs +69 -0
  91. data/ext/gqlparser/src/gqls/constraint.rs +79 -0
  92. data/ext/gqlparser/src/gqls/error.rs +22 -0
  93. data/ext/gqlparser/src/gqls/parser.rs +813 -0
  94. data/ext/gqlparser/src/gqls/prelude.rs +8 -0
  95. data/ext/gqlparser/src/gqls/properties.rs +115 -0
  96. data/ext/gqlparser/src/gqls/resolve.rs +207 -0
  97. data/ext/gqlparser/src/gqls.rs +265 -0
  98. data/ext/gqlparser/src/lib.rs +7 -0
  99. data/ext/gqlparser/src/oc/ast.rs +680 -0
  100. data/ext/gqlparser/src/oc/error.rs +172 -0
  101. data/ext/gqlparser/src/oc/lexer.rs +429 -0
  102. data/ext/gqlparser/src/oc/parser/tests.rs +2284 -0
  103. data/ext/gqlparser/src/oc/parser.rs +2005 -0
  104. data/ext/gqlparser/src/oc.rs +33 -0
  105. data/ext/gqlparser/src/prelude.rs +3 -0
  106. data/ext/graphcore/Cargo.toml +1 -0
  107. data/ext/graphcore/src/error.rs +26 -0
  108. data/ext/graphcore/src/graph.rs +177 -51
  109. data/ext/graphcore/src/lib.rs +4 -2
  110. data/ext/graphcore/src/open_cypher.rs +12 -0
  111. data/ext/graphcore/src/table.rs +50 -2
  112. data/ext/graphcore/src/timestamp.rs +127 -104
  113. data/ext/graphcore/src/value/tensor.rs +739 -0
  114. data/ext/graphcore/src/value/value_map.rs +1 -1
  115. data/ext/graphcore/src/value.rs +343 -19
  116. metadata +93 -28
  117. data/ext/gqlitedb/src/parser/ast.rs +0 -604
  118. data/ext/gqlitedb/src/parser/parser_impl.rs +0 -1213
  119. data/ext/gqlitedb/src/parser.rs +0 -4
@@ -0,0 +1,274 @@
1
+ use crate::graph;
2
+ use crate::prelude::*;
3
+ use crate::store::VectorMetric;
4
+ use db_index::hnsw::metric::{Cosine, InnerProduct, L2};
5
+ use db_index::hnsw::{Dense, Metric};
6
+ use serde::{Deserialize, Serialize};
7
+ use std::collections::HashMap;
8
+ use std::sync::{Arc, Mutex};
9
+
10
+ pub(crate) type IndexRef = Arc<dyn Index>;
11
+
12
+ /// Resolved HNSW graph construction and search parameters.
13
+ #[derive(
14
+ Debug, Clone, Copy, PartialEq, Eq, smart_default::SmartDefault, Serialize, Deserialize,
15
+ )]
16
+ pub(crate) struct HnswParams
17
+ {
18
+ #[default(16)]
19
+ pub m: usize,
20
+ #[default(200)]
21
+ pub ef_construction: usize,
22
+ #[default(50)]
23
+ pub ef_search: usize,
24
+ }
25
+
26
+ #[derive(Debug, Clone)]
27
+ pub(crate) enum IndexKind
28
+ {
29
+ Vector
30
+ {
31
+ dimension: usize,
32
+ metric: VectorMetric,
33
+ params: HnswParams,
34
+ },
35
+ }
36
+
37
+ pub(crate) trait Index: Send + Sync
38
+ {
39
+ fn name(&self) -> &str;
40
+ fn on_insert(&self, node: &graph::Node) -> Result<()>;
41
+ fn on_update(&self, old: &graph::Node, new: &graph::Node) -> Result<()>;
42
+ fn as_any(&self) -> &dyn std::any::Any;
43
+ }
44
+
45
+ pub(crate) struct IndexRegistry
46
+ {
47
+ inner: Mutex<HashMap<String, IndexRef>>,
48
+ }
49
+
50
+ impl IndexRegistry
51
+ {
52
+ pub(crate) fn new() -> Self
53
+ {
54
+ Self {
55
+ inner: Mutex::new(HashMap::new()),
56
+ }
57
+ }
58
+
59
+ pub(crate) fn register_index(&self, name: String, index: IndexRef)
60
+ {
61
+ let mut guard = self.inner.lock().unwrap();
62
+ guard.insert(name, index);
63
+ }
64
+
65
+ pub(crate) fn drop_index(&self, name: &str) -> Option<IndexRef>
66
+ {
67
+ let mut guard = self.inner.lock().unwrap();
68
+ guard.remove(name)
69
+ }
70
+
71
+ pub(crate) fn get_index(&self, name: &str) -> Option<IndexRef>
72
+ {
73
+ let guard = self.inner.lock().unwrap();
74
+ guard.get(name).cloned()
75
+ }
76
+
77
+ pub(crate) fn iter_indexes(&self) -> Vec<IndexRef>
78
+ {
79
+ let guard = self.inner.lock().unwrap();
80
+ guard.values().cloned().collect()
81
+ }
82
+ }
83
+
84
+ impl std::fmt::Debug for IndexRegistry
85
+ {
86
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
87
+ {
88
+ let keys: Vec<String> = self.inner.lock().unwrap().keys().cloned().collect();
89
+ let keys_str = keys.join(", ");
90
+ f.write_fmt(format_args!("IndexRegistry {{ {} }} ", keys_str))
91
+ }
92
+ }
93
+
94
+ pub(crate) enum MetricWrapper
95
+ {
96
+ Cosine(Cosine<f32>),
97
+ L2(L2<f32>),
98
+ DotProduct(InnerProduct<f32>),
99
+ }
100
+
101
+ impl Clone for MetricWrapper
102
+ {
103
+ fn clone(&self) -> Self
104
+ {
105
+ match self
106
+ {
107
+ MetricWrapper::Cosine(m) => MetricWrapper::Cosine(m.clone()),
108
+ MetricWrapper::L2(m) => MetricWrapper::L2(m.clone()),
109
+ MetricWrapper::DotProduct(m) => MetricWrapper::DotProduct(m.clone()),
110
+ }
111
+ }
112
+ }
113
+
114
+ impl MetricWrapper
115
+ {
116
+ pub(crate) fn new(metric: VectorMetric) -> Self
117
+ {
118
+ match metric
119
+ {
120
+ VectorMetric::Cosine => MetricWrapper::Cosine(Cosine::new()),
121
+ VectorMetric::L2 => MetricWrapper::L2(L2::new()),
122
+ VectorMetric::DotProduct => MetricWrapper::DotProduct(InnerProduct::new()),
123
+ }
124
+ }
125
+ }
126
+
127
+ impl Metric for MetricWrapper
128
+ {
129
+ type Family = Dense<f32>;
130
+
131
+ fn distance<'a, 'b>(
132
+ &self,
133
+ a: <Self::Family as db_index::hnsw::vector::VectorFamily>::Ref<'a>,
134
+ b: <Self::Family as db_index::hnsw::vector::VectorFamily>::Ref<'b>,
135
+ ) -> f32
136
+ {
137
+ match self
138
+ {
139
+ MetricWrapper::Cosine(m) => m.distance(a, b),
140
+ MetricWrapper::L2(m) => m.distance(a, b),
141
+ MetricWrapper::DotProduct(m) => m.distance(a, b),
142
+ }
143
+ }
144
+ }
145
+
146
+ pub(crate) struct HnswVectorIndex
147
+ {
148
+ name: String,
149
+ dimension: usize,
150
+ metric: VectorMetric,
151
+ params: HnswParams,
152
+ }
153
+
154
+ impl HnswVectorIndex
155
+ {
156
+ pub(crate) fn new(
157
+ name: String,
158
+ dimension: usize,
159
+ metric: VectorMetric,
160
+ params: HnswParams,
161
+ ) -> Self
162
+ {
163
+ Self {
164
+ name,
165
+ dimension,
166
+ metric,
167
+ params,
168
+ }
169
+ }
170
+
171
+ /// Create a new HnswIndex ready for upsert or search operations.
172
+ /// This is called per transaction to build a fresh stateless index.
173
+ pub(crate) fn upsert_and_search_ready(&self) -> db_index::hnsw::HnswIndex<MetricWrapper>
174
+ {
175
+ db_index::hnsw::HnswIndex::new(
176
+ MetricWrapper::new(self.metric),
177
+ db_index::hnsw::HnswConfig::new(self.dimension, u32::MAX as usize)
178
+ .m(self.params.m)
179
+ .ef_construction(self.params.ef_construction)
180
+ .ef_search(self.params.ef_search),
181
+ )
182
+ }
183
+
184
+ #[cfg(test)]
185
+ pub(crate) fn get_hnsw_parameters(&self) -> HnswParams
186
+ {
187
+ self.params
188
+ }
189
+
190
+ pub(crate) fn dimension(&self) -> usize
191
+ {
192
+ self.dimension
193
+ }
194
+
195
+ pub(crate) fn ef_search(&self) -> usize
196
+ {
197
+ self.params.ef_search
198
+ }
199
+
200
+ pub(crate) fn encoding(&self) -> db_index::hnsw::store::VectorEncoding
201
+ {
202
+ // Default to F32 for now; revisit per WI #8.7's dtype measurement
203
+ db_index::hnsw::store::VectorEncoding::F32
204
+ }
205
+ }
206
+
207
+ impl Index for HnswVectorIndex
208
+ {
209
+ fn name(&self) -> &str
210
+ {
211
+ &self.name
212
+ }
213
+
214
+ fn on_insert(&self, _node: &graph::Node) -> Result<()>
215
+ {
216
+ // No-op: real work happens through persistent stores in upsert_vector
217
+ Ok(())
218
+ }
219
+
220
+ fn on_update(&self, _old: &graph::Node, _new: &graph::Node) -> Result<()>
221
+ {
222
+ // No-op: real work happens through persistent stores in upsert_vector
223
+ Ok(())
224
+ }
225
+
226
+ fn as_any(&self) -> &dyn std::any::Any
227
+ {
228
+ self
229
+ }
230
+ }
231
+
232
+ pub(crate) fn create_index(kind: IndexKind, name: &str, _property: Option<String>) -> IndexRef
233
+ {
234
+ match kind
235
+ {
236
+ IndexKind::Vector {
237
+ dimension,
238
+ metric,
239
+ params,
240
+ } => Arc::new(HnswVectorIndex::new(
241
+ name.to_string(),
242
+ dimension,
243
+ metric,
244
+ params,
245
+ )),
246
+ }
247
+ }
248
+
249
+ #[cfg(test)]
250
+ mod tests
251
+ {
252
+ use super::*;
253
+ use crate::store::VectorMetric;
254
+
255
+ #[test]
256
+ fn test_hnsw_parameters_are_stored_in_config()
257
+ {
258
+ let hnsw = HnswVectorIndex::new(
259
+ "idx".into(),
260
+ 3,
261
+ VectorMetric::Cosine,
262
+ HnswParams {
263
+ m: 8,
264
+ ef_construction: 64,
265
+ ef_search: 24,
266
+ },
267
+ );
268
+
269
+ let params = hnsw.get_hnsw_parameters();
270
+ assert_eq!(params.m, 8);
271
+ assert_eq!(params.ef_construction, 64);
272
+ assert_eq!(params.ef_search, 24);
273
+ }
274
+ }