macros.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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 = $table_name::dsl::$table_name.filter($table_name::dsl::id.eq($changeset.id.clone()));
  80. let affected_row = diesel::update(filter).set($changeset).execute($connection)?;
  81. debug_assert_eq!(affected_row, 1);
  82. }};
  83. }
  84. #[macro_export]
  85. macro_rules! diesel_delete_table {
  86. (
  87. $table_name:ident,
  88. $id:ident,
  89. $connection:ident
  90. ) => {
  91. let filter = $table_name::dsl::$table_name.filter($table_name::dsl::id.eq($id));
  92. let affected_row = diesel::delete(filter).execute(&*$connection)?;
  93. debug_assert_eq!(affected_row, 1);
  94. };
  95. }
  96. #[macro_export]
  97. macro_rules! impl_sql_binary_expression {
  98. ($target:ident) => {
  99. impl diesel::serialize::ToSql<diesel::sql_types::Binary, diesel::sqlite::Sqlite> for $target {
  100. fn to_sql<W: std::io::Write>(
  101. &self,
  102. out: &mut diesel::serialize::Output<W, diesel::sqlite::Sqlite>,
  103. ) -> diesel::serialize::Result {
  104. let bytes: Vec<u8> = self.try_into().map_err(|e| format!("{:?}", e))?;
  105. diesel::serialize::ToSql::<diesel::sql_types::Binary, diesel::sqlite::Sqlite>::to_sql(&bytes, out)
  106. }
  107. }
  108. // https://docs.diesel.rs/src/diesel/sqlite/types/mod.rs.html#30-33
  109. // impl FromSql<sql_types::Binary, Sqlite> for *const [u8] {
  110. // fn from_sql(bytes: Option<&SqliteValue>) -> deserialize::Result<Self> {
  111. // let bytes = not_none!(bytes).read_blob();
  112. // Ok(bytes as *const _)
  113. // }
  114. // }
  115. impl<DB> diesel::deserialize::FromSql<diesel::sql_types::Binary, DB> for $target
  116. where
  117. DB: diesel::backend::Backend,
  118. *const [u8]: diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>,
  119. {
  120. fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
  121. let slice_ptr =
  122. <*const [u8] as diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>>::from_sql(bytes)?;
  123. let bytes = unsafe { &*slice_ptr };
  124. match $target::try_from(bytes) {
  125. Ok(object) => Ok(object),
  126. Err(e) => {
  127. log::error!(
  128. "{:?} deserialize from bytes fail. {:?}",
  129. std::any::type_name::<$target>(),
  130. e
  131. );
  132. panic!();
  133. }
  134. }
  135. }
  136. }
  137. };
  138. }
  139. #[macro_export]
  140. macro_rules! impl_sql_integer_expression {
  141. ($target:ident) => {
  142. impl<DB> diesel::serialize::ToSql<Integer, DB> for $target
  143. where
  144. DB: diesel::backend::Backend,
  145. i32: diesel::serialize::ToSql<Integer, DB>,
  146. {
  147. fn to_sql<W: std::io::Write>(
  148. &self,
  149. out: &mut diesel::serialize::Output<W, DB>,
  150. ) -> diesel::serialize::Result {
  151. (*self as i32).to_sql(out)
  152. }
  153. }
  154. impl<DB> diesel::deserialize::FromSql<Integer, DB> for $target
  155. where
  156. DB: diesel::backend::Backend,
  157. i32: diesel::deserialize::FromSql<Integer, DB>,
  158. {
  159. fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
  160. let smaill_int = i32::from_sql(bytes)?;
  161. Ok($target::from(smaill_int))
  162. }
  163. }
  164. };
  165. }
  166. #[macro_export]
  167. macro_rules! impl_rev_state_map {
  168. ($target:ident) => {
  169. impl std::convert::From<i32> for $target {
  170. fn from(value: i32) -> Self {
  171. match value {
  172. 0 => $target::Sync,
  173. 1 => $target::Ack,
  174. o => {
  175. tracing::error!("Unsupported rev state {}, fallback to RevState::Local", o);
  176. $target::Sync
  177. }
  178. }
  179. }
  180. }
  181. impl std::convert::From<$target> for RevisionState {
  182. fn from(s: $target) -> Self {
  183. match s {
  184. $target::Sync => RevisionState::Sync,
  185. $target::Ack => RevisionState::Ack,
  186. }
  187. }
  188. }
  189. impl std::convert::From<RevisionState> for $target {
  190. fn from(s: RevisionState) -> Self {
  191. match s {
  192. RevisionState::Sync => $target::Sync,
  193. RevisionState::Ack => $target::Ack,
  194. }
  195. }
  196. }
  197. };
  198. }