Skip to main content

toolu_orm_core/fts5/
options.rs

1//! FTS5 module options and their rendering into `key = 'value'` arguments.
2
3/// The `fts5(...)` settings that follow the column list.
4///
5/// `tokenize` is a free string: it holds a whole tokenizer chain
6/// (`porter unicode61 remove_diacritics 2`) and may name a tokenizer the
7/// application registered itself, so there is no closed set to validate
8/// against.
9#[derive(Debug, Clone, Default, PartialEq, Eq)]
10pub struct Fts5Options {
11  pub prefix: Option<String>,
12  pub tokenize: Option<String>,
13  pub content: Option<String>,
14  pub content_rowid: Option<String>,
15  pub columnsize: Option<u8>,
16  pub detail: Option<String>,
17}
18
19impl Fts5Options {
20  /// Rendered in a fixed order, so the same schema always produces the same
21  /// argument list and an unchanged schema never looks changed to the diff.
22  #[must_use]
23  pub fn render(&self) -> Vec<String> {
24    let mut args = Vec::new();
25    push_text(&mut args, "prefix", self.prefix.as_deref());
26    push_text(&mut args, "tokenize", self.tokenize.as_deref());
27    push_text(&mut args, "content", self.content.as_deref());
28    push_text(&mut args, "content_rowid", self.content_rowid.as_deref());
29    if let Some(columnsize) = self.columnsize {
30      args.push(format!("columnsize = {columnsize}"));
31    }
32    push_text(&mut args, "detail", self.detail.as_deref());
33    args
34  }
35}
36
37fn push_text(args: &mut Vec<String>, key: &str, value: Option<&str>) {
38  if let Some(value) = value {
39    args.push(format!("{key} = '{}'", escape_literal(value)));
40  }
41}
42
43/// SQL string-literal escaping: an embedded single quote doubles.
44fn escape_literal(value: &str) -> String {
45  value.replace('\'', "''")
46}