1use std::{
2 borrow::Borrow,
3 collections::HashMap,
4 fmt::{self, Write},
5 hash::Hash,
6 ops::{AddAssign, Deref},
7};
8
9use compact_str::CompactString;
10use rusqlite::{
11 ToSql,
12 types::{FromSql, FromSqlError, ToSqlOutput, Value, ValueRef},
13};
14use serde::{Deserialize, Serialize};
15use serde_json::value::RawValue;
16use smallvec::{SmallVec, ToSmallVec};
17use speedy::{Context, Readable, Reader, Writable, Writer};
18
19pub mod sqlite {
20 use rusqlite::{
21 ToSql,
22 types::{FromSql, FromSqlError},
23 };
24 use serde::{Deserialize, Serialize};
25 use speedy::{Readable, Writable};
26
27 #[derive(
28 Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Readable, Writable, strum::FromRepr,
29 )]
30 #[serde(rename_all = "snake_case")]
31 #[repr(u8)]
32 pub enum ChangeType {
33 Insert = 0,
34 Update = 1,
35 Delete = 2,
36 }
37
38 impl FromSql for ChangeType {
39 fn column_result(
40 value: rusqlite::types::ValueRef<'_>,
41 ) -> rusqlite::types::FromSqlResult<Self> {
42 match value {
43 rusqlite::types::ValueRef::Integer(i) => Ok(ChangeType::from_repr(
44 i.try_into().map_err(|e| FromSqlError::Other(Box::new(e)))?,
45 )
46 .ok_or_else(|| FromSqlError::OutOfRange(i))?),
47 _ => Err(FromSqlError::InvalidType),
48 }
49 }
50 }
51
52 impl ToSql for ChangeType {
53 fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
54 Ok(rusqlite::types::ToSqlOutput::Owned(
55 rusqlite::types::Value::Integer((*self as u8) as i64),
56 ))
57 }
58 }
59}
60
61use sqlite::ChangeType;
62
63pub type QueryEvent = TypedQueryEvent<Vec<SqliteValue>>;
64
65#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
66#[serde(rename_all = "snake_case")]
67pub enum TypedQueryEvent<T> {
68 Columns(Vec<ColumnName>),
69 Row(RowId, T),
70 #[serde(rename = "eoq")]
71 EndOfQuery {
72 time: f64,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 change_id: Option<ChangeId>,
75 },
76 Change(ChangeType, RowId, T, ChangeId),
77 Error(CompactString),
78}
79
80impl<T> TypedQueryEvent<T> {
81 pub fn meta(&self) -> QueryEventMeta {
82 match self {
83 TypedQueryEvent::Columns(_) => QueryEventMeta::Columns,
84 TypedQueryEvent::Row(rowid, _) => QueryEventMeta::Row(*rowid),
85 TypedQueryEvent::EndOfQuery { change_id, .. } => QueryEventMeta::EndOfQuery(*change_id),
86 TypedQueryEvent::Change(_, _, _, id) => QueryEventMeta::Change(*id),
87 TypedQueryEvent::Error(_) => QueryEventMeta::Error,
88 }
89 }
90}
91
92#[derive(Debug, Clone, Copy, PartialEq)]
93pub enum QueryEventMeta {
94 Columns,
95 Row(RowId),
96 EndOfQuery(Option<ChangeId>),
97 Change(ChangeId),
98 Error,
99 Notify,
100}
101
102pub type NotifyEvent = TypedNotifyEvent<Vec<SqliteValue>>;
103
104#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
105#[serde(rename_all = "snake_case")]
106pub enum TypedNotifyEvent<T> {
107 Notify(ChangeType, T),
108 Error(CompactString),
109}
110
111#[derive(
113 Debug,
114 Clone,
115 Copy,
116 Serialize,
117 Deserialize,
118 Readable,
119 Writable,
120 PartialEq,
121 Eq,
122 Ord,
123 PartialOrd,
124 Hash,
125)]
126#[serde(transparent)]
127pub struct RowId(pub u64);
128
129impl fmt::Display for RowId {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 self.0.fmt(f)
132 }
133}
134
135impl From<u64> for RowId {
136 fn from(value: u64) -> Self {
137 Self(value)
138 }
139}
140
141impl FromSql for RowId {
142 fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
143 u64::column_result(value).map(Self)
144 }
145}
146
147impl ToSql for RowId {
148 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
149 self.0.to_sql()
150 }
151}
152
153#[derive(
155 Debug,
156 Default,
157 Clone,
158 Copy,
159 Serialize,
160 Deserialize,
161 Readable,
162 Writable,
163 PartialEq,
164 Eq,
165 Ord,
166 PartialOrd,
167)]
168#[serde(transparent)]
169pub struct ChangeId(pub u64);
170
171impl ChangeId {
172 pub fn is_zero(&self) -> bool {
173 self.0 == 0
174 }
175}
176
177impl fmt::Display for ChangeId {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 self.0.fmt(f)
180 }
181}
182
183impl From<u64> for ChangeId {
184 fn from(value: u64) -> Self {
185 Self(value)
186 }
187}
188
189impl FromSql for ChangeId {
190 fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
191 u64::column_result(value).map(Self)
192 }
193}
194
195impl ToSql for ChangeId {
196 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
197 self.0.to_sql()
198 }
199}
200
201impl AddAssign<u64> for ChangeId {
202 fn add_assign(&mut self, rhs: u64) {
203 self.0 += rhs
204 }
205}
206
207impl AddAssign<Self> for ChangeId {
208 fn add_assign(&mut self, rhs: Self) {
209 self.0 += rhs.0
210 }
211}
212
213impl std::ops::Add<u64> for ChangeId {
214 type Output = ChangeId;
215
216 fn add(self, rhs: u64) -> Self::Output {
217 ChangeId(self.0 + rhs)
218 }
219}
220
221impl std::ops::Add<Self> for ChangeId {
222 type Output = ChangeId;
223
224 fn add(self, rhs: Self) -> Self::Output {
225 ChangeId(self.0 + rhs.0)
226 }
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
230#[serde(untagged)]
231pub enum Statement {
232 Verbose {
233 query: String,
234 params: Option<Vec<SqliteParam>>,
235 named_params: Option<HashMap<String, SqliteParam>>,
236 },
237 Simple(String),
238 WithParams(String, Vec<SqliteParam>),
239 WithNamedParams(String, HashMap<String, SqliteParam>),
240}
241
242impl Statement {
243 pub fn query(&self) -> &str {
244 match self {
245 Statement::Verbose { query, .. }
246 | Statement::Simple(query)
247 | Statement::WithParams(query, _)
248 | Statement::WithNamedParams(query, _) => query,
249 }
250 }
251}
252
253impl From<&str> for Statement {
254 fn from(value: &str) -> Self {
255 Statement::Simple(value.into())
256 }
257}
258
259#[derive(Debug, Serialize, Deserialize)]
260pub struct ExecResponse {
261 pub results: Vec<ExecResult>,
262 pub time: f64,
263 pub version: Option<u64>,
264 pub actor_id: Option<String>,
265}
266
267#[derive(Debug, Serialize, Deserialize)]
268#[serde(untagged)]
269pub enum ExecResult {
270 Execute { rows_affected: usize, time: f64 },
271 Error { error: String },
272}
273#[derive(Debug, Serialize, Deserialize)]
274pub struct TableStatRequest {
275 pub tables: Vec<String>,
276}
277
278#[derive(Debug, Serialize, Deserialize)]
280pub struct TableStatResponse {
281 pub total_row_count: i64,
282 pub invalid_tables: Vec<String>,
283}
284
285#[derive(Debug, Copy, Clone, PartialEq)]
286pub struct SqliteValueRef<'a>(pub ValueRef<'a>);
287
288impl<'a> SqliteValueRef<'a> {
289 pub fn is_null(&self) -> bool {
290 matches!(self.0, ValueRef::Null)
291 }
292
293 pub fn as_integer(&self) -> Option<i64> {
294 self.0.as_i64().ok()
295 }
296
297 pub fn as_real(&self) -> Option<f64> {
298 self.0.as_f64().ok()
299 }
300
301 pub fn as_text(&self) -> Option<&str> {
302 self.0.as_str().ok()
303 }
304
305 pub fn as_blob(&self) -> Option<&[u8]> {
306 self.0.as_blob().ok()
307 }
308
309 pub fn to_owned(&self) -> SqliteValue {
310 match self.0 {
311 ValueRef::Null => SqliteValue::Null,
312 ValueRef::Integer(v) => SqliteValue::Integer(v),
313 ValueRef::Real(v) => SqliteValue::Real(Real(v)),
314 ValueRef::Text(v) => SqliteValue::Text(CompactString::from_utf8_lossy(v)),
315 ValueRef::Blob(v) => SqliteValue::Blob(v.to_smallvec()),
316 }
317 }
318}
319
320impl<'a> Hash for SqliteValueRef<'a> {
321 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
322 core::mem::discriminant(&self.0).hash(state);
323 match self.0 {
324 ValueRef::Null => {}
325 ValueRef::Integer(v) => {
326 v.hash(state);
327 }
328 ValueRef::Real(v) => {
329 integer_decode(v).hash(state);
330 }
331 ValueRef::Text(v) => {
332 v.hash(state);
333 }
334 ValueRef::Blob(v) => {
335 v.hash(state);
336 }
337 }
338 }
339}
340
341#[derive(PartialEq, Debug)]
342pub enum ColumnType {
343 Integer = 1,
344 Float = 2,
345 Text = 3,
346 Blob = 4,
347 Null = 5,
348}
349
350impl ColumnType {
351 pub fn from_u8(u: u8) -> Option<Self> {
352 Some(match u {
353 1 => Self::Integer,
354 2 => Self::Float,
355 3 => Self::Text,
356 4 => Self::Blob,
357 5 => Self::Null,
358 _ => return None,
359 })
360 }
361
362 pub fn from_sqlite_name(s: &str) -> Option<Self> {
363 Some(match s {
364 "INTEGER" => Self::Integer,
365 "REAL" => Self::Float,
366 "TEXT" => Self::Text,
367 "BLOB" => Self::Blob,
368 _ => return None,
369 })
370 }
371}
372
373impl FromSql for ColumnType {
374 fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
375 match value {
376 ValueRef::Text(s) => Ok(match String::from_utf8_lossy(s).as_ref() {
377 "INTEGER" => Self::Integer,
378 "REAL" => Self::Float,
379 "TEXT" => Self::Text,
380 "BLOB" => Self::Blob,
381 _ => {
382 return Err(FromSqlError::InvalidType);
383 }
384 }),
385 _ => Err(FromSqlError::InvalidType),
386 }
387 }
388}
389
390#[allow(clippy::large_enum_variant)]
391#[derive(Debug, Default, Clone, Serialize, Deserialize)]
392#[serde(untagged)]
393pub enum SqliteParam {
394 #[default]
395 Null,
396 Bool(bool),
397 Integer(i64),
398 Real(f64),
399 Text(CompactString),
400 Blob(SmallVec<[u8; 512]>),
401 Json(Box<RawValue>),
402}
403
404impl From<&str> for SqliteParam {
405 fn from(value: &str) -> Self {
406 Self::Text(value.into())
407 }
408}
409
410impl From<Vec<u8>> for SqliteParam {
411 fn from(value: Vec<u8>) -> Self {
412 Self::Blob(value.into())
413 }
414}
415
416impl From<String> for SqliteParam {
417 fn from(value: String) -> Self {
418 Self::Text(value.into())
419 }
420}
421
422impl From<u16> for SqliteParam {
423 fn from(value: u16) -> Self {
424 Self::Integer(value as i64)
425 }
426}
427
428impl From<i64> for SqliteParam {
429 fn from(value: i64) -> Self {
430 Self::Integer(value)
431 }
432}
433
434impl ToSql for SqliteParam {
435 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
436 Ok(match self {
437 SqliteParam::Null => ToSqlOutput::Owned(Value::Null),
438 SqliteParam::Bool(v) => ToSqlOutput::Owned(Value::Integer(*v as i64)),
439 SqliteParam::Integer(i) => ToSqlOutput::Owned(Value::Integer(*i)),
440 SqliteParam::Real(f) => ToSqlOutput::Owned(Value::Real(*f)),
441 SqliteParam::Text(t) => ToSqlOutput::Borrowed(ValueRef::Text(t.as_bytes())),
442 SqliteParam::Blob(b) => ToSqlOutput::Borrowed(ValueRef::Blob(b)),
443 SqliteParam::Json(map) => ToSqlOutput::Borrowed(ValueRef::Text(map.get().as_bytes())),
444 })
445 }
446}
447
448impl<'a> ToSql for SqliteValueRef<'a> {
449 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'a>> {
450 Ok(ToSqlOutput::Borrowed(self.0))
451 }
452}
453
454impl<'a> From<ValueRef<'a>> for SqliteValueRef<'a> {
455 fn from(value: ValueRef<'a>) -> Self {
456 Self(value)
457 }
458}
459
460#[allow(clippy::large_enum_variant)]
461#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Hash)]
462#[serde(untagged)]
463pub enum SqliteValue {
464 #[default]
465 Null,
466 Integer(i64),
467 Real(Real),
468 Text(CompactString),
469 Blob(SmallVec<[u8; 512]>),
470}
471
472#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, PartialEq)]
473#[serde(transparent)]
474pub struct Real(pub f64);
475
476impl Deref for Real {
477 type Target = f64;
478
479 fn deref(&self) -> &Self::Target {
480 &self.0
481 }
482}
483
484impl Hash for Real {
485 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
486 integer_decode(self.0).hash(state)
487 }
488}
489
490fn integer_decode(val: f64) -> (u64, i16, i8) {
491 let bits: u64 = val.to_bits();
492 let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
493 let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
494 let mantissa = if exponent == 0 {
495 (bits & 0xfffffffffffff) << 1
496 } else {
497 (bits & 0xfffffffffffff) | 0x10000000000000
498 };
499
500 exponent -= 1023 + 52;
501 (mantissa, exponent, sign)
502}
503
504impl SqliteValue {
505 pub fn column_type(&self) -> ColumnType {
506 match self {
507 SqliteValue::Null => ColumnType::Null,
508 SqliteValue::Integer(_) => ColumnType::Integer,
509 SqliteValue::Real(_) => ColumnType::Float,
510 SqliteValue::Text(_) => ColumnType::Text,
511 SqliteValue::Blob(_) => ColumnType::Blob,
512 }
513 }
514
515 pub fn as_str(&self) -> Option<&str> {
516 if let Self::Text(s) = self {
517 Some(s)
518 } else {
519 None
520 }
521 }
522
523 pub fn is_null(&self) -> bool {
524 matches!(self, SqliteValue::Null)
525 }
526
527 pub fn as_integer(&self) -> Option<&i64> {
528 match self {
529 SqliteValue::Integer(i) => Some(i),
530 _ => None,
531 }
532 }
533
534 pub fn as_real(&self) -> Option<&f64> {
535 match self {
536 SqliteValue::Real(f) => Some(f),
537 _ => None,
538 }
539 }
540
541 pub fn as_text(&self) -> Option<&str> {
542 match self {
543 SqliteValue::Text(s) => Some(s),
544 _ => None,
545 }
546 }
547
548 pub fn as_blob(&self) -> Option<&[u8]> {
549 match self {
550 SqliteValue::Blob(b) => Some(b),
551 _ => None,
552 }
553 }
554
555 pub fn as_ref(&self) -> SqliteValueRef<'_> {
556 match self {
557 SqliteValue::Null => SqliteValueRef(ValueRef::Null),
558 SqliteValue::Integer(i) => SqliteValueRef(ValueRef::Integer(*i)),
559 SqliteValue::Real(r) => SqliteValueRef(ValueRef::Real(r.0)),
560 SqliteValue::Text(s) => SqliteValueRef(ValueRef::Text(s.as_bytes())),
561 SqliteValue::Blob(v) => SqliteValueRef(ValueRef::Blob(v.as_slice())),
562 }
563 }
564
565 pub fn estimated_byte_size(&self) -> usize {
566 1 + match self {
567 SqliteValue::Null => 1,
568 SqliteValue::Integer(_) => 8,
569 SqliteValue::Real(_) => 8,
570 SqliteValue::Text(t) => 4 + t.len(),
571 SqliteValue::Blob(v) => 4 + v.len(),
572 }
573 }
574}
575
576impl From<&str> for SqliteValue {
577 fn from(value: &str) -> Self {
578 Self::Text(value.into())
579 }
580}
581
582impl From<Vec<u8>> for SqliteValue {
583 fn from(value: Vec<u8>) -> Self {
584 Self::Blob(value.into())
585 }
586}
587
588impl From<String> for SqliteValue {
589 fn from(value: String) -> Self {
590 Self::Text(value.into())
591 }
592}
593
594impl From<u16> for SqliteValue {
595 fn from(value: u16) -> Self {
596 Self::Integer(value as i64)
597 }
598}
599
600impl From<i64> for SqliteValue {
601 fn from(value: i64) -> Self {
602 Self::Integer(value)
603 }
604}
605
606impl From<f64> for SqliteValue {
607 fn from(value: f64) -> Self {
608 Self::Real(Real(value))
609 }
610}
611
612impl FromSql for SqliteValue {
613 fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
614 Ok(match value {
615 ValueRef::Null => SqliteValue::Null,
616 ValueRef::Integer(i) => SqliteValue::Integer(i),
617 ValueRef::Real(f) => SqliteValue::Real(Real(f)),
618 ValueRef::Text(t) => SqliteValue::Text(
619 std::str::from_utf8(t)
620 .map_err(|e| FromSqlError::Other(Box::new(e)))?
621 .into(),
622 ),
623 ValueRef::Blob(b) => SqliteValue::Blob(b.into()),
624 })
625 }
626}
627
628impl ToSql for SqliteValue {
629 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
630 Ok(match self {
631 SqliteValue::Null => ToSqlOutput::Owned(Value::Null),
632 SqliteValue::Integer(i) => ToSqlOutput::Owned(Value::Integer(*i)),
633 SqliteValue::Real(f) => ToSqlOutput::Owned(Value::Real(f.0)),
634 SqliteValue::Text(t) => ToSqlOutput::Borrowed(ValueRef::Text(t.as_bytes())),
635 SqliteValue::Blob(b) => ToSqlOutput::Borrowed(ValueRef::Blob(b.as_slice())),
636 })
637 }
638}
639
640impl fmt::Display for SqliteValue {
641 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
642 match self {
643 SqliteValue::Null => f.write_str(""),
644 SqliteValue::Integer(v) => v.fmt(f),
645 SqliteValue::Real(v) => v.fmt(f),
646 SqliteValue::Text(v) => v.fmt(f),
647 SqliteValue::Blob(v) => {
648 f.write_str("x'")?;
649 f.write_str(&hex::encode(v))?;
650 f.write_char('\'')
651 }
652 }
653 }
654}
655
656impl<'a, C> Readable<'a, C> for SqliteValue
657where
658 C: Context,
659{
660 #[inline]
661 fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
662 Ok(match u8::read_from(reader)? {
663 0 => SqliteValue::Null,
664 1 => SqliteValue::Integer(i64::read_from(reader)?),
665 2 => SqliteValue::Real(Real(f64::read_from(reader)?)),
666 3 => {
667 let len = reader.read_u32()? as usize;
668
669 SqliteValue::Text(unsafe {
670 CompactString::from_utf8_unchecked(reader.read_vec(len)?)
671 })
672 }
673 4 => SqliteValue::Blob(Readable::read_from(reader)?),
674 _ => return Err(speedy::Error::custom("unknown SqliteValue variant").into()),
675 })
676 }
677
678 #[inline]
679 fn minimum_bytes_needed() -> usize {
680 1
681 }
682}
683
684impl<C> Writable<C> for SqliteValue
685where
686 C: Context,
687{
688 #[inline]
689 fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
690 match self {
691 SqliteValue::Null => writer.write_u8(0),
692 SqliteValue::Integer(i) => {
693 1u8.write_to(writer)?;
694 i.write_to(writer)
695 }
696 SqliteValue::Real(f) => {
697 2u8.write_to(writer)?;
698 f.write_to(writer)
699 }
700 SqliteValue::Text(s) => {
701 3u8.write_to(writer)?;
702 s.as_bytes().write_to(writer)
703 }
704 SqliteValue::Blob(b) => {
705 4u8.write_to(writer)?;
706 b.write_to(writer)
707 }
708 }
709 }
710
711 #[inline]
712 fn bytes_needed(&self) -> Result<usize, C::Error> {
713 Ok(1 + match self {
714 SqliteValue::Null => 0,
715 SqliteValue::Integer(i) => <i64 as Writable<C>>::bytes_needed(i)?,
716 SqliteValue::Real(f) => <f64 as Writable<C>>::bytes_needed(f)?,
717 SqliteValue::Text(s) => <[u8] as Writable<C>>::bytes_needed(s.as_bytes())?,
718 SqliteValue::Blob(b) => <[u8] as Writable<C>>::bytes_needed(b.as_slice())?,
719 })
720 }
721}
722
723impl<'a, C> Writable<C> for SqliteValueRef<'a>
724where
725 C: Context,
726{
727 #[inline]
728 fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
729 match self {
730 SqliteValueRef(ValueRef::Null) => writer.write_u8(0),
731 SqliteValueRef(ValueRef::Integer(i)) => {
732 1u8.write_to(writer)?;
733 i.write_to(writer)
734 }
735 SqliteValueRef(ValueRef::Real(f)) => {
736 2u8.write_to(writer)?;
737 f.write_to(writer)
738 }
739 SqliteValueRef(ValueRef::Text(s)) => {
740 3u8.write_to(writer)?;
741 (*s).write_to(writer)
742 }
743 SqliteValueRef(ValueRef::Blob(b)) => {
744 4u8.write_to(writer)?;
745 (*b).write_to(writer)
746 }
747 }
748 }
749
750 #[inline]
751 fn bytes_needed(&self) -> Result<usize, C::Error> {
752 Ok(1 + match self {
753 SqliteValueRef(ValueRef::Null) => 0,
754 SqliteValueRef(ValueRef::Integer(i)) => <i64 as Writable<C>>::bytes_needed(i)?,
755 SqliteValueRef(ValueRef::Real(f)) => <f64 as Writable<C>>::bytes_needed(f)?,
756 SqliteValueRef(ValueRef::Text(s)) => <[u8] as Writable<C>>::bytes_needed(s)?,
757 SqliteValueRef(ValueRef::Blob(b)) => <[u8] as Writable<C>>::bytes_needed(b)?,
758 })
759 }
760}
761
762#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
763#[serde(transparent)]
764pub struct TableName(pub CompactString);
765
766impl fmt::Display for TableName {
767 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
768 self.0.fmt(f)
769 }
770}
771
772impl Borrow<str> for TableName {
773 #[inline]
774 fn borrow(&self) -> &str {
775 self.as_str()
776 }
777}
778
779impl From<&str> for TableName {
780 fn from(value: &str) -> Self {
781 TableName(value.into())
782 }
783}
784
785#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
786#[serde(transparent)]
787pub struct ColumnName(pub CompactString);
788
789impl ColumnName {
790 pub fn is_crsql_sentinel(&self) -> bool {
791 self.0 == "-1"
792 }
793}
794
795impl Borrow<str> for ColumnName {
796 #[inline]
797 fn borrow(&self) -> &str {
798 self.as_str()
799 }
800}
801
802impl AsRef<[u8]> for ColumnName {
803 fn as_ref(&self) -> &[u8] {
804 self.as_bytes()
805 }
806}
807
808impl From<&str> for ColumnName {
809 fn from(value: &str) -> Self {
810 ColumnName(value.into())
811 }
812}
813
814impl Deref for TableName {
815 type Target = CompactString;
816
817 fn deref(&self) -> &Self::Target {
818 &self.0
819 }
820}
821
822impl<C> Writable<C> for TableName
823where
824 C: Context,
825{
826 #[inline]
827 fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), <C as Context>::Error> {
828 self.0.as_str().write_to(writer)
829 }
830
831 #[inline]
832 fn bytes_needed(&self) -> Result<usize, <C as Context>::Error> {
833 Writable::<C>::bytes_needed(self.0.as_str())
834 }
835}
836
837impl<'a, C> Readable<'a, C> for TableName
838where
839 C: Context,
840{
841 #[inline]
842 fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, <C as Context>::Error> {
843 let s: &'a str = Readable::<'a, C>::read_from(reader)?;
844 Ok(Self(CompactString::new(s)))
845 }
846}
847
848impl FromSql for TableName {
849 fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
850 Ok(Self(CompactString::new(value.as_str()?)))
851 }
852}
853
854impl ToSql for TableName {
855 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
856 self.0.as_str().to_sql()
857 }
858}
859
860impl Deref for ColumnName {
861 type Target = CompactString;
862
863 fn deref(&self) -> &Self::Target {
864 &self.0
865 }
866}
867
868impl<C> Writable<C> for ColumnName
869where
870 C: Context,
871{
872 #[inline]
873 fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), <C as Context>::Error> {
874 self.0.as_str().write_to(writer)
875 }
876
877 #[inline]
878 fn bytes_needed(&self) -> Result<usize, <C as Context>::Error> {
879 Writable::<C>::bytes_needed(self.0.as_str())
880 }
881}
882
883impl<'a, C> Readable<'a, C> for ColumnName
884where
885 C: Context,
886{
887 #[inline]
888 fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, <C as Context>::Error> {
889 let s: &'a str = Readable::<'a, C>::read_from(reader)?;
890 Ok(Self(CompactString::new(s)))
891 }
892}
893
894impl FromSql for ColumnName {
895 fn column_result(value: ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
896 Ok(Self(CompactString::new(value.as_str()?)))
897 }
898}
899
900impl ToSql for ColumnName {
901 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
902 self.0.as_str().to_sql()
903 }
904}
905
906#[cfg(test)]
907mod tests {
908 use super::*;
909
910 #[test]
911 fn test_statement_serialization() {
912 let s = serde_json::to_string(&vec![Statement::WithParams(
913 "select 1
914 from table
915 where column = ?"
916 .into(),
917 vec!["my-value".into()],
918 )])
919 .unwrap();
920 println!("{s}");
921
922 let stmts: Vec<Statement> = serde_json::from_str(&s).unwrap();
923 println!("stmts: {stmts:?}");
924
925 let json = r#"[["some statement",[1,"encodedID","nodeName",1,"Name","State",true,true,"",1234,1698084893487,1698084893487]]]"#;
926
927 let value: serde_json::Value = serde_json::from_str(json).unwrap();
928 println!("value: {value:#?}");
929
930 let stmts: Vec<Statement> = serde_json::from_str(json).unwrap();
931 println!("stmts: {stmts:?}");
932
933 let json = r#"[{"query": "some statement", "params": [1,"encodedID","nodeName",1,"Name","State",true,true,"",1234,1698084893487,1698084893487]}]"#;
934 let value: serde_json::Value = serde_json::from_str(json).unwrap();
935 println!("value: {value:#?}");
936
937 let stmts: Vec<Statement> = serde_json::from_str(json).unwrap();
938 println!("stmts: {stmts:?}");
939 }
940}