gqlite 1.5.1 → 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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Cargo.toml +10 -4
  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 -9
  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 +1 -1
  26. data/ext/gqlitedb/src/compiler/expression_analyser.rs +28 -20
  27. data/ext/gqlitedb/src/compiler/variables_manager.rs +97 -29
  28. data/ext/gqlitedb/src/compiler.rs +505 -225
  29. data/ext/gqlitedb/src/connection.rs +149 -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 +39 -2
  33. data/ext/gqlitedb/src/functions/math.rs +8 -3
  34. data/ext/gqlitedb/src/functions/path.rs +48 -11
  35. data/ext/gqlitedb/src/functions/value.rs +1 -1
  36. data/ext/gqlitedb/src/functions.rs +23 -7
  37. data/ext/gqlitedb/src/graph.rs +1 -9
  38. data/ext/gqlitedb/src/interpreter/evaluators.rs +968 -130
  39. data/ext/gqlitedb/src/interpreter/instructions.rs +39 -2
  40. data/ext/gqlitedb/src/lib.rs +5 -4
  41. data/ext/gqlitedb/src/planner.rs +329 -0
  42. data/ext/gqlitedb/src/prelude.rs +3 -3
  43. data/ext/gqlitedb/src/store/pgrx.rs +1 -1
  44. data/ext/gqlitedb/src/store/postgres.rs +735 -7
  45. data/ext/gqlitedb/src/store/redb/hnsw_store.rs +702 -0
  46. data/ext/gqlitedb/src/store/redb/index.rs +274 -0
  47. data/ext/gqlitedb/src/store/redb.rs +1268 -113
  48. data/ext/gqlitedb/src/store/sqlbase/sqlmetadata.rs +28 -0
  49. data/ext/gqlitedb/src/store/sqlbase/sqlstore.rs +103 -0
  50. data/ext/gqlitedb/src/store/sqlbase.rs +146 -16
  51. data/ext/gqlitedb/src/store/sqlite.rs +569 -5
  52. data/ext/gqlitedb/src/store/vector_extract.rs +56 -0
  53. data/ext/gqlitedb/src/store.rs +123 -3
  54. data/ext/gqlitedb/src/tests/compiler.rs +207 -10
  55. data/ext/gqlitedb/src/tests/connection/postgres.rs +38 -3
  56. data/ext/gqlitedb/src/tests/connection/redb.rs +23 -0
  57. data/ext/gqlitedb/src/tests/connection/sqlite.rs +31 -0
  58. data/ext/gqlitedb/src/tests/connection.rs +61 -1
  59. data/ext/gqlitedb/src/tests/evaluators.rs +162 -7
  60. data/ext/gqlitedb/src/tests/parser.rs +54 -23
  61. data/ext/gqlitedb/src/tests/planner.rs +511 -0
  62. data/ext/gqlitedb/src/tests/store/postgres.rs +7 -0
  63. data/ext/gqlitedb/src/tests/store/redb.rs +8 -0
  64. data/ext/gqlitedb/src/tests/store/sqlite.rs +8 -0
  65. data/ext/gqlitedb/src/tests/store/vector_index/postgres.rs +182 -0
  66. data/ext/gqlitedb/src/tests/store/vector_index/redb.rs +386 -0
  67. data/ext/gqlitedb/src/tests/store/vector_index/sqlite.rs +166 -0
  68. data/ext/gqlitedb/src/tests/store/vector_index.rs +2313 -0
  69. data/ext/gqlitedb/src/tests/store.rs +78 -14
  70. data/ext/gqlitedb/src/tests/templates/ast.rs +92 -16
  71. data/ext/gqlitedb/src/tests/templates/programs.rs +14 -7
  72. data/ext/gqlitedb/src/tests.rs +15 -9
  73. data/ext/gqlitedb/src/utils.rs +6 -1
  74. data/ext/gqlitedb/src/value/compare.rs +61 -3
  75. data/ext/gqlitedb/src/value.rs +136 -7
  76. data/ext/gqlitedb/templates/sql/postgres/metadata_delete.sql +1 -0
  77. data/ext/gqlitedb/templates/sql/postgres/node_select.sql +1 -1
  78. data/ext/gqlitedb/templates/sql/sqlite/metadata_delete.sql +1 -0
  79. data/ext/gqliterb/src/lib.rs +53 -8
  80. data/ext/gqlparser/Cargo.toml +25 -0
  81. data/ext/gqlparser/README.MD +9 -0
  82. data/ext/gqlparser/benches/pokec_divan.rs +34 -0
  83. data/ext/gqlparser/src/common.rs +69 -0
  84. data/ext/gqlparser/src/gqls/ast.rs +69 -0
  85. data/ext/gqlparser/src/gqls/constraint.rs +79 -0
  86. data/ext/gqlparser/src/gqls/error.rs +22 -0
  87. data/ext/gqlparser/src/gqls/parser.rs +813 -0
  88. data/ext/gqlparser/src/gqls/prelude.rs +8 -0
  89. data/ext/gqlparser/src/gqls/properties.rs +115 -0
  90. data/ext/gqlparser/src/gqls/resolve.rs +207 -0
  91. data/ext/gqlparser/src/gqls.rs +265 -0
  92. data/ext/gqlparser/src/lib.rs +7 -0
  93. data/ext/gqlparser/src/oc/ast.rs +680 -0
  94. data/ext/gqlparser/src/oc/error.rs +172 -0
  95. data/ext/gqlparser/src/oc/lexer.rs +429 -0
  96. data/ext/gqlparser/src/oc/parser/tests.rs +2284 -0
  97. data/ext/gqlparser/src/oc/parser.rs +2005 -0
  98. data/ext/gqlparser/src/oc.rs +33 -0
  99. data/ext/gqlparser/src/prelude.rs +3 -0
  100. data/ext/graphcore/Cargo.toml +1 -0
  101. data/ext/graphcore/src/error.rs +26 -0
  102. data/ext/graphcore/src/graph.rs +177 -51
  103. data/ext/graphcore/src/lib.rs +4 -2
  104. data/ext/graphcore/src/open_cypher.rs +12 -0
  105. data/ext/graphcore/src/table.rs +50 -2
  106. data/ext/graphcore/src/timestamp.rs +127 -104
  107. data/ext/graphcore/src/value/tensor.rs +739 -0
  108. data/ext/graphcore/src/value/value_map.rs +1 -1
  109. data/ext/graphcore/src/value.rs +343 -19
  110. metadata +90 -22
  111. data/ext/gqlitedb/src/parser/ast.rs +0 -604
  112. data/ext/gqlitedb/src/parser/parser_impl.rs +0 -1213
  113. data/ext/gqlitedb/src/parser.rs +0 -4
@@ -1,6 +1,7 @@
1
1
  use std::path::Path;
2
2
 
3
- use crate::{prelude::*, QueryResult};
3
+ use crate::{QueryResult, planner, prelude::*};
4
+ use substring::Substring;
4
5
  use value::ValueTryIntoRef;
5
6
 
6
7
  /// Backend
@@ -104,16 +105,126 @@ where
104
105
  {
105
106
  fn execute_oc_query(&self, query: &str, parameters: value::ValueMap) -> Result<QueryResult>
106
107
  {
107
- let queries = parser::parse(query)?;
108
+ use gqlparser::oc::ErrorKind;
109
+ let queries = gqlparser::oc::parse_oc_query(query).map_err(|e| match e.error_kind()
110
+ {
111
+ ErrorKind::IntegerOverflow => error::CompileTimeError::IntegerOverflow {
112
+ text: query.substring(e.span().start, e.span().end).to_string(),
113
+ },
114
+ ErrorKind::FloatingPointOverflow => error::CompileTimeError::FloatingPointOverflow {
115
+ text: query.substring(e.span().start, e.span().end).to_string(),
116
+ },
117
+ ErrorKind::RequiresDirectedEdge => error::CompileTimeError::RequiresDirectedRelationship {
118
+ text: query.substring(e.span().start, e.span().end).to_string(),
119
+ span: e.span().clone(),
120
+ },
121
+ ErrorKind::NoSingleRelationshipType => error::CompileTimeError::NoSingleRelationshipType {
122
+ text: query.substring(e.span().start, e.span().end).to_string(),
123
+ span: e.span().clone(),
124
+ },
125
+ _ => error::CompileTimeError::ParseError {
126
+ error_kind: e.error_kind().clone(),
127
+ text: query.substring(e.span().start, e.span().end).to_string(),
128
+ span: e.span().clone(),
129
+ },
130
+ })?;
131
+ if consts::SHOW_AST
132
+ {
133
+ log::debug!("ast = {:#?}", queries);
134
+ }
108
135
  let mut results = Vec::<QueryResult>::default();
109
136
  for query in queries
110
137
  {
111
- let program = compiler::compile(&self.function_manager, query)?;
112
- results.push(interpreter::evaluators::eval_program(
113
- &self.store,
114
- &program,
115
- &parameters,
116
- )?)
138
+ match query
139
+ {
140
+ gqlparser::oc::ast::Query::Statements(stmts) =>
141
+ {
142
+ let logical_plans: Result<Vec<_>> = stmts.into_iter().map(planner::plan).collect();
143
+ let program = compiler::compile(&self.function_manager, logical_plans?)?;
144
+ results.push(interpreter::evaluators::eval_program(
145
+ &self.store,
146
+ &program,
147
+ &parameters,
148
+ )?)
149
+ }
150
+ gqlparser::oc::ast::Query::Union { branches, all } =>
151
+ {
152
+ // Evaluate each branch independently
153
+ let branch_results: Result<Vec<_>> = branches
154
+ .into_iter()
155
+ .map(|stmts| {
156
+ let logical_plans: Result<Vec<_>> = stmts.into_iter().map(planner::plan).collect();
157
+ let program = compiler::compile(&self.function_manager, logical_plans?)?;
158
+ interpreter::evaluators::eval_program(&self.store, &program, &parameters)
159
+ })
160
+ .collect();
161
+
162
+ // Extract tables from results and validate headers
163
+ let branch_results = branch_results?;
164
+ let mut tables: Vec<graphcore::Table> = Vec::new();
165
+ let mut has_empty = false;
166
+
167
+ for result in branch_results
168
+ {
169
+ match result
170
+ {
171
+ QueryResult::Table(t) => tables.push(t),
172
+ QueryResult::Empty => has_empty = true,
173
+ _ => return Err(CompileTimeError::DifferentColumnsInUnion.into()),
174
+ }
175
+ }
176
+
177
+ // If all branches are empty, return Empty
178
+ if tables.is_empty()
179
+ {
180
+ results.push(QueryResult::Empty);
181
+ continue;
182
+ }
183
+
184
+ // Validate that all tables have identical headers
185
+ let headers = tables[0].headers().clone();
186
+ for t in &tables[1..]
187
+ {
188
+ if t.headers() != &headers
189
+ {
190
+ return Err(CompileTimeError::DifferentColumnsInUnion.into());
191
+ }
192
+ }
193
+
194
+ // If any branch was empty, that's a header mismatch
195
+ if has_empty
196
+ {
197
+ return Err(CompileTimeError::DifferentColumnsInUnion.into());
198
+ }
199
+
200
+ // Concatenate all row data
201
+ let mut data: Vec<graphcore::Value> = tables
202
+ .into_iter()
203
+ .flat_map(|t| t.into_row_iter().flatten())
204
+ .collect();
205
+
206
+ // UNION (distinct): deduplicate rows
207
+ if !all
208
+ {
209
+ let col_count = headers.len();
210
+ let mut result_rows: Vec<Vec<graphcore::Value>> = Vec::new();
211
+
212
+ for row_chunk in data.chunks(col_count)
213
+ {
214
+ let row = row_chunk.to_vec();
215
+ // Check if row is already in result
216
+ if !result_rows.iter().any(|r| r == &row)
217
+ {
218
+ result_rows.push(row);
219
+ }
220
+ }
221
+
222
+ data = result_rows.into_iter().flatten().collect();
223
+ }
224
+
225
+ results.push(QueryResult::Table(graphcore::Table::new(headers, data)?));
226
+ }
227
+ }
117
228
  }
118
229
  match results.len()
119
230
  {
@@ -160,6 +271,14 @@ pub struct Connection
160
271
  connection: Box<dyn ConnectionTrait>,
161
272
  }
162
273
 
274
+ impl std::fmt::Debug for Connection
275
+ {
276
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
277
+ {
278
+ f.write_str("Connection")
279
+ }
280
+ }
281
+
163
282
  ccutils::assert_impl_all!(Connection: Sync, Send);
164
283
 
165
284
  impl Connection
@@ -180,9 +299,9 @@ impl Connection
180
299
  /// ```rust
181
300
  /// # use gqlitedb::Connection;
182
301
  /// # fn example() -> gqlitedb::Result<()> {
183
- /// let connection = Connection::create(gqlitedb::value_map!("backend" => "redb"))?;
302
+ /// let connection = Connection::create(gqlitedb::value_map!("backend" => "sqlite"))?;
184
303
  /// # Ok(()) }
185
- /// ```
304
+ /// ```
186
305
  pub fn create(options: value::ValueMap) -> Result<Connection>
187
306
  {
188
307
  let backend = options.get("backend").map_or_else(
@@ -303,7 +422,7 @@ impl Connection
303
422
  /// Example of use:
304
423
  /// ```no_run
305
424
  /// # use gqlitedb::{Connection, Backend};
306
- /// let connection = Connection::builder().path("path/to/file").backend(Backend::SQLite).create().unwrap();
425
+ /// let connection = Connection::builder().path("path/to/file").backend(Backend::Redb).create().unwrap();
307
426
  /// ```
308
427
  pub fn builder() -> ConnectionBuilder
309
428
  {
@@ -345,3 +464,22 @@ impl Connection
345
464
  self.connection.execute_oc_query(query.as_ref(), parameters)
346
465
  }
347
466
  }
467
+
468
+ impl graphcore::OpenCypherQueryExecutor for Connection
469
+ {
470
+ fn execute_oc_query(
471
+ &self,
472
+ query: &str,
473
+ parameters: graphcore::ValueMap,
474
+ ) -> Result<Option<graphcore::Table>, graphcore::Error>
475
+ {
476
+ let qr = self
477
+ .execute_oc_query(query, parameters)
478
+ .map_err(|e| graphcore::Error::QueryExecutionError(e.to_string()))?;
479
+ match qr
480
+ {
481
+ QueryResult::Table(tbl) => Ok(Some(tbl)),
482
+ _ => Ok(None),
483
+ }
484
+ }
485
+ }
@@ -1,10 +1,9 @@
1
- pub(crate) const SHOW_PARSE_TREE: bool = false;
2
1
  pub(crate) const SHOW_AST: bool = false;
3
2
  pub(crate) const SHOW_PROGRAM: bool = false;
4
3
  pub(crate) const SHOW_EVALUATOR_STATE: bool = false;
5
4
 
6
5
  pub(crate) const GQLITE_VERSION: crate::utils::Version = crate::utils::Version {
7
6
  major: 1,
8
- minor: 2,
7
+ minor: 8,
9
8
  patch: 0,
10
9
  };
@@ -20,8 +20,22 @@ pub enum CompileTimeError
20
20
  text: String
21
21
  },
22
22
  /// Parse error
23
- #[error("ParseError: '{0}'")]
24
- ParseError(#[from] Box<pest::error::Error<crate::parser::parser_impl::Rule>>),
23
+ #[error("ParseError: {error_kind:?}: '{text}' at {span:?}.")]
24
+ ParseError
25
+ {
26
+ error_kind: gqlparser::oc::ErrorKind,
27
+ text: String,
28
+ span: std::ops::Range<usize>,
29
+ },
30
+ /// Unexpected syntax encountered at compile time (used to match TCK expectations)
31
+ #[error("UnexpectedSyntax: Expected token {expected} got {got} at ({line}, {col}).")]
32
+ UnexpectedSyntax
33
+ {
34
+ expected: String,
35
+ got: String,
36
+ line: usize,
37
+ col: usize,
38
+ },
25
39
  /// Variable is not defined
26
40
  #[error("UndefinedVariable: Unknown variable '{name}'.")]
27
41
  UndefinedVariable
@@ -43,13 +57,20 @@ pub enum CompileTimeError
43
57
  name: String
44
58
  },
45
59
  /// ()-[]-() is not accepted in this context
46
- #[error("RequiresDirectedRelationship: edges need to be directed in this context: '{context}'.")]
60
+ #[error("RequiresDirectedRelationship: edges need to be directed at: '{text}' at {span:?}.")]
47
61
  RequiresDirectedRelationship
48
62
  {
49
- context: &'static str
63
+ text: String,
64
+ span: std::ops::Range<usize>,
65
+ },
66
+ #[error(
67
+ "NoSingleRelationshipType: a single edge type need to be specified at: '{text}' at {span:?}."
68
+ )]
69
+ NoSingleRelationshipType
70
+ {
71
+ text: String,
72
+ span: std::ops::Range<usize>,
50
73
  },
51
- #[error("NoSingleRelationshipType: an edge type need to be specified.")]
52
- NoSingleRelationshipType,
53
74
  #[error("NotComparable: values are not comparable.")]
54
75
  NotComparable,
55
76
  #[error("UnknownFunction: {name}.")]
@@ -67,7 +88,9 @@ pub enum CompileTimeError
67
88
  #[error("InvalidDelete: invalid delete argument, expected node or edge.")]
68
89
  InvalidDelete,
69
90
  /// Too few or too many arguments
70
- #[error("InvalidNumberOfArguments: Invalid number of arguments for function '{function_name}' got {got} expected {expected}.")]
91
+ #[error(
92
+ "InvalidNumberOfArguments: Invalid number of arguments for function '{function_name}' got {got} expected {expected}."
93
+ )]
71
94
  InvalidNumberOfArguments
72
95
  {
73
96
  function_name: &'static str,
@@ -78,6 +101,35 @@ pub enum CompileTimeError
78
101
  NonConstantExpression,
79
102
  #[error("InvalidArgumentType: invalid argument type.")]
80
103
  InvalidArgumentType,
104
+ #[error("NegativeIntegerArgument: statement expect a positive integer.")]
105
+ NegativeIntegerArgument,
106
+ #[error("CreatingVarLength: attempt at creating a variable length edge.")]
107
+ CreatingVarLength,
108
+ #[error("InvalidVectorInput: Expected vector or tensor for SEARCH.")]
109
+ InvalidVectorInput,
110
+ #[error(
111
+ "InvalidVectorElement: Array element must be numeric (Integer or Float), got {type_name}."
112
+ )]
113
+ InvalidVectorElement
114
+ {
115
+ type_name: String
116
+ },
117
+ #[error("NestedArrayNotSupported: Nested arrays are not supported in vector inputs.")]
118
+ NestedArrayNotSupported,
119
+ #[error("EmptyVector: Vector cannot be empty.")]
120
+ EmptyVector,
121
+ #[error("ExpectedNode: Expected a value to be a node in {context}.")]
122
+ ExpectedNode
123
+ {
124
+ context: &'static str
125
+ },
126
+ #[error("ExpectedEdge: Expected a value to be an edge in {context}.")]
127
+ ExpectedEdge
128
+ {
129
+ context: &'static str
130
+ },
131
+ #[error("DifferentColumnsInUnion: All sub-queries in a UNION must have the same column names.")]
132
+ DifferentColumnsInUnion,
81
133
  }
82
134
 
83
135
  /// Runtime errors.
@@ -93,7 +145,9 @@ pub enum RunTimeError
93
145
  name: String
94
146
  },
95
147
  /// Too few or too many arguments
96
- #[error("InvalidNumberOfArguments: Invalid number of arguments for function '{function_name}' got {got} expected {expected}.")]
148
+ #[error(
149
+ "InvalidNumberOfArguments: Invalid number of arguments for function '{function_name}' got {got} expected {expected}."
150
+ )]
97
151
  InvalidNumberOfArguments
98
152
  {
99
153
  function_name: &'static str,
@@ -150,6 +204,11 @@ pub enum RunTimeError
150
204
  {
151
205
  graph_name: String
152
206
  },
207
+ #[error("DuplicatedVectorIndex: vector index '{index_name}' already exists.")]
208
+ DuplicatedVectorIndex
209
+ {
210
+ index_name: String
211
+ },
153
212
  #[error("UnknownGraph: {graph_name} does not exists.")]
154
213
  UnknownGraph
155
214
  {
@@ -167,6 +226,13 @@ pub enum RunTimeError
167
226
  {
168
227
  value: f64, min: f64, max: f64
169
228
  },
229
+ #[error("ExpectedEdge: Expected a value to be an edge in {context}.")]
230
+ ExpectedEdge
231
+ {
232
+ context: &'static str
233
+ },
234
+ #[error("MergeReadOwnWrites: Cannot merge node using null property value, which is not allowed.")]
235
+ MergeReadOwnWrites,
170
236
  }
171
237
 
172
238
  /// Internal errors, should be treated as bugs.
@@ -180,16 +246,6 @@ pub enum InternalError
180
246
  MissingAggregationArgument,
181
247
  #[error("Aggregations are missing.")]
182
248
  MissingAggregations,
183
- #[error("Expected a value to be a node in {context}.")]
184
- ExpectedNode
185
- {
186
- context: &'static str
187
- },
188
- #[error("Expected a value to be an edge in {context}.")]
189
- ExpectedEdge
190
- {
191
- context: &'static str
192
- },
193
249
  #[error("Missing a pair from pest parsing in {context}.")]
194
250
  MissingPair
195
251
  {
@@ -205,11 +261,6 @@ pub enum InternalError
205
261
  {
206
262
  context: &'static str
207
263
  },
208
- #[error("Path pattern was used in create expression in {context}.")]
209
- PathPatternInCreateExpression
210
- {
211
- context: &'static str
212
- },
213
264
  #[error("Invalid create labels expression {context}.")]
214
265
  InvalidCreateLabels
215
266
  {
@@ -257,7 +308,9 @@ pub enum InternalError
257
308
  {
258
309
  got: usize, expected: usize
259
310
  },
260
- #[error("Some variables were declared, but not set. Set variables are {set_variables:?}, all variables are {all_variables:?}")]
311
+ #[error(
312
+ "Some variables were declared, but not set. Set variables are {set_variables:?}, all variables are {all_variables:?}"
313
+ )]
261
314
  NotAllVariablesAreSet
262
315
  {
263
316
  set_variables: Vec<String>,
@@ -275,6 +328,9 @@ pub enum InternalError
275
328
  #[error("Invalid aggregation state")]
276
329
  InvalidAggregationState,
277
330
 
331
+ #[error("Migration error: {0}")]
332
+ MigrationError(String),
333
+
278
334
  #[error("Invalid query result cast")]
279
335
  InvalidQueryResultCast,
280
336
 
@@ -285,7 +341,7 @@ pub enum InternalError
285
341
  // Errors from askama
286
342
  #[cfg(feature = "sqlite")]
287
343
  #[error("Askama: {0}")]
288
- AskamaError(#[from] askama::Error),
344
+ AskamaError(askama::Error),
289
345
 
290
346
  // Serialization errors
291
347
  #[error("An error occured while serialization to Cbor: {0}")]
@@ -310,6 +366,8 @@ pub enum InternalError
310
366
  UnknownNode,
311
367
  #[error("Unknown edge")]
312
368
  UnknownEdge,
369
+ #[error("UnsupportedRecursivePatternInMerge")]
370
+ UnsupportedRecursivePatternInMerge,
313
371
  #[error("Unimplemented error at {0}")]
314
372
  Unimplemented(&'static str),
315
373
  #[error("Infallible.")]
@@ -367,7 +425,9 @@ pub enum StoreError
367
425
  {
368
426
  backend: &'static str
369
427
  },
370
- #[error("OpeningError: could not open database, got the following error messages from the backends: {errors}.")]
428
+ #[error(
429
+ "OpeningError: could not open database, got the following error messages from the backends: {errors}."
430
+ )]
371
431
  OpeningError
372
432
  {
373
433
  errors: String
@@ -377,6 +437,11 @@ pub enum StoreError
377
437
  {
378
438
  graph_name: String
379
439
  },
440
+ #[error("DuplicatedVectorIndex: vector index '{index_name}' already exists.")]
441
+ DuplicatedVectorIndex
442
+ {
443
+ index_name: String
444
+ },
380
445
  #[error("UnknownGraph: {graph_name} is not known.")]
381
446
  UnknownGraph
382
447
  {
@@ -390,6 +455,10 @@ pub enum StoreError
390
455
  actual: utils::Version,
391
456
  expected: utils::Version,
392
457
  },
458
+ #[error(
459
+ "MissingVersionMetadata: database has no version metadata; refusing to open an unrecognized or corrupted database file."
460
+ )]
461
+ MissingVersionMetadata,
393
462
  #[error("Invalid database format: {0}.")]
394
463
  InvalidFormat(String),
395
464
  }
@@ -522,37 +591,27 @@ impl<T> From<std::sync::PoisonError<T>> for Error
522
591
  }
523
592
  }
524
593
 
525
- impl From<pest::error::Error<crate::parser::parser_impl::Rule>> for Error
526
- {
527
- fn from(value: pest::error::Error<crate::parser::parser_impl::Rule>) -> Self
528
- {
529
- CompileTimeError::from(Box::new(value)).into()
530
- }
531
- }
532
-
533
- macro_rules! error_as_internal {
534
- ($err_type:ty) => {
594
+ macro_rules! error_as_ {
595
+ ($err_type:ty, $enum_name: ident) => {
535
596
  impl From<$err_type> for crate::prelude::ErrorType
536
597
  {
537
598
  fn from(value: $err_type) -> Self
538
599
  {
539
- let err: crate::error::InternalError = value.into();
600
+ let err: crate::error::$enum_name = value.into();
540
601
  err.into()
541
602
  }
542
603
  }
543
604
  };
544
605
  }
606
+ macro_rules! error_as_internal {
607
+ ($err_type:ty) => {
608
+ error_as_! {$err_type, InternalError}
609
+ };
610
+ }
545
611
 
546
612
  macro_rules! error_as_store {
547
613
  ($err_type:ty) => {
548
- impl From<$err_type> for crate::prelude::ErrorType
549
- {
550
- fn from(value: $err_type) -> Self
551
- {
552
- let err: crate::error::StoreError = value.into();
553
- err.into()
554
- }
555
- }
614
+ error_as_! {$err_type, StoreError}
556
615
  };
557
616
  }
558
617
 
@@ -563,6 +622,7 @@ error_as_internal! {ciborium::de::Error<std::io::Error>}
563
622
  error_as_internal! {serde_json::Error}
564
623
  error_as_internal! {std::num::ParseFloatError}
565
624
  error_as_internal! {std::str::Utf8Error}
625
+ error_as_internal! {std::io::Error}
566
626
 
567
627
  #[cfg(feature = "redb")]
568
628
  mod _trait_impl_redb
@@ -618,6 +678,13 @@ mod _trait_impl_postgres
618
678
  #[cfg(any(feature = "postgres", feature = "sqlite"))]
619
679
  mod _trait_impl_askama
620
680
  {
681
+ impl From<askama::Error> for crate::error::InternalError
682
+ {
683
+ fn from(err: askama::Error) -> Self
684
+ {
685
+ crate::error::InternalError::GenericStdError(Box::new(err))
686
+ }
687
+ }
621
688
  error_as_internal! {askama::Error}
622
689
  }
623
690
 
@@ -628,22 +695,6 @@ pub(crate) fn vec_to_error(errs: &[ErrorType]) -> String
628
695
  errs.join(", ")
629
696
  }
630
697
 
631
- pub(crate) fn parse_int_error_to_compile_error(
632
- text: &str,
633
- e: std::num::ParseIntError,
634
- ) -> crate::prelude::ErrorType
635
- {
636
- use std::num::IntErrorKind;
637
- match e.kind()
638
- {
639
- IntErrorKind::PosOverflow | IntErrorKind::NegOverflow => CompileTimeError::IntegerOverflow {
640
- text: text.to_owned(),
641
- }
642
- .into(),
643
- _ => InternalError::ParseIntError(e).into(),
644
- }
645
- }
646
-
647
698
  /// Convenient macro for mapping errors, for instance, from internal error to runtime error:
648
699
  ///
649
700
  /// ```notest
@@ -675,6 +726,17 @@ impl From<std::convert::Infallible> for Error
675
726
  }
676
727
  }
677
728
 
729
+ #[cfg(feature = "redb")]
730
+ impl From<db_index::hnsw::Error> for Error
731
+ {
732
+ fn from(value: db_index::hnsw::Error) -> Self
733
+ {
734
+ let error_msg = format!("HNSW error: {:?}", value);
735
+ log::error!("{}", error_msg);
736
+ InternalError::Unimplemented("HNSW operation error").into()
737
+ }
738
+ }
739
+
678
740
  // ____ _ _____
679
741
  // / ___| ___ _ __ ___ _ __(_) ___| ____|_ __ _ __ ___ _ __ ___
680
742
  // | | _ / _ \ '_ \ / _ \ '__| |/ __| _| | '__| '__/ _ \| '__/ __|
@@ -13,7 +13,6 @@ impl Size
13
13
  value::Value::String(str) => Ok(str.len() as i64),
14
14
  value::Value::Array(arr) => Ok(arr.len() as i64),
15
15
  value::Value::Map(obj) => Ok(obj.len() as i64),
16
- value::Value::Path(..) => Ok(1.into()),
17
16
  _ => Err(RunTimeError::InvalidArgument {
18
17
  function_name: "size",
19
18
  index: 0,
@@ -24,4 +23,42 @@ impl Size
24
23
  }
25
24
  }
26
25
 
27
- super::declare_function!(size, Size, call_impl(graphcore::Value) -> i64, null_handling(null_returns_null));
26
+ impl super::FunctionTrait for Size
27
+ {
28
+ fn call(&self, mut arguments: Vec<value::Value>) -> crate::Result<value::Value>
29
+ {
30
+ let arg = arguments
31
+ .first()
32
+ .ok_or(RunTimeError::InvalidNumberOfArguments {
33
+ function_name: "size",
34
+ got: arguments.len(),
35
+ expected: 1,
36
+ })?;
37
+ if arg.is_null()
38
+ {
39
+ return Ok(value::Value::Null);
40
+ }
41
+ let val = arguments.remove(0);
42
+ Self::call_impl(val).map(|r| r.into()).map_err(Into::into)
43
+ }
44
+
45
+ fn validate_arguments(
46
+ &self,
47
+ args: Vec<crate::compiler::expression_analyser::ExpressionType>,
48
+ ) -> crate::Result<crate::compiler::expression_analyser::ExpressionType>
49
+ {
50
+ use crate::compiler::expression_analyser::ExpressionType;
51
+ if args.iter().any(|t| matches!(t, ExpressionType::Path))
52
+ {
53
+ return Err(crate::error::CompileTimeError::InvalidArgumentType.into());
54
+ }
55
+ Ok(ExpressionType::Integer)
56
+ }
57
+
58
+ fn is_deterministic(&self) -> bool
59
+ {
60
+ true
61
+ }
62
+ }
63
+
64
+ super::declare_function!(size, Size, custom_trait);
@@ -1,4 +1,4 @@
1
- use rand::Rng;
1
+ use rand::RngExt;
2
2
 
3
3
  use crate::prelude::*;
4
4
 
@@ -48,7 +48,7 @@ impl Rand
48
48
  }
49
49
  }
50
50
 
51
- super::declare_function!(rand, Rand, call_impl() -> Vec<f64>);
51
+ super::declare_function!(rand, Rand, call_impl() -> Vec<f64>, non_deterministic);
52
52
 
53
53
  macro_rules! define_f64_function {
54
54
  ($name: ident, $class_name: ident, $rust_func: ident $(, $arg0: expr)*) => {
@@ -102,10 +102,15 @@ super::declare_function!(atan2, Atan2, call_impl(f64, f64) -> f64);
102
102
  #[cfg(test)]
103
103
  mod test
104
104
  {
105
- use crate::functions::math::Extra as _;
105
+ use crate::functions::math::{Extra as _, Rand};
106
106
  #[test]
107
107
  fn test_cot()
108
108
  {
109
109
  assert_eq!(0.5_f64.cot(), 1.830487721712452);
110
110
  }
111
+ #[test]
112
+ fn test_rand()
113
+ {
114
+ assert!(!Rand::create().1.is_deterministic());
115
+ }
111
116
  }