Skip to content

Instantly share code, notes, and snippets.

@YetAnotherMinion
Created February 19, 2018 01:54
Show Gist options
  • Save YetAnotherMinion/00a2a17880b485677ba0530df3214bfe to your computer and use it in GitHub Desktop.
Save YetAnotherMinion/00a2a17880b485677ba0530df3214bfe to your computer and use it in GitHub Desktop.
implement Point type for PG
#![feature(custom_attribute)]
#[macro_use]
extern crate diesel;
extern crate byteorder;
use diesel::prelude::*;
use diesel::pg::PgConnection;
//mod points;
mod geometric {
use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
use std::io::prelude::*;
use std::error::Error;
use diesel;
use diesel::deserialize::{self, FromSql};
use diesel::expression::AsExpression;
use diesel::expression::bound::Bound;
use diesel::pg::Pg;
use diesel::serialize::{self, IsNull, Output, ToSql};
pub mod sql_types {
// https://github.com/postgres/postgres/blob/master/src/include/catalog/pg_type.h
#[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
#[postgres(oid = "600", array_oid = "1017")]
pub struct Point;
}
macro_rules! not_none {
($bytes:expr) => {
match $bytes {
Some(bytes) => bytes,
None => return Err(Box::new(diesel::result::UnexpectedNullError)),
}
}
}
#[derive(Debug, Clone, Copy, FromSqlRow)]
#[sql_type="Point"]
pub struct PgPoint {
x: f64,
y: f64,
}
impl<'a> AsExpression<sql_types::Point> for &'a PgPoint {
type Expression = Bound<sql_types::Point, &'a PgPoint>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
impl FromSql<sql_types::Point, Pg> for PgPoint {
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
let mut bytes = not_none!(bytes);
let x = bytes.read_f64::<NetworkEndian>()
.map_err(|e| Box::new(e) as Box<Error + Send + Sync>)?;
let y = bytes.read_f64::<NetworkEndian>()
.map_err(|e| Box::new(e) as Box<Error + Send + Sync>)?;
Ok(PgPoint { x: x, y: y})
}
}
impl ToSql<sql_types::Point, Pg> for PgPoint {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
out.write_f64::<NetworkEndian>(self.x)?;
out.write_f64::<NetworkEndian>(self.y)?;
Ok(IsNull::No)
}
}
}
mod schema {
table! {
use diesel::sql_types::*;
use geometric::sql_types::Point;
hack (id) {
id -> Int8,
p -> Point,
}
}
}
use schema::hack;
#[derive(Debug, Queryable, Identifiable)]
#[table_name = "hack"]
#[primary_key(id)]
struct HackRow {
id: i64,
p: geometric::PgPoint,
}
fn main() {
let db_url = "postgres:///point_hack?host=/var/run/postgresql/";
let conn = PgConnection::establish(db_url).unwrap();
let query = schema::hack::dsl::hack
.select((schema::hack::dsl::id, schema::hack::dsl::p));
match query.get_results::<HackRow>(&conn) {
Ok(results) => println!("{:?}", results),
Err(diesel_err) => println!("{}", diesel_err),
}
println!("Hello, world!");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment