From 5165a34a273f6b6baee05b88aab810333229bb22 Mon Sep 17 00:00:00 2001 From: Micha de Vries Date: Mon, 26 Aug 2024 12:57:18 +0200 Subject: [PATCH] Revision `Value::Range`, `Id::Uuid`, `DefineStatement::Scope` and `DefineStatement::Token` (#4586) Co-authored-by: Emmanuel Keller --- core/src/sql/id/mod.rs | 3 +- core/src/sql/range.rs | 16 +++- .../sql/statements/define/deprecated/mod.rs | 4 + .../sql/statements/define/deprecated/scope.rs | 19 +++++ .../sql/statements/define/deprecated/token.rs | 18 ++++ core/src/sql/statements/define/mod.rs | 83 ++++++++++++++++++- core/src/sql/value/value.rs | 21 ++++- sdk/tests/define.rs | 2 +- 8 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 core/src/sql/statements/define/deprecated/mod.rs create mode 100644 core/src/sql/statements/define/deprecated/scope.rs create mode 100644 core/src/sql/statements/define/deprecated/token.rs diff --git a/core/src/sql/id/mod.rs b/core/src/sql/id/mod.rs index ac5e4f8b..8887222d 100644 --- a/core/src/sql/id/mod.rs +++ b/core/src/sql/id/mod.rs @@ -28,13 +28,14 @@ pub enum Gen { Uuid, } -#[revisioned(revision = 1)] +#[revisioned(revision = 2)] #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Key, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] pub enum Id { Number(i64), String(String), + #[revision(start = 2)] Uuid(Uuid), Array(Array), Object(Object), diff --git a/core/src/sql/range.rs b/core/src/sql/range.rs index 07a67732..1dee74d3 100644 --- a/core/src/sql/range.rs +++ b/core/src/sql/range.rs @@ -1,3 +1,4 @@ +use super::Id; use crate::cnf::GENERATION_ALLOCATION_LIMIT; use crate::ctx::Context; use crate::dbs::Options; @@ -13,8 +14,6 @@ use std::fmt; use std::ops::Bound; use std::str::FromStr; -use super::Id; - pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Range"; #[revisioned(revision = 1)] @@ -211,3 +210,16 @@ fn to_i64(v: Value) -> Result { }), } } + +// Structs needed for revision convertion from old ranges + +#[revisioned(revision = 1)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] +#[serde(rename = "$surrealdb::private::sql::Range")] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[non_exhaustive] +pub struct OldRange { + pub tb: String, + pub beg: Bound, + pub end: Bound, +} diff --git a/core/src/sql/statements/define/deprecated/mod.rs b/core/src/sql/statements/define/deprecated/mod.rs new file mode 100644 index 00000000..9d000bbb --- /dev/null +++ b/core/src/sql/statements/define/deprecated/mod.rs @@ -0,0 +1,4 @@ +// This folder houses DEFINE statements which have been deprecated. +// The old structs are needed for revision conversion. +pub mod scope; +pub mod token; diff --git a/core/src/sql/statements/define/deprecated/scope.rs b/core/src/sql/statements/define/deprecated/scope.rs new file mode 100644 index 00000000..10fd5c08 --- /dev/null +++ b/core/src/sql/statements/define/deprecated/scope.rs @@ -0,0 +1,19 @@ +use crate::sql::{Duration, Ident, Strand, Value}; +use derive::Store; +use revision::revisioned; +use serde::{Deserialize, Serialize}; + +#[revisioned(revision = 2)] +#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[non_exhaustive] +pub struct DefineScopeStatement { + pub name: Ident, + pub code: String, + pub session: Option, + pub signup: Option, + pub signin: Option, + pub comment: Option, + #[revision(start = 2)] + pub if_not_exists: bool, +} diff --git a/core/src/sql/statements/define/deprecated/token.rs b/core/src/sql/statements/define/deprecated/token.rs new file mode 100644 index 00000000..59e255cc --- /dev/null +++ b/core/src/sql/statements/define/deprecated/token.rs @@ -0,0 +1,18 @@ +use crate::sql::{Algorithm, Base, Ident, Strand}; +use derive::Store; +use revision::revisioned; +use serde::{Deserialize, Serialize}; + +#[revisioned(revision = 2)] +#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[non_exhaustive] +pub struct DefineTokenStatement { + pub name: Ident, + pub base: Base, + pub kind: Algorithm, + pub code: String, + pub comment: Option, + #[revision(start = 2)] + pub if_not_exists: bool, +} diff --git a/core/src/sql/statements/define/mod.rs b/core/src/sql/statements/define/mod.rs index 8fca0e58..75734a30 100644 --- a/core/src/sql/statements/define/mod.rs +++ b/core/src/sql/statements/define/mod.rs @@ -1,6 +1,7 @@ mod access; mod analyzer; mod database; +mod deprecated; mod event; mod field; mod function; @@ -24,18 +25,24 @@ pub use param::DefineParamStatement; pub use table::DefineTableStatement; pub use user::DefineUserStatement; -use crate::ctx::Context; +use deprecated::scope::DefineScopeStatement; +use deprecated::token::DefineTokenStatement; + use crate::dbs::Options; use crate::doc::CursorDoc; use crate::err::Error; +use crate::sql::access::AccessDuration; +use crate::sql::access_type::{JwtAccessIssue, JwtAccessVerify, JwtAccessVerifyKey}; use crate::sql::value::Value; +use crate::sql::{Algorithm, Base, JwtAccess, RecordAccess}; +use crate::{ctx::Context, sql::AccessType}; use derive::Store; use reblessive::tree::Stk; use revision::revisioned; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; -#[revisioned(revision = 1)] +#[revisioned(revision = 2)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[non_exhaustive] @@ -44,6 +51,18 @@ pub enum DefineStatement { Database(DefineDatabaseStatement), Function(DefineFunctionStatement), Analyzer(DefineAnalyzerStatement), + #[revision( + end = 2, + convert_fn = "convert_token_to_access", + fields_name = "DefineTokenStatementFields" + )] + Token(DefineTokenStatement), + #[revision( + end = 2, + convert_fn = "convert_scope_to_access", + fields_name = "DefineScopeStatementFields" + )] + Scope(DefineScopeStatement), Param(DefineParamStatement), Table(DefineTableStatement), Event(DefineEventStatement), @@ -51,9 +70,69 @@ pub enum DefineStatement { Index(DefineIndexStatement), User(DefineUserStatement), Model(DefineModelStatement), + #[revision(start = 2)] Access(DefineAccessStatement), } +// Revision implementations +impl DefineStatement { + fn convert_token_to_access( + fields: DefineTokenStatementFields, + _revision: u16, + ) -> Result { + Ok(DefineStatement::Access(DefineAccessStatement { + name: fields.0.name, + base: fields.0.base, + comment: fields.0.comment, + if_not_exists: fields.0.if_not_exists, + kind: AccessType::Jwt(JwtAccess { + issue: None, + verify: JwtAccessVerify::Key(JwtAccessVerifyKey { + alg: fields.0.kind, + key: fields.0.code, + }), + }), + // unused fields + authenticate: None, + duration: AccessDuration::default(), + overwrite: false, + })) + } + + fn convert_scope_to_access( + fields: DefineScopeStatementFields, + _revision: u16, + ) -> Result { + Ok(DefineStatement::Access(DefineAccessStatement { + name: fields.0.name, + base: Base::Db, + comment: fields.0.comment, + if_not_exists: fields.0.if_not_exists, + kind: AccessType::Record(RecordAccess { + signup: fields.0.signup, + signin: fields.0.signin, + jwt: JwtAccess { + issue: Some(JwtAccessIssue { + alg: Algorithm::Hs512, + key: fields.0.code.clone(), + }), + verify: JwtAccessVerify::Key(JwtAccessVerifyKey { + alg: Algorithm::Hs512, + key: fields.0.code, + }), + }, + }), + // unused fields + authenticate: None, + duration: AccessDuration { + session: fields.0.session, + ..AccessDuration::default() + }, + overwrite: false, + })) + } +} + impl DefineStatement { /// Check if we require a writeable transaction pub(crate) fn writeable(&self) -> bool { diff --git a/core/src/sql/value/value.rs b/core/src/sql/value/value.rs index d285d2ff..fc2c07dc 100644 --- a/core/src/sql/value/value.rs +++ b/core/src/sql/value/value.rs @@ -7,6 +7,7 @@ use crate::err::Error; use crate::fnc::util::string::fuzzy::Fuzzy; use crate::sql::id::range::IdRange; use crate::sql::kind::Literal; +use crate::sql::range::OldRange; use crate::sql::statements::info::InfoStructure; use crate::sql::Closure; use crate::sql::{ @@ -82,7 +83,7 @@ impl From<&Tables> for Values { } } -#[revisioned(revision = 1)] +#[revisioned(revision = 2)] #[derive(Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)] #[serde(rename = "$surrealdb::private::sql::Value")] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] @@ -123,6 +124,9 @@ pub enum Value { Regex(Regex), Cast(Box), Block(Box), + #[revision(end = 2, convert_fn = "convert_old_range", fields_name = "OldValueRangeFields")] + Range(OldRange), + #[revision(start = 2)] Range(Box), Edges(Box), Future(Box), @@ -136,6 +140,21 @@ pub enum Value { // Add new variants here } +impl Value { + fn convert_old_range( + fields: OldValueRangeFields, + _revision: u16, + ) -> Result { + Ok(Value::Thing(Thing { + tb: fields.0.tb, + id: Id::Range(Box::new(IdRange { + beg: fields.0.beg, + end: fields.0.end, + })), + })) + } +} + impl Eq for Value {} impl Ord for Value { diff --git a/sdk/tests/define.rs b/sdk/tests/define.rs index 7efed983..171fd787 100644 --- a/sdk/tests/define.rs +++ b/sdk/tests/define.rs @@ -1119,7 +1119,7 @@ async fn define_statement_search_index() -> Result<(), Error> { check_path(&tmp, &["doc_ids", "keys_count"], |v| assert_eq!(v, Value::from(2))); check_path(&tmp, &["doc_ids", "max_depth"], |v| assert_eq!(v, Value::from(1))); check_path(&tmp, &["doc_ids", "nodes_count"], |v| assert_eq!(v, Value::from(1))); - check_path(&tmp, &["doc_ids", "total_size"], |v| assert_eq!(v, Value::from(63))); + check_path(&tmp, &["doc_ids", "total_size"], |v| assert_eq!(v, Value::from(62))); check_path(&tmp, &["doc_lengths", "keys_count"], |v| assert_eq!(v, Value::from(2))); check_path(&tmp, &["doc_lengths", "max_depth"], |v| assert_eq!(v, Value::from(1)));