Skip to content

Commit d9d283e

Browse files
Split out ltree,query,txtquery protocol parsers, add tests, rust fmt
1 parent 6ae60d6 commit d9d283e

File tree

4 files changed

+274
-71
lines changed

4 files changed

+274
-71
lines changed

postgres-protocol/src/types/mod.rs

+46-5
Original file line numberDiff line numberDiff line change
@@ -1060,18 +1060,59 @@ impl Inet {
10601060
}
10611061
}
10621062

1063-
/// Serializes a Postgres l{tree,query,txtquery} string
1063+
/// Serializes a Postgres ltree string
10641064
#[inline]
10651065
pub fn ltree_to_sql(v: &str, buf: &mut BytesMut) {
1066-
// A version number is prepended to an Ltree string per spec
1066+
// A version number is prepended to an ltree string per spec
10671067
buf.put_u8(1);
10681068
// Append the rest of the query
10691069
buf.put_slice(v.as_bytes());
10701070
}
10711071

1072-
/// Deserialize a Postgres l{tree,query,txtquery} string
1072+
/// Deserialize a Postgres ltree string
10731073
#[inline]
10741074
pub fn ltree_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1075-
// Remove the version number from the front of the string per spec
1076-
Ok(str::from_utf8(&buf[1..])?)
1075+
match buf {
1076+
// Remove the version number from the front of the ltree per spec
1077+
[1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1078+
_ => Err("ltree version 1 only supported".into()),
1079+
}
1080+
}
1081+
1082+
/// Serializes a Postgres lquery string
1083+
#[inline]
1084+
pub fn lquery_to_sql(v: &str, buf: &mut BytesMut) {
1085+
// A version number is prepended to an lquery string per spec
1086+
buf.put_u8(1);
1087+
// Append the rest of the query
1088+
buf.put_slice(v.as_bytes());
1089+
}
1090+
1091+
/// Deserialize a Postgres lquery string
1092+
#[inline]
1093+
pub fn lquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1094+
match buf {
1095+
// Remove the version number from the front of the lquery per spec
1096+
[1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1097+
_ => Err("lquery version 1 only supported".into()),
1098+
}
1099+
}
1100+
1101+
/// Serializes a Postgres ltxtquery string
1102+
#[inline]
1103+
pub fn ltxtquery_to_sql(v: &str, buf: &mut BytesMut) {
1104+
// A version number is prepended to an ltxtquery string per spec
1105+
buf.put_u8(1);
1106+
// Append the rest of the query
1107+
buf.put_slice(v.as_bytes());
1108+
}
1109+
1110+
/// Deserialize a Postgres ltxtquery string
1111+
#[inline]
1112+
pub fn ltxtquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1113+
match buf {
1114+
// Remove the version number from the front of the ltxtquery per spec
1115+
[1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1116+
_ => Err("ltxtquery version 1 only supported".into()),
1117+
}
10771118
}

postgres-protocol/src/types/test.rs

+115-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use bytes::BytesMut;
1+
use bytes::{Buf, BytesMut};
22
use fallible_iterator::FallibleIterator;
33
use std::collections::HashMap;
44

@@ -156,3 +156,117 @@ fn non_null_array() {
156156
assert_eq!(array.dimensions().collect::<Vec<_>>().unwrap(), dimensions);
157157
assert_eq!(array.values().collect::<Vec<_>>().unwrap(), values);
158158
}
159+
160+
#[test]
161+
fn ltree_sql() {
162+
let mut query = vec![1u8];
163+
query.extend_from_slice("A.B.C".as_bytes());
164+
165+
let mut buf = BytesMut::new();
166+
167+
ltree_to_sql("A.B.C", &mut buf);
168+
169+
assert_eq!(query.as_slice(), buf.chunk());
170+
}
171+
172+
#[test]
173+
fn ltree_str() {
174+
let mut query = vec![1u8];
175+
query.extend_from_slice("A.B.C".as_bytes());
176+
177+
let success = match ltree_from_sql(query.as_slice()) {
178+
Ok(_) => true,
179+
_ => false,
180+
};
181+
182+
assert!(success)
183+
}
184+
185+
#[test]
186+
fn ltree_wrong_version() {
187+
let mut query = vec![2u8];
188+
query.extend_from_slice("A.B.C".as_bytes());
189+
190+
let success = match ltree_from_sql(query.as_slice()) {
191+
Err(_) => true,
192+
_ => false,
193+
};
194+
195+
assert!(success)
196+
}
197+
198+
#[test]
199+
fn lquery_sql() {
200+
let mut query = vec![1u8];
201+
query.extend_from_slice("A.B.C".as_bytes());
202+
203+
let mut buf = BytesMut::new();
204+
205+
lquery_to_sql("A.B.C", &mut buf);
206+
207+
assert_eq!(query.as_slice(), buf.chunk());
208+
}
209+
210+
#[test]
211+
fn lquery_str() {
212+
let mut query = vec![1u8];
213+
query.extend_from_slice("A.B.C".as_bytes());
214+
215+
let success = match lquery_from_sql(query.as_slice()) {
216+
Ok(_) => true,
217+
_ => false,
218+
};
219+
220+
assert!(success)
221+
}
222+
223+
#[test]
224+
fn lquery_wrong_version() {
225+
let mut query = vec![2u8];
226+
query.extend_from_slice("A.B.C".as_bytes());
227+
228+
let success = match lquery_from_sql(query.as_slice()) {
229+
Err(_) => true,
230+
_ => false,
231+
};
232+
233+
assert!(success)
234+
}
235+
236+
#[test]
237+
fn ltxtquery_sql() {
238+
let mut query = vec![1u8];
239+
query.extend_from_slice("a & b*".as_bytes());
240+
241+
let mut buf = BytesMut::new();
242+
243+
ltree_to_sql("a & b*", &mut buf);
244+
245+
assert_eq!(query.as_slice(), buf.chunk());
246+
}
247+
248+
#[test]
249+
fn ltxtquery_str() {
250+
let mut query = vec![1u8];
251+
query.extend_from_slice("a & b*".as_bytes());
252+
253+
let success = match ltree_from_sql(query.as_slice()) {
254+
Ok(_) => true,
255+
_ => false,
256+
};
257+
258+
assert!(success)
259+
}
260+
261+
#[test]
262+
fn ltxtquery_wrong_version() {
263+
let mut query = vec![2u8];
264+
query.extend_from_slice("a & b*".as_bytes());
265+
266+
let success = match ltree_from_sql(query.as_slice()) {
267+
Err(_) => true,
268+
_ => false,
269+
};
270+
271+
assert!(success)
272+
}

postgres-types/src/lib.rs

+25-25
Original file line numberDiff line numberDiff line change
@@ -619,24 +619,24 @@ impl<'a> FromSql<'a> for Box<str> {
619619
impl<'a> FromSql<'a> for &'a str {
620620
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box<dyn Error + Sync + Send>> {
621621
match *ty {
622-
ref ty if (
623-
ty.name() == "ltree" ||
624-
ty.name() == "lquery" ||
625-
ty.name() == "ltxtquery"
626-
) => types::ltree_from_sql(raw),
627-
_ => types::text_from_sql(raw)
622+
ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw),
623+
ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw),
624+
ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw),
625+
_ => types::text_from_sql(raw),
628626
}
629627
}
630628

631629
fn accepts(ty: &Type) -> bool {
632630
match *ty {
633631
Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
634-
ref ty if (
635-
ty.name() == "citext" ||
636-
ty.name() == "ltree" ||
637-
ty.name() == "lquery" ||
638-
ty.name() == "ltxtquery"
639-
) => true,
632+
ref ty
633+
if (ty.name() == "citext"
634+
|| ty.name() == "ltree"
635+
|| ty.name() == "lquery"
636+
|| ty.name() == "ltxtquery") =>
637+
{
638+
true
639+
}
640640
_ => false,
641641
}
642642
}
@@ -939,26 +939,26 @@ impl ToSql for Vec<u8> {
939939

940940
impl<'a> ToSql for &'a str {
941941
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
942-
match ty {
943-
ref ty if (
944-
ty.name() == "ltree" ||
945-
ty.name() == "lquery" ||
946-
ty.name() == "ltxtquery"
947-
) => types::ltree_to_sql(*self, w),
948-
_ => types::text_to_sql(*self, w)
942+
match *ty {
943+
ref ty if ty.name() == "ltree" => types::ltree_to_sql(*self, w),
944+
ref ty if ty.name() == "lquery" => types::lquery_to_sql(*self, w),
945+
ref ty if ty.name() == "ltxtquery" => types::ltxtquery_to_sql(*self, w),
946+
_ => types::text_to_sql(*self, w),
949947
}
950948
Ok(IsNull::No)
951949
}
952950

953951
fn accepts(ty: &Type) -> bool {
954952
match *ty {
955953
Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
956-
ref ty if (
957-
ty.name() == "citext" ||
958-
ty.name() == "ltree" ||
959-
ty.name() == "lquery" ||
960-
ty.name() == "ltxtquery"
961-
) => true,
954+
ref ty
955+
if (ty.name() == "citext"
956+
|| ty.name() == "ltree"
957+
|| ty.name() == "lquery"
958+
|| ty.name() == "ltxtquery") =>
959+
{
960+
true
961+
}
962962
_ => false,
963963
}
964964
}

0 commit comments

Comments
 (0)