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
//! # Introduction
//!
//! **_Ciboulette2Pg_** is an library that execute [_Ciboulette_](ciboulette) requests as _Postgres_ queries and convert back the
//! result to [_Ciboulette_](ciboulette) responses.
//!
//! It strive to always execute [_Ciboulette_](ciboulette) requests as a single _Postgres_ query reducing latency.
//!
//! It support sparse fields, sorting and including related objects.
//!
//! ## High level operations
//!
//! ### Query structure
//!
//! When building a query, this library will make heavy use of [CTE](https://www.postgresql.org/docs/13/queries-with.html)s.
//! It allows the query to reference itself, having multiple sub-queries that perform different tasks.
//!
//! All the query return data in the same way.
//!
//! | Key            | Description                                                                                                                                             |
//! |----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
//! | `id`           | The identifier of the resource, in TEXT format.                                                                                                         |
//! | `type`         | The type of the resource, in TEXT format.<br>If this row handles a relationship, this will be the relationship chain (i.e. `peoples.articles.comments`) |
//! | `data`         | Optional, JSON packed data object containing the attributes of the resource                                                                             |
//! | `related_id`   | The `id` of the resource it relates to                                                                                                                  |
//! | `related_type` | The `type` of the resource it relates to. If it relates to another relationship of the main data, it should contains the relationship chain             |
//!
//! The first [CTE](https://www.postgresql.org/docs/13/queries-with.html) will be the one applying the action of the request.
//! (i.e. For a create request, the first [CTE](https://www.postgresql.org/docs/13/queries-with.html) will perfom the `INSERT`).
//! Depending on the request type, a second [CTE](https://www.postgresql.org/docs/13/queries-with.html) will be used to select
//! the data modified by the first [CTE](https://www.postgresql.org/docs/13/queries-with.html).
//! After that, all the required (either included or required for sorting) relationships will be used.
//! Finally, depending on the sorting requirement, a final main [CTE](https://www.postgresql.org/docs/13/queries-with.html)
//! will be inserted to sort the main data.
//!
//! ### Query Response
//!
//! At the end of the query, all the necessary will be `UNION`ed together to form the response.
//!
//! All the [CTE](https://www.postgresql.org/docs/13/queries-with.html) have all the same commons keys as describe below,
//! some have additional columns for sorting or linking but these won't be included in the response.
//!
//! One can think of the response like the following schema in which different [CTE](https://www.postgresql.org/docs/13/queries-with.html)
//! contributing to the final reponse beeing built.
//!
//! ```ascii
//!                                                    ┌────────┐
//!                                                    │ Origin │
//!                                                    │ Table  │
//!                      ┌───┬─────────────────┬───────┴──────┬─┴─────────┬────────────┐
//!        Columns   ──► │ id│type             │     data     │related_id │related_type│
//!                      ├───┼─────────────────┼─────┬────────┴────┬──────┼────────────┤
//!                      │   │                 │     │cte_peoples_0│      │            │
//!      Action CTE  ──► │   │                 │     └────────┬────┘      │            │
//!                      │ 01│peoples          │   {<json>}   │   NULL    │ NULL       │
//!                      ├───┼─────────────────┼─────┬────────┴─────┬─────┼────────────┤
//!                      │   │                 │     │cte_articles_1│     │            │
//!                      │   │                 │     └────────┬─────┘     │            │
//!     Relationship ──► │ 42│articles         │   {<json>}   │    01     │ peoples    │
//!      "articles"      │ 43│articles         │   {<json>}   │    01     │ peoples    │
//!                      │ 44│articles         │   {<json>}   │    01     │ peoples    │
//!                      ├───┼─────────────────┼──┬───────────┴────────┬──┼────────────┤
//!                      │   │                 │  │cte_favorite_color_2│  │            │
//!     Relationship ──► │   │                 │  └───────────┬────────┘  │            │
//!   "favorite_color"   │ 61│favorite_color   │   {<json>}   │    01     │ peoples    │
//!                      ├───┼─────────────────┼──┬───────────┴───────────┼────────────┤
//!                      │   │                 │  │cte_articles_comments_3│            │
//!     Relationship ──► │   │                 │  └───────────┬───────────┤            │
//! "articles.comments"  │ 37│articles.comments│   {<json>}   │    42     │ articles   │
//!                      │ 30│articles.comments│   {<json>}   │    42     │ articles   │
//!                      │ 31│articles.comments│   {<json>}   │    43     │ articles   │
//!                      │ 32│articles.comments│   {<json>}   │    43     │ articles   │
//!                      │ 33│articles.comments│   {<json>}   │    44     │ articles   │
//!                      │ 35│articles.comments│   {<json>}   │    44     │ articles   │
//!                      └───┴─────────────────┴──────────────┴───────────┴────────────┘
//! ```
//!
//! The _Postgres_ response can be deserialized with [Ciboulette2PgRow](Ciboulette2PgRow).
//!
//! To then build the ciboulette response, one can convert the [Ciboulette2PgRow](Ciboulette2PgRow) to [Ciboulette response element](CibouletteResponseElement).

#![warn(clippy::all)]
mod builder;
mod ciboulette_row;
mod errors;
mod response_type;
mod safe_ident;
mod table_store;
#[cfg(test)]
mod tests;

mod value;

use arcstr::ArcStr;
pub use builder::Ciboulette2PgArguments;
pub use builder::Ciboulette2PgBuilder;
use ciboulette::*;
pub use ciboulette_row::Ciboulette2PgRow;
pub use errors::Ciboulette2PgError;
use getset::Getters;
use messy_json::{
    MessyJsonExpected, MessyJsonInner, MessyJsonNullType, MessyJsonObject, MessyJsonObjectValue,
    MessyJsonValue,
};
use response_type::Ciboulette2PgResponseType;
use safe_ident::Ciboulette2PgSafeIdentModifier;
pub use safe_ident::{Ciboulette2PgSafeIdent, Ciboulette2PgSafeIdentSelector};
use safe_ident::{
    CIBOULETTE_CTE_FINAL_MAIN_DATA, CIBOULETTE_DATA_IDENT, CIBOULETTE_DATA_SUFFIX,
    CIBOULETTE_EMPTY_IDENT, CIBOULETTE_ID_IDENT, CIBOULETTE_INSERT_SUFFIX,
    CIBOULETTE_MAIN_IDENTIFIER, CIBOULETTE_RELATED_ID_IDENT, CIBOULETTE_RELATED_TYPE_IDENT,
    CIBOULETTE_REL_PREFIX, CIBOULETTE_SORT_PREFIX, CIBOULETTE_TYPE_IDENT, CIBOULETTE_UPDATE_SUFFIX,
};
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::sync::Arc;
pub use table_store::{Ciboulette2PgId, Ciboulette2PgTable, Ciboulette2PgTableStore};
pub use value::Ciboulette2PgValue;
const POSTGRES_QUOTE: &[u8] = b"\"";