surrealdb_core/sql/statements/
show.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::{Action, ResourceKind};
use crate::sql::{Base, Datetime, Table, Value};
use crate::vs::{conv, Versionstamp};
use derive::Store;
use revision::revisioned;
use serde::{Deserialize, Serialize};
use std::fmt;

#[revisioned(revision = 1)]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ShowSince {
	Timestamp(Datetime),
	Versionstamp(u64),
}

impl ShowSince {
	pub fn versionstamp(vs: &Versionstamp) -> ShowSince {
		ShowSince::Versionstamp(conv::versionstamp_to_u64(vs))
	}

	pub fn as_versionstamp(&self) -> Option<Versionstamp> {
		match self {
			ShowSince::Timestamp(_) => None,
			ShowSince::Versionstamp(v) => Some(conv::u64_to_versionstamp(*v)),
		}
	}
}

// ShowStatement is used to show changes in a table or database via
// the SHOW CHANGES statement.
#[revisioned(revision = 1)]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ShowStatement {
	pub table: Option<Table>,
	pub since: ShowSince,
	pub limit: Option<u32>,
}

impl ShowStatement {
	/// Process this type returning a computed simple Value
	pub(crate) async fn compute(
		&self,
		_ctx: &Context<'_>,
		opt: &Options,
		txn: &Transaction,
		_doc: Option<&CursorDoc<'_>>,
	) -> Result<Value, Error> {
		// Selected DB?
		opt.is_allowed(Action::View, ResourceKind::Table, &Base::Db)?;
		// Clone transaction
		let txn = txn.clone();
		// Claim transaction
		let mut run = txn.lock().await;
		// Process the show query
		let tb = self.table.as_deref();
		let r = crate::cf::read(
			&mut run,
			opt.ns(),
			opt.db(),
			tb.map(|x| x.as_str()),
			self.since.clone(),
			self.limit,
		)
		.await?;
		// Return the changes
		let mut a = Vec::<Value>::new();
		for r in r.iter() {
			let v: Value = r.clone().into_value();
			a.push(v);
		}
		let v: Value = Value::Array(crate::sql::array::Array(a));
		Ok(v)
	}
}

impl fmt::Display for ShowStatement {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "SHOW CHANGES FOR")?;
		match self.table {
			Some(ref v) => write!(f, " TABLE {}", v)?,
			None => write!(f, " DATABASE")?,
		}
		match self.since {
			ShowSince::Timestamp(ref v) => write!(f, " SINCE {}", v)?,
			ShowSince::Versionstamp(ref v) => write!(f, " SINCE {}", v)?,
		}
		if let Some(ref v) = self.limit {
			write!(f, " LIMIT {}", v)?
		}
		Ok(())
	}
}

#[cfg(test)]
mod test {
	use crate::sql::Datetime;

	#[test]
	fn timestamps_are_not_versionstamps() {
		// given
		let sql_dt = Datetime::try_from("2020-01-01T00:00:00Z").unwrap();

		// when
		let since = super::ShowSince::Timestamp(sql_dt);

		// then
		assert_eq!(since.as_versionstamp(), None);
	}

	#[test]
	fn versionstamp_can_be_converted() {
		// given
		let versionstamp = crate::vs::conv::u64_to_versionstamp(1234567890);
		let since = super::ShowSince::Versionstamp(1234567890);

		// when
		let converted = since.as_versionstamp().unwrap();

		// then
		assert_eq!(converted, versionstamp);
	}
}