Skip to content

Commit

Permalink
refactor: expose ColumnType to quaint::ResultSet
Browse files Browse the repository at this point in the history
  • Loading branch information
Weakky committed Jul 19, 2024
1 parent 15f8fe4 commit 72064aa
Show file tree
Hide file tree
Showing 41 changed files with 1,536 additions and 901 deletions.
15 changes: 13 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion quaint/.envrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export TEST_MYSQL="mysql://root:prisma@localhost:3306/prisma"
export TEST_MYSQL8="mysql://root:prisma@localhost:3307/prisma"
export TEST_MYSQL_MARIADB="mysql://root:prisma@localhost:3308/prisma"
export TEST_PSQL="postgres://postgres:prisma@localhost:5432/postgres"
export TEST_PSQL="postgresql://postgres:prisma@localhost:5432/postgres"
export TEST_CRDB="postgresql://[email protected]:26259/postgres"
export TEST_MSSQL="jdbc:sqlserver://localhost:1433;database=master;user=SA;password=<YourStrong@Passw0rd>;trustServerCertificate=true"
if command -v nix-shell &> /dev/null
Expand Down
7 changes: 4 additions & 3 deletions quaint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ serde = { version = "1.0" }
sqlformat = { version = "0.2.3", optional = true }
uuid.workspace = true
crosstarget-utils = { path = "../libs/crosstarget-utils" }
concat-idents = "1.1.5"

[dev-dependencies]
once_cell = "1.3"
Expand Down Expand Up @@ -125,12 +126,12 @@ features = ["chrono", "column_decltype"]
optional = true

[target.'cfg(not(any(target_os = "macos", target_os = "ios")))'.dependencies.tiberius]
version = "0.11.6"
version = "0.11.8"
optional = true
features = ["sql-browser-tokio", "chrono", "bigdecimal"]

[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.tiberius]
version = "0.11.2"
[dependencies.tiberius]
version = "0.11.8"
optional = true
default-features = false
features = [
Expand Down
2 changes: 2 additions & 0 deletions quaint/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! implement the [Queryable](trait.Queryable.html) trait for generalized
//! querying interface.

mod column_type;
mod connection_info;

pub mod external;
Expand All @@ -24,6 +25,7 @@ mod transaction;
mod type_identifier;

pub use self::result_set::*;
pub use column_type::*;
pub use connection_info::*;

#[cfg(native)]
Expand Down
172 changes: 172 additions & 0 deletions quaint/src/connector/column_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
use crate::ValueType;

use super::TypeIdentifier;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColumnType {
Int32,
Int64,
Float,
Double,
Text,
Bytes,
Boolean,
Char,
Numeric,
Json,
Xml,
Uuid,
DateTime,
Date,
Time,
Enum,

Int32Array,
Int64Array,
FloatArray,
DoubleArray,
TextArray,
CharArray,
BytesArray,
BooleanArray,
NumericArray,
JsonArray,
XmlArray,
UuidArray,
DateTimeArray,
DateArray,
TimeArray,

Null,

Unknown,
}

impl ColumnType {
pub fn is_unknown(&self) -> bool {
matches!(self, ColumnType::Unknown)
}
}

impl std::fmt::Display for ColumnType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ColumnType::Int32 => write!(f, "int"),
ColumnType::Int64 => write!(f, "bigint"),
ColumnType::Float => write!(f, "float"),
ColumnType::Double => write!(f, "double"),
ColumnType::Text => write!(f, "string"),
ColumnType::Enum => write!(f, "enum"),
ColumnType::Bytes => write!(f, "bytes"),
ColumnType::Boolean => write!(f, "bool"),
ColumnType::Char => write!(f, "char"),
ColumnType::Numeric => write!(f, "decimal"),
ColumnType::Json => write!(f, "json"),
ColumnType::Xml => write!(f, "xml"),
ColumnType::Uuid => write!(f, "uuid"),
ColumnType::DateTime => write!(f, "datetime"),
ColumnType::Date => write!(f, "date"),
ColumnType::Time => write!(f, "time"),
ColumnType::Int32Array => write!(f, "int-array"),
ColumnType::Int64Array => write!(f, "bigint-array"),
ColumnType::FloatArray => write!(f, "float-array"),
ColumnType::DoubleArray => write!(f, "double-array"),
ColumnType::TextArray => write!(f, "string-array"),
ColumnType::BytesArray => write!(f, "bytes-array"),
ColumnType::BooleanArray => write!(f, "bool-array"),
ColumnType::CharArray => write!(f, "char-array"),
ColumnType::NumericArray => write!(f, "decimal-array"),
ColumnType::JsonArray => write!(f, "json-array"),
ColumnType::XmlArray => write!(f, "xml-array"),
ColumnType::UuidArray => write!(f, "uuid-array"),
ColumnType::DateTimeArray => write!(f, "datetime-array"),
ColumnType::DateArray => write!(f, "date-array"),
ColumnType::TimeArray => write!(f, "time-array"),
ColumnType::Null => write!(f, "null"),

ColumnType::Unknown => write!(f, "unknown"),
}
}
}

impl From<&ValueType<'_>> for ColumnType {
fn from(value: &ValueType) -> Self {
match value {
ValueType::Int32(_) => ColumnType::Int32,
ValueType::Int64(_) => ColumnType::Int64,
ValueType::Float(_) => ColumnType::Float,
ValueType::Double(_) => ColumnType::Double,
ValueType::Text(_) => ColumnType::Text,
ValueType::Enum(_, _) => ColumnType::Enum,
ValueType::EnumArray(_, _) => ColumnType::TextArray,
ValueType::Bytes(_) => ColumnType::Bytes,
ValueType::Boolean(_) => ColumnType::Boolean,
ValueType::Char(_) => ColumnType::Char,
ValueType::Numeric(_) => ColumnType::Numeric,
ValueType::Json(_) => ColumnType::Json,
ValueType::Xml(_) => ColumnType::Xml,
ValueType::Uuid(_) => ColumnType::Uuid,
ValueType::DateTime(_) => ColumnType::DateTime,
ValueType::Date(_) => ColumnType::Date,
ValueType::Time(_) => ColumnType::Time,
ValueType::Array(Some(vals)) if !vals.is_empty() => match &vals[0].typed {
ValueType::Int32(_) => ColumnType::Int32Array,
ValueType::Int64(_) => ColumnType::Int64Array,
ValueType::Float(_) => ColumnType::FloatArray,
ValueType::Double(_) => ColumnType::DoubleArray,
ValueType::Text(_) => ColumnType::TextArray,
ValueType::Enum(_, _) => ColumnType::TextArray,
ValueType::Bytes(_) => ColumnType::BytesArray,
ValueType::Boolean(_) => ColumnType::BooleanArray,
ValueType::Char(_) => ColumnType::CharArray,
ValueType::Numeric(_) => ColumnType::NumericArray,
ValueType::Json(_) => ColumnType::JsonArray,
ValueType::Xml(_) => ColumnType::TextArray,
ValueType::Uuid(_) => ColumnType::UuidArray,
ValueType::DateTime(_) => ColumnType::DateTimeArray,
ValueType::Date(_) => ColumnType::DateArray,
ValueType::Time(_) => ColumnType::TimeArray,
ValueType::Array(_) => ColumnType::Unknown,
ValueType::EnumArray(_, _) => ColumnType::Unknown,
},
ValueType::Array(_) => ColumnType::Unknown,
}
}
}

impl ColumnType {
pub(crate) fn from_type_identifier<T>(value: T) -> Self
where
T: TypeIdentifier,
{
if value.is_bool() {
ColumnType::Boolean
} else if value.is_bytes() {
ColumnType::Bytes
} else if value.is_date() {
ColumnType::Date
} else if value.is_datetime() {
ColumnType::DateTime
} else if value.is_time() {
ColumnType::Time
} else if value.is_double() {
ColumnType::Double
} else if value.is_float() {
ColumnType::Float
} else if value.is_int32() {
ColumnType::Int32
} else if value.is_int64() {
ColumnType::Int64
} else if value.is_enum() {
ColumnType::Enum
} else if value.is_json() {
ColumnType::Json
} else if value.is_real() {
ColumnType::Numeric
} else if value.is_text() {
ColumnType::Text
} else {
ColumnType::Unknown
}
}
}
2 changes: 2 additions & 0 deletions quaint/src/connector/mssql.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Wasm-compatible definitions for the MSSQL connector.
//! This module is only available with the `mssql` feature.
mod column_type;

pub(crate) mod url;

pub use self::url::*;
Expand Down
42 changes: 42 additions & 0 deletions quaint/src/connector/mssql/column_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::connector::ColumnType;
use tiberius::{Column, ColumnType as MssqlColumnType};

impl From<&Column> for ColumnType {
fn from(value: &Column) -> Self {
match value.column_type() {
MssqlColumnType::Null => ColumnType::Null,

MssqlColumnType::BigVarChar
| MssqlColumnType::BigChar
| MssqlColumnType::NVarchar
| MssqlColumnType::NChar
| MssqlColumnType::Text
| MssqlColumnType::NText => ColumnType::Text,
MssqlColumnType::Xml => ColumnType::Text,

MssqlColumnType::Bit | MssqlColumnType::Bitn => ColumnType::Boolean,
MssqlColumnType::Int1 | MssqlColumnType::Int2 | MssqlColumnType::Int4 => ColumnType::Int32,
MssqlColumnType::Int8 | MssqlColumnType::Intn => ColumnType::Int64,

MssqlColumnType::Datetime2
| MssqlColumnType::Datetime4
| MssqlColumnType::Datetime
| MssqlColumnType::Datetimen
| MssqlColumnType::DatetimeOffsetn => ColumnType::DateTime,

MssqlColumnType::Float4 => ColumnType::Float,
MssqlColumnType::Float8 | MssqlColumnType::Money | MssqlColumnType::Money4 | MssqlColumnType::Floatn => {
ColumnType::Double
}
MssqlColumnType::Guid => ColumnType::Uuid,
MssqlColumnType::Decimaln | MssqlColumnType::Numericn => ColumnType::Numeric,
MssqlColumnType::Daten => ColumnType::Date,
MssqlColumnType::Timen => ColumnType::Time,
MssqlColumnType::BigVarBin | MssqlColumnType::BigBinary | MssqlColumnType::Image => ColumnType::Bytes,

MssqlColumnType::Udt | MssqlColumnType::SSVariant => {
unreachable!("UDT and SSVariant types are not supported by Tiberius.")
}
}
}
}
3 changes: 1 addition & 2 deletions quaint/src/connector/mssql/native/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use crate::ast::{Value, ValueType};
use bigdecimal::BigDecimal;
use std::{borrow::Cow, convert::TryFrom};

use tiberius::ToSql;
use tiberius::{ColumnData, FromSql, IntoSql};
use tiberius::{ColumnData, FromSql, IntoSql, ToSql};

impl<'a> IntoSql<'a> for &'a Value<'a> {
fn into_sql(self) -> ColumnData<'a> {
Expand Down
16 changes: 13 additions & 3 deletions quaint/src/connector/mssql/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::connector::{timeout, IsolationLevel, Transaction, TransactionOptions}

use crate::{
ast::{Query, Value},
connector::{metrics, queryable::*, DefaultTransaction, ResultSet},
connector::{metrics, queryable::*, ColumnType as QuaintColumnType, DefaultTransaction, ResultSet},
visitor::{self, Visitor},
};
use async_trait::async_trait;
Expand Down Expand Up @@ -144,6 +144,10 @@ impl Queryable for Mssql {
Some(rows) => {
let mut columns_set = false;
let mut columns = Vec::new();

let mut types_set = false;
let mut types = Vec::new();

let mut result_rows = Vec::with_capacity(rows.len());

for row in rows.into_iter() {
Expand All @@ -152,6 +156,12 @@ impl Queryable for Mssql {
columns_set = true;
}

if !types_set {
dbg!(&row.columns());
types = row.columns().iter().map(QuaintColumnType::from).collect();
types_set = true;
}

let mut values: Vec<Value<'_>> = Vec::with_capacity(row.len());

for val in row.into_iter() {
Expand All @@ -161,9 +171,9 @@ impl Queryable for Mssql {
result_rows.push(values);
}

Ok(ResultSet::new(columns, result_rows))
Ok(ResultSet::new(columns, types, result_rows))
}
None => Ok(ResultSet::new(Vec::new(), Vec::new())),
None => Ok(ResultSet::new(Vec::new(), Vec::new(), Vec::new())),
}
})
.await
Expand Down
2 changes: 2 additions & 0 deletions quaint/src/connector/mysql.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Wasm-compatible definitions for the MySQL connector.
//! This module is only available with the `mysql` feature.
mod column_type;
mod defaults;

pub(crate) mod error;
pub(crate) mod url;

Expand Down
8 changes: 8 additions & 0 deletions quaint/src/connector/mysql/column_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::connector::ColumnType;
use mysql_async::Column;

impl From<&Column> for ColumnType {
fn from(value: &Column) -> Self {
ColumnType::from_type_identifier(value)
}
}
Loading

0 comments on commit 72064aa

Please sign in to comment.