Merge pull request #1311 from SeaQL/select-into-tuple
Select into tuple
This commit is contained in:
commit
4210526ec1
@ -352,8 +352,8 @@ impl ActiveEnum {
|
|||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl sea_orm::TryGetable for #ident {
|
impl sea_orm::TryGetable for #ident {
|
||||||
fn try_get(res: &sea_orm::QueryResult, pre: &str, col: &str) -> std::result::Result<Self, sea_orm::TryGetError> {
|
fn try_get_by<I: sea_orm::ColIdx>(res: &sea_orm::QueryResult, idx: I) -> std::result::Result<Self, sea_orm::TryGetError> {
|
||||||
let value = <<Self as sea_orm::ActiveEnum>::Value as sea_orm::TryGetable>::try_get(res, pre, col)?;
|
let value = <<Self as sea_orm::ActiveEnum>::Value as sea_orm::TryGetable>::try_get_by(res, idx)?;
|
||||||
<Self as sea_orm::ActiveEnum>::try_from_value(&value).map_err(sea_orm::TryGetError::DbErr)
|
<Self as sea_orm::ActiveEnum>::try_from_value(&value).map_err(sea_orm::TryGetError::DbErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,12 +203,25 @@ impl MockDatabaseTrait for MockDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MockRow {
|
impl MockRow {
|
||||||
/// Try to get the values of a [MockRow] and fail gracefully on error
|
/// Get a value from the [MockRow]
|
||||||
pub fn try_get<T>(&self, col: &str) -> Result<T, DbErr>
|
pub fn try_get<T, I: crate::ColIdx>(&self, index: I) -> Result<T, DbErr>
|
||||||
where
|
where
|
||||||
T: ValueType,
|
T: ValueType,
|
||||||
{
|
{
|
||||||
T::try_from(self.values.get(col).unwrap().clone()).map_err(|e| DbErr::Type(e.to_string()))
|
if let Some(index) = index.as_str() {
|
||||||
|
T::try_from(self.values.get(index).unwrap().clone())
|
||||||
|
.map_err(|e| DbErr::Type(e.to_string()))
|
||||||
|
} else if let Some(index) = index.as_usize() {
|
||||||
|
let (_, value) = self.values.iter().nth(*index).ok_or_else(|| {
|
||||||
|
DbErr::Query(RuntimeErr::Internal(format!(
|
||||||
|
"Column at index {} not found",
|
||||||
|
index
|
||||||
|
)))
|
||||||
|
})?;
|
||||||
|
T::try_from(value.clone()).map_err(|e| DbErr::Type(e.to_string()))
|
||||||
|
} else {
|
||||||
|
unreachable!("Missing ColIdx implementation for MockRow");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the keys and values of a mock row
|
/// An iterator over the keys and values of a mock row
|
||||||
@ -686,10 +699,10 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let mocked_row = row.into_mock_row();
|
let mocked_row = row.into_mock_row();
|
||||||
|
|
||||||
let a_id = mocked_row.try_get::<i32>("A_id");
|
let a_id = mocked_row.try_get::<i32, _>("A_id");
|
||||||
assert!(a_id.is_ok());
|
assert!(a_id.is_ok());
|
||||||
assert_eq!(1, a_id.unwrap());
|
assert_eq!(1, a_id.unwrap());
|
||||||
let b_id = mocked_row.try_get::<i32>("B_id");
|
let b_id = mocked_row.try_get::<i32, _>("B_id");
|
||||||
assert!(b_id.is_ok());
|
assert!(b_id.is_ok());
|
||||||
assert_eq!(2, b_id.unwrap());
|
assert_eq!(2, b_id.unwrap());
|
||||||
}
|
}
|
||||||
|
@ -275,7 +275,7 @@ impl DatabaseTransaction {
|
|||||||
if let Err(sqlx::Error::RowNotFound) = err {
|
if let Err(sqlx::Error::RowNotFound) = err {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
err.map_err(|e| sqlx_error_to_query_err(e))
|
err.map_err(sqlx_error_to_query_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,8 +152,8 @@ where
|
|||||||
T: ActiveEnum,
|
T: ActiveEnum,
|
||||||
T::ValueVec: TryGetable,
|
T::ValueVec: TryGetable,
|
||||||
{
|
{
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: crate::ColIdx>(res: &QueryResult, index: I) -> Result<Self, TryGetError> {
|
||||||
<T::ValueVec as TryGetable>::try_get(res, pre, col)?
|
<T::ValueVec as TryGetable>::try_get_by(res, index)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|value| T::try_from_value(&value).map_err(TryGetError::DbErr))
|
.map(|value| T::try_from_value(&value).map_err(TryGetError::DbErr))
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -21,10 +21,21 @@ pub(crate) enum QueryResultRow {
|
|||||||
Mock(crate::MockRow),
|
Mock(crate::MockRow),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constrain any type trying to get a Row in a database
|
/// An interface to get a value from the query result
|
||||||
pub trait TryGetable: Sized {
|
pub trait TryGetable: Sized {
|
||||||
/// Ensure the type implements this method
|
/// Get a value from the query result with an ColIdx
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError>;
|
fn try_get_by<I: ColIdx>(res: &QueryResult, index: I) -> Result<Self, TryGetError>;
|
||||||
|
|
||||||
|
/// Get a value from the query result with prefixed column name
|
||||||
|
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
||||||
|
let index = format!("{}{}", pre, col);
|
||||||
|
Self::try_get_by(res, index.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a value from the query result based on the order in the select expressions
|
||||||
|
fn try_get_by_index(res: &QueryResult, index: usize) -> Result<Self, TryGetError> {
|
||||||
|
Self::try_get_by(res, index)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An error from trying to get a row from a Model
|
/// An error from trying to get a row from a Model
|
||||||
@ -50,7 +61,16 @@ impl From<TryGetError> for DbErr {
|
|||||||
// QueryResult //
|
// QueryResult //
|
||||||
|
|
||||||
impl QueryResult {
|
impl QueryResult {
|
||||||
/// Get a Row from a Column
|
/// Get a value from the query result with an ColIdx
|
||||||
|
pub fn try_get_by<T, I>(&self, index: I) -> Result<T, DbErr>
|
||||||
|
where
|
||||||
|
T: TryGetable,
|
||||||
|
I: ColIdx,
|
||||||
|
{
|
||||||
|
Ok(T::try_get_by(self, index)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a value from the query result with prefixed column name
|
||||||
pub fn try_get<T>(&self, pre: &str, col: &str) -> Result<T, DbErr>
|
pub fn try_get<T>(&self, pre: &str, col: &str) -> Result<T, DbErr>
|
||||||
where
|
where
|
||||||
T: TryGetable,
|
T: TryGetable,
|
||||||
@ -58,13 +78,29 @@ impl QueryResult {
|
|||||||
Ok(T::try_get(self, pre, col)?)
|
Ok(T::try_get(self, pre, col)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform query operations on multiple Columns
|
/// Get a value from the query result based on the order in the select expressions
|
||||||
|
pub fn try_get_by_index<T>(&self, idx: usize) -> Result<T, DbErr>
|
||||||
|
where
|
||||||
|
T: TryGetable,
|
||||||
|
{
|
||||||
|
Ok(T::try_get_by_index(self, idx)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a tuple value from the query result with prefixed column name
|
||||||
pub fn try_get_many<T>(&self, pre: &str, cols: &[String]) -> Result<T, DbErr>
|
pub fn try_get_many<T>(&self, pre: &str, cols: &[String]) -> Result<T, DbErr>
|
||||||
where
|
where
|
||||||
T: TryGetableMany,
|
T: TryGetableMany,
|
||||||
{
|
{
|
||||||
Ok(T::try_get_many(self, pre, cols)?)
|
Ok(T::try_get_many(self, pre, cols)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a tuple value from the query result based on the order in the select expressions
|
||||||
|
pub fn try_get_many_by_index<T>(&self) -> Result<T, DbErr>
|
||||||
|
where
|
||||||
|
T: TryGetableMany,
|
||||||
|
{
|
||||||
|
Ok(T::try_get_many_by_index(self)?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@ -88,8 +124,8 @@ impl fmt::Debug for QueryResultRow {
|
|||||||
// TryGetable //
|
// TryGetable //
|
||||||
|
|
||||||
impl<T: TryGetable> TryGetable for Option<T> {
|
impl<T: TryGetable> TryGetable for Option<T> {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: ColIdx>(res: &QueryResult, index: I) -> Result<Self, TryGetError> {
|
||||||
match T::try_get(res, pre, col) {
|
match T::try_get_by(res, index) {
|
||||||
Ok(v) => Ok(Some(v)),
|
Ok(v) => Ok(Some(v)),
|
||||||
Err(TryGetError::Null(_)) => Ok(None),
|
Err(TryGetError::Null(_)) => Ok(None),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
@ -97,39 +133,133 @@ impl<T: TryGetable> TryGetable for Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Column Index, used by [`TryGetable`]
|
||||||
|
pub trait ColIdx: std::fmt::Debug + Copy {
|
||||||
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
|
/// Type shenanigans
|
||||||
|
type SqlxMySqlIndex: sqlx::ColumnIndex<sqlx::mysql::MySqlRow>;
|
||||||
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
|
/// Type shenanigans
|
||||||
|
type SqlxPostgresIndex: sqlx::ColumnIndex<sqlx::postgres::PgRow>;
|
||||||
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
|
/// Type shenanigans
|
||||||
|
type SqlxSqliteIndex: sqlx::ColumnIndex<sqlx::sqlite::SqliteRow>;
|
||||||
|
|
||||||
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
|
/// Basically a no-op; only to satisfy a trait bound
|
||||||
|
fn as_sqlx_mysql_index(&self) -> Self::SqlxMySqlIndex;
|
||||||
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
|
/// Basically a no-op; only to satisfy a trait bound
|
||||||
|
fn as_sqlx_postgres_index(&self) -> Self::SqlxPostgresIndex;
|
||||||
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
|
/// Basically a no-op; only to satisfy a trait bound
|
||||||
|
fn as_sqlx_sqlite_index(&self) -> Self::SqlxSqliteIndex;
|
||||||
|
|
||||||
|
/// Self must be `&str`, return `None` otherwise
|
||||||
|
fn as_str(&self) -> Option<&str>;
|
||||||
|
/// Self must be `usize`, return `None` otherwise
|
||||||
|
fn as_usize(&self) -> Option<&usize>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColIdx for &str {
|
||||||
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
|
type SqlxMySqlIndex = Self;
|
||||||
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
|
type SqlxPostgresIndex = Self;
|
||||||
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
|
type SqlxSqliteIndex = Self;
|
||||||
|
|
||||||
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
|
#[inline]
|
||||||
|
fn as_sqlx_mysql_index(&self) -> Self::SqlxMySqlIndex {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
|
#[inline]
|
||||||
|
fn as_sqlx_postgres_index(&self) -> Self::SqlxPostgresIndex {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
|
#[inline]
|
||||||
|
fn as_sqlx_sqlite_index(&self) -> Self::SqlxSqliteIndex {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> Option<&str> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn as_usize(&self) -> Option<&usize> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColIdx for usize {
|
||||||
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
|
type SqlxMySqlIndex = Self;
|
||||||
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
|
type SqlxPostgresIndex = Self;
|
||||||
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
|
type SqlxSqliteIndex = Self;
|
||||||
|
|
||||||
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
|
#[inline]
|
||||||
|
fn as_sqlx_mysql_index(&self) -> Self::SqlxMySqlIndex {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
|
#[inline]
|
||||||
|
fn as_sqlx_postgres_index(&self) -> Self::SqlxPostgresIndex {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
|
#[inline]
|
||||||
|
fn as_sqlx_sqlite_index(&self) -> Self::SqlxSqliteIndex {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> Option<&str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn as_usize(&self) -> Option<&usize> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! try_getable_all {
|
macro_rules! try_getable_all {
|
||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
#[allow(unused_variables)]
|
|
||||||
impl TryGetable for $type {
|
impl TryGetable for $type {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
#[allow(unused_variables)]
|
||||||
let column = format!("{}{}", pre, col);
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(idx.as_sqlx_sqlite_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -142,16 +272,15 @@ macro_rules! try_getable_all {
|
|||||||
macro_rules! try_getable_unsigned {
|
macro_rules! try_getable_unsigned {
|
||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
impl TryGetable for $type {
|
impl TryGetable for $type {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let column = format!("{}{}", pre, col);
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(_) => {
|
QueryResultRow::SqlxPostgres(_) => {
|
||||||
@ -160,15 +289,14 @@ macro_rules! try_getable_unsigned {
|
|||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(idx.as_sqlx_sqlite_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -181,16 +309,15 @@ macro_rules! try_getable_unsigned {
|
|||||||
macro_rules! try_getable_mysql {
|
macro_rules! try_getable_mysql {
|
||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
impl TryGetable for $type {
|
impl TryGetable for $type {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let column = format!("{}{}", pre, col);
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(_) => {
|
QueryResultRow::SqlxPostgres(_) => {
|
||||||
@ -201,10 +328,9 @@ macro_rules! try_getable_mysql {
|
|||||||
panic!("{} unsupported by sqlx-sqlite", stringify!($type))
|
panic!("{} unsupported by sqlx-sqlite", stringify!($type))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -218,40 +344,38 @@ macro_rules! try_getable_mysql {
|
|||||||
macro_rules! try_getable_date_time {
|
macro_rules! try_getable_date_time {
|
||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
impl TryGetable for $type {
|
impl TryGetable for $type {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let column = format!("{}{}", pre, col);
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<DateTime<Utc>>, _>(column.as_str())
|
row.try_get::<Option<DateTime<Utc>>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
.map(|v| v.into())
|
.map(|v| v.into())
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<DateTime<Utc>>, _>(column.as_str())
|
row.try_get::<Option<DateTime<Utc>>, _>(idx.as_sqlx_sqlite_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
.map(|v| v.into())
|
.map(|v| v.into())
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -313,28 +437,27 @@ use rust_decimal::Decimal;
|
|||||||
#[cfg(feature = "with-rust_decimal")]
|
#[cfg(feature = "with-rust_decimal")]
|
||||||
impl TryGetable for Decimal {
|
impl TryGetable for Decimal {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
let column = format!("{}{}", pre, col);
|
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<Decimal>, _>(column.as_str())
|
row.try_get::<Option<Decimal>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<Decimal>, _>(column.as_str())
|
row.try_get::<Option<Decimal>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
let val: Option<f64> = row
|
let val: Option<f64> = row
|
||||||
.try_get(column.as_str())
|
.try_get(idx.as_sqlx_sqlite_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))?;
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))?;
|
||||||
match val {
|
match val {
|
||||||
Some(v) => Decimal::try_from(v).map_err(|e| {
|
Some(v) => Decimal::try_from(v).map_err(|e| {
|
||||||
@ -344,14 +467,14 @@ impl TryGetable for Decimal {
|
|||||||
source: Box::new(e),
|
source: Box::new(e),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
None => Err(TryGetError::Null(column)),
|
None => Err(err_null_idx_col(idx)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -365,28 +488,27 @@ use bigdecimal::BigDecimal;
|
|||||||
#[cfg(feature = "with-bigdecimal")]
|
#[cfg(feature = "with-bigdecimal")]
|
||||||
impl TryGetable for BigDecimal {
|
impl TryGetable for BigDecimal {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
let column = format!("{}{}", pre, col);
|
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<BigDecimal>, _>(column.as_str())
|
row.try_get::<Option<BigDecimal>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<BigDecimal>, _>(column.as_str())
|
row.try_get::<Option<BigDecimal>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
let val: Option<f64> = row
|
let val: Option<f64> = row
|
||||||
.try_get(column.as_str())
|
.try_get(idx.as_sqlx_sqlite_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))?;
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))?;
|
||||||
match val {
|
match val {
|
||||||
Some(v) => BigDecimal::try_from(v).map_err(|e| {
|
Some(v) => BigDecimal::try_from(v).map_err(|e| {
|
||||||
@ -396,14 +518,14 @@ impl TryGetable for BigDecimal {
|
|||||||
source: Box::new(e),
|
source: Box::new(e),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
None => Err(TryGetError::Null(column)),
|
None => Err(err_null_idx_col(idx)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -415,16 +537,15 @@ impl TryGetable for BigDecimal {
|
|||||||
try_getable_all!(uuid::Uuid);
|
try_getable_all!(uuid::Uuid);
|
||||||
|
|
||||||
impl TryGetable for u32 {
|
impl TryGetable for u32 {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let column = format!("{}{}", pre, col);
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<u32>, _>(column.as_str())
|
row.try_get::<Option<u32>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
@ -432,23 +553,23 @@ impl TryGetable for u32 {
|
|||||||
// Since 0.6.0, SQLx has dropped direct mapping from PostgreSQL's OID to Rust's `u32`;
|
// Since 0.6.0, SQLx has dropped direct mapping from PostgreSQL's OID to Rust's `u32`;
|
||||||
// Instead, `u32` was wrapped by a `sqlx::Oid`.
|
// Instead, `u32` was wrapped by a `sqlx::Oid`.
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<Oid>, _>(column.as_str())
|
row.try_get::<Option<Oid>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
.map(|oid| oid.0)
|
.map(|oid| oid.0)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<u32>, _>(column.as_str())
|
row.try_get::<Option<u32>, _>(idx.as_sqlx_sqlite_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -456,6 +577,11 @@ impl TryGetable for u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn err_null_idx_col<I: ColIdx>(idx: I) -> TryGetError {
|
||||||
|
TryGetError::Null(format!("{:?}", idx))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "postgres-array")]
|
#[cfg(feature = "postgres-array")]
|
||||||
mod postgres_array {
|
mod postgres_array {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -463,30 +589,30 @@ mod postgres_array {
|
|||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
macro_rules! try_getable_postgres_array {
|
macro_rules! try_getable_postgres_array {
|
||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
impl TryGetable for Vec<$type> {
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
impl TryGetable for Vec<$type> {
|
||||||
let column = format!("{}{}", pre, col);
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(_) => {
|
||||||
panic!("{} unsupported by sqlx-mysql", stringify!($type))
|
panic!("{} unsupported by sqlx-mysql", stringify!($type))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<Vec<$type>>, _>(column.as_str())
|
row.try_get::<Option<Vec<$type>>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(_) => {
|
QueryResultRow::SqlxSqlite(_) => {
|
||||||
panic!("{} unsupported by sqlx-sqlite", stringify!($type))
|
panic!("{} unsupported by sqlx-sqlite", stringify!($type))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
#[allow(unused_variables)]
|
||||||
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -549,11 +675,10 @@ mod postgres_array {
|
|||||||
|
|
||||||
impl TryGetable for Vec<u32> {
|
impl TryGetable for Vec<u32> {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
let column = format!("{}{}", pre, col);
|
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(_) => {
|
||||||
panic!("{} unsupported by sqlx-mysql", stringify!($type))
|
panic!("{} unsupported by sqlx-mysql", stringify!($type))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
@ -562,9 +687,9 @@ mod postgres_array {
|
|||||||
// Since 0.6.0, SQLx has dropped direct mapping from PostgreSQL's OID to Rust's `u32`;
|
// Since 0.6.0, SQLx has dropped direct mapping from PostgreSQL's OID to Rust's `u32`;
|
||||||
// Instead, `u32` was wrapped by a `sqlx::Oid`.
|
// Instead, `u32` was wrapped by a `sqlx::Oid`.
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<Vec<Oid>>, _>(column.as_str())
|
row.try_get::<Option<Vec<Oid>>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)))
|
||||||
.map(|oids| oids.into_iter().map(|oid| oid.0).collect())
|
.map(|oids| oids.into_iter().map(|oid| oid.0).collect())
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
@ -572,9 +697,10 @@ mod postgres_array {
|
|||||||
panic!("{} unsupported by sqlx-sqlite", stringify!($type))
|
panic!("{} unsupported by sqlx-sqlite", stringify!($type))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
#[allow(unused_variables)]
|
||||||
|
QueryResultRow::Mock(row) => row.try_get(idx).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
}),
|
}),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -585,11 +711,14 @@ mod postgres_array {
|
|||||||
|
|
||||||
// TryGetableMany //
|
// TryGetableMany //
|
||||||
|
|
||||||
/// Perform a query on multiple columns
|
/// An interface to get a tuple value from the query result
|
||||||
pub trait TryGetableMany: Sized {
|
pub trait TryGetableMany: Sized {
|
||||||
/// THe method to perform a query on multiple columns
|
/// Get a tuple value from the query result with prefixed column name
|
||||||
fn try_get_many(res: &QueryResult, pre: &str, cols: &[String]) -> Result<Self, TryGetError>;
|
fn try_get_many(res: &QueryResult, pre: &str, cols: &[String]) -> Result<Self, TryGetError>;
|
||||||
|
|
||||||
|
/// Get a tuple value from the query result based on the order in the select expressions
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError>;
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, *};
|
/// # use sea_orm::{error::*, tests_cfg::*, *};
|
||||||
/// #
|
/// #
|
||||||
@ -663,6 +792,10 @@ where
|
|||||||
try_get_many_with_slice_len_of(1, cols)?;
|
try_get_many_with_slice_len_of(1, cols)?;
|
||||||
T::try_get(res, pre, &cols[0])
|
T::try_get(res, pre, &cols[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError> {
|
||||||
|
T::try_get_by_index(res, 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TryGetableMany for (T,)
|
impl<T> TryGetableMany for (T,)
|
||||||
@ -672,6 +805,10 @@ where
|
|||||||
fn try_get_many(res: &QueryResult, pre: &str, cols: &[String]) -> Result<Self, TryGetError> {
|
fn try_get_many(res: &QueryResult, pre: &str, cols: &[String]) -> Result<Self, TryGetError> {
|
||||||
T::try_get_many(res, pre, cols).map(|r| (r,))
|
T::try_get_many(res, pre, cols).map(|r| (r,))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError> {
|
||||||
|
T::try_get_many_by_index(res).map(|r| (r,))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B> TryGetableMany for (A, B)
|
impl<A, B> TryGetableMany for (A, B)
|
||||||
@ -686,6 +823,10 @@ where
|
|||||||
B::try_get(res, pre, &cols[1])?,
|
B::try_get(res, pre, &cols[1])?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError> {
|
||||||
|
Ok((A::try_get_by_index(res, 0)?, B::try_get_by_index(res, 1)?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, C> TryGetableMany for (A, B, C)
|
impl<A, B, C> TryGetableMany for (A, B, C)
|
||||||
@ -702,6 +843,14 @@ where
|
|||||||
C::try_get(res, pre, &cols[2])?,
|
C::try_get(res, pre, &cols[2])?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError> {
|
||||||
|
Ok((
|
||||||
|
A::try_get_by_index(res, 0)?,
|
||||||
|
B::try_get_by_index(res, 1)?,
|
||||||
|
C::try_get_by_index(res, 2)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, C, D> TryGetableMany for (A, B, C, D)
|
impl<A, B, C, D> TryGetableMany for (A, B, C, D)
|
||||||
@ -720,6 +869,15 @@ where
|
|||||||
D::try_get(res, pre, &cols[3])?,
|
D::try_get(res, pre, &cols[3])?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError> {
|
||||||
|
Ok((
|
||||||
|
A::try_get_by_index(res, 0)?,
|
||||||
|
B::try_get_by_index(res, 1)?,
|
||||||
|
C::try_get_by_index(res, 2)?,
|
||||||
|
D::try_get_by_index(res, 3)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, C, D, E> TryGetableMany for (A, B, C, D, E)
|
impl<A, B, C, D, E> TryGetableMany for (A, B, C, D, E)
|
||||||
@ -740,6 +898,16 @@ where
|
|||||||
E::try_get(res, pre, &cols[4])?,
|
E::try_get(res, pre, &cols[4])?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError> {
|
||||||
|
Ok((
|
||||||
|
A::try_get_by_index(res, 0)?,
|
||||||
|
B::try_get_by_index(res, 1)?,
|
||||||
|
C::try_get_by_index(res, 2)?,
|
||||||
|
D::try_get_by_index(res, 3)?,
|
||||||
|
E::try_get_by_index(res, 4)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, C, D, E, F> TryGetableMany for (A, B, C, D, E, F)
|
impl<A, B, C, D, E, F> TryGetableMany for (A, B, C, D, E, F)
|
||||||
@ -762,6 +930,17 @@ where
|
|||||||
F::try_get(res, pre, &cols[5])?,
|
F::try_get(res, pre, &cols[5])?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_many_by_index(res: &QueryResult) -> Result<Self, TryGetError> {
|
||||||
|
Ok((
|
||||||
|
A::try_get_by_index(res, 0)?,
|
||||||
|
B::try_get_by_index(res, 1)?,
|
||||||
|
C::try_get_by_index(res, 2)?,
|
||||||
|
D::try_get_by_index(res, 3)?,
|
||||||
|
E::try_get_by_index(res, 4)?,
|
||||||
|
F::try_get_by_index(res, 5)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_get_many_with_slice_len_of(len: usize, cols: &[String]) -> Result<(), TryGetError> {
|
fn try_get_many_with_slice_len_of(len: usize, cols: &[String]) -> Result<(), TryGetError> {
|
||||||
@ -778,44 +957,43 @@ fn try_get_many_with_slice_len_of(len: usize, cols: &[String]) -> Result<(), Try
|
|||||||
|
|
||||||
// TryGetableFromJson //
|
// TryGetableFromJson //
|
||||||
|
|
||||||
/// Perform a query on multiple columns
|
/// An interface to get a JSON from the query result
|
||||||
#[cfg(feature = "with-json")]
|
#[cfg(feature = "with-json")]
|
||||||
pub trait TryGetableFromJson: Sized
|
pub trait TryGetableFromJson: Sized
|
||||||
where
|
where
|
||||||
for<'de> Self: serde::Deserialize<'de>,
|
for<'de> Self: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
/// Ensure the type implements this method
|
/// Get a JSON from the query result with prefixed column name
|
||||||
#[allow(unused_variables, unreachable_code)]
|
#[allow(unused_variables, unreachable_code)]
|
||||||
fn try_get_from_json(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_from_json<I: ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
let column = format!("{}{}", pre, col);
|
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<sqlx::types::Json<Self>>, _>(column.as_str())
|
row.try_get::<Option<sqlx::types::Json<Self>>, _>(idx.as_sqlx_mysql_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)).map(|json| json.0))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)).map(|json| json.0))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<sqlx::types::Json<Self>>, _>(column.as_str())
|
row.try_get::<Option<sqlx::types::Json<Self>>, _>(idx.as_sqlx_postgres_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)).map(|json| json.0))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)).map(|json| json.0))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<sqlx::types::Json<Self>>, _>(column.as_str())
|
row.try_get::<Option<sqlx::types::Json<Self>>, _>(idx.as_sqlx_sqlite_index())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null(column)).map(|json| json.0))
|
.and_then(|opt| opt.ok_or_else(|| err_null_idx_col(idx)).map(|json| json.0))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
QueryResultRow::Mock(row) => row
|
QueryResultRow::Mock(row) => row
|
||||||
.try_get::<serde_json::Value>(column.as_str())
|
.try_get::<serde_json::Value, I>(idx)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null(column)
|
err_null_idx_col(idx)
|
||||||
})
|
})
|
||||||
.and_then(|json| {
|
.and_then(|json| {
|
||||||
serde_json::from_value(json)
|
serde_json::from_value(json)
|
||||||
@ -832,8 +1010,8 @@ impl<T> TryGetable for T
|
|||||||
where
|
where
|
||||||
T: TryGetableFromJson,
|
T: TryGetableFromJson,
|
||||||
{
|
{
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: ColIdx>(res: &QueryResult, index: I) -> Result<Self, TryGetError> {
|
||||||
T::try_get_from_json(res, pre, col)
|
T::try_get_from_json(res, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ pub trait SelectorTrait {
|
|||||||
fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr>;
|
fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform an operation on an entity that can yield a Value
|
/// Get tuple from query result based on a list of column identifiers
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SelectGetableValue<T, C>
|
pub struct SelectGetableValue<T, C>
|
||||||
where
|
where
|
||||||
@ -52,6 +52,15 @@ where
|
|||||||
model: PhantomData<T>,
|
model: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get tuple from query result based on column index
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SelectGetableTuple<T>
|
||||||
|
where
|
||||||
|
T: TryGetableMany,
|
||||||
|
{
|
||||||
|
model: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Defines a type to get a Model
|
/// Defines a type to get a Model
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SelectModel<M>
|
pub struct SelectModel<M>
|
||||||
@ -84,6 +93,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> SelectorTrait for SelectGetableTuple<T>
|
||||||
|
where
|
||||||
|
T: TryGetableMany,
|
||||||
|
{
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
|
||||||
|
T::try_get_many_by_index(&res).map_err(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<M> SelectorTrait for SelectModel<M>
|
impl<M> SelectorTrait for SelectModel<M>
|
||||||
where
|
where
|
||||||
M: FromQueryResult + Sized,
|
M: FromQueryResult + Sized,
|
||||||
@ -253,6 +273,104 @@ where
|
|||||||
Selector::<SelectGetableValue<T, C>>::with_columns(self.query)
|
Selector::<SelectGetableValue<T, C>>::with_columns(self.query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// # use sea_orm::{error::*, tests_cfg::*, *};
|
||||||
|
/// #
|
||||||
|
/// # #[smol_potat::main]
|
||||||
|
/// # #[cfg(all(feature = "mock", feature = "macros"))]
|
||||||
|
/// # pub async fn main() -> Result<(), DbErr> {
|
||||||
|
/// #
|
||||||
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
|
/// # .append_query_results(vec![vec![
|
||||||
|
/// # maplit::btreemap! {
|
||||||
|
/// # "cake_name" => Into::<Value>::into("Chocolate Forest"),
|
||||||
|
/// # },
|
||||||
|
/// # maplit::btreemap! {
|
||||||
|
/// # "cake_name" => Into::<Value>::into("New York Cheese"),
|
||||||
|
/// # },
|
||||||
|
/// # ]])
|
||||||
|
/// # .into_connection();
|
||||||
|
/// #
|
||||||
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake};
|
||||||
|
///
|
||||||
|
/// let res: Vec<String> = cake::Entity::find()
|
||||||
|
/// .select_only()
|
||||||
|
/// .column(cake::Column::Name)
|
||||||
|
/// .into_tuple()
|
||||||
|
/// .all(&db)
|
||||||
|
/// .await?;
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// res,
|
||||||
|
/// vec!["Chocolate Forest".to_owned(), "New York Cheese".to_owned()]
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// db.into_transaction_log(),
|
||||||
|
/// vec![Transaction::from_sql_and_values(
|
||||||
|
/// DbBackend::Postgres,
|
||||||
|
/// r#"SELECT "cake"."name" FROM "cake""#,
|
||||||
|
/// vec![]
|
||||||
|
/// )]
|
||||||
|
/// );
|
||||||
|
/// #
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use sea_orm::{error::*, tests_cfg::*, *};
|
||||||
|
/// #
|
||||||
|
/// # #[smol_potat::main]
|
||||||
|
/// # #[cfg(all(feature = "mock", feature = "macros"))]
|
||||||
|
/// # pub async fn main() -> Result<(), DbErr> {
|
||||||
|
/// #
|
||||||
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
|
/// # .append_query_results(vec![vec![
|
||||||
|
/// # maplit::btreemap! {
|
||||||
|
/// # "cake_name" => Into::<Value>::into("Chocolate Forest"),
|
||||||
|
/// # "num_of_cakes" => Into::<Value>::into(2i64),
|
||||||
|
/// # },
|
||||||
|
/// # ]])
|
||||||
|
/// # .into_connection();
|
||||||
|
/// #
|
||||||
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake};
|
||||||
|
///
|
||||||
|
/// let res: Vec<(String, i64)> = cake::Entity::find()
|
||||||
|
/// .select_only()
|
||||||
|
/// .column(cake::Column::Name)
|
||||||
|
/// .column(cake::Column::Id)
|
||||||
|
/// .group_by(cake::Column::Name)
|
||||||
|
/// .into_tuple()
|
||||||
|
/// .all(&db)
|
||||||
|
/// .await?;
|
||||||
|
///
|
||||||
|
/// assert_eq!(res, vec![("Chocolate Forest".to_owned(), 2i64)]);
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// db.into_transaction_log(),
|
||||||
|
/// vec![Transaction::from_sql_and_values(
|
||||||
|
/// DbBackend::Postgres,
|
||||||
|
/// vec![
|
||||||
|
/// r#"SELECT "cake"."name", "cake"."id""#,
|
||||||
|
/// r#"FROM "cake" GROUP BY "cake"."name""#,
|
||||||
|
/// ]
|
||||||
|
/// .join(" ")
|
||||||
|
/// .as_str(),
|
||||||
|
/// vec![]
|
||||||
|
/// )]
|
||||||
|
/// );
|
||||||
|
/// #
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn into_tuple<T>(self) -> Selector<SelectGetableTuple<T>>
|
||||||
|
where
|
||||||
|
T: TryGetableMany,
|
||||||
|
{
|
||||||
|
Selector::<SelectGetableTuple<T>>::into_tuple(self.query)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get one Model from the SELECT query
|
/// Get one Model from the SELECT query
|
||||||
pub async fn one<'a, C>(self, db: &C) -> Result<Option<E::Model>, DbErr>
|
pub async fn one<'a, C>(self, db: &C) -> Result<Option<E::Model>, DbErr>
|
||||||
where
|
where
|
||||||
@ -402,7 +520,7 @@ impl<S> Selector<S>
|
|||||||
where
|
where
|
||||||
S: SelectorTrait,
|
S: SelectorTrait,
|
||||||
{
|
{
|
||||||
/// Create `Selector` from Statment and columns. Executing this `Selector`
|
/// Create `Selector` from Statement and columns. Executing this `Selector`
|
||||||
/// will return a type `T` which implement `TryGetableMany`.
|
/// will return a type `T` which implement `TryGetableMany`.
|
||||||
pub fn with_columns<T, C>(query: SelectStatement) -> Selector<SelectGetableValue<T, C>>
|
pub fn with_columns<T, C>(query: SelectStatement) -> Selector<SelectGetableValue<T, C>>
|
||||||
where
|
where
|
||||||
@ -418,6 +536,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get tuple from query result based on column index
|
||||||
|
pub fn into_tuple<T>(query: SelectStatement) -> Selector<SelectGetableTuple<T>>
|
||||||
|
where
|
||||||
|
T: TryGetableMany,
|
||||||
|
{
|
||||||
|
Selector {
|
||||||
|
query,
|
||||||
|
selector: SelectGetableTuple { model: PhantomData },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn into_selector_raw<C>(self, db: &C) -> SelectorRaw<S>
|
fn into_selector_raw<C>(self, db: &C) -> SelectorRaw<S>
|
||||||
where
|
where
|
||||||
C: ConnectionTrait,
|
C: ConnectionTrait,
|
||||||
|
@ -76,5 +76,23 @@ pub async fn create_and_update(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Entity::find()
|
||||||
|
.filter(Column::Id.eq(vec![1_u8, 2_u8, 3_u8])) // annotate it as Vec<u8> explicitly
|
||||||
|
.into_values::<_, Column>()
|
||||||
|
.one(db)
|
||||||
|
.await?,
|
||||||
|
Some((vec![1_u8, 2_u8, 3_u8], "First Row (Updated)".to_owned(),))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Entity::find()
|
||||||
|
.filter(Column::Id.eq(vec![1_u8, 2_u8, 3_u8])) // annotate it as Vec<u8> explicitly
|
||||||
|
.into_tuple()
|
||||||
|
.one(db)
|
||||||
|
.await?,
|
||||||
|
Some((vec![1_u8, 2_u8, 3_u8], "First Row (Updated)".to_owned(),))
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ impl From<Events> for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TryGetable for Events {
|
impl TryGetable for Events {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: sea_orm::ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
let vec: Vec<String> = res.try_get(pre, col).map_err(TryGetError::DbErr)?;
|
let vec: Vec<String> = res.try_get_by(idx).map_err(TryGetError::DbErr)?;
|
||||||
Ok(Events(vec.into_iter().map(Event).collect()))
|
Ok(Events(vec.into_iter().map(Event).collect()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ impl From<StringVec> for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TryGetable for StringVec {
|
impl TryGetable for StringVec {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get_by<I: sea_orm::ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
|
||||||
let json_str: String = res.try_get(pre, col).map_err(TryGetError::DbErr)?;
|
let json_str: String = res.try_get_by(idx).map_err(TryGetError::DbErr)?;
|
||||||
serde_json::from_str(&json_str).map_err(|e| TryGetError::DbErr(DbErr::Json(e.to_string())))
|
serde_json::from_str(&json_str).map_err(|e| TryGetError::DbErr(DbErr::Json(e.to_string())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user