taos_query/common/
field.rs

1use std::fmt::{Debug, Display};
2
3use serde::{Deserialize, Serialize};
4
5use crate::util::{Inlinable, InlinableRead, InlinableWrite};
6
7use super::ty::Ty;
8
9#[repr(C)]
10#[derive(Debug, Copy, Clone)]
11#[allow(non_camel_case_types)]
12pub struct c_field_t {
13    pub name: [u8; 65usize],
14    pub type_: u8,
15    pub bytes: i32,
16}
17
18#[test]
19fn test_c_field_t() {
20    let bytes = 1960820204i32;
21    println!("{:0b}", bytes);
22}
23
24/// A `Field` represents the name and data type of one column or tag.
25///
26/// For example, a table as "create table tb1 (ts timestamp, n nchar(100))".
27///
28/// When query with "select * from tb1", you will get two fields:
29///
30/// 1. `{ name: "ts", ty: Timestamp, bytes: 8 }`, a `TIMESTAMP` field with name `ts`,
31///    bytes length 8 which is the byte-width of `i64`.
32/// 2. `{ name: "n", ty: NChar, bytes: 100 }`, a `NCHAR` filed with name `n`,
33///    bytes length 100 which is the length of the variable-length data.
34
35#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
36pub struct Field {
37    pub(crate) name: String,
38    #[serde(rename = "type")]
39    pub(crate) ty: Ty,
40    #[serde(default)]
41    #[serde(rename = "length")]
42    pub(crate) bytes: u32,
43}
44
45// impl From<Field> for c_field_t {
46//     fn from(value: Field) -> Self {
47//         value.into()
48//     }
49// }
50impl From<&Field> for c_field_t {
51    fn from(value: &Field) -> Self {
52        // let name = value.name().into_c_str().into_owned();
53        let name = value.name().as_bytes();
54        let mut field = c_field_t {
55            name: [0; 65],
56            type_: value.ty() as _,
57            bytes: value.bytes() as _,
58        };
59
60        unsafe {
61            std::ptr::copy_nonoverlapping(name.as_ptr(), field.name.as_mut_ptr() as _, name.len());
62        }
63
64        field
65    }
66}
67
68impl Inlinable for Field {
69    fn write_inlined<W: std::io::Write>(&self, wtr: &mut W) -> std::io::Result<usize> {
70        let mut l = wtr.write_u8_le(self.ty as u8)?;
71        l += wtr.write_u32_le(self.bytes)?;
72        l += wtr.write_inlined_str::<2>(&self.name)?;
73        Ok(l)
74    }
75
76    fn read_inlined<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
77        let ty = Ty::from(reader.read_u8()?);
78        let bytes = reader.read_u32()?;
79        let name = reader.read_inlined_str::<2>()?;
80        Ok(Self { name, ty, bytes })
81    }
82}
83
84impl Field {
85    pub const fn empty() -> Self {
86        Self {
87            name: String::new(),
88            ty: Ty::Null,
89            bytes: 0,
90        }
91    }
92    pub fn new(name: impl Into<String>, ty: Ty, bytes: u32) -> Self {
93        let name = name.into();
94        Self { name, ty, bytes }
95    }
96
97    /// Field name.
98    pub fn name(&self) -> &str {
99        &self.name
100    }
101
102    /// Escaped file name
103    pub fn escaped_name(&self) -> String {
104        format!("`{}`", self.name())
105    }
106
107    /// Data type of the field.
108    pub const fn ty(&self) -> Ty {
109        self.ty
110    }
111
112    /// Preset length of variable length data type.
113    ///
114    /// It's the byte-width in other types.
115    pub const fn bytes(&self) -> u32 {
116        self.bytes
117    }
118
119    pub fn to_c_field(&self) -> c_field_t {
120        self.into()
121    }
122
123    /// Represent the data type in sql.
124    ///
125    /// For example: "INT", "VARCHAR(100)".
126    pub fn sql_repr(&self) -> String {
127        let ty = self.ty();
128        if ty.is_var_type() {
129            format!("`{}` {}({})", self.name(), ty.name(), self.bytes())
130        } else {
131            format!("`{}` {}", self.name(), ty.name())
132        }
133    }
134}
135
136impl Display for Field {
137    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138        let ty = self.ty();
139        if ty.is_var_type() {
140            write!(f, "`{}` {}({})", self.name(), ty.name(), self.bytes())
141        } else {
142            write!(f, "`{}` {}", self.name(), ty.name())
143        }
144    }
145}