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
#![macro_use]
use super::*;
use getset::{Getters, MutGetters};
use numtoa::NumToA;
use std::io::Write;

macro_rules! get_state {
    ($ciboulette_store:expr, $ciboulette_table_store:expr, $req:expr) => {
        Ciboulette2PgBuilderState::new(
            $ciboulette_store,
            $ciboulette_table_store,
            $req.path(),
            $req.query(),
            Ciboulette2PgResponseType::from(*$req.expected_response_type()),
        )
    };
}

mod additional_fields;
mod builder_state;
mod delete;
mod extracting_data;
mod insert;
mod relating_field;
mod select;
mod table_field;
mod update;
mod utils;

use relating_field::Ciboulette2PgRelatingField;

#[cfg(test)]
pub mod tests;

use additional_fields::{Ciboulette2PgAdditionalField, Ciboulette2PgAdditionalFieldType};
use builder_state::Ciboulette2PgBuilderState;
use extracting_data::*;
use table_field::Ciboulette2PgTableField;

type Ciboulette2PgBuf = buf_redux::BufWriter<std::io::Cursor<Vec<u8>>>;

/// A list of parameters to send along side the query to database
#[derive(Clone, Debug, Default, Getters)]
#[getset(get = "pub")]
pub struct Ciboulette2PgArguments<'request> {
    inner: Vec<Ciboulette2PgValue<'request>>,
}

impl<'request> Ciboulette2PgArguments<'request> {
    pub fn with_capacity(cap: usize) -> Self {
        Ciboulette2PgArguments {
            inner: Vec::with_capacity(cap),
        }
    }

    pub fn take(self) -> Vec<Ciboulette2PgValue<'request>> {
        self.inner
    }
}

impl<'request> std::ops::Deref for Ciboulette2PgArguments<'request> {
    type Target = Vec<Ciboulette2PgValue<'request>>;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<'request> std::ops::DerefMut for Ciboulette2PgArguments<'request> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

/// Ciboulette to Postgres Query builder
#[derive(Debug, Getters, MutGetters)]
#[getset(get = "pub")]
pub struct Ciboulette2PgBuilder<'request> {
    buf: Ciboulette2PgBuf,
    params: Ciboulette2PgArguments<'request>,
    #[getset(get_mut = "pub")]
    working_tables: BTreeMap<
        Vec<CibouletteResourceRelationshipDetails>,
        (Ciboulette2PgTable, Ciboulette2PgResponseType),
    >,
    cte_index: usize,
}

impl<'request> Default for Ciboulette2PgBuilder<'request> {
    fn default() -> Self {
        Ciboulette2PgBuilder {
            buf: Ciboulette2PgBuf::new_ringbuf(std::io::Cursor::new(Vec::with_capacity(4096))),
            params: Ciboulette2PgArguments::with_capacity(128),
            working_tables: BTreeMap::default(),
            cte_index: 0,
        }
    }
}

impl<'request> Ciboulette2PgBuilder<'request> {
    pub(crate) fn add_working_table(
        &mut self,
        rel_chain: Vec<CibouletteResourceRelationshipDetails>,
        table: Ciboulette2PgTable,
        response_type: Ciboulette2PgResponseType,
    ) -> Option<(Ciboulette2PgTable, Ciboulette2PgResponseType)> {
        self.working_tables
            .insert(rel_chain, (table, response_type))
    }

    pub(crate) fn get_new_cte_index(&mut self) -> usize {
        let res = self.cte_index;
        self.cte_index += 1;
        res
    }
}