#![allow(non_snake_case)]
use crate::{
DynamicDecimal, SqlDecimal, SqlString, Weight,
array::Array,
binary::{ByteArray, to_hex_},
byte_index,
error::{SqlResult, SqlRuntimeError, r2o},
geopoint::*,
interval::*,
map::Map,
source::SourceMap,
timestamp::*,
uuid::*,
variant::*,
};
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use dbsp::algebra::{F32, F64, HasOne, HasZero};
use num::{One, Zero};
use num_traits::{CheckedDiv, cast::NumCast};
use regex::{Captures, Regex};
use smallstr::SmallString;
use std::{
error::Error,
fmt::Display,
fmt::Write,
iter::once,
marker::PhantomData,
ops::{Div, Mul},
str::FromStr,
sync::LazyLock,
};
trait ToSmallString: Display {
fn to_small_string<const N: usize>(&self) -> SmallString<[u8; N]>;
}
impl<T> ToSmallString for T
where
T: Display,
{
fn to_small_string<const N: usize>(&self) -> SmallString<[u8; N]> {
let mut output = SmallString::new();
write!(&mut output, "{}", self).unwrap();
output
}
}
#[doc(hidden)]
pub(crate) fn type_name(name: &'static str) -> &'static str {
match name {
"b" => "BOOLEAN",
"bytes" => "(VAR)BINARY",
"i8" => "TINYINT",
"i16" => "SMALLINT",
"i32" => "INTEGER",
"i64" => "BIGINT",
"i128" => "BIGINT",
"u8" => "TINYINT UNSIGNED",
"u16" => "SMALLINT UNSIGNED",
"u32" => "INTEGER UNSIGNED",
"u64" => "BIGINT UNSIGNED",
"u128" => "BIGINT UNSIGNED",
"f" => "REAL",
"d" => "FLOAT",
"Timestamp" => "TIMESTAMP",
"TimestampTz" => "TIMESTAMP WITH TIME ZONE",
"Date" => "DATE",
"Time" => "TIME",
"SqlDecimal" => "DECIMAL",
"ShortInterval" => "INTERVAL",
"LongInterval" => "INTERVAL",
"s" => "(VAR)CHAR",
"V" => "VARIANT",
"Uuid" => "UUID",
_ => "Unexpected type",
}
}
#[doc(hidden)]
pub(crate) fn rust_type_name(name: &'static str) -> &'static str {
match name {
"b" => "BOOLEAN",
"bytes" => "(VAR)BINARY",
"i8" => "TINYINT",
"i16" => "SMALLINT",
"i32" => "INTEGER",
"i64" => "BIGINT",
"i128" => "BIGINT",
"u8" => "TINYINT UNSIGNED",
"u16" => "SMALLINT UNSIGNED",
"u32" => "INTEGER UNSIGNED",
"u64" => "BIGINT UNSIGNED",
"u128" => "BIGINT UNSIGNED",
"F32" => "REAL",
"F64" => "FLOAT",
"Timestamp" => "TIMESTAMP",
"TimestampTz" => "TIMESTAMP WITH TIME ZONE",
"Date" => "DATE",
"Time" => "TIME",
"SqlDecimal" => "DECIMAL",
"ShortInterval" => "INTERVAL",
"LongInterval" => "INTERVAL",
"String" => "(VAR)CHAR",
"Variant" => "VARIANT",
"Uuid" => "UUID",
_ => "Unexpected type",
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! tn {
($result_name: ident) => {
type_name(stringify!($result_name))
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! ttn {
($result_type: ty) => {
rust_type_name(stringify!($result_type))
};
}
#[doc(hidden)]
macro_rules! cn {
($result_name: ident) => {
cast_null(tn!($result_name))
};
}
#[doc(hidden)]
pub fn handle_error<T>(value: SqlResult<T>) -> T {
match value {
Err(ce) => panic!("{}", *ce),
Ok(v) => v,
}
}
#[doc(hidden)]
pub fn handle_error_with_position<T>(
operator_hash: &'static str,
id: u32,
map: &'static SourceMap,
value: SqlResult<T>,
) -> T {
match value {
Err(ce) => match map.getPosition(operator_hash, id) {
None => panic!("{}", *ce),
Some(position) => panic!("{}: {}", position, *ce),
},
Ok(v) => v,
}
}
#[doc(hidden)]
pub fn handle_error_safe<T>(value: SqlResult<Option<T>>) -> Option<T> {
value.unwrap_or_default()
}
pub(crate) fn cast_null(t: &str) -> Box<SqlRuntimeError> {
SqlRuntimeError::from_string(format!("cast of NULL value to non-null type {}", t))
}
macro_rules! cast_function {
($result_name: ident $(< $( const $var:ident : $ty: ty),* >)?, $result_type: ty, $type_name: ident, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_ $result_name N_ $type_name>] $(< $( const $var : $ty),* >)? ( value: $arg_type ) -> SqlResult<Option<$result_type>> {
r2o([<cast_to_ $result_name _ $type_name>] $(:: < $($var),* >)? (value))
}
#[doc(hidden)]
pub fn [<cast_to_ $result_name _ $type_name N >] $(< $( const $var : $ty),* >)? ( value: Option<$arg_type> ) -> SqlResult<$result_type> {
match value {
None => Err(cn!($type_name)),
Some(value) => [<cast_to_ $result_name _ $type_name>] $(:: < $($var),* >)? (value),
}
}
#[doc(hidden)]
pub fn [<cast_to_ $result_name N_ $type_name N >] $(< $( const $var : $ty),* >)? ( value: Option<$arg_type> ) -> SqlResult<Option<$result_type>> {
match value {
None => Ok(None),
Some(v) => r2o([<cast_to_ $result_name _ $type_name >] $(:: < $($var),* >)? (v)),
}
}
}
};
}
macro_rules! cast_to_b {
($type_name: ident $(< $( const $var: ident : $ty: ty),* >)?, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_b_ $type_name>] $(< $( const $var : $ty ),* >)? ( value: $arg_type ) -> SqlResult<bool> {
Ok(value != <$arg_type as num::Zero>::zero())
}
#[doc(hidden)]
pub fn [<cast_to_b_ $type_name N >] $(< $( const $var : $ty ),* >)? ( value: Option<$arg_type> ) -> SqlResult<bool> {
match value {
None => Err(cast_null("bool")),
Some(value) => [<cast_to_b_ $type_name>] $(:: < $( $var ),* >)? (value),
}
}
#[doc(hidden)]
pub fn [<cast_to_bN_ $type_name >] $(< $( const $var : $ty ),* >)? ( value: $arg_type ) -> SqlResult<Option<bool>> {
r2o([< cast_to_b_ $type_name >] $(:: < $( $var ),* >)? (value))
}
#[doc(hidden)]
pub fn [<cast_to_bN_ $type_name N >] $(< $( const $var : $ty ),* >)? ( value: Option<$arg_type> ) -> SqlResult<Option<bool>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_bN_ $type_name >] $(:: < $( $var ),* >)? (value),
}
}
}
};
}
macro_rules! cast_to_b_fp {
($type_name: ident, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_b_ $type_name>]( value: $arg_type ) -> SqlResult<bool> {
Ok(value != $arg_type::zero())
}
#[doc(hidden)]
pub fn [<cast_to_b_ $type_name N >]( value: Option<$arg_type> ) -> SqlResult<bool> {
match value {
None => Err(cast_null("bool")),
Some(value) => [<cast_to_b_ $type_name>](value),
}
}
#[doc(hidden)]
pub fn [<cast_to_bN_ $type_name >]( value: $arg_type ) -> SqlResult<Option<bool>> {
r2o([< cast_to_b_ $type_name >](value))
}
#[doc(hidden)]
pub fn [<cast_to_bN_ $type_name N >]( value: Option<$arg_type> ) -> SqlResult<Option<bool>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_bN_ $type_name >](value),
}
}
}
};
}
#[doc(hidden)]
#[inline]
pub fn cast_to_b_b(value: bool) -> SqlResult<bool> {
Ok(value)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_b_bN(value: Option<bool>) -> SqlResult<bool> {
match value {
None => Err(cast_null("bool")),
Some(value) => Ok(value),
}
}
cast_to_b!(SqlDecimal<const P: usize, const S: usize>, SqlDecimal<P, S>);
cast_to_b_fp!(d, F64);
cast_to_b_fp!(f, F32);
cast_to_b!(i8, i8);
cast_to_b!(i16, i16);
cast_to_b!(i32, i32);
cast_to_b!(i64, i64);
cast_to_b!(u8, u8);
cast_to_b!(u16, u16);
cast_to_b!(u32, u32);
cast_to_b!(u64, u64);
cast_to_b!(i, isize);
cast_to_b!(u, usize);
#[doc(hidden)]
pub fn cast_to_b_s(value: SqlString) -> SqlResult<bool> {
match value.str().to_lowercase().trim() {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(SqlRuntimeError::from_string(format!(
"Cannot convert string '{value}' to BOOLEAN",
))),
}
}
#[doc(hidden)]
pub fn cast_to_b_sN(value: Option<SqlString>) -> SqlResult<bool> {
match value {
None => Err(cast_null("bool")),
Some(value) => cast_to_b_s(value),
}
}
#[doc(hidden)]
pub fn cast_to_bN_sN(value: Option<SqlString>) -> SqlResult<Option<bool>> {
match value {
None => Ok(None),
Some(value) => r2o(cast_to_b_s(value)),
}
}
#[doc(hidden)]
pub fn cast_to_bN_s(value: SqlString) -> SqlResult<Option<bool>> {
r2o(cast_to_b_s(value))
}
#[doc(hidden)]
#[inline]
pub fn cast_to_bN_nullN(_value: Option<()>) -> SqlResult<Option<bool>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_bN_b(value: bool) -> SqlResult<Option<bool>> {
Ok(Some(value))
}
#[doc(hidden)]
#[inline]
pub fn cast_to_bN_bN(value: Option<bool>) -> SqlResult<Option<bool>> {
Ok(value)
}
#[doc(hidden)]
pub fn cast_to_Date_s(value: SqlString) -> SqlResult<Date> {
match NaiveDate::parse_from_str(value.str(), "%Y-%m-%d") {
Ok(value) => Ok(Date::from_days(
(value.and_hms_opt(0, 0, 0).unwrap().and_utc().timestamp() / 86400) as i32,
)),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to DATE: {}",
e
))),
}
}
cast_function!(Date, Date, s, SqlString);
#[doc(hidden)]
pub fn cast_to_Date_Timestamp(value: Timestamp) -> SqlResult<Date> {
Ok(value.get_date())
}
cast_function!(Date, Date, Timestamp, Timestamp);
#[doc(hidden)]
pub fn cast_to_Date_TimestampTz(value: TimestampTz) -> SqlResult<Date> {
cast_to_Date_Timestamp(value.into())
}
cast_function!(Date, Date, TimestampTz, TimestampTz);
#[doc(hidden)]
#[inline]
pub fn cast_to_DateN_nullN(_value: Option<()>) -> SqlResult<Option<Date>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_Date_Date(value: Date) -> SqlResult<Date> {
Ok(value)
}
cast_function!(Date, Date, Date, Date);
#[doc(hidden)]
pub fn cast_to_Time_s(value: SqlString) -> SqlResult<Time> {
match NaiveTime::parse_from_str(value.str(), "%H:%M:%S%.f") {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIME: {}",
e
))),
Ok(value) => Ok(Time::from_time(value)),
}
}
cast_function!(Time, Time, s, SqlString);
#[doc(hidden)]
#[inline]
pub fn cast_to_TimeN_nullN(_value: Option<()>) -> SqlResult<Option<Time>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_Time_Time(value: Time) -> SqlResult<Time> {
Ok(value)
}
cast_function!(Time, Time, Time, Time);
#[doc(hidden)]
pub fn cast_to_Time_Timestamp(value: Timestamp) -> SqlResult<Time> {
Ok(Time::from_time(value.to_dateTime().time()))
}
cast_function!(Time, Time, Timestamp, Timestamp);
#[doc(hidden)]
pub fn cast_to_Time_TimestampTz(value: TimestampTz) -> SqlResult<Time> {
Ok(Time::from_time(value.to_dateTime().time()))
}
cast_function!(Time, Time, TimestampTz, TimestampTz);
#[doc(hidden)]
pub fn cast_to_SqlDecimal_b<const P: usize, const S: usize>(
value: bool,
) -> SqlResult<SqlDecimal<P, S>> {
if value {
Ok(<SqlDecimal<P, S> as One>::one())
} else {
Ok(<SqlDecimal<P, S> as Zero>::zero())
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_bN<const P: usize, const S: usize>(
value: Option<bool>,
) -> SqlResult<SqlDecimal<P, S>> {
match value {
None => Err(cast_null("DECIMAL")),
Some(value) => cast_to_SqlDecimal_b::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_SqlDecimal<
const P0: usize,
const S0: usize,
const P1: usize,
const S1: usize,
>(
value: SqlDecimal<P1, S1>,
) -> SqlResult<SqlDecimal<P0, S0>> {
let result = value.convert();
match result {
None => Err(SqlRuntimeError::from_string(format!(
"Cannot represent {value} as DECIMAL({P0}, {S0}): precision of DECIMAL type too small to represent value"
))),
Some(value) => Ok(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_SqlDecimalN<
const P0: usize,
const S0: usize,
const P1: usize,
const S1: usize,
>(
value: Option<SqlDecimal<P1, S1>>,
) -> SqlResult<SqlDecimal<P0, S0>> {
match value {
None => Err(cast_null("DECIMAL")),
Some(value) => cast_to_SqlDecimal_SqlDecimal::<P0, S0, P1, S1>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_d<const P: usize, const S: usize>(
value: F64,
) -> SqlResult<SqlDecimal<P, S>> {
match SqlDecimal::<P, S>::try_from(value.into_inner()) {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to DECIMAL({P}, {S}): {}",
e
))),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_dN<const P: usize, const S: usize>(
value: Option<F64>,
) -> SqlResult<SqlDecimal<P, S>> {
match value {
None => Err(cast_null("DECIMAL")),
Some(value) => cast_to_SqlDecimal_d::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_f<const P: usize, const S: usize>(
value: F32,
) -> SqlResult<SqlDecimal<P, S>> {
match SqlDecimal::<P, S>::try_from(value.into_inner() as f64) {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to DECIMAL({P}, {S}): {}",
e
))),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_fN<const P: usize, const S: usize>(
value: Option<F32>,
) -> SqlResult<SqlDecimal<P, S>> {
match value {
None => Err(cast_null("DECIMAL")),
Some(value) => cast_to_SqlDecimal_f::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_s<const P: usize, const S: usize>(
value: SqlString,
) -> SqlResult<SqlDecimal<P, S>> {
let str = value.str().trim();
match str.parse() {
Err(_) => Err(SqlRuntimeError::from_string(format!(
"While converting '{}' to DECIMAL: parse error",
value
))),
Ok(result) => Ok(result),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_sN<const P: usize, const S: usize>(
value: Option<SqlString>,
) -> SqlResult<SqlDecimal<P, S>> {
match value {
None => Ok(<SqlDecimal<P, S> as num_traits::Zero>::zero()),
Some(value) => cast_to_SqlDecimal_s::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_V<const P: usize, const S: usize>(
value: Variant,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
Variant::String(x) => r2o(cast_to_SqlDecimal_s::<P, S>(x)),
Variant::TinyInt(i) => r2o(cast_to_SqlDecimal_i8::<P, S>(i)),
Variant::SmallInt(i) => r2o(cast_to_SqlDecimal_i16::<P, S>(i)),
Variant::Int(i) => r2o(cast_to_SqlDecimal_i32::<P, S>(i)),
Variant::BigInt(i) => r2o(cast_to_SqlDecimal_i64::<P, S>(i)),
Variant::UTinyInt(i) => r2o(cast_to_SqlDecimal_u8::<P, S>(i)),
Variant::USmallInt(i) => r2o(cast_to_SqlDecimal_u16::<P, S>(i)),
Variant::UInt(i) => r2o(cast_to_SqlDecimal_u32::<P, S>(i)),
Variant::UBigInt(i) => r2o(cast_to_SqlDecimal_u64::<P, S>(i)),
Variant::Real(f) => r2o(cast_to_SqlDecimal_f::<P, S>(f)),
Variant::Double(f) => r2o(cast_to_SqlDecimal_d::<P, S>(f)),
Variant::SqlDecimal(d) => {
let dd = DynamicDecimal::new(d.0, d.1);
match SqlDecimal::<P, S>::try_from(dd) {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error while converting 'VARIANT({:?})' to DECIMAL({P}, {S}): {}",
value, e
))),
Ok(value) => Ok(Some(value)),
}
}
_ => Ok(None),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_VN<const P: usize, const S: usize>(
value: Option<Variant>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_V::<P, S>(value),
}
}
macro_rules! cast_to_sqldecimal {
($type_name: ident, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_SqlDecimal_ $type_name> ]<const P: usize, const S: usize>( value: $arg_type ) -> SqlResult<SqlDecimal<P, S>> {
match SqlDecimal::<P, S>::try_from(value) {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(
format!("Error converting {value} to DECIMAL({P}, {S}): {}", e.to_string())
)),
}
}
#[doc(hidden)]
pub fn [<cast_to_SqlDecimal_ $type_name N> ]<const P: usize, const S: usize>( value: Option<$arg_type> ) -> SqlResult<SqlDecimal<P, S>> {
match value {
None => Err(cast_null("DECIMAL")),
Some(value) => [<cast_to_SqlDecimal_ $type_name >]::<P, S>(value),
}
}
#[doc(hidden)]
pub fn [<cast_to_SqlDecimalN_ $type_name> ]<const P: usize, const S: usize>( value: $arg_type ) -> SqlResult<Option<SqlDecimal<P, S>>> {
r2o([< cast_to_SqlDecimal_ $type_name >]::<P, S>(value))
}
#[doc(hidden)]
pub fn [<cast_to_SqlDecimalN_ $type_name N> ]<const P: usize, const S: usize>( value: Option<$arg_type> ) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_SqlDecimalN_ $type_name >]::<P, S>(value),
}
}
}
}
}
cast_to_sqldecimal!(i, isize);
cast_to_sqldecimal!(i8, i8);
cast_to_sqldecimal!(i16, i16);
cast_to_sqldecimal!(i32, i32);
cast_to_sqldecimal!(i64, i64);
cast_to_sqldecimal!(u8, u8);
cast_to_sqldecimal!(u16, u16);
cast_to_sqldecimal!(u32, u32);
cast_to_sqldecimal!(u64, u64);
cast_to_sqldecimal!(u, usize);
#[doc(hidden)]
#[inline]
pub fn cast_to_SqlDecimalN_nullN<const P: usize, const S: usize>(
_value: Option<()>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_SqlDecimalN_b<const P: usize, const S: usize>(
value: bool,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
r2o(cast_to_SqlDecimal_b::<P, S>(value))
}
#[doc(hidden)]
#[inline]
pub fn cast_to_SqlDecimalN_bN<const P: usize, const S: usize>(
value: Option<bool>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_b::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_SqlDecimal<
const P0: usize,
const S0: usize,
const P1: usize,
const S1: usize,
>(
value: SqlDecimal<P1, S1>,
) -> SqlResult<Option<SqlDecimal<P0, S0>>> {
r2o(cast_to_SqlDecimal_SqlDecimal::<P0, S0, P1, S1>(value))
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_SqlDecimalN<
const P0: usize,
const S0: usize,
const P1: usize,
const S1: usize,
>(
value: Option<SqlDecimal<P1, S1>>,
) -> SqlResult<Option<SqlDecimal<P0, S0>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_SqlDecimal::<P0, S0, P1, S1>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_d<const P: usize, const S: usize>(
value: F64,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
r2o(cast_to_SqlDecimal_d::<P, S>(value))
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_dN<const P: usize, const S: usize>(
value: Option<F64>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_d::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_f<const P: usize, const S: usize>(
value: F32,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
r2o(cast_to_SqlDecimal_f::<P, S>(value))
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_fN<const P: usize, const S: usize>(
value: Option<F32>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_f::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_s<const P: usize, const S: usize>(
value: SqlString,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match SqlDecimal::<P, S>::from_str(value.str()) {
Ok(value) => Ok(Some(value)),
Err(_) => Err(SqlRuntimeError::from_string(format!(
"Cannot parse {} into a DECIMAL({P}, {S})",
value.str(),
))),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_sN<const P: usize, const S: usize>(
value: Option<SqlString>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_s::<P, S>(value),
}
}
macro_rules! cast_to_fp {
($type_name: ident, $arg_type: ty,
$result_type_name: ident, $result_type: ty, $result_base_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_ $result_type_name _ $type_name >]( value: $arg_type ) -> SqlResult<$result_type> {
let result: Option<$result_base_type> = NumCast::from(value);
match result {
None => Err(SqlRuntimeError::from_string(format!("Cannot convert {value} to {}", tn!($result_type)))),
Some(value) => Ok($result_type::from(value)),
}
}
#[doc(hidden)]
pub fn [<cast_to_ $result_type_name _ $type_name N >]( value: Option<$arg_type> ) -> SqlResult<$result_type> {
match value {
None => Err(cn!($result_type)),
Some(value) => {
let result: Option<$result_base_type> = NumCast::from(value);
match result {
None => Err(SqlRuntimeError::from_string(format!("Cannot convert {value} to {}", tn!($result_type)))),
Some(value) => Ok($result_type::from(value)),
}
}
}
}
#[doc(hidden)]
pub fn [<cast_to_ $result_type_name N_ $type_name >]( value: $arg_type ) -> SqlResult<Option<$result_type>> {
r2o([<cast_to_ $result_type_name _ $type_name >](value))
}
#[doc(hidden)]
pub fn [<cast_to_ $result_type_name N_ $type_name N >]( value: Option<$arg_type> ) -> SqlResult<Option<$result_type>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_ $result_type_name N_ $type_name >](value),
}
}
}
}
}
macro_rules! cast_to_fps {
($type_name: ident, $arg_type: ty) => {
cast_to_fp!($type_name, $arg_type, d, F64, f64);
cast_to_fp!($type_name, $arg_type, f, F32, f32);
};
}
#[doc(hidden)]
#[inline]
pub fn cast_to_d_b(value: bool) -> SqlResult<F64> {
if value {
Ok(F64::one())
} else {
Ok(F64::zero())
}
}
cast_function!(d, F64, b, bool);
#[doc(hidden)]
pub fn cast_to_d_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<F64> {
Ok(F64::from(
<f64 as std::convert::From<SqlDecimal<P, S>>>::from(value),
))
}
cast_function!(d <const P: usize, const S: usize>, F64, SqlDecimal, SqlDecimal<P, S>);
#[doc(hidden)]
#[inline]
pub fn cast_to_d_d(value: F64) -> SqlResult<F64> {
Ok(value)
}
cast_function!(d, F64, d, F64);
#[doc(hidden)]
#[inline]
pub fn cast_to_d_f(value: F32) -> SqlResult<F64> {
Ok(F64::from(value.into_inner()))
}
cast_function!(d, F64, f, F32);
#[doc(hidden)]
pub fn cast_to_d_s(value: SqlString) -> SqlResult<F64> {
match value.str().trim().parse::<f64>() {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Parse error during conversion of '{value}' to DOUBLE: {}",
e
))),
Ok(x) => Ok(F64::from(x)),
}
}
cast_function!(d, F64, s, SqlString);
#[doc(hidden)]
#[inline]
pub fn cast_to_dN_nullN(_value: Option<()>) -> SqlResult<Option<F64>> {
Ok(None)
}
cast_to_fps!(i, isize);
cast_to_fps!(i8, i8);
cast_to_fps!(i16, i16);
cast_to_fps!(i32, i32);
cast_to_fps!(i64, i64);
cast_to_fps!(i128, i128);
cast_to_fps!(u8, u8);
cast_to_fps!(u16, u16);
cast_to_fps!(u32, u32);
cast_to_fps!(u64, u64);
cast_to_fps!(u128, u128);
cast_to_fps!(u, usize);
#[doc(hidden)]
#[inline]
pub fn cast_to_f_b(value: bool) -> SqlResult<F32> {
if value {
Ok(F32::one())
} else {
Ok(F32::zero())
}
}
cast_function!(f, F32, b, bool);
#[doc(hidden)]
pub fn cast_to_f_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<F32> {
Ok(F32::from(
<f64 as std::convert::From<SqlDecimal<P, S>>>::from(value) as f32,
))
}
cast_function!(f <const P: usize, const S: usize>, F32, SqlDecimal, SqlDecimal<P, S>);
#[doc(hidden)]
pub fn cast_to_f_d(value: F64) -> SqlResult<F32> {
Ok(F32::from(value.into_inner() as f32))
}
cast_function!(f, F32, d, F64);
#[doc(hidden)]
#[inline]
pub fn cast_to_f_f(value: F32) -> SqlResult<F32> {
Ok(value)
}
cast_function!(f, F32, f, F32);
#[doc(hidden)]
pub fn cast_to_f_s(value: SqlString) -> SqlResult<F32> {
match value.str().trim().parse::<f32>() {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Parse error during conversion of '{value}' to REAL: {}",
e
))),
Ok(x) => Ok(F32::from(x)),
}
}
cast_function!(f, F32, s, SqlString);
#[doc(hidden)]
#[inline]
pub fn cast_to_fN_nullN(_value: Option<()>) -> SqlResult<Option<F32>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_geopoint_geopoint(value: GeoPoint) -> SqlResult<GeoPoint> {
Ok(value)
}
cast_function!(geopoint, GeoPoint, geopoint, GeoPoint);
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CharacterCount {
Exact(usize),
Limit(usize),
}
impl CharacterCount {
fn new(n_chars: i32, fixed: bool) -> Option<Self> {
let n_chars: Option<usize> = n_chars.try_into().ok();
if fixed {
Some(Self::Exact(n_chars.unwrap()))
} else {
n_chars.map(Self::Limit)
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
struct SizedStringSpec<'a> {
head: &'a str,
n_spaces: usize,
}
impl<'a> SizedStringSpec<'a> {
pub fn for_character_count(value: &str, n_chars: i32, fixed: bool) -> SizedStringSpec<'_> {
match CharacterCount::new(n_chars, fixed) {
None => SizedStringSpec::new(value),
Some(CharacterCount::Exact(n_chars)) => {
let mut char_count = 0;
for (byte_index, _) in value.char_indices() {
char_count += 1;
if char_count > n_chars {
return SizedStringSpec::new(&value[..byte_index]);
}
}
SizedStringSpec::new(value).with_spaces(n_chars - char_count)
}
Some(CharacterCount::Limit(max)) => {
if value.len() <= max {
SizedStringSpec::new(value)
} else {
SizedStringSpec::new(&value[..byte_index(value, max)])
}
}
}
}
pub fn into_sql_string(self) -> SqlString {
match self.n_spaces {
0 => SqlString::from_ref(self.head),
n => SqlString::from_concat_iterator(once(self.head).chain(Spaces::new(n))),
}
}
fn new(head: &'a str) -> Self {
Self { head, n_spaces: 0 }
}
fn with_spaces(self, n_spaces: usize) -> Self {
Self { n_spaces, ..self }
}
}
#[derive(Clone)]
struct Spaces<'a> {
n: usize,
_phantom: PhantomData<&'a ()>,
}
impl<'a> Spaces<'a> {
fn new(n: usize) -> Self {
Self {
n,
_phantom: PhantomData,
}
}
}
impl<'a> Iterator for Spaces<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item> {
static SPACES: &str = " ";
let chunk = self.n.min(SPACES.len());
if chunk > 0 {
self.n -= chunk;
Some(&SPACES[..chunk])
} else {
None
}
}
}
#[inline(always)]
#[doc(hidden)]
pub fn limit_or_size_string(value: &str, n_chars: i32, fixed: bool) -> SqlResult<SqlString> {
Ok(SizedStringSpec::for_character_count(value, n_chars, fixed).into_sql_string())
}
macro_rules! cast_to_string {
($type_name: ident $(< $( const $var:ident : $ty: ty),* >)?, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_s_ $type_name N >] $(< $( const $var : $ty ),* >)? ( value: Option<$arg_type>, size: i32, fixed: bool ) -> SqlResult<SqlString> {
match value {
None => Err(cast_null("VARCHAR")),
Some(value) => [<cast_to_s_ $type_name>] $(:: < $($var),* >)? (value, size, fixed),
}
}
#[doc(hidden)]
pub fn [<cast_to_sN_ $type_name >] $(< $( const $var : $ty ),* >)? ( value: $arg_type, size: i32, fixed: bool ) -> SqlResult<Option<SqlString>> {
r2o([< cast_to_s_ $type_name >] $(:: < $($var),* >)? (value, size, fixed))
}
#[doc(hidden)]
pub fn [<cast_to_sN_ $type_name N >] $(< $( const $var : $ty ),* >)? ( value: Option<$arg_type>, size: i32, fixed: bool ) -> SqlResult<Option<SqlString>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_sN_ $type_name >] $(:: < $($var),* >)? (value, size, fixed),
}
}
}
};
}
#[doc(hidden)]
#[inline]
pub fn cast_to_s_b(value: bool, size: i32, fixed: bool) -> SqlResult<SqlString> {
if !fixed && !(0..=4).contains(&size) {
if value {
Ok(arcstr::literal!("TRUE").into())
} else {
Ok(arcstr::literal!("FALSE").into())
}
} else {
let result = if value { "TRUE" } else { "FALSE" };
limit_or_size_string(result, size, fixed)
}
}
#[doc(hidden)]
pub fn cast_to_s_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let result = value.to_small_string::<64>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_d(value: F64, size: i32, fixed: bool) -> SqlResult<SqlString> {
let v = value.into_inner();
cast_to_s_fp(v, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_fp<T>(v: T, size: i32, fixed: bool) -> SqlResult<SqlString>
where
T: num::Float + ryu::Float,
{
let mut buffer = ryu::Buffer::new();
let result = buffer.format(v);
limit_or_size_string(result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_f(value: F32, size: i32, fixed: bool) -> SqlResult<SqlString> {
let v = value.into_inner();
cast_to_s_fp(v, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_s(value: SqlString, n_chars: i32, fixed: bool) -> SqlResult<SqlString> {
let spec = SizedStringSpec::for_character_count(value.str(), n_chars, fixed);
if spec.head.len() == value.len() && spec.n_spaces == 0 {
Ok(value)
} else {
Ok(spec.into_sql_string())
}
}
#[doc(hidden)]
pub fn cast_to_s_Timestamp(value: Timestamp, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_string();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_TimestampTz(value: TimestampTz, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_string();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_Date(value: Date, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_string();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_Time(value: Time, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_string();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_i(value: isize, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_i8(value: i8, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<8>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_i16(value: i16, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<8>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_i32(value: i32, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<16>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_i64(value: i64, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_u(value: usize, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_u8(value: u8, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<8>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_u16(value: u16, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<8>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_u32(value: u32, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<16>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_u64(value: u64, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_V(value: Variant, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result: SqlString = value.try_into().unwrap();
limit_or_size_string(result.str(), size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_VN(value: Option<Variant>, size: i32, fixed: bool) -> SqlResult<SqlString> {
cast_to_s_V(value.unwrap(), size, fixed)
}
#[doc(hidden)]
pub fn cast_to_sN_V(value: Variant, size: i32, fixed: bool) -> SqlResult<Option<SqlString>> {
let result: Result<SqlString, _> = value.try_into();
match result {
Err(_) => Ok(None),
Ok(result) => r2o(limit_or_size_string(result.str(), size, fixed)),
}
}
#[doc(hidden)]
pub fn cast_to_sN_VN(
value: Option<Variant>,
size: i32,
fixed: bool,
) -> SqlResult<Option<SqlString>> {
match value {
None => Ok(None),
Some(value) => cast_to_sN_V(value, size, fixed),
}
}
#[doc(hidden)]
pub fn cast_to_bytes_V(value: Variant, size: i32, fixed: bool) -> SqlResult<ByteArray> {
let result: Result<ByteArray, _> = value.try_into();
match result {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting VARIANT to BINARY: {}",
e
))),
Ok(result) => Ok(ByteArray::with_size(result.as_slice(), size, fixed)),
}
}
#[doc(hidden)]
pub fn cast_to_bytes_VN(value: Option<Variant>, size: i32, fixed: bool) -> SqlResult<ByteArray> {
match value {
None => Err(cast_null("BINARY")),
Some(value) => cast_to_bytes_V(value, size, fixed),
}
}
#[doc(hidden)]
pub fn cast_to_bytesN_V(value: Variant, size: i32, fixed: bool) -> SqlResult<Option<ByteArray>> {
let result: Result<ByteArray, _> = value.try_into();
match result {
Err(_) => Ok(None),
Ok(value) => Ok(Some(ByteArray::with_size(value.as_slice(), size, fixed))),
}
}
#[doc(hidden)]
pub fn cast_to_bytesN_VN(
value: Option<Variant>,
size: i32,
fixed: bool,
) -> SqlResult<Option<ByteArray>> {
match value {
None => Ok(None),
Some(value) => cast_to_bytesN_V(value, size, fixed),
}
}
#[doc(hidden)]
pub fn cast_to_s_LongInterval_YEARS(
interval: LongInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let mut result = SmallString::<[u8; 16]>::new();
write!(&mut result, "{:+}", interval.years()).unwrap();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub(crate) const fn sign(negative: bool) -> &'static str {
if negative { "-" } else { "+" }
}
#[doc(hidden)]
pub fn cast_to_s_LongInterval_MONTHS(
interval: LongInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let result = format_args!("{:+}", interval.months()).to_small_string::<16>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_LongInterval_YEARS_TO_MONTHS(
interval: LongInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let months = interval.months();
let sign = sign(months < 0);
let years = months.unsigned_abs() / 12;
let months = months.unsigned_abs() % 12;
let result = format_args!("{sign}{years}-{months:02}").to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
impl ShortInterval {
#[doc(hidden)]
pub(crate) fn into_sign_and_magnitude(self) -> (&'static str, Self) {
if self.microseconds() < 0 {
("-", Self::from_microseconds(-self.microseconds()))
} else {
("+", self)
}
}
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_DAYS(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let days = extract_day_ShortInterval(interval);
let result = format_args!("{sign}{days}").to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_HOURS(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let days = extract_day_ShortInterval(interval);
let hours = extract_hour_ShortInterval(interval);
let result = format_args!("{sign}{}", 24 * days + hours).to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_DAYS_TO_HOURS(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let days = extract_day_ShortInterval(interval);
let hours = extract_hour_ShortInterval(interval);
let result = format_args!("{sign}{} {:02}", days, hours).to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_MINUTES(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let minutes = interval.microseconds() / 60_000_000;
let result = format_args!("{minutes:+}").to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_DAYS_TO_MINUTES(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let days = extract_day_ShortInterval(interval);
let hours = extract_hour_ShortInterval(interval);
let minutes = extract_minute_ShortInterval(interval);
let result = format_args!("{sign}{} {:02}:{:02}", days, hours, minutes).to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_HOURS_TO_MINUTES(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let days = extract_day_ShortInterval(interval);
let hours = extract_hour_ShortInterval(interval);
let minutes = extract_minute_ShortInterval(interval);
let result = format_args!("{sign}{}:{:02}", days * 24 + hours, minutes).to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_SECONDS(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let seconds = interval.microseconds() / 1_000_000;
let micros = interval.microseconds() % 1_000_000;
let result = format_args!("{sign}{seconds}.{:06}", micros).to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_DAYS_TO_SECONDS(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let result = interval.to_string();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_HOURS_TO_SECONDS(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let days = extract_day_ShortInterval(interval);
let hours = extract_hour_ShortInterval(interval);
let minutes = extract_minute_ShortInterval(interval);
let seconds = extract_second_ShortInterval(interval);
let micros = interval.microseconds() % 1_000_000;
let result = format_args!(
"{sign}{}:{:02}:{:02}.{:06}",
days * 24 + hours,
minutes,
seconds,
micros
)
.to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_ShortInterval_MINUTES_TO_SECONDS(
interval: ShortInterval,
size: i32,
fixed: bool,
) -> SqlResult<SqlString> {
let (sign, interval) = interval.into_sign_and_magnitude();
let days = extract_day_ShortInterval(interval);
let hours = extract_hour_ShortInterval(interval);
let minutes = extract_minute_ShortInterval(interval);
let seconds = extract_second_ShortInterval(interval);
let micros = interval.microseconds() % 1_000_000;
let result = format_args!(
"{sign}{:02}:{:02}.{:06}",
(days * 24 + hours) * 60 + minutes,
seconds,
micros
)
.to_small_string::<32>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_Uuid(value: Uuid, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = value.to_small_string::<40>();
limit_or_size_string(&result, size, fixed)
}
#[doc(hidden)]
pub fn cast_to_s_bytes(value: ByteArray, size: i32, fixed: bool) -> SqlResult<SqlString> {
let result = to_hex_(value);
limit_or_size_string(result.str(), size, fixed)
}
cast_to_string!(b, bool);
cast_to_string!(SqlDecimal<const P: usize, const S: usize>, SqlDecimal<P, S>);
cast_to_string!(f, F32);
cast_to_string!(d, F64);
cast_to_string!(s, SqlString);
cast_to_string!(i, isize);
cast_to_string!(u, usize);
cast_to_string!(i8, i8);
cast_to_string!(i16, i16);
cast_to_string!(i32, i32);
cast_to_string!(i64, i64);
cast_to_string!(u8, u8);
cast_to_string!(u16, u16);
cast_to_string!(u32, u32);
cast_to_string!(u64, u64);
cast_to_string!(Timestamp, Timestamp);
cast_to_string!(TimestampTz, TimestampTz);
cast_to_string!(Time, Time);
cast_to_string!(Date, Date);
cast_to_string!(bytes, ByteArray);
cast_to_string!(LongInterval_MONTHS, LongInterval);
cast_to_string!(LongInterval_YEARS, LongInterval);
cast_to_string!(LongInterval_YEARS_TO_MONTHS, LongInterval);
cast_to_string!(ShortInterval_DAYS, ShortInterval);
cast_to_string!(ShortInterval_HOURS, ShortInterval);
cast_to_string!(ShortInterval_DAYS_TO_HOURS, ShortInterval);
cast_to_string!(ShortInterval_MINUTES, ShortInterval);
cast_to_string!(ShortInterval_DAYS_TO_MINUTES, ShortInterval);
cast_to_string!(ShortInterval_HOURS_TO_MINUTES, ShortInterval);
cast_to_string!(ShortInterval_SECONDS, ShortInterval);
cast_to_string!(ShortInterval_DAYS_TO_SECONDS, ShortInterval);
cast_to_string!(ShortInterval_HOURS_TO_SECONDS, ShortInterval);
cast_to_string!(ShortInterval_MINUTES_TO_SECONDS, ShortInterval);
cast_to_string!(Uuid, Uuid);
#[doc(hidden)]
#[inline]
pub fn cast_to_sN_nullN(
_value: Option<()>,
_size: i32,
_fixed: bool,
) -> SqlResult<Option<SqlString>> {
Ok(None)
}
macro_rules! cast_to_i_i {
($result_type: ty, $arg_type_name: ident, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
#[inline]
pub fn [<cast_to_ $result_type _ $arg_type_name>]( value: $arg_type ) -> SqlResult<$result_type> {
match $result_type::try_from(value) {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(
format!("Error converting {value} to {}: {}", tn!($result_type), e)
)),
}
}
#[doc(hidden)]
#[inline]
pub fn [<cast_to_ $result_type _ $arg_type_name N>]( value: Option<$arg_type> ) -> SqlResult<$result_type> {
match value {
None => Err(cn!($result_type)),
Some(value) => [< cast_to_ $result_type _ $arg_type_name >](value),
}
}
#[doc(hidden)]
#[inline]
pub fn [<cast_to_ $result_type N_ $arg_type_name >]( value: $arg_type ) -> SqlResult<Option<$result_type>> {
r2o([< cast_to_ $result_type _ $arg_type_name >](value))
}
#[doc(hidden)]
#[inline]
pub fn [<cast_to_ $result_type N_ $arg_type_name N>]( value: Option<$arg_type> ) -> SqlResult<Option<$result_type>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_ $result_type N_ $arg_type_name >](value),
}
}
}
}
}
macro_rules! cast_to_i {
($result_type: ty) => {
::paste::paste! {
#[doc(hidden)]
#[inline]
pub fn [< cast_to_ $result_type _nullN >](_value: Option<()>) -> SqlResult<$result_type> {
Err(SqlRuntimeError::from_string(
format!("Casting NULL value to {}", tn!($result_type))
))
}
#[doc(hidden)]
#[inline]
pub fn [< cast_to_ $result_type N_nullN >](_value: Option<()>) -> SqlResult<Option<$result_type>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn [<cast_to_ $result_type _ b >]( value: bool ) -> SqlResult<$result_type> {
Ok(if value { 1 } else { 0 })
}
cast_function!($result_type, $result_type, b, bool);
#[doc(hidden)]
pub fn [< cast_to_ $result_type _SqlDecimal >]<const P: usize, const S: usize>(value: SqlDecimal<P, S>) -> SqlResult<$result_type> {
match value.try_into() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting DECIMAL({P},{S}) {value} to {}: {}",
tn!($result_type), e
))),
}
}
cast_function!($result_type <const P: usize, const S: usize>, $result_type, SqlDecimal, SqlDecimal<P, S>);
#[doc(hidden)]
pub fn [< cast_to_ $result_type _d >](value: F64) -> SqlResult<$result_type> {
let value = value.into_inner().trunc();
match <$result_type as NumCast>::from(value) {
Some(value) => Ok(value),
None => Err(SqlRuntimeError::from_string(
format!("Cannot convert {value} to {}", tn!($result_type))
)),
}
}
cast_function!($result_type, $result_type, d, F64);
#[doc(hidden)]
pub fn [< cast_to_ $result_type _f >](value: F32) -> SqlResult<$result_type> {
let value = value.into_inner().trunc();
match <$result_type as NumCast>::from(value) {
Some(value) => Ok(value),
None => Err(SqlRuntimeError::from_string(
format!("Cannot convert {value} to {}", tn!($result_type))
)),
}
}
cast_function!($result_type, $result_type, f, F32);
#[doc(hidden)]
pub fn [< cast_to_ $result_type _s >](value: SqlString) -> SqlResult<$result_type> {
match value.str().trim().parse::<$result_type>() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(
format!("Error converting '{value}' to {}: {}", tn!($result_type), e)
)),
}
}
cast_function!($result_type, $result_type, s, SqlString);
cast_to_i_i!($result_type, i8, i8);
cast_to_i_i!($result_type, i16, i16);
cast_to_i_i!($result_type, i32, i32);
cast_to_i_i!($result_type, i64, i64);
cast_to_i_i!($result_type, i128, i128);
cast_to_i_i!($result_type, u8, u8);
cast_to_i_i!($result_type, u16, u16);
cast_to_i_i!($result_type, u32, u32);
cast_to_i_i!($result_type, u64, u64);
cast_to_i_i!($result_type, u128, u128);
cast_to_i_i!($result_type, i, isize);
cast_to_i_i!($result_type, u, usize);
}
}
}
cast_to_i!(i8);
cast_to_i!(i16);
cast_to_i!(i32);
cast_to_i!(i64);
cast_to_i!(i128);
cast_to_i!(u8);
cast_to_i!(u16);
cast_to_i!(u32);
cast_to_i!(u64);
cast_to_i!(u128);
#[doc(hidden)]
#[inline]
#[allow(clippy::unnecessary_cast)]
pub fn cast_to_i64_Weight(w: Weight) -> SqlResult<i64> {
Ok(w as i64)
}
macro_rules! cast_interval_to_integer {
($result_type: ty, $type_name: ident, $arg_type: ty, $intermediate_type: ty, $method: ident) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_ $result_type _ $type_name >](value: $arg_type) -> SqlResult<$result_type> {
[< cast_to_ $result_type _ $intermediate_type >]( value. $method() )
}
cast_function!($result_type, $result_type, $type_name, $arg_type);
}
}
}
cast_interval_to_integer!(i8, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(i16, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(i32, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(i64, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(u8, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(u16, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(u32, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(u64, LongInterval_YEARS, LongInterval, i32, years);
cast_interval_to_integer!(i8, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(i16, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(i32, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(i64, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(u8, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(u16, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(u32, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(u64, LongInterval_MONTHS, LongInterval, i32, months);
cast_interval_to_integer!(i8, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(i16, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(i32, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(i64, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(u8, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(u16, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(u32, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(u64, ShortInterval_SECONDS, ShortInterval, i64, seconds);
cast_interval_to_integer!(i8, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(i16, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(i32, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(i64, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(u8, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(u16, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(u32, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(u64, ShortInterval_MINUTES, ShortInterval, i64, minutes);
cast_interval_to_integer!(i8, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(i16, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(i32, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(i64, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(u8, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(u16, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(u32, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(u64, ShortInterval_HOURS, ShortInterval, i64, hours);
cast_interval_to_integer!(i8, ShortInterval_DAYS, ShortInterval, i64, days);
cast_interval_to_integer!(i16, ShortInterval_DAYS, ShortInterval, i64, days);
cast_interval_to_integer!(i32, ShortInterval_DAYS, ShortInterval, i64, days);
cast_interval_to_integer!(i64, ShortInterval_DAYS, ShortInterval, i64, days);
cast_interval_to_integer!(u8, ShortInterval_DAYS, ShortInterval, i64, days);
cast_interval_to_integer!(u16, ShortInterval_DAYS, ShortInterval, i64, days);
cast_interval_to_integer!(u32, ShortInterval_DAYS, ShortInterval, i64, days);
cast_interval_to_integer!(u64, ShortInterval_DAYS, ShortInterval, i64, days);
#[doc(hidden)]
pub fn cast_to_SqlDecimal_LongInterval_YEARS<const P: usize, const S: usize>(
value: LongInterval,
) -> SqlResult<SqlDecimal<P, S>> {
cast_to_SqlDecimal_i32::<P, S>(value.years())
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_LongInterval_MONTHS<const P: usize, const S: usize>(
value: LongInterval,
) -> SqlResult<SqlDecimal<P, S>> {
cast_to_SqlDecimal_i32::<P, S>(value.months())
}
cast_function!(SqlDecimal <const P: usize, const S: usize>, SqlDecimal<P, S>, LongInterval_YEARS, LongInterval);
cast_function!(SqlDecimal <const P: usize, const S: usize>, SqlDecimal<P, S>, LongInterval_MONTHS, LongInterval);
fn convert_to_SqlDecimal_ShortInterval<const P: usize, const S: usize>(
value: ShortInterval,
divider: i64,
) -> SqlResult<SqlDecimal<P, S>> {
let v = DynamicDecimal::from(value.microseconds());
let num = DynamicDecimal::from(divider);
let div = match v.checked_div(&num) {
None => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to DECIMAL",
)))?,
Some(result) => result,
};
feldera_fxp::Fixed::<P, S>::try_from(div).map_err(|e| {
SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to DECIMAL: {}",
e
))
})
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_ShortInterval_SECONDS<const P: usize, const S: usize>(
value: ShortInterval,
) -> SqlResult<SqlDecimal<P, S>> {
convert_to_SqlDecimal_ShortInterval::<P, S>(value, 1_000_000)
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_ShortInterval_MINUTES<const P: usize, const S: usize>(
value: ShortInterval,
) -> SqlResult<SqlDecimal<P, S>> {
convert_to_SqlDecimal_ShortInterval::<P, S>(value, 60 * 1_000_000)
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_ShortInterval_HOURS<const P: usize, const S: usize>(
value: ShortInterval,
) -> SqlResult<SqlDecimal<P, S>> {
convert_to_SqlDecimal_ShortInterval::<P, S>(value, 60 * 60 * 1_000_000i64)
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_ShortInterval_DAYS<const P: usize, const S: usize>(
value: ShortInterval,
) -> SqlResult<SqlDecimal<P, S>> {
convert_to_SqlDecimal_ShortInterval::<P, S>(value, 24 * 60 * 60 * 1_000_000i64)
}
cast_function!(SqlDecimal <const P: usize, const S: usize>, SqlDecimal<P, S>, ShortInterval_SECONDS, ShortInterval);
cast_function!(SqlDecimal <const P: usize, const S: usize>, SqlDecimal<P, S>, ShortInterval_MINUTES, ShortInterval);
cast_function!(SqlDecimal <const P: usize, const S: usize>, SqlDecimal<P, S>, ShortInterval_HOURS, ShortInterval);
cast_function!(SqlDecimal <const P: usize, const S: usize>, SqlDecimal<P, S>, ShortInterval_DAYS, ShortInterval);
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_i8(value: i8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_DAYS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_i16(value: i16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_DAYS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_i32(value: i32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_DAYS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_i64(value: i64) -> SqlResult<ShortInterval> {
let val = value.checked_mul(86400 * 1000 * 1000);
match val {
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL DAYS"
))),
Some(value) => Ok(ShortInterval::from_microseconds(value)),
}
}
fn convert_to_ShortInterval_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
multiplier: i64,
kind: &'static str,
) -> SqlResult<ShortInterval> {
let dd = DynamicDecimal::from(value);
let mul = DynamicDecimal::from(multiplier);
let val = dd.mul(mul);
i64::try_from(val)
.map(ShortInterval::from_microseconds)
.map_err(|e| {
SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL {}: {}",
kind, e
))
})
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<ShortInterval> {
convert_to_ShortInterval_SqlDecimal::<P, S>(value, 86400i64 * 1000 * 1000, "DAYS")
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_HOURS_i8(value: i8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_HOURS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_HOURS_i16(value: i16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_HOURS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_HOURS_i32(value: i32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_HOURS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_HOURS_i64(value: i64) -> SqlResult<ShortInterval> {
let val = value.checked_mul(3600 * 1000);
match val {
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL HOURS"
))),
Some(value) => Ok(ShortInterval::from_milliseconds(value)),
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_HOURS_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<ShortInterval> {
convert_to_ShortInterval_SqlDecimal::<P, S>(value, 3600i64 * 1000 * 1000, "DAYS")
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_MINUTES_i8(value: i8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_MINUTES_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_MINUTES_i16(value: i16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_MINUTES_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_MINUTES_i32(value: i32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_MINUTES_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_MINUTES_i64(value: i64) -> SqlResult<ShortInterval> {
let val = value.checked_mul(60 * 1000);
match val {
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL MINUTES"
))),
Some(value) => Ok(ShortInterval::from_milliseconds(value)),
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_MINUTES_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<ShortInterval> {
convert_to_ShortInterval_SqlDecimal::<P, S>(value, 60 * 1_000_000, "MINUTES")
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_SECONDS_i8(value: i8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_SECONDS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_SECONDS_i16(value: i16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_SECONDS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_SECONDS_i32(value: i32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_SECONDS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_SECONDS_i64(value: i64) -> SqlResult<ShortInterval> {
let val = value.checked_mul(1000);
match val {
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL SECONDS"
))),
Some(value) => Ok(ShortInterval::from_milliseconds(value)),
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_SECONDS_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<ShortInterval> {
convert_to_ShortInterval_SqlDecimal::<P, S>(value, 1_000_000, "SECONDS")
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_DAYS_u8(value: u8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_DAYS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_DAYS_u16(value: u16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_DAYS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_DAYS_u32(value: u32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_DAYS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_u64(value: u64) -> SqlResult<ShortInterval> {
let value = match <i64 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL DAYS"
)));
}
};
let val = value.checked_mul(86400 * 1000);
match val {
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL DAYS"
))),
Some(value) => Ok(ShortInterval::from_milliseconds(value)),
}
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_HOURS_u8(value: u8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_HOURS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_HOURS_u16(value: u16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_HOURS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_HOURS_u32(value: u32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_HOURS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_HOURS_u64(value: u64) -> SqlResult<ShortInterval> {
let value = match <i64 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL HOURS"
)));
}
};
let val = value.checked_mul(3600 * 1000);
match val {
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL HOURS"
))),
Some(value) => Ok(ShortInterval::from_milliseconds(value)),
}
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_MINUTES_u8(value: u8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_MINUTES_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_MINUTES_u16(value: u16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_MINUTES_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_MINUTES_u32(value: u32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_MINUTES_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_MINUTES_u64(value: u64) -> SqlResult<ShortInterval> {
let value = match <i64 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL MINUTES"
)));
}
};
let val = value.checked_mul(60 * 1000);
match val {
Some(value) => Ok(ShortInterval::from_milliseconds(value)),
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL MINUTES"
))),
}
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_SECONDS_u8(value: u8) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_SECONDS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_SECONDS_u16(value: u16) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_SECONDS_i64(value as i64)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_SECONDS_u32(value: u32) -> SqlResult<ShortInterval> {
cast_to_ShortInterval_SECONDS_i64(value as i64)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_SECONDS_u64(value: u64) -> SqlResult<ShortInterval> {
let value = match <i64 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL SECONDS"
)));
}
};
let val = value.checked_mul(1000);
match val {
Some(value) => Ok(ShortInterval::from_milliseconds(value)),
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL SECONDS"
))),
}
}
cast_function!(ShortInterval_DAYS, ShortInterval, i8, i8);
cast_function!(ShortInterval_DAYS, ShortInterval, i16, i16);
cast_function!(ShortInterval_DAYS, ShortInterval, i32, i32);
cast_function!(ShortInterval_DAYS, ShortInterval, i64, i64);
cast_function!(ShortInterval_DAYS, ShortInterval, u8, u8);
cast_function!(ShortInterval_DAYS, ShortInterval, u16, u16);
cast_function!(ShortInterval_DAYS, ShortInterval, u32, u32);
cast_function!(ShortInterval_DAYS, ShortInterval, u64, u64);
cast_function!(ShortInterval_DAYS <const P: usize, const S: usize>, ShortInterval, SqlDecimal, SqlDecimal<P, S>);
cast_function!(ShortInterval_HOURS, ShortInterval, i8, i8);
cast_function!(ShortInterval_HOURS, ShortInterval, i16, i16);
cast_function!(ShortInterval_HOURS, ShortInterval, i32, i32);
cast_function!(ShortInterval_HOURS, ShortInterval, i64, i64);
cast_function!(ShortInterval_HOURS, ShortInterval, u8, u8);
cast_function!(ShortInterval_HOURS, ShortInterval, u16, u16);
cast_function!(ShortInterval_HOURS, ShortInterval, u32, u32);
cast_function!(ShortInterval_HOURS, ShortInterval, u64, u64);
cast_function!(ShortInterval_HOURS <const P: usize, const S: usize>, ShortInterval, SqlDecimal, SqlDecimal<P, S>);
cast_function!(ShortInterval_MINUTES, ShortInterval, i8, i8);
cast_function!(ShortInterval_MINUTES, ShortInterval, i16, i16);
cast_function!(ShortInterval_MINUTES, ShortInterval, i32, i32);
cast_function!(ShortInterval_MINUTES, ShortInterval, i64, i64);
cast_function!(ShortInterval_MINUTES, ShortInterval, u8, u8);
cast_function!(ShortInterval_MINUTES, ShortInterval, u16, u16);
cast_function!(ShortInterval_MINUTES, ShortInterval, u32, u32);
cast_function!(ShortInterval_MINUTES, ShortInterval, u64, u64);
cast_function!(ShortInterval_MINUTES <const P: usize, const S: usize>, ShortInterval, SqlDecimal, SqlDecimal<P, S>);
cast_function!(ShortInterval_SECONDS, ShortInterval, i8, i8);
cast_function!(ShortInterval_SECONDS, ShortInterval, i16, i16);
cast_function!(ShortInterval_SECONDS, ShortInterval, i32, i32);
cast_function!(ShortInterval_SECONDS, ShortInterval, i64, i64);
cast_function!(ShortInterval_SECONDS, ShortInterval, u8, u8);
cast_function!(ShortInterval_SECONDS, ShortInterval, u16, u16);
cast_function!(ShortInterval_SECONDS, ShortInterval, u32, u32);
cast_function!(ShortInterval_SECONDS, ShortInterval, u64, u64);
cast_function!(ShortInterval_SECONDS <const P: usize, const S: usize>, ShortInterval, SqlDecimal, SqlDecimal<P, S>);
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortIntervalN_nullN(_value: Option<()>) -> SqlResult<Option<ShortInterval>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_YEARS_i8(value: i8) -> SqlResult<LongInterval> {
cast_to_LongInterval_YEARS_i32(value as i32)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_YEARS_i16(value: i16) -> SqlResult<LongInterval> {
cast_to_LongInterval_YEARS_i32(value as i32)
}
#[doc(hidden)]
pub fn cast_to_LongInterval_YEARS_i32(value: i32) -> SqlResult<LongInterval> {
let val = value.checked_mul(12);
match val {
Some(value) => Ok(LongInterval::from_months(value)),
None => Err(SqlRuntimeError::from_string(format!(
"Overflow during conversion of {value} to INTERVAL YEARS"
))),
}
}
#[doc(hidden)]
pub fn cast_to_LongInterval_YEARS_i64(value: i64) -> SqlResult<LongInterval> {
let value = match <i32 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL YEARS"
)));
}
};
cast_to_LongInterval_YEARS_i32(value)
}
#[doc(hidden)]
pub fn cast_to_LongInterval_YEARS_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<LongInterval> {
let value = cast_to_i32_SqlDecimal::<P, S>(value)?;
cast_to_LongInterval_YEARS_i32(value)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_MONTHS_i8(value: i8) -> SqlResult<LongInterval> {
cast_to_LongInterval_MONTHS_i32(value as i32)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_MONTHS_i16(value: i16) -> SqlResult<LongInterval> {
cast_to_LongInterval_MONTHS_i32(value as i32)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_MONTHS_i32(value: i32) -> SqlResult<LongInterval> {
Ok(LongInterval::from_months(value))
}
#[doc(hidden)]
pub fn cast_to_LongInterval_MONTHS_i64(value: i64) -> SqlResult<LongInterval> {
let value = match <i32 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL MONTHS"
)));
}
};
cast_to_LongInterval_MONTHS_i32(value)
}
#[doc(hidden)]
pub fn cast_to_LongInterval_MONTHS_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<LongInterval> {
let value = cast_to_i32_SqlDecimal::<P, S>(value)?;
cast_to_LongInterval_MONTHS_i32(value)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_YEARS_u8(value: u8) -> SqlResult<LongInterval> {
cast_to_LongInterval_YEARS_i32(value as i32)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_YEARS_u16(value: u16) -> SqlResult<LongInterval> {
cast_to_LongInterval_YEARS_i32(value as i32)
}
#[doc(hidden)]
pub fn cast_to_LongInterval_YEARS_u32(value: u32) -> SqlResult<LongInterval> {
let value = match <i32 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL YEARS"
)));
}
};
cast_to_LongInterval_YEARS_i32(value)
}
#[doc(hidden)]
pub fn cast_to_LongInterval_YEARS_u64(value: u64) -> SqlResult<LongInterval> {
let value = match <i32 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL YEARS"
)));
}
};
cast_to_LongInterval_YEARS_i32(value)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_MONTHS_u8(value: u8) -> SqlResult<LongInterval> {
cast_to_LongInterval_MONTHS_i32(value as i32)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_MONTHS_u16(value: u16) -> SqlResult<LongInterval> {
cast_to_LongInterval_MONTHS_i32(value as i32)
}
#[doc(hidden)]
pub fn cast_to_LongInterval_MONTHS_u32(value: u32) -> SqlResult<LongInterval> {
let value = match <i32 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL MONTHS"
)));
}
};
Ok(LongInterval::from_months(value))
}
#[doc(hidden)]
pub fn cast_to_LongInterval_MONTHS_u64(value: u64) -> SqlResult<LongInterval> {
let value = match <i32 as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL MONTHS"
)));
}
};
cast_to_LongInterval_MONTHS_i32(value)
}
cast_function!(LongInterval_YEARS, LongInterval, i8, i8);
cast_function!(LongInterval_YEARS, LongInterval, i16, i16);
cast_function!(LongInterval_YEARS, LongInterval, i32, i32);
cast_function!(LongInterval_YEARS, LongInterval, i64, i64);
cast_function!(LongInterval_YEARS, LongInterval, u8, u8);
cast_function!(LongInterval_YEARS, LongInterval, u16, u16);
cast_function!(LongInterval_YEARS, LongInterval, u32, u32);
cast_function!(LongInterval_YEARS, LongInterval, u64, u64);
cast_function!(LongInterval_YEARS <const P: usize, const S: usize>, LongInterval, SqlDecimal, SqlDecimal<P, S>);
cast_function!(LongInterval_MONTHS, LongInterval, i8, i8);
cast_function!(LongInterval_MONTHS, LongInterval, i16, i16);
cast_function!(LongInterval_MONTHS, LongInterval, i32, i32);
cast_function!(LongInterval_MONTHS, LongInterval, i64, i64);
cast_function!(LongInterval_MONTHS, LongInterval, u8, u8);
cast_function!(LongInterval_MONTHS, LongInterval, u16, u16);
cast_function!(LongInterval_MONTHS, LongInterval, u32, u32);
cast_function!(LongInterval_MONTHS, LongInterval, u64, u64);
cast_function!(LongInterval_MONTHS <const P: usize, const S: usize>, LongInterval, SqlDecimal, SqlDecimal<P, S>);
#[doc(hidden)]
pub fn cast_to_LongInterval_YEARS_s(value: SqlString) -> SqlResult<LongInterval> {
match value.str().parse::<i32>() {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL YEARS: {}",
e
))),
Ok(years) => cast_to_LongInterval_YEARS_i32(years),
}
}
static YEARS_TO_MONTHS: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([-+]?\d+)(-(\d+))?$").unwrap());
#[doc(hidden)]
pub fn cast_to_LongInterval_YEARS_TO_MONTHS_s(value: SqlString) -> SqlResult<LongInterval> {
if let Some(captures) = YEARS_TO_MONTHS.captures(value.str()) {
let yearcap = captures.get(1).unwrap().as_str();
let mut years = match yearcap.parse::<i32>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL YEARS TO MONTHS: {}",
e
)));
}
Ok(years) => years,
};
let months: i32;
match captures.get(2) {
None => {
months = years;
years = 0;
}
_ => {
let monthcap = captures.get(3).unwrap().as_str();
months = match monthcap.parse() {
Ok(months) => months,
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL YEARS TO MONTHS: {}",
e
)));
}
}
}
}
let months = if years < 0 {
12 * years - months
} else {
12 * years + months
};
Ok(LongInterval::from_months(months))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'years-months'",
)))
}
}
#[doc(hidden)]
pub fn cast_to_LongInterval_MONTHS_s(value: SqlString) -> SqlResult<LongInterval> {
match value.str().parse::<i32>() {
Ok(months) => cast_to_LongInterval_MONTHS_i32(months),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL MONTHS: {}",
e
))),
}
}
cast_function!(LongInterval_YEARS, LongInterval, s, SqlString);
cast_function!(LongInterval_YEARS_TO_MONTHS, LongInterval, s, SqlString);
cast_function!(LongInterval_MONTHS, LongInterval, s, SqlString);
#[doc(hidden)]
#[inline]
pub fn cast_to_LongInterval_LongInterval(value: LongInterval) -> SqlResult<LongInterval> {
Ok(value)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_ShortInterval_ShortInterval(value: ShortInterval) -> SqlResult<ShortInterval> {
Ok(value)
}
cast_function!(LongInterval, LongInterval, LongInterval, LongInterval);
cast_function!(ShortInterval, ShortInterval, ShortInterval, ShortInterval);
static DAYS_TO_HOURS: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([+-])?(\d+)\s+(\d{1,2})$").unwrap());
static DAYS_TO_MINUTES: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([+-])?(\d+)\s+(\d{1,2}):(\d{1,2})$").unwrap());
static DAYS_TO_SECONDS: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^([+-])?(\d+)\s+(\d{1,2}):(\d{1,2}):(\d{1,2})([.](\d{1,6}))?$").unwrap()
});
static HOURS_TO_MINUTES: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([+-])?(\d+):(\d{1,2})$").unwrap());
static HOURS_TO_SECONDS: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([+-])?(\d+):(\d{1,2}):(\d{1,2})([.](\d{1,6}))?$").unwrap());
static MINUTES_TO_SECONDS: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([+-])?(\d+):(\d{1,2})([.](\d{1,6}))?$").unwrap());
static SECONDS: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([+-])?(\d+)([.](\d{1,6}))?$").unwrap());
fn validate_unit(value: i64, name: &str, max: i64) {
if num::abs(value) >= max {
panic!("{name} '{value}' must be between 0 and {max}");
}
}
fn validate_hours(value: i64) {
validate_unit(value, "hour", 24)
}
fn validate_minutes(value: i64) {
validate_unit(value, "minute", 60)
}
fn validate_seconds(value: i64) {
validate_unit(value, "second", 60)
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_s(value: SqlString) -> SqlResult<ShortInterval> {
match value.str().parse::<i64>() {
Ok(value) => cast_to_ShortInterval_DAYS_i64(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL DAYS: {}",
e
))),
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_HOURS_s(value: SqlString) -> SqlResult<ShortInterval> {
match value.str().parse::<i64>() {
Ok(value) => cast_to_ShortInterval_HOURS_i64(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL HOURS: {}",
e
))),
}
}
#[doc(hidden)]
pub fn negative(captures: &Captures) -> bool {
captures.get(1).is_some() && captures.get(1).unwrap().as_str() == "-"
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_TO_HOURS_s(value: SqlString) -> SqlResult<ShortInterval> {
if let Some(captures) = DAYS_TO_HOURS.captures(value.str()) {
let negative = negative(&captures);
let daycap = captures.get(2).unwrap().as_str();
let days = match daycap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL DAYS TO HOURS: {}",
e
)));
}
Ok(days) => days,
};
let hourcap = captures.get(3).unwrap().as_str().trim();
let hours = match hourcap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL DAYS TO HOURS: {}",
e
)));
}
Ok(hours) => hours,
};
validate_hours(hours);
let hours = if negative {
-days * 24 - hours
} else {
days * 24 + hours
};
Ok(ShortInterval::from_milliseconds(hours * 3600 * 1000))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'days hours'",
)))
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_MINUTES_s(value: SqlString) -> SqlResult<ShortInterval> {
match value.str().parse::<i64>() {
Ok(value) => cast_to_ShortInterval_MINUTES_i64(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to INTERVAL MINUTES: {}",
e
))),
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_TO_MINUTES_s(value: SqlString) -> SqlResult<ShortInterval> {
if let Some(captures) = DAYS_TO_MINUTES.captures(value.str()) {
let negative = negative(&captures);
let daycap = captures.get(2).unwrap().as_str();
let days = match daycap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse DAYS: {}; {}",
daycap, e,
)));
}
Ok(days) => days,
};
let hourcap = captures.get(3).unwrap().as_str().trim();
let hours = match hourcap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse HOURS: {}; {}",
hourcap, e,
)));
}
Ok(hours) => hours,
};
validate_hours(hours);
let mincap = captures.get(4).unwrap().as_str().trim();
let minutes = match mincap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MINUTES: {}; {}",
mincap, e,
)));
}
Ok(minutes) => minutes,
};
validate_minutes(minutes);
let minutes = if negative {
-(days * 24 + hours) * 60 - minutes
} else {
(days * 24 + hours) * 60 + minutes
};
Ok(ShortInterval::from_milliseconds(minutes * 60 * 1000))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'days hours:minutes'",
)))
}
}
#[doc(hidden)]
pub fn cast_to_GeoPoint_s(value: SqlString) -> SqlResult<GeoPoint> {
Err(SqlRuntimeError::from_string(format!(
"String '{value}' cannot be cast to ST_POINT"
)))
}
cast_function!(GeoPoint, GeoPoint, s, SqlString);
#[doc(hidden)]
pub fn cast_to_ShortInterval_HOURS_TO_MINUTES_s(value: SqlString) -> SqlResult<ShortInterval> {
if let Some(captures) = HOURS_TO_MINUTES.captures(value.str()) {
let negative = negative(&captures);
let hourcap = captures.get(2).unwrap().as_str();
let hours = match hourcap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse HOURS: {}; {}",
hourcap, e,
)));
}
Ok(hours) => hours,
};
let mincap = captures.get(3).unwrap().as_str().trim();
let minutes = match mincap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MINUTES: {}; {}",
mincap, e,
)));
}
Ok(minutes) => minutes,
};
validate_minutes(minutes);
let minutes = if negative {
-hours * 60 - minutes
} else {
hours * 60 + minutes
};
Ok(ShortInterval::from_milliseconds(minutes * 60 * 1000))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'hours:minutes'",
)))
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_SECONDS_s(value: SqlString) -> SqlResult<ShortInterval> {
if let Some(captures) = SECONDS.captures(value.str()) {
let negative = negative(&captures);
let seccap = captures.get(2).unwrap().as_str().trim();
let seconds = match seccap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse SECONDS: {}; {}",
seccap, e,
)));
}
Ok(seconds) => seconds,
};
let ms = match captures.get(3) {
None => Ok(0i64),
Some(_) => {
let mscap = captures.get(4).unwrap().as_str();
(mscap.to_owned() + "000000")[..3].parse::<i64>()
}
};
let ms = match ms {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MILLISECONDS: {}; {}",
captures.get(4).unwrap().as_str(),
e,
)));
}
Ok(ms) => ms,
};
let ms = if negative {
-seconds * 1000 - ms
} else {
seconds * 1000 + ms
};
Ok(ShortInterval::from_milliseconds(ms))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'seconds.fractions'",
)))
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_DAYS_TO_SECONDS_s(value: SqlString) -> SqlResult<ShortInterval> {
if let Some(captures) = DAYS_TO_SECONDS.captures(value.str()) {
let negative = negative(&captures);
let daycap = captures.get(2).unwrap().as_str();
let days = match daycap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse DAYS: {}; {}",
daycap, e,
)));
}
Ok(days) => days,
};
let hourcap = captures.get(3).unwrap().as_str().trim();
let hours = match hourcap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse HOURS: {}; {}",
hourcap, e,
)));
}
Ok(hours) => hours,
};
validate_hours(hours);
let mincap = captures.get(4).unwrap().as_str().trim();
let minutes = match mincap.parse::<i64>() {
Err(_) => {
return Err(SqlRuntimeError::from_string(format!(
"MINUTES is not a number: {}",
mincap
)));
}
Ok(minutes) => minutes,
};
validate_minutes(minutes);
let seccap = captures.get(5).unwrap().as_str().trim();
let seconds = match seccap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse SECONDS: {}; {}",
seccap, e,
)));
}
Ok(seconds) => seconds,
};
validate_seconds(seconds);
let ms = match captures.get(6) {
None => Ok(0i64),
Some(_) => {
let mscap = captures.get(7).unwrap().as_str();
(mscap.to_owned() + "000000")[..3].parse::<i64>()
}
};
let ms = match ms {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MILLISECONDS: {}; {}",
captures.get(7).unwrap().as_str(),
e,
)));
}
Ok(ms) => ms,
};
let ms = if negative {
-((days * 24 + hours) * 60 + minutes) * 60000 - seconds * 1000 - ms
} else {
((days * 24 + hours) * 60 + minutes) * 60000 + seconds * 1000 + ms
};
Ok(ShortInterval::from_milliseconds(ms))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'days hours:minutes:seconds'"
)))
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_HOURS_TO_SECONDS_s(value: SqlString) -> SqlResult<ShortInterval> {
if let Some(captures) = HOURS_TO_SECONDS.captures(value.str()) {
let negative = negative(&captures);
let hourcap = captures.get(2).unwrap().as_str().trim();
let hours = match hourcap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse HOURS: {}; {}",
hourcap, e,
)));
}
Ok(hours) => hours,
};
let mincap = captures.get(3).unwrap().as_str().trim();
let minutes = match mincap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MINUTES: {}; {}",
mincap, e,
)));
}
Ok(minutes) => minutes,
};
validate_minutes(minutes);
let seccap = captures.get(4).unwrap().as_str().trim();
let seconds = match seccap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse SECONDS: {}; {}",
seccap, e,
)));
}
Ok(seconds) => seconds,
};
validate_seconds(seconds);
let ms = match captures.get(5) {
None => Ok(0i64),
Some(_) => {
let mscap = captures.get(6).unwrap().as_str();
(mscap.to_owned() + "000000")[..3].parse::<i64>()
}
};
let ms = match ms {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MILLISECONDS: {}; {}",
captures.get(6).unwrap().as_str(),
e,
)));
}
Ok(ms) => ms,
};
let ms = if negative {
(-hours * 60 - minutes) * 60000 - seconds * 1000 - ms
} else {
(hours * 60 + minutes) * 60000 + seconds * 1000 + ms
};
Ok(ShortInterval::from_milliseconds(ms))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'hours:minutes:seconds.fractions'"
)))
}
}
#[doc(hidden)]
pub fn cast_to_ShortInterval_MINUTES_TO_SECONDS_s(value: SqlString) -> SqlResult<ShortInterval> {
if let Some(captures) = MINUTES_TO_SECONDS.captures(value.str()) {
let negative = negative(&captures);
let mincap = captures.get(2).unwrap().as_str().trim();
let minutes = match mincap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MINUTES: {}; {}",
mincap, e,
)));
}
Ok(minutes) => minutes,
};
let seccap = captures.get(3).unwrap().as_str().trim();
let seconds = match seccap.parse::<i64>() {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse SECONDS: {}; {}",
seccap, e,
)));
}
Ok(seconds) => seconds,
};
validate_seconds(seconds);
let ms = match captures.get(4) {
None => Ok(0i64),
Some(_) => {
let mscap = captures.get(5).unwrap().as_str();
(mscap.to_owned() + "000000")[..3].parse::<i64>()
}
};
let ms = match ms {
Err(e) => {
return Err(SqlRuntimeError::from_string(format!(
"Could not parse MILLISECONDS: {}; {}",
captures.get(5).unwrap().as_str(),
e,
)));
}
Ok(ms) => ms,
};
let ms = if negative {
-minutes * 60000 - seconds * 1000 - ms
} else {
minutes * 60000 + seconds * 1000 + ms
};
Ok(ShortInterval::from_milliseconds(ms))
} else {
Err(SqlRuntimeError::from_string(format!(
"Interval '{value}' does not have format 'minutes:seconds.fractions'"
)))
}
}
cast_function!(ShortInterval_DAYS, ShortInterval, s, SqlString);
cast_function!(ShortInterval_HOURS, ShortInterval, s, SqlString);
cast_function!(ShortInterval_DAYS_TO_HOURS, ShortInterval, s, SqlString);
cast_function!(ShortInterval_MINUTES, ShortInterval, s, SqlString);
cast_function!(ShortInterval_DAYS_TO_MINUTES, ShortInterval, s, SqlString);
cast_function!(ShortInterval_HOURS_TO_MINUTES, ShortInterval, s, SqlString);
cast_function!(ShortInterval_SECONDS, ShortInterval, s, SqlString);
cast_function!(ShortInterval_DAYS_TO_SECONDS, ShortInterval, s, SqlString);
cast_function!(ShortInterval_HOURS_TO_SECONDS, ShortInterval, s, SqlString);
cast_function!(
ShortInterval_MINUTES_TO_SECONDS,
ShortInterval,
s,
SqlString
);
#[doc(hidden)]
pub fn cast_to_Timestamp_s(value: SqlString) -> SqlResult<Timestamp> {
if let Ok(v) = NaiveDateTime::parse_from_str(value.str(), "%Y-%m-%d %H:%M:%S%.f") {
return Ok(Timestamp::from_naiveDateTime(v));
}
if let Ok(v) = NaiveDate::parse_from_str(value.str(), "%Y-%m-%d") {
let dt = v.and_hms_opt(0, 0, 0).unwrap();
let result = Timestamp::from_microseconds(dt.and_utc().timestamp_micros());
return Ok(result);
}
Err(SqlRuntimeError::from_string(format!(
"Failed to parse '{value}' as a TIMESTAMP"
)))
}
cast_function!(Timestamp, Timestamp, s, SqlString);
#[doc(hidden)]
pub fn cast_to_Timestamp_Date(value: Date) -> SqlResult<Timestamp> {
Ok(value.to_timestamp())
}
cast_function!(Timestamp, Timestamp, Date, Date);
#[doc(hidden)]
pub fn cast_to_Timestamp_Time(value: Time) -> SqlResult<Timestamp> {
let dt = NaiveDateTime::new(
NaiveDate::from_ymd_opt(1970, 1, 1).unwrap(),
value.to_time(),
);
Ok(Timestamp::from_naiveDateTime(dt))
}
cast_function!(Timestamp, Timestamp, Time, Time);
#[doc(hidden)]
#[inline]
pub fn cast_to_TimestampN_nullN(_value: Option<()>) -> SqlResult<Option<Timestamp>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_Timestamp_Timestamp(value: Timestamp) -> SqlResult<Timestamp> {
Ok(value)
}
cast_function!(Timestamp, Timestamp, Timestamp, Timestamp);
#[doc(hidden)]
#[inline]
pub fn cast_to_Timestamp_TimestampTz(value: TimestampTz) -> SqlResult<Timestamp> {
Ok(value.into())
}
cast_function!(Timestamp, Timestamp, TimestampTz, TimestampTz);
#[doc(hidden)]
pub fn cast_to_Timestamp_i64(value: i64) -> SqlResult<Timestamp> {
Ok(Timestamp::from_milliseconds((value / 1000) * 1000))
}
cast_function!(Timestamp, Timestamp, i64, i64);
#[doc(hidden)]
pub fn cast_to_Timestamp_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<Timestamp> {
match TryInto::<i64>::try_into(value) {
Ok(value) => Ok(Timestamp::from_milliseconds((value / 1000) * 1000)),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIMESTAMP: {}",
e
))),
}
}
cast_function!(Timestamp <const P: usize, const S: usize>, Timestamp, SqlDecimal, SqlDecimal<P, S>);
#[doc(hidden)]
pub fn cast_to_Timestamp_u64(value: u64) -> SqlResult<Timestamp> {
let result: Result<i64, _> = value.try_into();
match result {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIMESTAMP: {}",
e
))),
Ok(result) => Ok(Timestamp::from_milliseconds(result)),
}
}
cast_function!(Timestamp, Timestamp, u64, u64);
#[doc(hidden)]
#[inline]
pub fn cast_to_i64_Timestamp(value: Timestamp) -> SqlResult<i64> {
Ok(value.milliseconds())
}
cast_function!(i64, i64, Timestamp, Timestamp);
#[doc(hidden)]
pub fn cast_to_u64_Timestamp(value: Timestamp) -> SqlResult<u64> {
let ms = value.milliseconds();
if ms < 0 {
Err(SqlRuntimeError::from_string(format!(
"Negative value converted to unsigned {}",
value
)))
} else {
Ok(ms as u64)
}
}
cast_function!(u64, u64, Timestamp, Timestamp);
#[doc(hidden)]
pub fn cast_to_SqlDecimal_Timestamp<const P: usize, const S: usize>(
value: Timestamp,
) -> SqlResult<SqlDecimal<P, S>> {
cast_to_SqlDecimal_i64::<P, S>(value.microseconds())
.map(|x| x.div(SqlDecimal::<P, S>::for_i32(1000)))
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_Timestamp<const P: usize, const S: usize>(
value: Timestamp,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
r2o(cast_to_SqlDecimal_Timestamp::<P, S>(value))
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_TimestampN<const P: usize, const S: usize>(
value: Option<Timestamp>,
) -> SqlResult<SqlDecimal<P, S>> {
match value {
None => Err(cast_null("DECIMAL")),
Some(value) => cast_to_SqlDecimal_Timestamp::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_TimestampN<const P: usize, const S: usize>(
value: Option<Timestamp>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_Timestamp::<P, S>(value),
}
}
macro_rules! cast_ts {
($type_name: ident, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_Timestamp_ $type_name>](value: $arg_type) -> SqlResult<Timestamp> {
match [< cast_to_i64_ $type_name >](value) {
Ok(value) => cast_to_Timestamp_i64(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIMESTAMP: {}",
e
))),
}
}
cast_function!(Timestamp, Timestamp, $type_name, $arg_type);
#[doc(hidden)]
pub fn [<cast_to_ $type_name _Timestamp>](value: Timestamp) -> SqlResult<$arg_type> {
match cast_to_i64_Timestamp(value) {
Ok(value) => [< cast_to_ $type_name _i64 >] (value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIMESTAMP: {}",
e
))),
}
}
cast_function!($type_name, $arg_type, Timestamp, Timestamp);
}
};
}
cast_ts!(i32, i32);
cast_ts!(i16, i16);
cast_ts!(i8, i8);
cast_ts!(u32, u32);
cast_ts!(u16, u16);
cast_ts!(u8, u8);
cast_ts!(f, F32);
cast_ts!(d, F64);
#[doc(hidden)]
pub fn cast_to_TimestampTz_s(value: SqlString) -> SqlResult<TimestampTz> {
parse_timestamp_tz(value.str())
}
cast_function!(TimestampTz, TimestampTz, s, SqlString);
#[doc(hidden)]
pub fn cast_to_TimestampTz_Date(value: Date) -> SqlResult<TimestampTz> {
Ok(value.to_timestamp().into())
}
cast_function!(TimestampTz, TimestampTz, Date, Date);
#[doc(hidden)]
pub fn cast_to_TimestampTz_Time(value: Time) -> SqlResult<TimestampTz> {
cast_to_Timestamp_Time(value).map(|x| x.into())
}
cast_function!(TimestampTz, TimestampTz, Time, Time);
#[doc(hidden)]
#[inline]
pub fn cast_to_TimestampTzN_nullN(_value: Option<()>) -> SqlResult<Option<TimestampTz>> {
Ok(None)
}
#[doc(hidden)]
#[inline]
pub fn cast_to_TimestampTz_TimestampTz(value: TimestampTz) -> SqlResult<TimestampTz> {
Ok(value)
}
cast_function!(TimestampTz, TimestampTz, TimestampTz, TimestampTz);
#[doc(hidden)]
#[inline]
pub fn cast_to_TimestampTz_Timestamp(value: Timestamp) -> SqlResult<TimestampTz> {
Ok(value.into())
}
cast_function!(TimestampTz, TimestampTz, Timestamp, Timestamp);
#[doc(hidden)]
pub fn cast_to_TimestampTz_i64(value: i64) -> SqlResult<TimestampTz> {
cast_to_Timestamp_i64(value).map(|x| x.into())
}
cast_function!(TimestampTz, TimestampTz, i64, i64);
#[doc(hidden)]
pub fn cast_to_TimestampTz_SqlDecimal<const P: usize, const S: usize>(
value: SqlDecimal<P, S>,
) -> SqlResult<TimestampTz> {
cast_to_Timestamp_SqlDecimal::<P, S>(value).map(|x| x.into())
}
cast_function!(TimestampTz <const P: usize, const S: usize>, TimestampTz, SqlDecimal, SqlDecimal<P, S>);
#[doc(hidden)]
pub fn cast_to_TimestampTz_u64(value: u64) -> SqlResult<TimestampTz> {
let result: Result<i64, _> = value.try_into();
match result {
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIMESTAMP WITH TIME ZONE: {}",
e
))),
Ok(result) => Ok(TimestampTz::from_milliseconds(result)),
}
}
cast_function!(TimestampTz, TimestampTz, u64, u64);
#[doc(hidden)]
#[inline]
pub fn cast_to_i64_TimestampTz(value: TimestampTz) -> SqlResult<i64> {
Ok(value.milliseconds())
}
cast_function!(i64, i64, TimestampTz, TimestampTz);
#[doc(hidden)]
pub fn cast_to_u64_TimestampTz(value: TimestampTz) -> SqlResult<u64> {
cast_to_u64_Timestamp(value.into())
}
cast_function!(u64, u64, TimestampTz, TimestampTz);
#[doc(hidden)]
pub fn cast_to_SqlDecimal_TimestampTz<const P: usize, const S: usize>(
value: TimestampTz,
) -> SqlResult<SqlDecimal<P, S>> {
cast_to_SqlDecimal_Timestamp(value.into())
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_TimestampTz<const P: usize, const S: usize>(
value: TimestampTz,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
r2o(cast_to_SqlDecimal_TimestampTz::<P, S>(value))
}
#[doc(hidden)]
pub fn cast_to_SqlDecimal_TimestampTzN<const P: usize, const S: usize>(
value: Option<TimestampTz>,
) -> SqlResult<SqlDecimal<P, S>> {
match value {
None => Err(cast_null("DECIMAL")),
Some(value) => cast_to_SqlDecimal_TimestampTz::<P, S>(value),
}
}
#[doc(hidden)]
pub fn cast_to_SqlDecimalN_TimestampTzN<const P: usize, const S: usize>(
value: Option<TimestampTz>,
) -> SqlResult<Option<SqlDecimal<P, S>>> {
match value {
None => Ok(None),
Some(value) => cast_to_SqlDecimalN_TimestampTz::<P, S>(value),
}
}
macro_rules! cast_ts_tz {
($type_name: ident, $arg_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_TimestampTz_ $type_name>](value: $arg_type) -> SqlResult<TimestampTz> {
match [< cast_to_i64_ $type_name >](value) {
Ok(value) => cast_to_TimestampTz_i64(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIMESTAMP WITH TIME ZONE: {}",
e
))),
}
}
cast_function!(TimestampTz, TimestampTz, $type_name, $arg_type);
#[doc(hidden)]
pub fn [<cast_to_ $type_name _TimestampTz>](value: TimestampTz) -> SqlResult<$arg_type> {
match cast_to_i64_TimestampTz(value) {
Ok(value) => [< cast_to_ $type_name _i64 >] (value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to TIMESTAMP WITH TIME ZONE: {}",
e
))),
}
}
cast_function!($type_name, $arg_type, TimestampTz, TimestampTz);
}
};
}
cast_ts_tz!(i32, i32);
cast_ts_tz!(i16, i16);
cast_ts_tz!(i8, i8);
cast_ts_tz!(u32, u32);
cast_ts_tz!(u16, u16);
cast_ts_tz!(u8, u8);
cast_ts_tz!(f, F32);
cast_ts_tz!(d, F64);
#[doc(hidden)]
pub fn cast_to_u_i32(value: i32) -> SqlResult<usize> {
match value.try_into() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to unsigned: {}",
e
))),
}
}
cast_function!(u, usize, i32, i32);
#[doc(hidden)]
pub fn cast_to_u_i64(value: i64) -> SqlResult<usize> {
match value.try_into() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to usize: {}",
e
))),
}
}
cast_function!(u, usize, i64, i64);
#[doc(hidden)]
#[inline]
pub fn cast_to_i_i32(value: i32) -> SqlResult<isize> {
Ok(value as isize)
}
cast_function!(i, isize, i32, i32);
#[doc(hidden)]
pub fn cast_to_i_i64(value: i64) -> SqlResult<isize> {
let value = match <isize as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to isize"
)));
}
};
Ok(value)
}
cast_function!(i, isize, i64, i64);
#[doc(hidden)]
pub fn cast_to_u_u32(value: u32) -> SqlResult<usize> {
match value.try_into() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to usize: {}",
e
))),
}
}
cast_function!(u, usize, u32, u32);
#[doc(hidden)]
pub fn cast_to_u_u64(value: u64) -> SqlResult<usize> {
match value.try_into() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting {value} to usize: {}",
e
))),
}
}
cast_function!(u, usize, u64, u64);
#[doc(hidden)]
#[inline]
pub fn cast_to_i_u32(value: u32) -> SqlResult<isize> {
Ok(value as isize)
}
cast_function!(i, isize, u32, u32);
#[doc(hidden)]
pub fn cast_to_i_u64(value: u64) -> SqlResult<isize> {
let value = match <isize as NumCast>::from(value) {
Some(value) => value,
None => {
return Err(SqlRuntimeError::from_string(format!(
"Cannot convert {value} to INTERVAL MONTHS"
)));
}
};
Ok(value)
}
cast_function!(i, isize, u64, u64);
pub fn cast_to_bytesN_nullN(
_value: Option<()>,
_precision: i32,
_fixed: bool,
) -> SqlResult<Option<ByteArray>> {
Ok(None)
}
#[doc(hidden)]
pub fn cast_to_bytes_s(value: SqlString, precision: i32, fixed: bool) -> SqlResult<ByteArray> {
let s = value.str();
let array = s.as_bytes();
Ok(ByteArray::with_size(array, precision, fixed))
}
#[doc(hidden)]
pub fn cast_to_bytesN_s(
value: SqlString,
precision: i32,
fixed: bool,
) -> SqlResult<Option<ByteArray>> {
r2o(cast_to_bytes_s(value, precision, fixed))
}
#[doc(hidden)]
pub fn cast_to_bytes_sN(
value: Option<SqlString>,
precision: i32,
fixed: bool,
) -> SqlResult<ByteArray> {
cast_to_bytes_s(value.unwrap(), precision, fixed)
}
#[doc(hidden)]
pub fn cast_to_bytesN_sN(
value: Option<SqlString>,
precision: i32,
fixed: bool,
) -> SqlResult<Option<ByteArray>> {
match value {
None => Ok(None),
Some(value) => cast_to_bytesN_s(value, precision, fixed),
}
}
#[doc(hidden)]
pub fn cast_to_bytes_bytes(value: ByteArray, precision: i32, fixed: bool) -> SqlResult<ByteArray> {
Ok(ByteArray::with_size(value.as_slice(), precision, fixed))
}
#[doc(hidden)]
pub fn cast_to_bytes_bytesN(
value: Option<ByteArray>,
precision: i32,
fixed: bool,
) -> SqlResult<ByteArray> {
match value {
None => Err(cast_null("BINARY")),
Some(value) => cast_to_bytes_bytes(value, precision, fixed),
}
}
#[doc(hidden)]
pub fn cast_to_bytesN_bytes(
value: ByteArray,
precision: i32,
fixed: bool,
) -> SqlResult<Option<ByteArray>> {
r2o(cast_to_bytes_bytes(value, precision, fixed))
}
#[doc(hidden)]
pub fn cast_to_bytesN_bytesN(
value: Option<ByteArray>,
precision: i32,
fixed: bool,
) -> SqlResult<Option<ByteArray>> {
match value {
None => Ok(None),
Some(value) => cast_to_bytesN_bytes(value, precision, fixed),
}
}
#[doc(hidden)]
pub fn cast_to_bytes_Uuid(value: Uuid, precision: i32, fixed: bool) -> SqlResult<ByteArray> {
Ok(ByteArray::with_size(value.to_bytes(), precision, fixed))
}
#[doc(hidden)]
pub fn cast_to_bytesN_Uuid(
value: Uuid,
precision: i32,
fixed: bool,
) -> SqlResult<Option<ByteArray>> {
Ok(Some(ByteArray::with_size(
value.to_bytes(),
precision,
fixed,
)))
}
#[doc(hidden)]
pub fn cast_to_bytes_UuidN(
value: Option<Uuid>,
precision: i32,
fixed: bool,
) -> SqlResult<ByteArray> {
Ok(ByteArray::with_size(
value.unwrap().to_bytes(),
precision,
fixed,
))
}
#[doc(hidden)]
pub fn cast_to_bytesN_UuidN(
value: Option<Uuid>,
precision: i32,
fixed: bool,
) -> SqlResult<Option<ByteArray>> {
match value {
None => Ok(None),
Some(value) => cast_to_bytesN_Uuid(value, precision, fixed),
}
}
macro_rules! cast_to_bytes_i {
($result_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [<cast_to_bytes_ $result_type >] ( value: $result_type, precision: i32, fixed: bool ) -> SqlResult<ByteArray> {
Ok(ByteArray::with_size_truncate_left(&value.to_be_bytes(), precision, fixed))
}
#[doc(hidden)]
pub fn [<cast_to_bytes_ $result_type N >] ( value: Option<$result_type>, precision: i32, fixed: bool ) -> SqlResult<ByteArray> {
match value {
None => Err(cn!($result_type)),
Some(value) => [< cast_to_bytes_ $result_type >](value, precision, fixed),
}
}
#[doc(hidden)]
pub fn [<cast_to_bytesN_ $result_type >] ( value: $result_type, precision: i32, fixed: bool ) -> SqlResult<Option<ByteArray>> {
r2o([< cast_to_bytes_ $result_type >] (value, precision, fixed))
}
#[doc(hidden)]
pub fn [<cast_to_bytesN_ $result_type N >] ( value: Option<$result_type>, precision: i32, fixed: bool ) -> SqlResult<Option<ByteArray>> {
match (value) {
None => Ok(None),
Some(value) => r2o([< cast_to_bytes_ $result_type >](value, precision, fixed))
}
}
}
};
}
cast_to_bytes_i!(i8);
cast_to_bytes_i!(i16);
cast_to_bytes_i!(i32);
cast_to_bytes_i!(i64);
cast_to_bytes_i!(i128);
cast_to_bytes_i!(u8);
cast_to_bytes_i!(u16);
cast_to_bytes_i!(u32);
cast_to_bytes_i!(u64);
cast_to_bytes_i!(u128);
macro_rules! cast_to_variant {
($result_name: ident $(< $( const $var:ident : $ty: ty),* >)?, $result_type: ty, $enum: ident) => {
::paste::paste! {
#[doc(hidden)]
#[inline]
pub fn [<cast_to_ V_ $result_name >] $(< $( const $var : $ty),* >)? ( value: $result_type ) -> SqlResult<Variant> {
Ok(Variant::from(value))
}
#[doc(hidden)]
pub fn [<cast_to_ VN_ $result_name >] $(< $( const $var : $ty),* >)? ( value: $result_type ) -> SqlResult<Option<Variant>> {
Ok(Some(Variant::from(value)))
}
#[doc(hidden)]
pub fn [<cast_to_ V_ $result_name N>] $(< $( const $var : $ty),* >)? ( value: Option<$result_type> ) -> SqlResult<Variant> {
match value {
None => Ok(Variant::SqlNull),
Some(value) => Ok(Variant::from(value)),
}
}
#[doc(hidden)]
pub fn [<cast_to_ VN_ $result_name N>] $(< $( const $var : $ty),* >)? ( value: Option<$result_type> ) -> SqlResult<Option<Variant>> {
r2o([ <cast_to_ V_ $result_name N >] $(:: < $($var),* >)? (value))
}
}
};
}
macro_rules! cast_from_variant {
($result_name: ident, $result_type: ty, $enum: ident) => {
::paste::paste! {
#[doc(hidden)]
pub fn [< cast_to_ $result_name N _V >](value: Variant) -> SqlResult<Option<$result_type>> {
match value {
Variant::String(x) => r2o([< cast_to_ $result_name _s>](x)),
Variant::$enum(value) => Ok(Some(value)),
_ => Ok(None),
}
}
#[doc(hidden)]
pub fn [<cast_to_ $result_name N_ VN >]( value: Option<Variant> ) -> SqlResult<Option<$result_type>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_ $result_name N_V >](value),
}
}
}
};
}
macro_rules! cast_variant {
($result_name: ident, $result_type: ty, $enum: ident) => {
cast_to_variant!($result_name, $result_type, $enum);
cast_from_variant!($result_name, $result_type, $enum);
};
}
macro_rules! cast_from_variant_numeric {
($result_name: ident, $result_type: ty) => {
::paste::paste! {
#[doc(hidden)]
pub fn [< cast_to_ $result_name N _V >](value: Variant) -> SqlResult<Option<$result_type>> {
match value {
Variant::String(x) => r2o([< cast_to_ $result_name _s>](x)),
Variant::TinyInt(value) => r2o([< cast_to_ $result_name _i8 >](value)),
Variant::SmallInt(value) => r2o([< cast_to_ $result_name _i16 >](value)),
Variant::Int(value) => r2o([< cast_to_ $result_name _i32 >](value)),
Variant::BigInt(value) => r2o([< cast_to_ $result_name _i64 >](value)),
Variant::UTinyInt(value) => r2o([< cast_to_ $result_name _u8 >](value)),
Variant::USmallInt(value) => r2o([< cast_to_ $result_name _u16 >](value)),
Variant::UInt(value) => r2o([< cast_to_ $result_name _u32 >](value)),
Variant::UBigInt(value) => r2o([< cast_to_ $result_name _u64 >](value)),
Variant::Real(value) => r2o([< cast_to_ $result_name _f >](value)),
Variant::Double(value) => r2o([< cast_to_ $result_name _d >](value)),
Variant::SqlDecimal((value, scale)) => {
let dd = DynamicDecimal::new(value, scale);
let result = $result_type :: try_from(dd);
match result {
Ok(value) => Ok(Some(value)),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting '{value}' to {}: {}",
tn!($result_name), e
))),
}
},
_ => Ok(None),
}
}
#[doc(hidden)]
pub fn [<cast_to_ $result_name N_ VN >]( value: Option<Variant> ) -> SqlResult<Option<$result_type>> {
match value {
None => Ok(None),
Some(value) => [<cast_to_ $result_name N_V >](value),
}
}
}
};
}
macro_rules! cast_variant_numeric {
($result_name: ident, $result_type: ty, $enum: ident) => {
cast_to_variant!($result_name, $result_type, $enum);
cast_from_variant_numeric!($result_name, $result_type);
};
}
cast_variant!(b, bool, Boolean);
cast_variant_numeric!(i8, i8, TinyInt);
cast_variant_numeric!(i16, i16, SmallInt);
cast_variant_numeric!(i32, i32, Int);
cast_variant_numeric!(i64, i64, BigInt);
cast_variant_numeric!(u8, u8, UTinyInt);
cast_variant_numeric!(u16, u16, USmallInt);
cast_variant_numeric!(u32, u32, UInt);
cast_variant_numeric!(u64, u64, UBigInt);
cast_variant_numeric!(f, F32, Real);
cast_variant_numeric!(d, F64, Double);
cast_to_variant!(SqlDecimal<const P: usize, const S: usize>, SqlDecimal<P, S>, SqlDecimal); cast_to_variant!(s, SqlString, SqlString); cast_to_variant!(bytes, ByteArray, Binary); cast_variant!(Date, Date, Date);
cast_variant!(Time, Time, Time);
cast_variant!(Uuid, Uuid, Uuid);
cast_variant!(Timestamp, Timestamp, Timestamp);
cast_variant!(TimestampTz, TimestampTz, TimestampTz);
cast_variant!(ShortInterval_DAYS, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_HOURS, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_DAYS_TO_HOURS, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_MINUTES, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_DAYS_TO_MINUTES, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_HOURS_TO_MINUTES, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_SECONDS, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_DAYS_TO_SECONDS, ShortInterval, ShortInterval);
cast_variant!(ShortInterval_HOURS_TO_SECONDS, ShortInterval, ShortInterval);
cast_variant!(
ShortInterval_MINUTES_TO_SECONDS,
ShortInterval,
ShortInterval
);
cast_variant!(LongInterval_YEARS_TO_MONTHS, LongInterval, LongInterval);
cast_variant!(LongInterval_MONTHS, LongInterval, LongInterval);
cast_variant!(LongInterval_YEARS, LongInterval, LongInterval);
cast_variant!(GeoPoint, GeoPoint, Geometry);
#[doc(hidden)]
pub fn cast_to_V_vec<T>(vec: Array<T>) -> SqlResult<Variant>
where
Variant: From<T>,
T: Clone,
{
Ok(vec.into())
}
#[doc(hidden)]
pub fn cast_to_VN_vec<T>(vec: Array<T>) -> SqlResult<Option<Variant>>
where
Variant: From<T>,
T: Clone,
{
Ok(Some(vec.into()))
}
#[doc(hidden)]
pub fn cast_to_V_vecN<T>(vec: Option<Array<T>>) -> SqlResult<Variant>
where
Variant: From<T>,
T: Clone,
{
match vec {
None => Ok(Variant::SqlNull),
Some(vec) => Ok(vec.into()),
}
}
#[doc(hidden)]
pub fn cast_to_VN_vecN<T>(vec: Option<Array<T>>) -> SqlResult<Option<Variant>>
where
Variant: From<T>,
T: Clone,
{
r2o(cast_to_V_vecN(vec))
}
#[doc(hidden)]
pub fn cast_to_vec_V<T>(value: Variant) -> SqlResult<Array<T>>
where
Array<T>: TryFrom<Variant, Error = Box<dyn Error>>,
{
match value.try_into() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting VARIANT to ARRAY: {}",
e
))),
}
}
#[doc(hidden)]
pub fn cast_to_vec_VN<T>(value: Option<Variant>) -> SqlResult<Option<Array<T>>>
where
Array<T>: TryFrom<Variant, Error = Box<dyn Error>>,
T: std::fmt::Debug,
{
match value {
None => Ok(None),
Some(value) => cast_to_vecN_V(value),
}
}
#[doc(hidden)]
pub fn cast_to_vecN_V<T>(value: Variant) -> SqlResult<Option<Array<T>>>
where
Array<T>: TryFrom<Variant, Error = Box<dyn Error>>,
T: std::fmt::Debug,
{
let val = value.try_into();
match val {
Ok(value) => Ok(Some(value)),
Err(_) => Ok(None),
}
}
#[doc(hidden)]
pub fn cast_to_vecN_VN<T>(value: Option<Variant>) -> SqlResult<Option<Array<T>>>
where
Array<T>: TryFrom<Variant, Error = Box<dyn Error>>,
T: std::fmt::Debug,
{
match value {
None => Ok(None),
Some(value) => cast_to_vecN_V(value),
}
}
#[doc(hidden)]
pub fn cast_to_V_VN(value: Option<Variant>) -> SqlResult<Variant> {
match value {
None => Ok(Variant::SqlNull),
Some(x) => Ok(x),
}
}
#[doc(hidden)]
pub fn cast_to_V_map<K, V>(map: Map<K, V>) -> SqlResult<Variant>
where
Variant: From<K> + From<V>,
K: Clone + Ord,
V: Clone,
{
Ok(map.into())
}
#[doc(hidden)]
pub fn cast_to_VN_map<K, V>(map: Map<K, V>) -> SqlResult<Option<Variant>>
where
Variant: From<K> + From<V>,
K: Clone + Ord,
V: Clone,
{
r2o(cast_to_V_map(map))
}
pub fn cast_to_V_mapN<K, V>(map: Option<Map<K, V>>) -> SqlResult<Variant>
where
Variant: From<K> + From<V>,
K: Clone + Ord,
V: Clone,
{
match map {
None => Ok(Variant::SqlNull),
Some(map) => Ok(map.into()),
}
}
#[doc(hidden)]
pub fn cast_to_VN_mapN<K, V>(map: Option<Map<K, V>>) -> SqlResult<Option<Variant>>
where
Variant: From<K> + From<V>,
K: Clone + Ord,
V: Clone,
{
r2o(cast_to_V_mapN(map))
}
pub fn cast_to_map_V<K, V>(value: Variant) -> SqlResult<Map<K, V>>
where
Map<K, V>: TryFrom<Variant, Error = Box<dyn Error>>,
{
match value.try_into() {
Ok(value) => Ok(value),
Err(e) => Err(SqlRuntimeError::from_string(format!(
"Error converting VARIANT to MAP: {}",
e
))),
}
}
#[doc(hidden)]
pub fn cast_to_map_VN<K, V>(value: Option<Variant>) -> SqlResult<Option<Map<K, V>>>
where
Map<K, V>: TryFrom<Variant, Error = Box<dyn Error>>,
{
match value {
None => Ok(None),
Some(value) => cast_to_mapN_V(value),
}
}
#[doc(hidden)]
pub fn cast_to_mapN_V<K, V>(value: Variant) -> SqlResult<Option<Map<K, V>>>
where
Map<K, V>: TryFrom<Variant, Error = Box<dyn Error>>,
{
match value.try_into() {
Ok(value) => Ok(Some(value)),
Err(_) => Ok(None),
}
}
#[doc(hidden)]
pub fn cast_to_mapN_VN<K, V>(value: Option<Variant>) -> SqlResult<Option<Map<K, V>>>
where
Map<K, V>: TryFrom<Variant, Error = Box<dyn Error>>,
{
match value {
None => Ok(None),
Some(value) => cast_to_mapN_V(value),
}
}
#[doc(hidden)]
pub fn cast_to_Uuid_s(value: SqlString) -> SqlResult<Uuid> {
Uuid::try_from_ref(value.str())
}
cast_function!(Uuid, Uuid, s, SqlString);
#[doc(hidden)]
pub fn cast_to_Uuid_bytes(value: ByteArray) -> SqlResult<Uuid> {
if value.length() < 16 {
Err(SqlRuntimeError::from_strng(
"Need at least 16 bytes in BINARY value to create an UUID",
))
} else {
let slice = value.as_slice();
let slice = unsafe { *(slice.as_ptr() as *const [u8; 16]) };
Ok(Uuid::from_bytes(slice))
}
}
cast_function!(Uuid, Uuid, bytes, ByteArray);
#[doc(hidden)]
pub fn unwrap_value<T>(value: Option<T>, message: &'static str) -> SqlResult<T> {
match value {
None => Err(SqlRuntimeError::from_strng(message)),
Some(value) => Ok(value),
}
}
#[cfg(test)]
mod tests {
use arcstr::ArcStr;
use crate::{
SqlString, Uuid, cast_to_s_LongInterval_MONTHS, cast_to_s_LongInterval_YEARS,
cast_to_s_LongInterval_YEARS_TO_MONTHS, cast_to_s_ShortInterval_DAYS,
cast_to_s_ShortInterval_DAYS_TO_HOURS, cast_to_s_ShortInterval_DAYS_TO_MINUTES,
cast_to_s_ShortInterval_DAYS_TO_SECONDS, cast_to_s_ShortInterval_HOURS,
cast_to_s_ShortInterval_HOURS_TO_MINUTES, cast_to_s_ShortInterval_HOURS_TO_SECONDS,
cast_to_s_ShortInterval_MINUTES, cast_to_s_ShortInterval_MINUTES_TO_SECONDS,
cast_to_s_ShortInterval_SECONDS, cast_to_s_SqlDecimal, cast_to_s_Uuid, cast_to_s_b,
cast_to_s_i, cast_to_s_i8, cast_to_s_i16, cast_to_s_i32, cast_to_s_i64, cast_to_s_s,
cast_to_s_u, cast_to_s_u8, cast_to_s_u16, cast_to_s_u32, cast_to_s_u64,
casts::{CharacterCount, SizedStringSpec},
decimal::SqlDecimal,
interval::{LongInterval, ShortInterval},
limit_or_size_string,
};
#[test]
fn string_casts() {
assert_eq!(
cast_to_s_SqlDecimal(SqlDecimal::<38, 5>::new(123456789, 5).unwrap(), -1, false)
.unwrap(),
SqlString::from_ref("1234.56789")
);
assert_eq!(
cast_to_s_i(12345, -1, false).unwrap(),
SqlString::from_ref("12345")
);
assert_eq!(
cast_to_s_i8(-123, -1, false).unwrap(),
SqlString::from_ref("-123")
);
assert_eq!(
cast_to_s_i16(12345, -1, false).unwrap(),
SqlString::from_ref("12345")
);
assert_eq!(
cast_to_s_i32(1048576, -1, false).unwrap(),
SqlString::from_ref("1048576")
);
assert_eq!(
cast_to_s_i64(4503599627370496, -1, false).unwrap(),
SqlString::from_ref("4503599627370496")
);
assert_eq!(
cast_to_s_u(12345, -1, false).unwrap(),
SqlString::from_ref("12345")
);
assert_eq!(
cast_to_s_u8(123, -1, false).unwrap(),
SqlString::from_ref("123")
);
assert_eq!(
cast_to_s_u16(12345, -1, false).unwrap(),
SqlString::from_ref("12345")
);
assert_eq!(
cast_to_s_u32(1048576, -1, false).unwrap(),
SqlString::from_ref("1048576")
);
assert_eq!(
cast_to_s_u64(4503599627370496, -1, false).unwrap(),
SqlString::from_ref("4503599627370496")
);
assert_eq!(
cast_to_s_Uuid(
Uuid::try_from_ref(&String::from("6bc89d6d-5e0d-4c1b-9b57-787bfde2c30d")).unwrap(),
-1,
false
)
.unwrap(),
SqlString::from_ref("6bc89d6d-5e0d-4c1b-9b57-787bfde2c30d")
);
}
#[test]
fn long_interval_to_string() {
assert_eq!(
cast_to_s_LongInterval_YEARS(LongInterval::from_months(123), -1, false).unwrap(),
SqlString::from_ref("+10")
);
assert_eq!(
cast_to_s_LongInterval_YEARS(LongInterval::from_months(-123), -1, false).unwrap(),
SqlString::from_ref("-10")
);
assert_eq!(
cast_to_s_LongInterval_MONTHS(LongInterval::from_months(123), -1, false).unwrap(),
SqlString::from_ref("+123")
);
assert_eq!(
cast_to_s_LongInterval_MONTHS(LongInterval::from_months(-123), -1, false).unwrap(),
SqlString::from_ref("-123")
);
assert_eq!(
cast_to_s_LongInterval_YEARS_TO_MONTHS(LongInterval::from_months(123), -1, false)
.unwrap(),
SqlString::from_ref("+10-03")
);
assert_eq!(
cast_to_s_LongInterval_YEARS_TO_MONTHS(LongInterval::from_months(-123), -1, false)
.unwrap(),
SqlString::from_ref("-10-03")
);
}
#[test]
fn short_interval_to_string() {
assert_eq!(
cast_to_s_ShortInterval_DAYS(ShortInterval::from_milliseconds(123456789), -1, false)
.unwrap(),
SqlString::from_ref("+1")
);
assert_eq!(
cast_to_s_ShortInterval_DAYS(ShortInterval::from_milliseconds(-123456789), -1, false)
.unwrap(),
SqlString::from_ref("-1")
);
assert_eq!(
cast_to_s_ShortInterval_HOURS(ShortInterval::from_milliseconds(123456789), -1, false)
.unwrap(),
SqlString::from_ref("+34")
);
assert_eq!(
cast_to_s_ShortInterval_HOURS(ShortInterval::from_milliseconds(-123456789), -1, false)
.unwrap(),
SqlString::from_ref("-34")
);
assert_eq!(
cast_to_s_ShortInterval_DAYS_TO_HOURS(
ShortInterval::from_milliseconds(123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("+1 10")
);
assert_eq!(
cast_to_s_ShortInterval_DAYS_TO_HOURS(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-1 10")
);
assert_eq!(
cast_to_s_ShortInterval_MINUTES(ShortInterval::from_milliseconds(123456789), -1, false)
.unwrap(),
SqlString::from_ref("+2057")
);
assert_eq!(
cast_to_s_ShortInterval_MINUTES(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-2057")
);
assert_eq!(
cast_to_s_ShortInterval_DAYS_TO_MINUTES(
ShortInterval::from_milliseconds(123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("+1 10:17")
);
assert_eq!(
cast_to_s_ShortInterval_DAYS_TO_MINUTES(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-1 10:17")
);
assert_eq!(
cast_to_s_ShortInterval_HOURS_TO_MINUTES(
ShortInterval::from_milliseconds(123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("+34:17")
);
assert_eq!(
cast_to_s_ShortInterval_HOURS_TO_MINUTES(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-34:17")
);
assert_eq!(
cast_to_s_ShortInterval_SECONDS(ShortInterval::from_milliseconds(123456789), -1, false)
.unwrap(),
SqlString::from_ref("+123456.789000")
);
assert_eq!(
cast_to_s_ShortInterval_SECONDS(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-123456.789000")
);
assert_eq!(
cast_to_s_ShortInterval_DAYS_TO_SECONDS(
ShortInterval::from_milliseconds(123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("+1 10:17:36.789000")
);
assert_eq!(
cast_to_s_ShortInterval_DAYS_TO_SECONDS(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-1 10:17:36.789000")
);
assert_eq!(
cast_to_s_ShortInterval_HOURS_TO_SECONDS(
ShortInterval::from_milliseconds(123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("+34:17:36.789000")
);
assert_eq!(
cast_to_s_ShortInterval_HOURS_TO_SECONDS(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-34:17:36.789000")
);
assert_eq!(
cast_to_s_ShortInterval_MINUTES_TO_SECONDS(
ShortInterval::from_milliseconds(123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("+2057:36.789000")
);
assert_eq!(
cast_to_s_ShortInterval_MINUTES_TO_SECONDS(
ShortInterval::from_milliseconds(-123456789),
-1,
false
)
.unwrap(),
SqlString::from_ref("-2057:36.789000")
);
}
#[test]
fn bool_to_string() {
assert_eq!(
cast_to_s_b(true, -1, false).unwrap(),
SqlString::from_ref("TRUE")
);
assert_eq!(
cast_to_s_b(false, -1, false).unwrap(),
SqlString::from_ref("FALSE")
);
assert!(ArcStr::is_static(
cast_to_s_b(true, -1, false).unwrap().as_ref()
));
assert!(ArcStr::is_static(
cast_to_s_b(false, -1, false).unwrap().as_ref()
));
}
#[test]
fn character_count() {
assert_eq!(
CharacterCount::new(10, true),
Some(CharacterCount::Exact(10))
);
assert_eq!(
CharacterCount::new(10, false),
Some(CharacterCount::Limit(10))
);
assert_eq!(CharacterCount::new(-1, false), None);
}
#[test]
#[should_panic]
fn invalid_character_count() {
CharacterCount::new(-1, true);
}
#[test]
fn sized_string_spec() {
for (size, expected, n_spaces) in [
(0, "", 0),
(1, "a", 0),
(2, "ab", 0),
(3, "ab🥳", 0),
(4, "ab🥳c", 0),
(5, "ab🥳cd", 0),
(6, "ab🥳cd", 1),
(7, "ab🥳cd", 2),
(8, "ab🥳cd", 3),
] {
assert_eq!(
SizedStringSpec::for_character_count("ab🥳cd", size, true),
SizedStringSpec::new(expected).with_spaces(n_spaces)
);
}
for (size, expected) in [
(-1, "ab🥳cd"),
(0, ""),
(1, "a"),
(2, "ab"),
(3, "ab🥳"),
(4, "ab🥳c"),
(5, "ab🥳cd"),
(6, "ab🥳cd"),
(7, "ab🥳cd"),
(8, "ab🥳cd"),
] {
assert_eq!(
SizedStringSpec::for_character_count("ab🥳cd", size, false),
SizedStringSpec::new(expected),
"size={size}"
);
}
}
#[test]
fn test_limit_or_size_string() {
for (size, fixed, expected) in [
(0, true, ""),
(1, true, "a"),
(2, true, "ab"),
(3, true, "ab🥳"),
(4, true, "ab🥳c"),
(5, true, "ab🥳cd"),
(6, true, "ab🥳cd "),
(7, true, "ab🥳cd "),
(-1, false, "ab🥳cd"),
(0, false, ""),
(1, false, "a"),
(2, false, "ab"),
(3, false, "ab🥳"),
(4, false, "ab🥳c"),
(5, false, "ab🥳cd"),
(6, false, "ab🥳cd"),
(7, false, "ab🥳cd"),
] {
assert_eq!(
limit_or_size_string("ab🥳cd", size, fixed).unwrap(),
SqlString::from_ref(expected)
);
assert_eq!(
cast_to_s_s(SqlString::from_ref("ab🥳cd"), size, fixed).unwrap(),
SqlString::from_ref(expected)
);
}
}
}