Advertisement
Guest User

Untitled

a guest
May 3rd, 2019
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.57 KB | None | 0 0
  1. #[macro_use]
  2. pub mod query_builder {
  3. //! SQL like generic query builder.
  4. //! 構文木の生成までを行うので、それをトラバースして必要な処理を行う。
  5.  
  6. use std::rc::Rc;
  7. use std::fmt::Debug;
  8. use std::marker::PhantomData;
  9.  
  10. /// Entityのフィールドを表す型が実装するメソッド
  11. pub trait Field: Debug {
  12. /// 演算子の右辺の型
  13. type Data: Debug;
  14. }
  15.  
  16. /// クエリ全体を表すtrait。単なるマーク。
  17. pub trait Query<P, O>: Debug {
  18. fn walk(&self) -> O;
  19. }
  20.  
  21. #[derive(Debug)]
  22. pub struct BoxedQuery<P, O> {
  23. pub query: Rc<Query<P, O>>,
  24. }
  25.  
  26. // impl<P, O> Query<P, O> for BoxedQuery<P, O> {}
  27.  
  28. impl<P, O> BoxedQuery<P, O> {
  29. fn new<Q: Query<P, O> + 'static>(query: Q) -> BoxedQuery<P, O> {
  30. BoxedQuery {
  31. query: Rc::new(query),
  32. }
  33. }
  34. }
  35.  
  36. #[derive(Debug, Clone, PartialEq, Eq)]
  37. pub struct And<P, O, Q1: Query<P, O>, Q2: Query<P, O>>(pub Q1, pub Q2, PhantomData<P>, PhantomData<O>);
  38. // impl<P, O, Q1: Query<P, O>, Q2: Query<P, O>> Query<P, O> for And<P, O, Q1, Q2> {}
  39.  
  40. impl<P, O, T, S> And<P, O, T, S>
  41. where
  42. T: Query<P, O>,
  43. S: Query<P, O>,
  44. {
  45. pub fn new(l: T, r: S) -> And<P, O, T, S> {
  46. And(l, r, PhantomData, PhantomData)
  47. }
  48. }
  49.  
  50. impl<P, O, T, S> And<P, O, T, S>
  51. where
  52. T: Query<P, O>,
  53. S: Query<P, O>,
  54. Self: Query<P, O>,
  55. {
  56. pub fn and<Q: Query<P, O>>(self, rhs: Q) -> And<P, O, Self, Q> {
  57. And::new(self, rhs)
  58. }
  59. }
  60.  
  61. impl<P, O, T, S> And<P, O, T, S>
  62. where
  63. P: 'static,
  64. O: 'static,
  65. T: Query<P, O> + 'static,
  66. S: Query<P, O> + 'static,
  67. Self: Query<P, O>,
  68. {
  69. pub fn into_boxed(self) -> BoxedQuery<P, O> {
  70. BoxedQuery::new(self)
  71. }
  72. }
  73.  
  74. #[derive(Debug, Clone, PartialEq, Eq)]
  75. pub struct Or<P, O, T: Query<P, O>, S: Query<P, O>>(pub T, pub S, PhantomData<P>, PhantomData<O>);
  76. // impl<P, O, T: Query<P, O>, S: Query<P, O>> Query<P, O> for Or<P, O, T, S> {}
  77.  
  78. impl<P, O, T, S> Or<P, O, T, S>
  79. where
  80. T: Query<P, O>,
  81. S: Query<P, O>,
  82. {
  83. pub fn new(l: T, r: S) -> Or<P, O, T, S> {
  84. Or(l, r, PhantomData, PhantomData)
  85. }
  86. }
  87.  
  88. impl<P, O, T: Query<P, O>, S: Query<P, O>> Or<P, O, T, S>
  89. where
  90. T: Query<P, O>,
  91. S: Query<P, O>,
  92. Self: Query<P, O>,
  93. {
  94. pub fn or<Q: Query<P,O>>(self, rhs: Q) -> Or<P, O, Self, Q> {
  95. Or::new(self, rhs)
  96. }
  97. }
  98.  
  99. impl<P, O, T: Query<P, O> + 'static, S: Query<P, O> + 'static> Or<P, O, T, S>
  100. where
  101. P: 'static,
  102. O: 'static,
  103. T: Query<P, O> + 'static,
  104. S: Query<P, O> + 'static,
  105. Self: Query<P, O>,
  106. {
  107. pub fn into_boxed(self) -> BoxedQuery<P, O> {
  108. BoxedQuery::new(self)
  109. }
  110. }
  111.  
  112. #[derive(Debug, Clone, PartialEq, Eq)]
  113. pub struct Not<P, O, T: Query<P, O>>(pub T, PhantomData<P>, PhantomData<O>);
  114. // impl<P, O, T: Query<P, O>> Query<P,O> for Not<P, O, T> {}
  115.  
  116. pub fn not<P, O, T: Query<P,O>>(q: T) -> Not<P, O, T> {
  117. Not(q, PhantomData, PhantomData)
  118. }
  119.  
  120. impl<P, O, T> Not<P, O, T>
  121. where
  122. T: Query<P, O>,
  123. Self: Query<P, O>,
  124. {
  125. pub fn and<Q: Query<P, O>>(self, rhs: Q) -> And<P, O, Self, Q> {
  126. And::new(self, rhs)
  127. }
  128.  
  129. pub fn or<Q: Query<P, O>>(self, rhs: Q) -> Or<P, O, Self, Q> {
  130. Or::new(self, rhs)
  131. }
  132. }
  133.  
  134. impl<P, O, T> Not<P, O, T>
  135. where
  136. P: 'static,
  137. O: 'static,
  138. T: Query<P, O> + 'static,
  139. Self: Query<P, O>,
  140. {
  141. pub fn into_boxed(self) -> BoxedQuery<P, O> {
  142. BoxedQuery::new(self)
  143. }
  144. }
  145.  
  146. #[derive(Debug, Clone)]
  147. pub enum Operator<T: Field> {
  148. /// `==`
  149. Eq(T, T::Data),
  150. /// `!=`
  151. NotEq(T, T::Data),
  152. /// `>`
  153. Gt(T, T::Data),
  154. /// `>=`
  155. Ge(T, T::Data),
  156. /// `<`
  157. Lt(T, T::Data),
  158. /// `<=`
  159. Le(T, T::Data),
  160. /// Like SQL `between`
  161. Between(T, T::Data, T::Data),
  162. /// Like SQL `like`
  163. Like(T, T::Data),
  164. Any(T, Vec<T::Data>),
  165. NotAny(T, Vec<T::Data>),
  166. }
  167. // impl<P, O, T: Field + Debug + 'static> Query<P, O> for Operator<T> {}
  168.  
  169. impl<T> Operator<T>
  170. where
  171. T: Field + Debug + 'static,
  172. {
  173. pub fn and<P, O, Q>(self, rhs: Q) -> And<P, O, Self, Q>
  174. where
  175. Q: Query<P, O>,
  176. Self: Query<P, O>,
  177. {
  178. And::new(self, rhs)
  179. }
  180.  
  181. pub fn or<P, O, Q>(self, rhs: Q) -> Or<P, O, Self, Q>
  182. where
  183. Q: Query<P, O>,
  184. Self: Query<P, O>,
  185. {
  186. Or::new(self, rhs)
  187. }
  188.  
  189. pub fn into_boxed<P, O>(self) -> BoxedQuery<P, O>
  190. where
  191. Self: Query<P, O>,
  192. {
  193. BoxedQuery::new(self)
  194. }
  195. }
  196.  
  197. /// Entityのfield型に生やすメソッド。演算子。
  198. pub trait OperatorMethod: Field + Sized {
  199. /// `==`
  200. fn eq(self, rhs: Self::Data) -> Operator<Self> {
  201. Operator::Eq(self, rhs)
  202. }
  203.  
  204. /// `!=`
  205. fn not_eq(self, rhs: Self::Data) -> Operator<Self> {
  206. Operator::NotEq(self, rhs)
  207. }
  208.  
  209. /// `>`
  210. fn gt(self, rhs: Self::Data) -> Operator<Self> {
  211. Operator::Gt(self, rhs)
  212. }
  213.  
  214. /// `>=`
  215. fn ge(self, rhs: Self::Data) -> Operator<Self> {
  216. Operator::Ge(self, rhs)
  217. }
  218.  
  219. /// `<`
  220. fn lt(self, rhs: Self::Data) -> Operator<Self> {
  221. Operator::Lt(self, rhs)
  222. }
  223.  
  224. /// `<=`
  225. fn le(self, rhs: Self::Data) -> Operator<Self> {
  226. Operator::Le(self, rhs)
  227. }
  228.  
  229. /// Like SQL `between`
  230. fn between(self, from: Self::Data, until: Self::Data) -> Operator<Self> {
  231. Operator::Between(self, from, until)
  232. }
  233.  
  234. /// Like SQL `like`
  235. fn like(self, rhs: Self::Data) -> Operator<Self> {
  236. Operator::Like(self, rhs)
  237. }
  238.  
  239. fn any(self, rhs: Vec<Self::Data>) -> Operator<Self> {
  240. Operator::Any(self, rhs)
  241. }
  242.  
  243. fn not_any(self, rhs: Vec<Self::Data>) -> Operator<Self> {
  244. Operator::NotAny(self, rhs)
  245. }
  246. }
  247.  
  248. #[macro_export]
  249. macro_rules! query_info {
  250. ( $( @ $item:item )* $name:ident { $( $field:ident : $field_type:ty ),* $(,)* } ) => {
  251. pub mod $name {
  252. pub mod query {
  253. use crate::query_builder::*;
  254.  
  255. $( $item )*
  256.  
  257. $(
  258. #[allow(dead_code, non_camel_case_types)]
  259. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
  260. pub struct $field;
  261.  
  262. impl Field for $field {
  263. type Data = $field_type;
  264. }
  265.  
  266. impl OperatorMethod for $field {}
  267. )*
  268. }
  269. }
  270. }
  271. }
  272. }
  273.  
  274. mod entity {
  275. use chrono::prelude::*;
  276.  
  277. pub trait FieldName {
  278. fn name(&self) -> &str;
  279. }
  280.  
  281. macro_rules! impl_field_name {
  282. ( $( $field:ty > $name:tt ),* $(,)* ) => {
  283. $(
  284. impl FieldName for $field {
  285. fn name(&self) -> &str {
  286. $name
  287. }
  288. }
  289. )*
  290. }
  291. }
  292.  
  293. #[derive(Debug)]
  294. pub struct User {
  295. pub id: u64,
  296. pub id_name: String,
  297. pub display_name: String,
  298. pub password: String,
  299. pub status: u8,
  300. pub created_at: DateTime<Utc>,
  301. pub updated_at: DateTime<Utc>,
  302. }
  303.  
  304. query_info! {
  305. @use chrono::prelude::*;
  306.  
  307. user {
  308. id: u64,
  309. id_name: String,
  310. display_name: String,
  311. password: String,
  312. status: u8,
  313. created_at: DateTime<Utc>,
  314. updated_at: DateTime<Utc>,
  315. }
  316. }
  317.  
  318. impl_field_name!(
  319. self::user::query::id > "id",
  320. self::user::query::id_name > "id_name",
  321. self::user::query::display_name > "display_name",
  322. self::user::query::password > "password",
  323. self::user::query::status > "status",
  324. self::user::query::created_at > "created_at",
  325. self::user::query::updated_at > "updated_at",
  326. );
  327.  
  328. pub struct User2 {
  329. pub id: u64,
  330. pub id_name: String,
  331. pub display_name: String,
  332. pub password: String,
  333. pub status: u8,
  334. pub created_at: DateTime<Utc>,
  335. pub updated_at: DateTime<Utc>,
  336. }
  337.  
  338. query_info! {
  339. @use chrono::prelude::*;
  340.  
  341. user2 {
  342. id: u64,
  343. id_name: String,
  344. display_name: String,
  345. password: String,
  346. status: u8,
  347. created_at: DateTime<Utc>,
  348. updated_at: DateTime<Utc>,
  349. }
  350. }
  351.  
  352. impl_field_name!(
  353. self::user2::query::id > "id",
  354. self::user2::query::id_name > "id_name",
  355. self::user2::query::display_name > "display_name",
  356. self::user2::query::password > "password",
  357. self::user2::query::status > "status",
  358. self::user2::query::created_at > "created_at",
  359. self::user2::query::updated_at > "updated_at",
  360. );
  361. }
  362.  
  363. mod repository {
  364. pub mod user {
  365. //! ストレージ上での格納形式に対応する型はここで定義。
  366.  
  367. use crate::entity::{FieldName, User};
  368. use crate::query_builder::{And, Field, Not, Operator, Or, Query, BoxedQuery};
  369. use failure::bail;
  370. use std::fmt::Display;
  371.  
  372. pub struct Repository;
  373.  
  374. impl Repository {
  375. // 複数entityに対してはtraitを使った型による条件分岐が必要。
  376. pub fn search<Q>(&self, query: Q) -> Result<Vec<User>, failure::Error>
  377. where
  378. Q: Query<StringProcessor, String>,
  379. {
  380. println!("Build: {}", query.walk());
  381. bail!("hoge")
  382. }
  383. }
  384.  
  385. pub trait Processor<T> {
  386. type Input;
  387. type Output;
  388.  
  389. fn process(input: &Self::Input) -> Self::Output;
  390. }
  391.  
  392. #[derive(Debug)]
  393. pub struct StringProcessor;
  394.  
  395. impl<T> Processor<Operator<T>> for StringProcessor
  396. where
  397. T: Field + FieldName,
  398. T::Data: Display,
  399. {
  400. type Input = Operator<T>;
  401. type Output = String;
  402.  
  403. fn process(input: &Operator<T>) -> String {
  404. use itertools::join;
  405. match input {
  406. Operator::Eq(field, rhs) => format!("{} = {}", field.name(), rhs),
  407. Operator::NotEq(field, rhs) => format!("{} != {}", field.name(), rhs),
  408. Operator::Gt(field, rhs) => format!("{} > {}", field.name(), rhs),
  409. Operator::Ge(field, rhs) => format!("{} >= {}", field.name(), rhs),
  410. Operator::Lt(field, rhs) => format!("{} < {}", field.name(), rhs),
  411. Operator::Le(field, rhs) => format!("{} <= {}", field.name(), rhs),
  412. Operator::Between(field, from, until) => {
  413. format!("{} between {} and {}", field.name(), from, until)
  414. }
  415. Operator::Like(field, rhs) => format!("{} like '{}'", field.name(), rhs),
  416. Operator::Any(field, rhs) => format!("{} in ({})", field.name(), join(rhs.iter(), ", ")),
  417. Operator::NotAny(field, rhs) => format!("{} like ({})", field.name(), join(rhs.iter(), ", ")),
  418. }
  419. }
  420. }
  421.  
  422. impl<Q1, Q2> Processor<And<StringProcessor, String, Q1, Q2>> for StringProcessor
  423. where
  424. Q1: Query<StringProcessor, String>,
  425. Q2: Query<StringProcessor, String>,
  426. {
  427. type Input = (String, String);
  428. type Output = String;
  429.  
  430. fn process(input: &(String, String)) -> String {
  431. format!("({}) and ({})", input.0, input.1)
  432. }
  433. }
  434.  
  435. impl<Q1, Q2> Processor<Or<StringProcessor, String, Q1, Q2>> for StringProcessor
  436. where
  437. Q1: Query<StringProcessor, String>,
  438. Q2: Query<StringProcessor, String>,
  439. {
  440. type Input = (String, String);
  441. type Output = String;
  442.  
  443. fn process(input: &(String, String)) -> String {
  444. format!("({}) or ({})", input.0, input.1)
  445. }
  446. }
  447.  
  448. impl<Q1> Processor<Not<StringProcessor, String, Q1>> for StringProcessor
  449. where
  450. Q1: Query<StringProcessor, String>,
  451. {
  452. type Input = String;
  453. type Output = String;
  454.  
  455. fn process(input: &String) -> String {
  456. format!("not ({})", input)
  457. }
  458. }
  459.  
  460. impl<T> Query<StringProcessor, String> for Operator<T>
  461. where
  462. T: Field + FieldName,
  463. T::Data: Display,
  464. {
  465. fn walk(&self) -> String {
  466. <StringProcessor as Processor<Self>>::process(self)
  467. }
  468. }
  469.  
  470. impl<Q1, Q2> Query<StringProcessor, String> for And<StringProcessor, String, Q1, Q2>
  471. where
  472. Q1: Query<StringProcessor, String>,
  473. Q2: Query<StringProcessor, String>,
  474. {
  475. fn walk(&self) -> String {
  476. <StringProcessor as Processor<Self>>::process(&(self.0.walk(), self.1.walk()))
  477. }
  478. }
  479.  
  480. impl<Q1, Q2> Query<StringProcessor, String> for Or<StringProcessor, String, Q1, Q2>
  481. where
  482. Q1: Query<StringProcessor, String>,
  483. Q2: Query<StringProcessor, String>,
  484. {
  485. fn walk(&self) -> String {
  486. <StringProcessor as Processor<Self>>::process(&(self.0.walk(), self.1.walk()))
  487. }
  488. }
  489.  
  490. impl<Q1> Query<StringProcessor, String> for Not<StringProcessor, String, Q1>
  491. where
  492. Q1: Query<StringProcessor, String>,
  493. {
  494. fn walk(&self) -> String {
  495. <StringProcessor as Processor<Self>>::process(&self.0.walk())
  496. }
  497. }
  498.  
  499. impl Query<StringProcessor, String> for BoxedQuery<StringProcessor, String>
  500. {
  501. fn walk(&self) -> String {
  502. self.query.as_ref().walk()
  503. }
  504. }
  505. }
  506. }
  507.  
  508. fn main() -> Result<(), failure::Error> {
  509. use crate::entity::user2::query::*;
  510. use crate::query_builder::*;
  511. use crate::repository;
  512. use chrono::prelude::*;
  513.  
  514. println!("===== static query =====");
  515. let query = id
  516. .eq(32)
  517. .and(created_at.eq(Utc::now()).or(updated_at.eq(Utc::now())));
  518. let query = display_name.like("foo".into()).or(query);
  519. println!("{:?}", query);
  520. let _ = repository::user::Repository.search(query);
  521. let _ = repository::user::Repository.search(status.eq(1));
  522.  
  523. println!("===== dynamic query =====");
  524. let mut query = id.eq(1).and(id.eq(2)).into_boxed();
  525. if rand::random::<u8>() < 127 {
  526. query = created_at.eq(Utc::now()).or(query).into_boxed();
  527. }
  528. query = And::new(
  529. updated_at.eq(Utc::now()),
  530. if rand::random::<u8>() % 2 == 0 {
  531. status.eq(1).or(query).into_boxed()
  532. } else {
  533. status.eq(2).or(query).into_boxed()
  534. }
  535. ).and(id_name.any(vec!["yamada".into(), "satoh".into()])).into_boxed();
  536. println!("{:?}", query);
  537. let _ = repository::user::Repository.search(query);
  538.  
  539. Ok(())
  540. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement