/
typesystem.rs
92 lines (86 loc) · 2.79 KB
/
typesystem.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use super::errors::SQLiteSourceError;
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use fehler::{throw, throws};
use rusqlite::types::Type;
use std::convert::TryFrom;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SQLiteTypeSystem {
Bool(bool),
Int8(bool),
Int4(bool),
Int2(bool),
Real(bool),
Text(bool),
Date(bool),
Time(bool),
Timestamp(bool),
Blob(bool),
}
impl_typesystem! {
system = SQLiteTypeSystem,
mappings = {
{ Bool => bool }
{ Int8 => i64 }
{ Int4 => i32 }
{ Int2 => i16 }
{ Real => f64 }
{ Text => Box<str> }
{ Date => NaiveDate}
{ Time => NaiveTime}
{ Timestamp => NaiveDateTime}
{ Blob => Vec<u8>}
}
}
impl TryFrom<Type> for SQLiteTypeSystem {
type Error = SQLiteSourceError;
#[throws(SQLiteSourceError)]
fn try_from(ty: Type) -> Self {
use SQLiteTypeSystem::*;
match ty {
Type::Integer => Int8(true),
Type::Real => Real(true),
Type::Text => Text(true),
Type::Blob => Blob(true),
Type::Null => throw!(SQLiteSourceError::InferTypeFromNull),
}
}
}
impl TryFrom<(Option<&str>, Type)> for SQLiteTypeSystem {
type Error = SQLiteSourceError;
#[throws(SQLiteSourceError)]
fn try_from(types: (Option<&str>, Type)) -> Self {
use SQLiteTypeSystem::*;
match types {
// derive from column's declare type, some rules refer to:
// https://www.sqlite.org/datatype3.html#affname
(Some(decl_type), ty) => {
let decl_type = decl_type.to_lowercase();
match decl_type.as_str() {
"int4" => Int4(true),
"int2" => Int2(true),
"boolean" | "bool" => Bool(true),
"date" => Date(true),
"time" => Time(true),
"datetime" | "timestamp" => Timestamp(true),
_ if decl_type.contains("int") => Int8(true),
_ if decl_type.contains("char")
|| decl_type.contains("clob")
|| decl_type.contains("text") =>
{
Text(true)
}
_ if decl_type.contains("real")
|| decl_type.contains("floa")
|| decl_type.contains("doub") =>
{
Real(true)
}
_ if decl_type.contains("blob") => Blob(true),
_ => SQLiteTypeSystem::try_from(ty)?,
}
}
// derive from value type directly if no declare type available
(None, ty) => SQLiteTypeSystem::try_from(ty)?,
}
}
}