mirror of
https://github.com/launchbadge/sqlx.git
synced 2026-03-06 05:42:38 +00:00
feat(mysql): expand MySqlRow
This commit is contained in:
parent
3470195839
commit
9a31baa15a
@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use sqlx_core::{Result, Runtime};
|
||||
|
||||
use crate::connection::command::QueryCommand;
|
||||
@ -31,7 +33,7 @@ macro_rules! impl_recv_columns {
|
||||
// STATE: remember that we are now expecting a row or the end
|
||||
*$cmd = QueryCommand::QueryStep;
|
||||
|
||||
Ok(columns)
|
||||
Ok(columns.into())
|
||||
}};
|
||||
}
|
||||
|
||||
@ -42,7 +44,7 @@ impl<Rt: Runtime> MySqlStream<Rt> {
|
||||
store: bool,
|
||||
columns: u16,
|
||||
cmd: &mut QueryCommand,
|
||||
) -> Result<Vec<MySqlColumn>>
|
||||
) -> Result<Arc<[MySqlColumn]>>
|
||||
where
|
||||
Rt: sqlx_core::Async,
|
||||
{
|
||||
@ -55,7 +57,7 @@ impl<Rt: Runtime> MySqlStream<Rt> {
|
||||
store: bool,
|
||||
columns: u16,
|
||||
cmd: &mut QueryCommand,
|
||||
) -> Result<Vec<MySqlColumn>>
|
||||
) -> Result<Arc<[MySqlColumn]>>
|
||||
where
|
||||
Rt: sqlx_core::blocking::Runtime,
|
||||
{
|
||||
|
||||
@ -31,7 +31,7 @@ macro_rules! impl_raw_prepare {
|
||||
|
||||
// extract the type only from the column definition
|
||||
// most other fields are useless
|
||||
stmt.parameters.push(MySqlTypeInfo::new(&def));
|
||||
stmt.parameters_mut().push(MySqlTypeInfo::new(&def));
|
||||
}
|
||||
|
||||
// TODO: handle EOF for old MySQL
|
||||
@ -42,7 +42,7 @@ macro_rules! impl_raw_prepare {
|
||||
|
||||
let def = read_packet!($(@$blocking)? stream).deserialize()?;
|
||||
|
||||
stmt.columns.push(MySqlColumn::new(ordinal, def));
|
||||
stmt.columns_mut().push(MySqlColumn::new(ordinal, def));
|
||||
}
|
||||
|
||||
// TODO: handle EOF for old MySQL
|
||||
|
||||
@ -12,7 +12,7 @@ macro_rules! impl_raw_query {
|
||||
// execute the prepared statement
|
||||
$self.stream.write_packet(&protocol::Execute {
|
||||
statement: statement.id(),
|
||||
parameters: &statement.parameters,
|
||||
parameters: statement.parameters(),
|
||||
arguments: &arguments,
|
||||
})?;
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use crate::protocol::PrepareOk;
|
||||
use crate::{MySqlColumn, MySqlTypeInfo};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct RawStatement {
|
||||
id: u32,
|
||||
pub(crate) columns: Vec<MySqlColumn>,
|
||||
pub(crate) parameters: Vec<MySqlTypeInfo>,
|
||||
columns: Vec<MySqlColumn>,
|
||||
parameters: Vec<MySqlTypeInfo>,
|
||||
}
|
||||
|
||||
impl RawStatement {
|
||||
@ -17,7 +17,23 @@ impl RawStatement {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> u32 {
|
||||
pub(crate) const fn id(&self) -> u32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub(crate) fn columns(&self) -> &[MySqlColumn] {
|
||||
&self.columns
|
||||
}
|
||||
|
||||
pub(crate) fn columns_mut(&mut self) -> &mut Vec<MySqlColumn> {
|
||||
&mut self.columns
|
||||
}
|
||||
|
||||
pub(crate) fn parameters(&self) -> &[MySqlTypeInfo] {
|
||||
&self.parameters
|
||||
}
|
||||
|
||||
pub(crate) fn parameters_mut(&mut self) -> &mut Vec<MySqlTypeInfo> {
|
||||
&mut self.parameters
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,46 +1,97 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::Bytes;
|
||||
use sqlx_core::{Decode, Error, Row};
|
||||
use sqlx_core::{ColumnIndex, Decode, Error, Result, Row};
|
||||
|
||||
use crate::{protocol, MySql, MySqlColumn, MySqlRawValue, MySqlRawValueFormat};
|
||||
|
||||
/// A single row from a result set generated from MySQL.
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct MySqlRow {
|
||||
format: MySqlRawValueFormat,
|
||||
columns: Vec<MySqlColumn>,
|
||||
columns: Arc<[MySqlColumn]>,
|
||||
values: Vec<Option<Bytes>>,
|
||||
}
|
||||
|
||||
impl MySqlRow {
|
||||
// FIXME: Use Arc or some other way of sharing columns between rows
|
||||
pub(crate) fn new(row: protocol::Row, columns: &Vec<MySqlColumn>) -> Self {
|
||||
Self { values: row.values, columns: columns.clone(), format: row.format }
|
||||
pub(crate) fn new(row: protocol::Row, columns: &Arc<[MySqlColumn]>) -> Self {
|
||||
Self { values: row.values, columns: Arc::clone(columns), format: row.format }
|
||||
}
|
||||
|
||||
/// Returns `true` if the row contains only `NULL` values.
|
||||
fn is_null(&self) -> bool {
|
||||
self.values.iter().all(Option::is_some)
|
||||
}
|
||||
|
||||
/// Returns the number of columns in the row.
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
self.values.len()
|
||||
}
|
||||
|
||||
/// Returns `true` if there are no columns in the row.
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn try_get<'r, T>(&'r self, index: usize) -> sqlx_core::Result<T>
|
||||
/// Returns a reference to the columns in the row.
|
||||
#[must_use]
|
||||
pub fn columns(&self) -> &[MySqlColumn] {
|
||||
&self.columns
|
||||
}
|
||||
|
||||
/// Returns the column name, given the ordinal (also known as index) of the column.
|
||||
#[must_use]
|
||||
pub fn column_name_of(&self, ordinal: usize) -> &str {
|
||||
self.try_column_name_of(ordinal).unwrap()
|
||||
}
|
||||
|
||||
/// Returns the column name, given the ordinal (also known as index) of the column.
|
||||
pub fn try_column_name_of(&self, ordinal: usize) -> Result<&str> {
|
||||
self.columns
|
||||
.get(ordinal)
|
||||
.map(MySqlColumn::name)
|
||||
.ok_or_else(|| Error::ColumnIndexOutOfBounds { index: ordinal, len: self.len() })
|
||||
}
|
||||
|
||||
/// Returns the column ordinal, given the name of the column.
|
||||
#[must_use]
|
||||
pub fn ordinal_of(&self, name: &str) -> usize {
|
||||
self.try_ordinal_of(name).unwrap()
|
||||
}
|
||||
|
||||
/// Returns the column ordinal, given the name of the column.
|
||||
pub fn try_ordinal_of(&self, name: &str) -> Result<usize> {
|
||||
self.columns
|
||||
.iter()
|
||||
.position(|col| col.name() == name)
|
||||
.ok_or_else(|| Error::ColumnNotFound { name: name.to_owned().into_boxed_str() })
|
||||
}
|
||||
|
||||
/// Returns the decoded value at the index.
|
||||
pub fn try_get<'r, T, I>(&'r self, index: I) -> Result<T>
|
||||
where
|
||||
I: ColumnIndex<Self>,
|
||||
T: Decode<'r, MySql>,
|
||||
{
|
||||
Ok(self.try_get_raw(index)?.decode()?)
|
||||
}
|
||||
|
||||
// noinspection RsNeedlessLifetimes
|
||||
pub fn try_get_raw<'r>(&'r self, index: usize) -> sqlx_core::Result<MySqlRawValue<'r>> {
|
||||
/// Returns the raw representation of the value at the index.
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn try_get_raw<'r, I>(&'r self, index: I) -> Result<MySqlRawValue<'r>>
|
||||
where
|
||||
I: ColumnIndex<Self>,
|
||||
{
|
||||
let ordinal = index.get(self)?;
|
||||
|
||||
let value = self
|
||||
.values
|
||||
.get(index)
|
||||
.ok_or_else(|| Error::ColumnIndexOutOfBounds { len: self.len(), index })?;
|
||||
.get(ordinal)
|
||||
.ok_or_else(|| Error::ColumnIndexOutOfBounds { len: self.len(), index: ordinal })?;
|
||||
|
||||
let column = &self.columns[index];
|
||||
let column = &self.columns[ordinal];
|
||||
|
||||
Ok(MySqlRawValue::new(value, self.format, column.type_info()))
|
||||
}
|
||||
@ -50,7 +101,7 @@ impl Row for MySqlRow {
|
||||
type Database = MySql;
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
todo!()
|
||||
self.is_null()
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
@ -58,34 +109,35 @@ impl Row for MySqlRow {
|
||||
}
|
||||
|
||||
fn columns(&self) -> &[MySqlColumn] {
|
||||
todo!()
|
||||
self.columns()
|
||||
}
|
||||
|
||||
fn column_name_of(&self, ordinal: usize) -> &str {
|
||||
todo!()
|
||||
self.column_name_of(ordinal)
|
||||
}
|
||||
|
||||
fn try_column_name_of(&self, ordinal: usize) -> sqlx_core::Result<&str> {
|
||||
todo!()
|
||||
fn try_column_name_of(&self, ordinal: usize) -> Result<&str> {
|
||||
self.try_column_name_of(ordinal)
|
||||
}
|
||||
|
||||
fn ordinal_of(&self, name: &str) -> usize {
|
||||
todo!()
|
||||
self.ordinal_of(name)
|
||||
}
|
||||
|
||||
fn try_ordinal_of(&self, name: &str) -> sqlx_core::Result<usize> {
|
||||
todo!()
|
||||
fn try_ordinal_of(&self, name: &str) -> Result<usize> {
|
||||
self.try_ordinal_of(name)
|
||||
}
|
||||
|
||||
fn try_get<'r, T>(&'r self, index: usize) -> sqlx_core::Result<T>
|
||||
fn try_get<'r, T, I>(&'r self, index: I) -> Result<T>
|
||||
where
|
||||
I: ColumnIndex<Self>,
|
||||
T: Decode<'r, MySql>,
|
||||
{
|
||||
self.try_get(index)
|
||||
}
|
||||
|
||||
// noinspection RsNeedlessLifetimes
|
||||
fn try_get_raw<'r>(&'r self, index: usize) -> sqlx_core::Result<MySqlRawValue<'r>> {
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
fn try_get_raw<'r, I: ColumnIndex<Self>>(&'r self, index: I) -> Result<MySqlRawValue<'r>> {
|
||||
self.try_get_raw(index)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user