mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
postgres: tweak DataRow::read
This commit is contained in:
parent
9be0401b38
commit
bbbc1811ce
@ -29,6 +29,8 @@ sqlite = [ "libsqlite3-sys" ]
|
||||
tls = [ "async-native-tls" ]
|
||||
runtime-async-std = [ "async-native-tls/runtime-async-std", "async-std" ]
|
||||
runtime-tokio = [ "async-native-tls/runtime-tokio", "tokio" ]
|
||||
# intended for internal benchmarking, do not use
|
||||
bench = []
|
||||
|
||||
[dependencies]
|
||||
async-native-tls = { version = "0.3.2", default-features = false, optional = true }
|
||||
|
||||
@ -7,8 +7,12 @@
|
||||
#![cfg_attr(not(feature = "sqlite"), forbid(unsafe_code))]
|
||||
#![recursion_limit = "512"]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(all(test, feature = "bench"), feature(test))]
|
||||
// #![warn(missing_docs)]
|
||||
|
||||
#[cfg(all(test, feature = "bench"))]
|
||||
extern crate test;
|
||||
|
||||
// HACK: Allow a feature name the same name as a dependency
|
||||
#[cfg(feature = "bigdecimal")]
|
||||
extern crate bigdecimal_ as bigdecimal;
|
||||
@ -65,7 +69,3 @@ pub mod postgres;
|
||||
pub mod sqlite;
|
||||
|
||||
pub use error::{Error, Result};
|
||||
|
||||
// Named Lifetimes:
|
||||
// 'c: connection
|
||||
// 'q: query string (and arguments)
|
||||
|
||||
@ -98,7 +98,7 @@ pub struct PgConnection {
|
||||
|
||||
// Work buffer for the value ranges of the current row
|
||||
// This is used as the backing memory for each Row's value indexes
|
||||
pub(super) current_row_values: Vec<Option<Range<u32>>>,
|
||||
pub(super) current_row_values: Vec<Option<(u32, u32)>>,
|
||||
|
||||
// TODO: Find a use for these values. Perhaps in a debug impl of PgConnection?
|
||||
#[allow(dead_code)]
|
||||
|
||||
@ -4,27 +4,26 @@ use byteorder::NetworkEndian;
|
||||
use std::ops::Range;
|
||||
|
||||
pub(crate) struct DataRow<'c> {
|
||||
len: u16,
|
||||
values: &'c [Option<(u32, u32)>],
|
||||
buffer: &'c [u8],
|
||||
values: &'c [Option<Range<u32>>],
|
||||
}
|
||||
|
||||
impl<'c> DataRow<'c> {
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
self.len as usize
|
||||
self.values.len()
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self, index: usize) -> Option<&'c [u8]> {
|
||||
let range = self.values[index].as_ref()?;
|
||||
|
||||
Some(&self.buffer[(range.start as usize)..(range.end as usize)])
|
||||
self.values[index]
|
||||
.as_ref()
|
||||
.map(|(offset, size)| &self.buffer[(*offset as usize)..((*offset + *size) as usize)])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'c> DataRow<'c> {
|
||||
pub(crate) fn read(
|
||||
buffer: &'c [u8],
|
||||
values: &'c mut Vec<Option<Range<u32>>>,
|
||||
values: &'c mut Vec<Option<(u32, u32)>>,
|
||||
) -> crate::Result<Self> {
|
||||
values.clear();
|
||||
|
||||
@ -32,30 +31,53 @@ impl<'c> DataRow<'c> {
|
||||
|
||||
let len = buf.get_u16::<NetworkEndian>()?;
|
||||
|
||||
let mut index = 6;
|
||||
let mut offset = 6;
|
||||
|
||||
while values.len() < (len as usize) {
|
||||
// The length of the column value, in bytes (this count does not include itself).
|
||||
// Can be zero. As a special case, -1 indicates a NULL column value.
|
||||
// No value bytes follow in the NULL case.
|
||||
let size = buf.get_i32::<NetworkEndian>()?;
|
||||
let mut size = buf.get_i32::<NetworkEndian>()?;
|
||||
|
||||
if size == -1 {
|
||||
if size < 0 {
|
||||
values.push(None);
|
||||
|
||||
index += 4;
|
||||
offset += 4;
|
||||
} else {
|
||||
values.push(Some((index)..(index + (size as u32))));
|
||||
values.push(Some((offset, size as u32)));
|
||||
|
||||
index += (size as u32) + 4;
|
||||
offset += (size as u32) + 4;
|
||||
buf.advance(size as usize);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
len,
|
||||
buffer,
|
||||
values,
|
||||
})
|
||||
Ok(Self { buffer, values })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "bench")]
|
||||
#[bench]
|
||||
fn bench_get_data_row(b: &mut test::Bencher) {
|
||||
let buffer = b"\x00\x08\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\n\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00(\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00P";
|
||||
let mut values = Vec::with_capacity(10);
|
||||
let row = DataRow::read(buffer, &mut values).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
assert_eq!(row.get(0), None);
|
||||
assert_eq!(row.get(1), Some(&[0, 0, 0, 10][..]));
|
||||
assert_eq!(row.get(2), None);
|
||||
assert_eq!(row.get(3), Some(&[0, 0, 0, 20][..]));
|
||||
assert_eq!(row.get(4), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "bench")]
|
||||
#[bench]
|
||||
fn bench_read_data_row(b: &mut test::Bencher) {
|
||||
let buffer = b"\x00\x08\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\n\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00(\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00P";
|
||||
let mut values = Vec::with_capacity(10);
|
||||
|
||||
b.iter(|| {
|
||||
let row = DataRow::read(buffer, &mut values).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
@ -176,7 +176,7 @@ where
|
||||
mod tests {
|
||||
use super::PgArrayDecoder;
|
||||
use super::PgArrayEncoder;
|
||||
use crate::postgres::{PgRawBuffer, PgValue, Postgres};
|
||||
use crate::postgres::{PgRawBuffer, PgValue};
|
||||
|
||||
const BUF_BINARY_I32: &[u8] = b"\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x04";
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user