macros.rs 6.5 KB

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