use std::borrow::Cow;
use crate::{tds::codec::BaseMetaDataColumn, SqlReadBytes};
#[derive(Debug, Clone)]
pub struct AltMetaDataColumn<'a> {
pub op: u8,
pub operand: u16,
pub base: BaseMetaDataColumn,
pub col_name: Cow<'a, str>,
}
#[derive(Debug, Clone)]
pub struct TokenAltMetaData<'a> {
pub id: u16,
pub by_columns: Vec<u16>,
pub columns: Vec<AltMetaDataColumn<'a>>,
}
impl TokenAltMetaData<'static> {
pub(crate) async fn decode<R>(src: &mut R) -> crate::Result<Self>
where
R: SqlReadBytes + Unpin,
{
let column_count = src.read_u16_le().await?;
let id = src.read_u16_le().await?;
let by_cols = src.read_u8().await?;
let mut by_columns = Vec::with_capacity(by_cols as usize);
for _ in 0..by_cols {
by_columns.push(src.read_u16_le().await?);
}
let mut columns = Vec::with_capacity(
(column_count as usize).min(crate::tds::codec::column_data::MAX_PREALLOC),
);
for _ in 0..column_count {
let op = src.read_u8().await?;
let operand = src.read_u16_le().await?;
let base = BaseMetaDataColumn::decode(src).await?;
let col_name = Cow::from(src.read_b_varchar().await?);
columns.push(AltMetaDataColumn {
op,
operand,
base,
col_name,
});
}
Ok(TokenAltMetaData {
id,
by_columns,
columns,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{sql_read_bytes::test_utils::IntoSqlReadBytes, tds::codec::TypeInfo, FixedLenType};
use bytes::{BufMut, BytesMut};
#[tokio::test]
async fn decode_alt_meta_data_single_sum_column() {
let mut buf = BytesMut::new();
buf.put_u16_le(1); buf.put_u16_le(7); buf.put_u8(1); buf.put_u16_le(2);
buf.put_u8(0x4f); buf.put_u16_le(1);
buf.put_u32_le(0); buf.put_u16_le(0x0001); buf.put_u8(FixedLenType::Int4 as u8);
let name: Vec<u16> = "sum".encode_utf16().collect();
buf.put_u8(name.len() as u8);
for c in name {
buf.put_u16_le(c);
}
let mut reader = buf.into_sql_read_bytes();
let meta = TokenAltMetaData::decode(&mut reader).await.unwrap();
assert_eq!(7, meta.id);
assert_eq!(vec![2], meta.by_columns);
assert_eq!(1, meta.columns.len());
let col = &meta.columns[0];
assert_eq!(0x4f, col.op);
assert_eq!(1, col.operand);
assert_eq!("sum", col.col_name);
assert!(matches!(
col.base.ty,
TypeInfo::FixedLen(FixedLenType::Int4)
));
}
}