rupg_types/value.rs
1//! `Value`, one value of any type in the engine.
2//!
3//! A value does not carry its type. The expression that gives the value has the type OID and the typmod, as a `Datum` of PostgreSQL has no type and the plan node has it. So one variant holds the values of many types: `Text` holds `text`, `name`, `varchar`, `bpchar`, `unknown` and the other types whose value is a string, and `Oid` holds `oid`, `xid`, `cid` and the OID alias types such as `regclass`. [`Datum`](crate::Datum) is the value of the M1 storage, which stores fewer types.
4
5use std::sync::Arc;
6
7use crate::array::Array;
8use crate::datetime::Interval;
9use crate::jsonpath::JsonPath;
10use crate::network::Inet;
11use crate::numeric::Numeric;
12use crate::range::Range;
13use crate::tsquery::QueryItem;
14use crate::tsvector::Lexeme;
15
16/// One value of the engine.
17#[derive(Clone, Debug, PartialEq)]
18pub enum Value {
19 /// SQL NULL.
20 Null,
21 Bool(bool),
22 Int2(i16),
23 Int4(i32),
24 Int8(i64),
25 Float4(f32),
26 Float8(f64),
27 Numeric(Numeric),
28 /// `oid`, `xid`, `cid` and the OID alias types.
29 Oid(u32),
30 /// The type `"char"`. The byte 0 is the empty string.
31 Char(u8),
32 /// The string types, `unknown`, `cstring`, `json` and the other types that the engine keeps as their text form.
33 Text(String),
34 Bytea(Vec<u8>),
35 Uuid([u8; 16]),
36 /// `date`, the days since 1 January 2000.
37 Date(i32),
38 /// `time`, the microseconds since midnight.
39 Time(i64),
40 /// `timetz`, the microseconds since midnight and the zone offset in seconds west of UTC.
41 TimeTz(i64, i32),
42 /// `timestamp`, the microseconds since 1 January 2000.
43 Timestamp(i64),
44 /// `timestamptz`, the microseconds since 1 January 2000 UTC.
45 TimestampTz(i64),
46 Interval(Interval),
47 /// `inet` and `cidr`.
48 Inet(Inet),
49 /// An array, `int2vector` or `oidvector`. A null element is `None`, and no element is `Some(Value::Null)`.
50 Array(Box<Array<Value>>),
51 /// A row of a composite type or of `record`.
52 Record(Box<Record>),
53 /// A value of a range type.
54 Range(Box<Range>),
55 /// A value of a multirange type: the ranges in order, with no empty range and no two ranges that overlap or touch.
56 Multirange(Vec<Range>),
57 /// A value of `tsvector`: the lexemes in order.
58 TsVector(Vec<Lexeme>),
59 /// A value of `tsquery`: the operands and operators in prefix order, or no items for a query with no lexemes.
60 TsQuery(Vec<QueryItem>),
61 /// A value of `jsonpath`.
62 JsonPath(Box<JsonPath>),
63}
64
65/// The value of a composite type or of `record`, as a `HeapTupleHeader` datum. As that datum keeps the type of the row, a record keeps the type of each field, so that the output of an anonymous `record` can show the fields.
66#[derive(Clone, Debug)]
67pub struct Record {
68 /// The type of each field.
69 pub types: Vec<u32>,
70 /// The value of each field, with `Null` for a null field.
71 pub values: Vec<Value>,
72 /// The names of the fields of an anonymous `record`, as the row descriptor that `BlessTupleDesc` keeps for the typmod of the value. `None` when the type of the value gives the names, or when the fields are `f1`, `f2` and so on.
73 pub names: Option<Arc<[String]>>,
74}
75
76impl Record {
77 /// A record with no names for its fields.
78 pub fn new(types: Vec<u32>, values: Vec<Value>) -> Record {
79 Record { types, values, names: None }
80 }
81}
82
83/// Two records are equal when their fields are equal. The names of the fields are not part of the value.
84impl PartialEq for Record {
85 fn eq(&self, other: &Record) -> bool {
86 self.types == other.types && self.values == other.values
87 }
88}
89
90impl Value {
91 /// True for `Null`.
92 pub fn is_null(&self) -> bool {
93 matches!(self, Value::Null)
94 }
95
96 /// The value of a `bool`, or `None` for `Null`.
97 pub fn as_bool(&self) -> Option<bool> {
98 match self {
99 Value::Bool(v) => Some(*v),
100 _ => None,
101 }
102 }
103
104 /// The string of a value of a string type, or `None` for `Null`.
105 pub fn as_str(&self) -> Option<&str> {
106 match self {
107 Value::Text(v) => Some(v),
108 _ => None,
109 }
110 }
111
112 /// The value of an integer type as an `i64`, or `None` for `Null` and for the other types.
113 pub fn as_i64(&self) -> Option<i64> {
114 match self {
115 Value::Int2(v) => Some(i64::from(*v)),
116 Value::Int4(v) => Some(i64::from(*v)),
117 Value::Int8(v) => Some(*v),
118 _ => None,
119 }
120 }
121
122 /// The value of `oid` or of an OID alias type, or `None` for `Null`.
123 pub fn as_oid(&self) -> Option<u32> {
124 match self {
125 Value::Oid(v) => Some(*v),
126 _ => None,
127 }
128 }
129
130 /// A text value.
131 pub fn text(s: impl Into<String>) -> Value {
132 Value::Text(s.into())
133 }
134}