value.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. use std::fmt::Debug;
  2. use cdk_sql_common::value::Value;
  3. use tokio_postgres::types::{self, FromSql, ToSql};
  4. #[derive(Debug)]
  5. pub enum PgValue<'a> {
  6. Null,
  7. Integer(i64),
  8. Real(f64),
  9. Text(&'a str),
  10. Blob(&'a [u8]),
  11. }
  12. impl<'a> From<&'a Value> for PgValue<'a> {
  13. fn from(value: &'a Value) -> Self {
  14. match value {
  15. Value::Blob(b) => PgValue::Blob(b),
  16. Value::Text(text) => PgValue::Text(text.as_str()),
  17. Value::Null => PgValue::Null,
  18. Value::Integer(i) => PgValue::Integer(*i),
  19. Value::Real(r) => PgValue::Real(*r),
  20. }
  21. }
  22. }
  23. impl<'a> From<PgValue<'a>> for Value {
  24. fn from(val: PgValue<'a>) -> Self {
  25. match val {
  26. PgValue::Blob(value) => Value::Blob(value.to_owned()),
  27. PgValue::Text(value) => Value::Text(value.to_owned()),
  28. PgValue::Null => Value::Null,
  29. PgValue::Integer(n) => Value::Integer(n),
  30. PgValue::Real(r) => Value::Real(r),
  31. }
  32. }
  33. }
  34. impl<'a> FromSql<'a> for PgValue<'a> {
  35. fn accepts(_ty: &types::Type) -> bool {
  36. true
  37. }
  38. fn from_sql(
  39. ty: &types::Type,
  40. raw: &'a [u8],
  41. ) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
  42. Ok(match *ty {
  43. types::Type::VARCHAR | types::Type::TEXT | types::Type::BPCHAR | types::Type::NAME => {
  44. PgValue::Text(<&str as FromSql>::from_sql(ty, raw)?)
  45. }
  46. types::Type::BOOL => PgValue::Integer(if <bool as FromSql>::from_sql(ty, raw)? {
  47. 1
  48. } else {
  49. 0
  50. }),
  51. types::Type::INT2 => PgValue::Integer(<i8 as FromSql>::from_sql(ty, raw)? as i64),
  52. types::Type::INT4 => PgValue::Integer(<i32 as FromSql>::from_sql(ty, raw)? as i64),
  53. types::Type::INT8 => PgValue::Integer(<i64 as FromSql>::from_sql(ty, raw)?),
  54. types::Type::BIT_ARRAY | types::Type::BYTEA | types::Type::UNKNOWN => {
  55. PgValue::Blob(<&[u8] as FromSql>::from_sql(ty, raw)?)
  56. }
  57. _ => panic!("Unsupported type {ty:?}"),
  58. })
  59. }
  60. fn from_sql_null(_ty: &types::Type) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
  61. Ok(PgValue::Null)
  62. }
  63. }
  64. impl ToSql for PgValue<'_> {
  65. fn to_sql(
  66. &self,
  67. ty: &types::Type,
  68. out: &mut types::private::BytesMut,
  69. ) -> Result<types::IsNull, Box<dyn std::error::Error + Sync + Send>>
  70. where
  71. Self: Sized,
  72. {
  73. match self {
  74. PgValue::Blob(blob) => (*blob).to_sql(ty, out),
  75. PgValue::Text(text) => (*text).to_sql(ty, out),
  76. PgValue::Null => Ok(types::IsNull::Yes),
  77. PgValue::Real(r) => r.to_sql(ty, out),
  78. PgValue::Integer(i) => match *ty {
  79. types::Type::BOOL => (*i != 0).to_sql(ty, out),
  80. types::Type::INT2 => (*i as i16).to_sql(ty, out),
  81. types::Type::INT4 => (*i as i32).to_sql(ty, out),
  82. _ => i.to_sql_checked(ty, out),
  83. },
  84. }
  85. }
  86. fn accepts(_ty: &types::Type) -> bool
  87. where
  88. Self: Sized,
  89. {
  90. true
  91. }
  92. fn encode_format(&self, ty: &types::Type) -> types::Format {
  93. match self {
  94. PgValue::Blob(blob) => blob.encode_format(ty),
  95. PgValue::Text(text) => text.encode_format(ty),
  96. PgValue::Null => types::Format::Text,
  97. PgValue::Real(r) => r.encode_format(ty),
  98. PgValue::Integer(i) => i.encode_format(ty),
  99. }
  100. }
  101. fn to_sql_checked(
  102. &self,
  103. ty: &types::Type,
  104. out: &mut types::private::BytesMut,
  105. ) -> Result<types::IsNull, Box<dyn std::error::Error + Sync + Send>> {
  106. match self {
  107. PgValue::Blob(blob) => blob.to_sql_checked(ty, out),
  108. PgValue::Text(text) => text.to_sql_checked(ty, out),
  109. PgValue::Null => Ok(types::IsNull::Yes),
  110. PgValue::Real(r) => r.to_sql_checked(ty, out),
  111. PgValue::Integer(i) => match *ty {
  112. types::Type::BOOL => (*i != 0).to_sql_checked(ty, out),
  113. types::Type::INT2 => (*i as i16).to_sql_checked(ty, out),
  114. types::Type::INT4 => (*i as i32).to_sql_checked(ty, out),
  115. _ => i.to_sql_checked(ty, out),
  116. },
  117. }
  118. }
  119. }