postgres: tweak DataRow::read

This commit is contained in:
Ryan Leckey 2020-03-30 18:31:00 -07:00
parent 9be0401b38
commit bbbc1811ce
5 changed files with 48 additions and 24 deletions

View File

@ -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 }

View File

@ -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)

View File

@ -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)]

View File

@ -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();
});
}

View File

@ -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";