macros.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #[rustfmt::skip]
  2. /*
  3. diesel master support on_conflict on sqlite but not 1.4.7 version. Workaround for this
  4. match dsl::workspace_table
  5. .filter(workspace_table::id.eq(table.id.clone()))
  6. .count()
  7. .get_result(conn)
  8. .unwrap_or(0)
  9. {
  10. 0 => diesel::insert_into(workspace_table::table).values(table)
  11. .on_conflict(workspace_table::id)
  12. .do_update()
  13. .set(WorkspaceTableChangeset::from_table(workspace_table))
  14. .execute(conn)?,
  15. _ => {
  16. let changeset = WorkspaceTableChangeset::from_table(table);
  17. let filter = dsl::workspace_table.filter(workspace_table::id.eq(changeset.id.clone()));
  18. diesel::update(filter).set(changeset).execute(conn)?;
  19. },
  20. }
  21. is equivalent to:
  22. match diesel_record_count!(workspace_table, &table.id, conn) {
  23. 0 => diesel_insert_table!(workspace_table, table, conn),
  24. _ => diesel_update_table!(workspace_table, WorkspaceTableChangeset::from_table(table), &*conn),
  25. }
  26. */
  27. #[macro_export]
  28. macro_rules! diesel_insert_table {
  29. (
  30. $table_name:ident,
  31. $table:expr,
  32. $connection:expr
  33. ) => {
  34. {
  35. let _ = diesel::insert_into($table_name::table)
  36. .values($table)
  37. // .on_conflict($table_name::dsl::id)
  38. // .do_update()
  39. // .set(WorkspaceTableChangeset::from_table(workspace_table))
  40. .execute($connection)?;
  41. }
  42. };
  43. }
  44. #[macro_export]
  45. macro_rules! diesel_record_count {
  46. (
  47. $table_name:ident,
  48. $id:expr,
  49. $connection:expr
  50. ) => {
  51. $table_name::dsl::$table_name
  52. .filter($table_name::dsl::id.eq($id.clone()))
  53. .count()
  54. .get_result($connection)
  55. .unwrap_or(0);
  56. };
  57. }
  58. #[macro_export]
  59. macro_rules! diesel_revision_record_count {
  60. (
  61. $table_name:expr,
  62. $filter:expr,
  63. $connection:expr
  64. ) => {
  65. $table_name
  66. .filter($table_name::dsl::id.eq($id))
  67. .count()
  68. .get_result($connection)
  69. .unwrap_or(0);
  70. };
  71. }
  72. #[macro_export]
  73. macro_rules! diesel_update_table {
  74. (
  75. $table_name:ident,
  76. $changeset:expr,
  77. $connection:expr
  78. ) => {{
  79. let filter =
  80. $table_name::dsl::$table_name.filter($table_name::dsl::id.eq($changeset.id.clone()));
  81. let affected_row = diesel::update(filter)
  82. .set($changeset)
  83. .execute($connection)?;
  84. debug_assert_eq!(affected_row, 1);
  85. }};
  86. }
  87. #[macro_export]
  88. macro_rules! diesel_delete_table {
  89. (
  90. $table_name:ident,
  91. $id:ident,
  92. $connection:ident
  93. ) => {
  94. let filter = $table_name::dsl::$table_name.filter($table_name::dsl::id.eq($id));
  95. let affected_row = diesel::delete(filter).execute(&*$connection)?;
  96. debug_assert_eq!(affected_row, 1);
  97. };
  98. }
  99. #[macro_export]
  100. macro_rules! impl_sql_binary_expression {
  101. ($target:ident) => {
  102. impl diesel::serialize::ToSql<diesel::sql_types::Binary, diesel::sqlite::Sqlite> for $target {
  103. fn to_sql<W: std::io::Write>(
  104. &self,
  105. out: &mut diesel::serialize::Output<W, diesel::sqlite::Sqlite>,
  106. ) -> diesel::serialize::Result {
  107. let bytes: Vec<u8> = self.try_into().map_err(|e| format!("{:?}", e))?;
  108. diesel::serialize::ToSql::<diesel::sql_types::Binary, diesel::sqlite::Sqlite>::to_sql(
  109. &bytes, out,
  110. )
  111. }
  112. }
  113. // https://docs.diesel.rs/src/diesel/sqlite/types/mod.rs.html#30-33
  114. // impl FromSql<sql_types::Binary, Sqlite> for *const [u8] {
  115. // fn from_sql(bytes: Option<&SqliteValue>) -> deserialize::Result<Self> {
  116. // let bytes = not_none!(bytes).read_blob();
  117. // Ok(bytes as *const _)
  118. // }
  119. // }
  120. impl<DB> diesel::deserialize::FromSql<diesel::sql_types::Binary, DB> for $target
  121. where
  122. DB: diesel::backend::Backend,
  123. *const [u8]: diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>,
  124. {
  125. fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
  126. let slice_ptr = <*const [u8] as diesel::deserialize::FromSql<
  127. diesel::sql_types::Binary,
  128. DB,
  129. >>::from_sql(bytes)?;
  130. let bytes = unsafe { &*slice_ptr };
  131. match $target::try_from(bytes) {
  132. Ok(object) => Ok(object),
  133. Err(e) => {
  134. log::error!(
  135. "{:?} deserialize from bytes fail. {:?}",
  136. std::any::type_name::<$target>(),
  137. e
  138. );
  139. panic!();
  140. },
  141. }
  142. }
  143. }
  144. };
  145. }
  146. #[macro_export]
  147. macro_rules! impl_sql_integer_expression {
  148. ($target:ident) => {
  149. impl<DB> diesel::serialize::ToSql<Integer, DB> for $target
  150. where
  151. DB: diesel::backend::Backend,
  152. i32: diesel::serialize::ToSql<Integer, DB>,
  153. {
  154. fn to_sql<W: std::io::Write>(
  155. &self,
  156. out: &mut diesel::serialize::Output<W, DB>,
  157. ) -> diesel::serialize::Result {
  158. (*self as i32).to_sql(out)
  159. }
  160. }
  161. impl<DB> diesel::deserialize::FromSql<Integer, DB> for $target
  162. where
  163. DB: diesel::backend::Backend,
  164. i32: diesel::deserialize::FromSql<Integer, DB>,
  165. {
  166. fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
  167. let smaill_int = i32::from_sql(bytes)?;
  168. Ok($target::from(smaill_int))
  169. }
  170. }
  171. };
  172. }
  173. #[macro_export]
  174. macro_rules! impl_rev_state_map {
  175. ($target:ident) => {
  176. impl std::convert::From<i32> for $target {
  177. fn from(value: i32) -> Self {
  178. match value {
  179. 0 => $target::Sync,
  180. 1 => $target::Ack,
  181. o => {
  182. tracing::error!("Unsupported rev state {}, fallback to RevState::Local", o);
  183. $target::Sync
  184. },
  185. }
  186. }
  187. }
  188. impl std::convert::From<$target> for RevisionState {
  189. fn from(s: $target) -> Self {
  190. match s {
  191. $target::Sync => RevisionState::Sync,
  192. $target::Ack => RevisionState::Ack,
  193. }
  194. }
  195. }
  196. impl std::convert::From<RevisionState> for $target {
  197. fn from(s: RevisionState) -> Self {
  198. match s {
  199. RevisionState::Sync => $target::Sync,
  200. RevisionState::Ack => $target::Ack,
  201. }
  202. }
  203. }
  204. };
  205. }