1use anyhow::Context;
5use diesel::FromSqlRow;
6use diesel::backend::Backend;
7use diesel::deserialize;
8use diesel::expression::AsExpression;
9use diesel::prelude::*;
10use diesel::serialize;
11use diesel::sql_types::SmallInt;
12use sui_field_count::FieldCount;
13use sui_types::object::Object;
14use sui_types::object::Owner;
15
16use crate::schema::coin_balance_buckets;
17use crate::schema::coin_balance_buckets_deletion_reference;
18use crate::schema::kv_objects;
19use crate::schema::obj_info;
20use crate::schema::obj_info_deletion_reference;
21use crate::schema::obj_versions;
22
23#[derive(Insertable, Debug, Clone, FieldCount, Queryable)]
24#[diesel(table_name = kv_objects, primary_key(object_id, object_version))]
25#[diesel(treat_none_as_default_value = false)]
26pub struct StoredObject {
27 pub object_id: Vec<u8>,
28 pub object_version: i64,
29 pub serialized_object: Option<Vec<u8>>,
30}
31
32#[derive(
33 Insertable, Selectable, Debug, Clone, PartialEq, Eq, FieldCount, Queryable, QueryableByName,
34)]
35#[diesel(table_name = obj_versions, primary_key(object_id, object_version))]
36pub struct StoredObjVersion {
37 pub object_id: Vec<u8>,
38 pub object_version: i64,
39 pub object_digest: Option<Vec<u8>>,
40 pub cp_sequence_number: i64,
41}
42
43#[derive(AsExpression, FromSqlRow, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
44#[diesel(sql_type = SmallInt)]
45#[repr(i16)]
46pub enum StoredOwnerKind {
47 Immutable = 0,
48 Address = 1,
49 Object = 2,
50 Shared = 3,
51}
52
53#[derive(AsExpression, FromSqlRow, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
54#[diesel(sql_type = SmallInt)]
55#[repr(i16)]
56pub enum StoredCoinOwnerKind {
57 Fastpath = 0,
58 Consensus = 1,
59}
60
61#[derive(Insertable, Debug, Clone, FieldCount, Queryable)]
62#[diesel(table_name = obj_info, primary_key(object_id, cp_sequence_number))]
63#[diesel(treat_none_as_default_value = false)]
64pub struct StoredObjInfo {
65 pub object_id: Vec<u8>,
66 pub cp_sequence_number: i64,
67 pub owner_kind: Option<StoredOwnerKind>,
68 pub owner_id: Option<Vec<u8>>,
69 pub package: Option<Vec<u8>>,
70 pub module: Option<String>,
71 pub name: Option<String>,
72 pub instantiation: Option<Vec<u8>>,
73}
74
75#[derive(Insertable, Debug, Clone, FieldCount, Queryable)]
76#[diesel(table_name = obj_info_deletion_reference, primary_key(cp_sequence_number, object_id))]
77pub struct StoredObjInfoDeletionReference {
78 pub object_id: Vec<u8>,
79 pub cp_sequence_number: i64,
80}
81
82#[derive(Insertable, Queryable, Debug, Clone, FieldCount, Eq, PartialEq)]
83#[diesel(table_name = coin_balance_buckets, primary_key(object_id, cp_sequence_number))]
84#[diesel(treat_none_as_default_value = false)]
85pub struct StoredCoinBalanceBucket {
86 pub object_id: Vec<u8>,
87 pub cp_sequence_number: i64,
88 pub owner_kind: Option<StoredCoinOwnerKind>,
89 pub owner_id: Option<Vec<u8>>,
90 pub coin_type: Option<Vec<u8>>,
91 pub coin_balance_bucket: Option<i16>,
92}
93
94#[derive(Insertable, Queryable, Debug, Clone, FieldCount, Eq, PartialEq)]
95#[diesel(table_name = coin_balance_buckets_deletion_reference, primary_key(cp_sequence_number, object_id))]
96pub struct StoredCoinBalanceBucketDeletionReference {
97 pub object_id: Vec<u8>,
98 pub cp_sequence_number: i64,
99}
100
101impl StoredObjInfo {
102 pub fn from_object(object: &Object, cp_sequence_number: i64) -> anyhow::Result<Self> {
103 let type_ = object.type_();
104 Ok(Self {
105 object_id: object.id().to_vec(),
106 cp_sequence_number,
107 owner_kind: Some(match object.owner() {
108 Owner::AddressOwner(_) => StoredOwnerKind::Address,
109 Owner::ObjectOwner(_) => StoredOwnerKind::Object,
110 Owner::Shared { .. } => StoredOwnerKind::Shared,
111 Owner::Immutable => StoredOwnerKind::Immutable,
112 Owner::ConsensusAddressOwner { .. } => StoredOwnerKind::Address,
115 }),
116
117 owner_id: match object.owner() {
118 Owner::AddressOwner(a) => Some(a.to_vec()),
119 Owner::ObjectOwner(o) => Some(o.to_vec()),
120 Owner::Shared { .. } | Owner::Immutable => None,
121 Owner::ConsensusAddressOwner { owner, .. } => Some(owner.to_vec()),
122 },
123
124 package: type_.map(|t| t.address().to_vec()),
125 module: type_.map(|t| t.module().to_string()),
126 name: type_.map(|t| t.name().to_string()),
127 instantiation: type_
128 .map(|t| bcs::to_bytes(&t.type_params()))
129 .transpose()
130 .with_context(|| {
131 format!(
132 "Failed to serialize type parameters for {}",
133 object.id().to_canonical_display(true),
134 )
135 })?,
136 })
137 }
138}
139
140impl<DB: Backend> serialize::ToSql<SmallInt, DB> for StoredOwnerKind
141where
142 i16: serialize::ToSql<SmallInt, DB>,
143{
144 fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, DB>) -> serialize::Result {
145 match self {
146 StoredOwnerKind::Immutable => 0.to_sql(out),
147 StoredOwnerKind::Address => 1.to_sql(out),
148 StoredOwnerKind::Object => 2.to_sql(out),
149 StoredOwnerKind::Shared => 3.to_sql(out),
150 }
151 }
152}
153
154impl<DB: Backend> deserialize::FromSql<SmallInt, DB> for StoredOwnerKind
155where
156 i16: deserialize::FromSql<SmallInt, DB>,
157{
158 fn from_sql(raw: DB::RawValue<'_>) -> deserialize::Result<Self> {
159 Ok(match i16::from_sql(raw)? {
160 0 => StoredOwnerKind::Immutable,
161 1 => StoredOwnerKind::Address,
162 2 => StoredOwnerKind::Object,
163 3 => StoredOwnerKind::Shared,
164 o => return Err(format!("Unexpected StoredOwnerKind: {o}").into()),
165 })
166 }
167}
168
169impl<DB: Backend> serialize::ToSql<SmallInt, DB> for StoredCoinOwnerKind
170where
171 i16: serialize::ToSql<SmallInt, DB>,
172{
173 fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, DB>) -> serialize::Result {
174 match self {
175 StoredCoinOwnerKind::Fastpath => 0.to_sql(out),
176 StoredCoinOwnerKind::Consensus => 1.to_sql(out),
177 }
178 }
179}
180
181impl<DB: Backend> deserialize::FromSql<SmallInt, DB> for StoredCoinOwnerKind
182where
183 i16: deserialize::FromSql<SmallInt, DB>,
184{
185 fn from_sql(raw: DB::RawValue<'_>) -> deserialize::Result<Self> {
186 Ok(match i16::from_sql(raw)? {
187 0 => StoredCoinOwnerKind::Fastpath,
188 1 => StoredCoinOwnerKind::Consensus,
189 o => return Err(format!("Unexpected StoredCoinOwnerKind: {o}").into()),
190 })
191 }
192}