pub struct Capabilities {
pub max_sql_len: usize,
pub max_statements: usize,
pub udf: bool,
pub interactive_transactions: bool,
pub int64_as_text: bool,
pub max_compound_select: usize,
pub compound_recursive_cte: bool,
pub vectors: bool,
pub vector_index_methods: bool,
pub name: String,
pub versioning: Versioning,
}Expand description
What a backend can do. The compiler adapts SQL generation to it.
Fields§
§max_sql_len: usizeMaximum length of one SQL statement in bytes (D1: 100 KB).
max_statements: usizeMaximum number of statements in one request.
udf: boolThe oxilite_* user-defined functions (regex, replace, hashes, Unicode case) exist.
interactive_transactions: boolThe backend supports interactive (read-then-write) transactions.
int64_as_text: bool64-bit integers must be returned as TEXT (JavaScript numbers lose precision above 2^53).
max_compound_select: usizeMaximum number of terms in one compound SELECT (UNION ALL chain); D1 allows 5.
compound_recursive_cte: boolA recursive CTE may have a compound recursive term (SQLite 3.34.0, 2020-12-01). A backend whose version cannot be established MUST leave this false: mutual recursion then takes a strategy that does not need it, instead of emitting SQL that would fail.
vectors: boolVector types and distance functions (vector32, vector_distance_cos…; Turso): vector
indexes can be built and searched (see crate::vector).
vector_index_methods: boolIndex methods (CREATE INDEX … USING method; Turso): sparse vector indexes get an
inverted-file index.
name: StringName of the backend, for explain().
versioning: VersioningThe versioning level of the store (set by the store at open, not by the backend):
from stamped on, writers record the current tick in quads.t.
Implementations§
Source§impl Capabilities
impl Capabilities
Sourcepub fn native() -> Self
pub fn native() -> Self
A native SQLite linked in-process.
Examples found in repository?
62pub fn dump(root: &Path) -> Vec<String> {
63 let backends = [
64 ("native", Capabilities::native()),
65 ("d1", Capabilities::d1()),
66 ];
67 let mut paths = Vec::new();
68 for sub in ["sparql10", "sparql11", "sparql12"] {
69 files(&root.join(sub), &mut paths);
70 }
71 paths.sort();
72 let mut out = Vec::new();
73 let options = QueryOptions::default();
74 let stats = Stats::default();
75 for p in &paths {
76 let Ok(text) = std::fs::read_to_string(p) else {
77 continue;
78 };
79 // How `\u` escapes parse depends on spargebra's `standard-unicode-escaping` feature, which
80 // workspace builds enable (for the W3C runner): leave those files out, so the rendering
81 // depends on the compiler alone.
82 if text.contains("\\u") || text.contains("\\U") {
83 continue;
84 }
85 let rel = p.strip_prefix(root).unwrap().display().to_string();
86 let parser = || {
87 SparqlParser::new()
88 .with_base_iri("http://example.com/base/")
89 .unwrap()
90 };
91 let is_update = p.extension().and_then(|x| x.to_str()) == Some("ru");
92 for (name, caps) in &backends {
93 let render = || -> Option<String> {
94 Some(if is_update {
95 match plan_update(&parser().parse_update(&text).ok()?, caps) {
96 Ok(plan) => explain_plan(&plan),
97 Err(e) => format!("ERR {e}"),
98 }
99 } else {
100 match compile_query(&parser().parse_query(&text).ok()?, &stats, caps, &options)
101 {
102 Ok(c) => c.explain(),
103 Err(e) => format!("ERR {e}"),
104 }
105 })
106 };
107 let Some(first) = render() else { continue };
108 // Updates creating fresh blank nodes embed random ids: record that they vary.
109 let h = if render().map(|r| hash(&r)) == Some(hash(&first)) {
110 hash(&first)
111 } else {
112 "varies".to_owned()
113 };
114 out.push(format!("{rel}\t{name}\t{h}"));
115 }
116 }
117 // The batch writer: inserts and deletes of a fixed set of quads.
118 let ex = |s: String| oxrdf::NamedNode::new_unchecked(format!("http://example.com/{s}"));
119 let quads: Vec<oxrdf::Quad> = (0..700)
120 .map(|i| {
121 oxrdf::Quad::new(
122 ex(format!("s{i}")),
123 ex(format!("p{}", i % 7)),
124 oxrdf::Literal::new_simple_literal(format!("value {i}")),
125 if i % 3 == 0 {
126 oxrdf::GraphName::DefaultGraph
127 } else {
128 ex(format!("g{}", i % 5)).into()
129 },
130 )
131 })
132 .collect();
133 let enc = EncodedQuads::new(quads.iter().map(oxrdf::Quad::as_ref));
134 for (name, caps) in &backends {
135 let ins: Vec<String> = enc
136 .insert_statements(caps)
137 .into_iter()
138 .map(|s| s.sql)
139 .collect();
140 let del: Vec<String> = enc
141 .delete_statements(caps)
142 .into_iter()
143 .map(|s| s.sql)
144 .collect();
145 out.push(format!("writer/insert\t{name}\t{}", hash(&ins.join("\n"))));
146 out.push(format!("writer/delete\t{name}\t{}", hash(&del.join("\n"))));
147 }
148 out
149}Sourcepub fn d1() -> Self
pub fn d1() -> Self
Cloudflare D1 limits.
Examples found in repository?
62pub fn dump(root: &Path) -> Vec<String> {
63 let backends = [
64 ("native", Capabilities::native()),
65 ("d1", Capabilities::d1()),
66 ];
67 let mut paths = Vec::new();
68 for sub in ["sparql10", "sparql11", "sparql12"] {
69 files(&root.join(sub), &mut paths);
70 }
71 paths.sort();
72 let mut out = Vec::new();
73 let options = QueryOptions::default();
74 let stats = Stats::default();
75 for p in &paths {
76 let Ok(text) = std::fs::read_to_string(p) else {
77 continue;
78 };
79 // How `\u` escapes parse depends on spargebra's `standard-unicode-escaping` feature, which
80 // workspace builds enable (for the W3C runner): leave those files out, so the rendering
81 // depends on the compiler alone.
82 if text.contains("\\u") || text.contains("\\U") {
83 continue;
84 }
85 let rel = p.strip_prefix(root).unwrap().display().to_string();
86 let parser = || {
87 SparqlParser::new()
88 .with_base_iri("http://example.com/base/")
89 .unwrap()
90 };
91 let is_update = p.extension().and_then(|x| x.to_str()) == Some("ru");
92 for (name, caps) in &backends {
93 let render = || -> Option<String> {
94 Some(if is_update {
95 match plan_update(&parser().parse_update(&text).ok()?, caps) {
96 Ok(plan) => explain_plan(&plan),
97 Err(e) => format!("ERR {e}"),
98 }
99 } else {
100 match compile_query(&parser().parse_query(&text).ok()?, &stats, caps, &options)
101 {
102 Ok(c) => c.explain(),
103 Err(e) => format!("ERR {e}"),
104 }
105 })
106 };
107 let Some(first) = render() else { continue };
108 // Updates creating fresh blank nodes embed random ids: record that they vary.
109 let h = if render().map(|r| hash(&r)) == Some(hash(&first)) {
110 hash(&first)
111 } else {
112 "varies".to_owned()
113 };
114 out.push(format!("{rel}\t{name}\t{h}"));
115 }
116 }
117 // The batch writer: inserts and deletes of a fixed set of quads.
118 let ex = |s: String| oxrdf::NamedNode::new_unchecked(format!("http://example.com/{s}"));
119 let quads: Vec<oxrdf::Quad> = (0..700)
120 .map(|i| {
121 oxrdf::Quad::new(
122 ex(format!("s{i}")),
123 ex(format!("p{}", i % 7)),
124 oxrdf::Literal::new_simple_literal(format!("value {i}")),
125 if i % 3 == 0 {
126 oxrdf::GraphName::DefaultGraph
127 } else {
128 ex(format!("g{}", i % 5)).into()
129 },
130 )
131 })
132 .collect();
133 let enc = EncodedQuads::new(quads.iter().map(oxrdf::Quad::as_ref));
134 for (name, caps) in &backends {
135 let ins: Vec<String> = enc
136 .insert_statements(caps)
137 .into_iter()
138 .map(|s| s.sql)
139 .collect();
140 let del: Vec<String> = enc
141 .delete_statements(caps)
142 .into_iter()
143 .map(|s| s.sql)
144 .collect();
145 out.push(format!("writer/insert\t{name}\t{}", hash(&ins.join("\n"))));
146 out.push(format!("writer/delete\t{name}\t{}", hash(&del.join("\n"))));
147 }
148 out
149}