1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![allow(dead_code)]

extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate rustc_serialize;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;

use std::sync::RwLock;
use postgres::rows::Row;
use postgres::types::{ToSql,FromSql};
use r2d2::{Config, Pool, PooledConnection};
use r2d2_postgres::{PostgresConnectionManager, SslMode};

pub trait Entity {
    fn convert(row: Row) -> Self;
}


impl<T: FromSql> Entity for T {
    fn convert(row: Row) -> Self {
        row.get(0)
    }
}

#[macro_export]
macro_rules! reposable {
    (struct $name:ident($table_name:ident) {
        $($field_name:ident: $field_type:ty,)*
    }) => {
        #[derive(Default,Debug,RustcEncodable, RustcDecodable,Clone, PartialEq,Eq)]
        struct $name {
            $($field_name: $field_type,)*
        }

        impl Entity for $name{
            fn convert(row: ::postgres::rows::Row)->Self{
               let mut m=$name::default();
               //println!("table_name:{}",stringify!($table_name));
               $(m.$field_name=row.get(stringify!($field_name));)*
               m
            }
        }

    }
}

pub struct PostgresConfig {
    pub host: String,
    pub port: String,
    pub user_name: String,
    pub password: String,
    pub db_name: String,
}

lazy_static! {
    static ref POSTGRES_POOL: RwLock<Option<Pool<PostgresConnectionManager>>>  = RwLock::new(None);
}

pub fn init(c: &PostgresConfig) {
    let connect_str = format!("postgres://{}:{}@{}:{}/{}", c.user_name, c.password, c.host, c.port, c.db_name);
    info!("Connecting to postgres:{}", connect_str);
    let manager = PostgresConnectionManager::new(connect_str.as_str(), SslMode::None).unwrap();
    let config = Config::builder().pool_size(10).build();
    match Pool::new(config, manager) {
        Ok(pool) => {
            info!("Connected to postgres with pool: {:?}", pool);
            let mut w = POSTGRES_POOL.write().unwrap();
            *w = Some(pool);
        }
        Err(err) => {
            panic!("error occurs when connect to postgres {}.Error info:{}", connect_str, err);
        }
    };
}

fn get_conn() -> PooledConnection<PostgresConnectionManager> {
    match *POSTGRES_POOL.read().unwrap() {
        Some(ref pool) => {
            match pool.get() {
                Ok(conn) => conn,
                Err(err) => panic!("error in get_conn():{}", err),
            }
        },
        None => panic!("repository not initialized"),
    }
}


pub fn find_one<T: Entity>(query: &str, params: &[&ToSql]) -> Option<T> {
    info!("find_one: {}, params:{:?}", query, params);
    let conn = get_conn();
    match conn.query(query, params) {
        Ok(rows) => {
            return rows.into_iter().next().map(T::convert);
        }
        Err(err) => {
            panic!("error occur when execute query:{},params:{:?},error:{}", query, params, err)
        }
    }
    None
}

pub fn find_list<T: Entity>(query: &str, params: &[&ToSql]) -> Vec<T> {
    info!("find_list: {}, params:{:?}", query, params);
    let conn = get_conn();
    match conn.query(query, params) {
        Ok(rows) => {
            return rows.into_iter().map(T::convert).collect();
        }
        Err(err) => {
            panic!("error occur when execute query:{},params:{:?},error:{}", query, params, err)
        }
    }
    vec![]
}

// return: the number of rows modified
pub fn execute(query: &str, params: &[&ToSql]) -> u64 {
    info!("execute :{}, params:{:?}", query, params);
    let conn = get_conn();
    // conn.execute(query,params).unwrap()
    match conn.execute(query, params) {
        Ok(count) => count,
        Err(err) => panic!("error occur when execute query:{},params:{:?},error:{}", query, params, err),
    }
}

pub fn batch_execute(query: &str) -> postgres::Result<()> {
    info!("batch_execute :{}", query);
    let conn = get_conn();
    conn.batch_execute(query)
}