Skip to main content

persistant_relational/
value.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2use std::fmt;
3
4/// The SQL dialect a backend speaks, which decides how a statement is written.
5#[derive(Debug, Clone, PartialEq, Eq, Hash)]
6#[non_exhaustive]
7pub enum Dialect {
8    /// PostgreSQL (and wire-compatible servers that keep its SQL).
9    Postgres,
10    /// SQLite.
11    Sqlite,
12    /// MySQL.
13    MySql,
14    /// MariaDB.
15    MariaDb,
16    /// Anything else, by name.
17    Other(String),
18}
19
20impl fmt::Display for Dialect {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        match self {
23            Dialect::Postgres => f.write_str("postgres"),
24            Dialect::Sqlite => f.write_str("sqlite"),
25            Dialect::MySql => f.write_str("mysql"),
26            Dialect::MariaDb => f.write_str("mariadb"),
27            Dialect::Other(n) => f.write_str(n),
28        }
29    }
30}
31
32/// A portable parameter or column value. Deliberately narrow: what a key-value or migration
33/// statement needs. A program with richer types uses the driver's own handle.
34#[derive(Debug, Clone, PartialEq)]
35#[non_exhaustive]
36pub enum Value {
37    /// SQL `NULL`.
38    Null,
39    /// Boolean.
40    Bool(bool),
41    /// 64-bit integer (also read from narrower integer columns).
42    Int(i64),
43    /// 64-bit float (also read from single-precision columns).
44    Float(f64),
45    /// Text.
46    Text(String),
47    /// Bytes (`BYTEA`, `BLOB`).
48    Bytes(Vec<u8>),
49}
50
51/// One result row, columns in select order.
52#[derive(Debug, Clone, PartialEq)]
53pub struct Row {
54    /// The column values.
55    pub values: Vec<Value>,
56}
57
58impl Row {
59    /// A row of `values`.
60    pub fn new(values: Vec<Value>) -> Self {
61        Row { values }
62    }
63
64    /// Column `i` as bytes, if it is `Bytes`.
65    pub fn bytes(&self, i: usize) -> Option<&[u8]> {
66        match self.values.get(i) {
67            Some(Value::Bytes(b)) => Some(b),
68            _ => None,
69        }
70    }
71
72    /// Column `i` as an integer, if it is `Int`.
73    pub fn int(&self, i: usize) -> Option<i64> {
74        match self.values.get(i) {
75            Some(Value::Int(n)) => Some(*n),
76            _ => None,
77        }
78    }
79
80    /// Column `i` as text, if it is `Text`.
81    pub fn text(&self, i: usize) -> Option<&str> {
82        match self.values.get(i) {
83            Some(Value::Text(s)) => Some(s),
84            _ => None,
85        }
86    }
87}