Skip to content

Commit

Permalink
Merge remote-tracking branch 'sfackler/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
benesch committed May 17, 2022
2 parents 6c65369 + 8785773 commit c46e0af
Show file tree
Hide file tree
Showing 22 changed files with 428 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
- run: docker compose up -d
- uses: sfackler/actions/rustup@master
with:
version: 1.53.0
version: 1.56.0
- run: echo "::set-output name=version::$(rustc --version)"
id: rust-version
- uses: actions/cache@v1
Expand Down
1 change: 1 addition & 0 deletions docker/sql_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,5 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
CREATE ROLE ssl_user LOGIN;
CREATE EXTENSION hstore;
CREATE EXTENSION citext;
CREATE EXTENSION ltree;
EOSQL
6 changes: 6 additions & 0 deletions postgres-derive/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## v0.4.2 - 2022-04-30

### Added

* Added support for transparent wrapper types.

## v0.4.1 - 2021-11-23

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion postgres-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "postgres-derive"
version = "0.4.1"
version = "0.4.2"
authors = ["Steven Fackler <[email protected]>"]
license = "MIT/Apache-2.0"
edition = "2018"
Expand Down
6 changes: 6 additions & 0 deletions postgres-protocol/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## v0.6.4 - 2022-04-03

### Added

* Added parsing support for `ltree`, `lquery`, and `ltxtquery`.

## v0.6.3 - 2021-12-10

### Changed
Expand Down
2 changes: 1 addition & 1 deletion postgres-protocol/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "postgres-protocol"
version = "0.6.3"
version = "0.6.4"
authors = ["Steven Fackler <[email protected]>"]
edition = "2018"
description = "Low level Postgres protocol APIs"
Expand Down
57 changes: 57 additions & 0 deletions postgres-protocol/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1059,3 +1059,60 @@ impl Inet {
self.netmask
}
}

/// Serializes a Postgres ltree string
#[inline]
pub fn ltree_to_sql(v: &str, buf: &mut BytesMut) {
// A version number is prepended to an ltree string per spec
buf.put_u8(1);
// Append the rest of the query
buf.put_slice(v.as_bytes());
}

/// Deserialize a Postgres ltree string
#[inline]
pub fn ltree_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
match buf {
// Remove the version number from the front of the ltree per spec
[1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
_ => Err("ltree version 1 only supported".into()),
}
}

/// Serializes a Postgres lquery string
#[inline]
pub fn lquery_to_sql(v: &str, buf: &mut BytesMut) {
// A version number is prepended to an lquery string per spec
buf.put_u8(1);
// Append the rest of the query
buf.put_slice(v.as_bytes());
}

/// Deserialize a Postgres lquery string
#[inline]
pub fn lquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
match buf {
// Remove the version number from the front of the lquery per spec
[1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
_ => Err("lquery version 1 only supported".into()),
}
}

/// Serializes a Postgres ltxtquery string
#[inline]
pub fn ltxtquery_to_sql(v: &str, buf: &mut BytesMut) {
// A version number is prepended to an ltxtquery string per spec
buf.put_u8(1);
// Append the rest of the query
buf.put_slice(v.as_bytes());
}

/// Deserialize a Postgres ltxtquery string
#[inline]
pub fn ltxtquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
match buf {
// Remove the version number from the front of the ltxtquery per spec
[1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
_ => Err("ltxtquery version 1 only supported".into()),
}
}
86 changes: 85 additions & 1 deletion postgres-protocol/src/types/test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bytes::BytesMut;
use bytes::{Buf, BytesMut};
use fallible_iterator::FallibleIterator;
use std::collections::HashMap;

Expand Down Expand Up @@ -156,3 +156,87 @@ fn non_null_array() {
assert_eq!(array.dimensions().collect::<Vec<_>>().unwrap(), dimensions);
assert_eq!(array.values().collect::<Vec<_>>().unwrap(), values);
}

#[test]
fn ltree_sql() {
let mut query = vec![1u8];
query.extend_from_slice("A.B.C".as_bytes());

let mut buf = BytesMut::new();

ltree_to_sql("A.B.C", &mut buf);

assert_eq!(query.as_slice(), buf.chunk());
}

#[test]
fn ltree_str() {
let mut query = vec![1u8];
query.extend_from_slice("A.B.C".as_bytes());

assert!(matches!(ltree_from_sql(query.as_slice()), Ok(_)))
}

#[test]
fn ltree_wrong_version() {
let mut query = vec![2u8];
query.extend_from_slice("A.B.C".as_bytes());

assert!(matches!(ltree_from_sql(query.as_slice()), Err(_)))
}

#[test]
fn lquery_sql() {
let mut query = vec![1u8];
query.extend_from_slice("A.B.C".as_bytes());

let mut buf = BytesMut::new();

lquery_to_sql("A.B.C", &mut buf);

assert_eq!(query.as_slice(), buf.chunk());
}

#[test]
fn lquery_str() {
let mut query = vec![1u8];
query.extend_from_slice("A.B.C".as_bytes());

assert!(matches!(lquery_from_sql(query.as_slice()), Ok(_)))
}

#[test]
fn lquery_wrong_version() {
let mut query = vec![2u8];
query.extend_from_slice("A.B.C".as_bytes());

assert!(matches!(lquery_from_sql(query.as_slice()), Err(_)))
}

#[test]
fn ltxtquery_sql() {
let mut query = vec![1u8];
query.extend_from_slice("a & b*".as_bytes());

let mut buf = BytesMut::new();

ltree_to_sql("a & b*", &mut buf);

assert_eq!(query.as_slice(), buf.chunk());
}

#[test]
fn ltxtquery_str() {
let mut query = vec![1u8];
query.extend_from_slice("a & b*".as_bytes());

assert!(matches!(ltree_from_sql(query.as_slice()), Ok(_)))
}

#[test]
fn ltxtquery_wrong_version() {
let mut query = vec![2u8];
query.extend_from_slice("a & b*".as_bytes());

assert!(matches!(ltree_from_sql(query.as_slice()), Err(_)))
}
10 changes: 10 additions & 0 deletions postgres-types/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Change Log

## v0.2.3 - 2022-04-30

### Added

* Added `ToSql` and `FromSql` implementations for `Box<str>`.
* Added `BorrowToSql` implementations for `Box<dyn ToSql + Sync>` and `Box<dyn ToSql + Sync + Send>`.
* Added support for `cidr` 0.2 via the `with-cidr-02` feature.
* Added conversions between the `LTREE`, `LQUERY` and `LTXTQUERY` types and Rust strings.
* Added support for `uuid` 1.0 via the `with-uuid-1` feature.

## v0.2.2 - 2021-09-29

### Added
Expand Down
14 changes: 10 additions & 4 deletions postgres-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "postgres-types"
version = "0.2.2"
version = "0.2.3"
authors = ["Steven Fackler <[email protected]>"]
edition = "2018"
license = "MIT/Apache-2.0"
Expand All @@ -14,31 +14,37 @@ categories = ["database"]
derive = ["postgres-derive"]
array-impls = ["array-init"]
with-bit-vec-0_6 = ["bit-vec-06"]
with-cidr-0_2 = ["cidr-02"]
with-chrono-0_4 = ["chrono-04"]
with-eui48-0_4 = ["eui48-04"]
with-eui48-1 = ["eui48-1"]
with-geo-types-0_6 = ["geo-types-06"]
with-geo-types-0_7 = ["geo-types-0_7"]
with-serde_json-1 = ["serde-1", "serde_json-1"]
with-uuid-0_8 = ["uuid-08"]
with-uuid-1 = ["uuid-1"]
with-time-0_2 = ["time-02"]
with-time-0_3 = ["time-03"]

[dependencies]
bytes = "1.0"
fallible-iterator = "0.2"
postgres-protocol = { version = "0.6.1", path = "../postgres-protocol" }
postgres-derive = { version = "0.4.0", optional = true, path = "../postgres-derive" }
postgres-protocol = { version = "0.6.4", path = "../postgres-protocol" }
postgres-derive = { version = "0.4.2", optional = true, path = "../postgres-derive" }

array-init = { version = "2", optional = true }
bit-vec-06 = { version = "0.6", package = "bit-vec", optional = true }
chrono-04 = { version = "0.4.16", package = "chrono", default-features = false, features = ["clock"], optional = true }
chrono-04 = { version = "0.4.16", package = "chrono", default-features = false, features = [
"clock",
], optional = true }
cidr-02 = { version = "0.2", package = "cidr", optional = true }
eui48-04 = { version = "0.4", package = "eui48", optional = true }
eui48-1 = { version = "1.0", package = "eui48", optional = true }
geo-types-06 = { version = "0.6", package = "geo-types", optional = true }
geo-types-0_7 = { version = "0.7", package = "geo-types", optional = true }
serde-1 = { version = "1.0", package = "serde", optional = true }
serde_json-1 = { version = "1.0", package = "serde_json", optional = true }
uuid-08 = { version = "0.8", package = "uuid", optional = true }
uuid-1 = { version = "1.0", package = "uuid", optional = true }
time-02 = { version = "0.2", package = "time", optional = true }
time-03 = { version = "0.3", package = "time", default-features = false, optional = true }
44 changes: 44 additions & 0 deletions postgres-types/src/cidr_02.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use bytes::BytesMut;
use cidr_02::{IpCidr, IpInet};
use postgres_protocol::types;
use std::error::Error;

use crate::{FromSql, IsNull, ToSql, Type};

impl<'a> FromSql<'a> for IpCidr {
fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
let inet = types::inet_from_sql(raw)?;
Ok(IpCidr::new(inet.addr(), inet.netmask())?)
}

accepts!(CIDR);
}

impl ToSql for IpCidr {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
types::inet_to_sql(self.first_address(), self.network_length(), w);
Ok(IsNull::No)
}

accepts!(CIDR);
to_sql_checked!();
}

impl<'a> FromSql<'a> for IpInet {
fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
let inet = types::inet_from_sql(raw)?;
Ok(IpInet::new(inet.addr(), inet.netmask())?)
}

accepts!(INET);
}

impl ToSql for IpInet {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
types::inet_to_sql(self.address(), self.network_length(), w);
Ok(IsNull::No)
}

accepts!(INET);
to_sql_checked!();
}
Loading

0 comments on commit c46e0af

Please sign in to comment.