Add info structure (#3876)
Co-authored-by: Micha de Vries <micha@devrie.sh>
This commit is contained in:
parent
77f1318152
commit
e62bedf9bb
33 changed files with 804 additions and 26 deletions
|
@ -1,3 +1,5 @@
|
|||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::Value;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
@ -49,3 +51,8 @@ impl fmt::Display for Algorithm {
|
|||
})
|
||||
}
|
||||
}
|
||||
impl InfoStructure for Algorithm {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::sql::Ident;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Ident, Value};
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
@ -30,3 +31,8 @@ impl fmt::Display for Base {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl InfoStructure for Base {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::sql::fmt::{is_pretty, pretty_indent, Fmt, Pretty};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::statements::{
|
||||
BreakStatement, ContinueStatement, CreateStatement, DefineStatement, DeleteStatement,
|
||||
ForeachStatement, IfelseStatement, InsertStatement, OutputStatement, RelateStatement,
|
||||
|
@ -166,6 +167,11 @@ impl Display for Block {
|
|||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Block {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::sql::duration::Duration;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::Value;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
@ -31,3 +33,8 @@ impl Default for ChangeFeed {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl InfoStructure for ChangeFeed {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::value::Value;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -22,3 +23,8 @@ impl fmt::Display for Cond {
|
|||
write!(f, "WHERE {}", self.0)
|
||||
}
|
||||
}
|
||||
impl InfoStructure for Cond {
|
||||
fn structure(self) -> Value {
|
||||
self.0.structure()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::sql::fmt::Fmt;
|
||||
use crate::sql::idiom::Idiom;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::Value;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
@ -32,6 +34,11 @@ impl fmt::Display for Fetchs {
|
|||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Fetchs {
|
||||
fn structure(self) -> Value {
|
||||
Value::Array(self.0.into_iter().map(|f| f.0.structure()).collect())
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
|
||||
#[revisioned(revision = 1)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::ctx::Context;
|
|||
use crate::dbs::{Options, Transaction};
|
||||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{fmt::Fmt, Idiom, Part, Value};
|
||||
use crate::syn;
|
||||
use revision::revisioned;
|
||||
|
@ -65,6 +66,11 @@ impl Display for Fields {
|
|||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Fields {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
impl Fields {
|
||||
/// Process this type returning a computed simple Value
|
||||
pub(crate) async fn compute(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::sql::{escape::escape_ident, strand::no_nul_bytes};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{escape::escape_ident, strand::no_nul_bytes, Value};
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
@ -58,3 +59,9 @@ impl Display for Ident {
|
|||
Display::fmt(&escape_ident(&self.0), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Ident {
|
||||
fn structure(self) -> Value {
|
||||
self.0.into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::ctx::Context;
|
|||
use crate::dbs::{Options, Transaction};
|
||||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{
|
||||
fmt::{fmt_separated_by, Fmt},
|
||||
part::Next,
|
||||
|
@ -199,3 +200,15 @@ impl Display for Idiom {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Idioms {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Idiom {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ use crate::fnc::util::math::vector::{
|
|||
};
|
||||
use crate::sql::ident::Ident;
|
||||
use crate::sql::scoring::Scoring;
|
||||
use crate::sql::Number;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Number, Value};
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
@ -204,3 +205,9 @@ impl Display for Index {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Index {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::sql::{fmt::Fmt, Table};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{fmt::Fmt, Table, Value};
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
@ -130,3 +131,9 @@ impl Display for Kind {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Kind {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::sql::fmt::is_pretty;
|
||||
use crate::sql::fmt::pretty_indent;
|
||||
use crate::sql::fmt::pretty_sequence_item;
|
||||
use crate::sql::Value;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Object, Value};
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Write;
|
||||
|
@ -166,3 +167,32 @@ impl Display for Permission {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Permission {
|
||||
fn structure(self) -> Value {
|
||||
match self {
|
||||
Permission::None => Value::Bool(false),
|
||||
Permission::Full => Value::Bool(true),
|
||||
Permission::Specific(v) => Value::Strand(v.to_string().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Permissions {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
select,
|
||||
create,
|
||||
update,
|
||||
delete,
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("select".to_string(), select.structure());
|
||||
acc.insert("create".to_string(), create.structure());
|
||||
acc.insert("update".to_string(), update.structure());
|
||||
acc.insert("delete".to_string(), delete.structure());
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{filter::Filter, tokenizer::Tokenizer, Base, Ident, Strand, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{filter::Filter, tokenizer::Tokenizer, Base, Ident, Object, Strand, Value};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -89,3 +90,43 @@ impl Display for DefineAnalyzerStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineAnalyzerStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
function,
|
||||
tokenizers,
|
||||
filters,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
if let Some(function) = function {
|
||||
acc.insert("function".to_string(), function.structure());
|
||||
}
|
||||
|
||||
if let Some(tokenizers) = tokenizers {
|
||||
acc.insert(
|
||||
"tokenizers".to_string(),
|
||||
Value::Array(tokenizers.into_iter().map(|t| t.to_string().into()).collect()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(filters) = filters {
|
||||
acc.insert(
|
||||
"filters".to_string(),
|
||||
Value::Array(filters.into_iter().map(|f| f.to_string().into()).collect()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{changefeed::ChangeFeed, Base, Ident, Strand, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{changefeed::ChangeFeed, Base, Ident, Object, Strand, Value};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -87,3 +88,22 @@ impl Display for DefineDatabaseStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineDatabaseStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{Base, Ident, Strand, Value, Values};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Base, Ident, Object, Strand, Value, Values};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -80,3 +81,34 @@ impl Display for DefineEventStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineEventStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
what,
|
||||
when,
|
||||
then,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("what".to_string(), what.structure());
|
||||
|
||||
acc.insert("when".to_string(), when.structure());
|
||||
|
||||
acc.insert(
|
||||
"then".to_string(),
|
||||
Value::Array(then.0.iter().map(|v| v.to_string().into()).collect()),
|
||||
);
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,12 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::statements::DefineTableStatement;
|
||||
use crate::sql::Part;
|
||||
use crate::sql::{
|
||||
fmt::is_pretty, fmt::pretty_indent, Base, Ident, Idiom, Kind, Permissions, Strand, Value,
|
||||
};
|
||||
use crate::sql::{Object, Part};
|
||||
use crate::sql::{Relation, TableType};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
|
@ -204,3 +205,54 @@ impl Display for DefineFieldStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineFieldStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
what,
|
||||
flex,
|
||||
kind,
|
||||
readonly,
|
||||
value,
|
||||
assert,
|
||||
default,
|
||||
permissions,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("what".to_string(), what.structure());
|
||||
|
||||
acc.insert("flex".to_string(), flex.into());
|
||||
|
||||
if let Some(kind) = kind {
|
||||
acc.insert("kind".to_string(), kind.structure());
|
||||
}
|
||||
|
||||
acc.insert("readonly".to_string(), readonly.into());
|
||||
|
||||
if let Some(value) = value {
|
||||
acc.insert("value".to_string(), value.structure());
|
||||
}
|
||||
|
||||
if let Some(assert) = assert {
|
||||
acc.insert("assert".to_string(), assert.structure());
|
||||
}
|
||||
|
||||
if let Some(default) = default {
|
||||
acc.insert("default".to_string(), default.structure());
|
||||
}
|
||||
|
||||
acc.insert("permissions".to_string(), permissions.structure());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{
|
||||
fmt::{is_pretty, pretty_indent},
|
||||
Base, Block, Ident, Kind, Permission, Strand, Value,
|
||||
Base, Block, Ident, Kind, Object, Permission, Strand, Value,
|
||||
};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
|
@ -93,3 +94,39 @@ impl fmt::Display for DefineFunctionStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineFunctionStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
args,
|
||||
block,
|
||||
comment,
|
||||
permissions,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert(
|
||||
"args".to_string(),
|
||||
Value::Array(
|
||||
args.into_iter()
|
||||
.map(|(n, k)| Value::Array(vec![n.structure(), k.structure()].into()))
|
||||
.collect::<Vec<Value>>()
|
||||
.into(),
|
||||
),
|
||||
);
|
||||
|
||||
acc.insert("block".to_string(), block.structure());
|
||||
|
||||
acc.insert("permissions".to_string(), permissions.structure());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,10 @@ use crate::dbs::{Force, Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{statements::UpdateStatement, Base, Ident, Idioms, Index, Strand, Value, Values};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{
|
||||
statements::UpdateStatement, Base, Ident, Idioms, Index, Object, Strand, Value, Values,
|
||||
};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -98,3 +101,31 @@ impl Display for DefineIndexStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineIndexStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
what,
|
||||
cols,
|
||||
index,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("what".to_string(), what.structure());
|
||||
|
||||
acc.insert("cols".to_string(), cols.structure());
|
||||
|
||||
acc.insert("index".to_string(), index.structure());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{
|
||||
fmt::{is_pretty, pretty_indent},
|
||||
Base, Ident, Permission, Strand, Value,
|
||||
Base, Ident, Object, Permission, Strand, Value,
|
||||
};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
|
@ -89,3 +90,28 @@ impl DefineModelStatement {
|
|||
Ok(Value::None)
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineModelStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
version,
|
||||
comment,
|
||||
permissions,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("version".to_string(), version.into());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
acc.insert("permissions".to_string(), permissions.structure());
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{Base, Ident, Strand, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Base, Ident, Object, Strand, Value};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -80,3 +81,22 @@ impl Display for DefineNamespaceStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineNamespaceStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ use crate::doc::CursorDoc;
|
|||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::fmt::{is_pretty, pretty_indent};
|
||||
use crate::sql::{Base, Ident, Permission, Strand, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Base, Ident, Object, Permission, Strand, Value};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -84,3 +85,28 @@ impl Display for DefineParamStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineParamStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
value,
|
||||
comment,
|
||||
permissions,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("value".to_string(), value.structure());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
acc.insert("permissions".to_string(), permissions.structure());
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{Base, Duration, Ident, Strand, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Base, Duration, Ident, Object, Strand, Value};
|
||||
use derive::Store;
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
|
@ -93,3 +94,32 @@ impl Display for DefineScopeStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineScopeStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
signup,
|
||||
signin,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
if let Some(signup) = signup {
|
||||
acc.insert("signup".to_string(), signup.structure());
|
||||
}
|
||||
|
||||
if let Some(signin) = signin {
|
||||
acc.insert("signin".to_string(), signin.structure());
|
||||
}
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@ use crate::sql::{
|
|||
changefeed::ChangeFeed,
|
||||
fmt::{is_pretty, pretty_indent},
|
||||
statements::UpdateStatement,
|
||||
Base, Ident, Permissions, Strand, Value, Values, View,
|
||||
Base, Ident, Object, Permissions, Strand, Value, Values, View,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Idiom, Kind, Part, Table, TableType};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
|
@ -211,3 +212,43 @@ impl Display for DefineTableStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineTableStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
drop,
|
||||
full,
|
||||
view,
|
||||
permissions,
|
||||
changefeed,
|
||||
comment,
|
||||
kind,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("drop".to_string(), drop.into());
|
||||
acc.insert("full".to_string(), full.into());
|
||||
|
||||
if let Some(view) = view {
|
||||
acc.insert("view".to_string(), view.structure());
|
||||
}
|
||||
|
||||
acc.insert("permissions".to_string(), permissions.structure());
|
||||
|
||||
if let Some(changefeed) = changefeed {
|
||||
acc.insert("changefeed".to_string(), changefeed.structure());
|
||||
}
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
acc.insert("kind".to_string(), kind.structure());
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{escape::quote_str, Algorithm, Base, Ident, Strand, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{escape::quote_str, Algorithm, Base, Ident, Object, Strand, Value};
|
||||
use derive::Store;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -143,3 +144,31 @@ impl Display for DefineTokenStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineTokenStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
base,
|
||||
kind,
|
||||
code,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("base".to_string(), base.structure());
|
||||
|
||||
acc.insert("kind".to_string(), kind.structure());
|
||||
|
||||
acc.insert("code".to_string(), code.into());
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::iam::{Action, ResourceKind};
|
||||
use crate::sql::{escape::quote_str, fmt::Fmt, Base, Ident, Strand, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{escape::quote_str, fmt::Fmt, Base, Ident, Object, Strand, Value};
|
||||
use argon2::{
|
||||
password_hash::{PasswordHasher, SaltString},
|
||||
Argon2,
|
||||
|
@ -199,3 +200,34 @@ impl Display for DefineUserStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for DefineUserStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
name,
|
||||
base,
|
||||
code,
|
||||
roles,
|
||||
comment,
|
||||
..
|
||||
} = self;
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("name".to_string(), name.structure());
|
||||
|
||||
acc.insert("base".to_string(), base.structure());
|
||||
|
||||
acc.insert("code".to_string(), code.into());
|
||||
|
||||
acc.insert(
|
||||
"roles".to_string(),
|
||||
Value::Array(roles.into_iter().map(|r| r.structure()).collect()),
|
||||
);
|
||||
|
||||
if let Some(comment) = comment {
|
||||
acc.insert("comment".to_string(), comment.into());
|
||||
}
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@ pub enum InfoStatement {
|
|||
Sc(Ident),
|
||||
Tb(Ident),
|
||||
User(Ident, Option<Base>),
|
||||
RootStructure,
|
||||
NsStructure,
|
||||
DbStructure,
|
||||
ScStructure(Ident),
|
||||
TbStructure(Ident),
|
||||
}
|
||||
|
||||
impl InfoStatement {
|
||||
|
@ -215,6 +220,130 @@ impl InfoStatement {
|
|||
// Ok all good
|
||||
Value::from(res.to_string()).ok()
|
||||
}
|
||||
InfoStatement::RootStructure => {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Root)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Create the result set
|
||||
let mut res = Object::default();
|
||||
// Process the namespaces
|
||||
res.insert("namespaces".to_owned(), process_arr(run.all_ns().await?));
|
||||
// Process the users
|
||||
res.insert("users".to_owned(), process_arr(run.all_root_users().await?));
|
||||
// Ok all good
|
||||
Value::from(res).ok()
|
||||
}
|
||||
InfoStatement::NsStructure => {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Ns)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Create the result set
|
||||
let mut res = Object::default();
|
||||
// Process the databases
|
||||
res.insert("databases".to_owned(), process_arr(run.all_db(opt.ns()).await?));
|
||||
// Process the users
|
||||
res.insert("users".to_owned(), process_arr(run.all_ns_users(opt.ns()).await?));
|
||||
// Process the tokens
|
||||
res.insert("tokens".to_owned(), process_arr(run.all_ns_tokens(opt.ns()).await?));
|
||||
// Ok all good
|
||||
Value::from(res).ok()
|
||||
}
|
||||
InfoStatement::DbStructure => {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Create the result set
|
||||
let mut res = Object::default();
|
||||
// Process the users
|
||||
res.insert(
|
||||
"users".to_owned(),
|
||||
process_arr(run.all_db_users(opt.ns(), opt.db()).await?),
|
||||
);
|
||||
// Process the tokens
|
||||
res.insert(
|
||||
"tokens".to_owned(),
|
||||
process_arr(run.all_db_tokens(opt.ns(), opt.db()).await?),
|
||||
);
|
||||
// Process the functions
|
||||
res.insert(
|
||||
"functions".to_owned(),
|
||||
process_arr(run.all_db_functions(opt.ns(), opt.db()).await?),
|
||||
);
|
||||
// Process the models
|
||||
res.insert(
|
||||
"models".to_owned(),
|
||||
process_arr(run.all_db_models(opt.ns(), opt.db()).await?),
|
||||
);
|
||||
// Process the params
|
||||
res.insert(
|
||||
"params".to_owned(),
|
||||
process_arr(run.all_db_params(opt.ns(), opt.db()).await?),
|
||||
);
|
||||
// Process the scopes
|
||||
res.insert("scopes".to_owned(), process_arr(run.all_sc(opt.ns(), opt.db()).await?));
|
||||
// Process the tables
|
||||
res.insert("tables".to_owned(), process_arr(run.all_tb(opt.ns(), opt.db()).await?));
|
||||
// Process the analyzers
|
||||
res.insert(
|
||||
"analyzers".to_owned(),
|
||||
process_arr(run.all_db_analyzers(opt.ns(), opt.db()).await?),
|
||||
);
|
||||
// Ok all good
|
||||
Value::from(res).ok()
|
||||
}
|
||||
InfoStatement::ScStructure(sc) => {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Create the result set
|
||||
let mut res = Object::default();
|
||||
// Process the tokens
|
||||
res.insert(
|
||||
"tokens".to_owned(),
|
||||
process_arr(run.all_sc_tokens(opt.ns(), opt.db(), sc).await?),
|
||||
);
|
||||
// Ok all good
|
||||
Value::from(res).ok()
|
||||
}
|
||||
InfoStatement::TbStructure(tb) => {
|
||||
// Allowed to run?
|
||||
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
|
||||
// Claim transaction
|
||||
let mut run = txn.lock().await;
|
||||
// Create the result set
|
||||
let mut res = Object::default();
|
||||
// Process the events
|
||||
res.insert(
|
||||
"events".to_owned(),
|
||||
process_arr(run.all_tb_events(opt.ns(), opt.db(), tb).await?),
|
||||
);
|
||||
// Process the fields
|
||||
res.insert(
|
||||
"fields".to_owned(),
|
||||
process_arr(run.all_tb_fields(opt.ns(), opt.db(), tb).await?),
|
||||
);
|
||||
// Process the tables
|
||||
res.insert(
|
||||
"tables".to_owned(),
|
||||
process_arr(run.all_tb_views(opt.ns(), opt.db(), tb).await?),
|
||||
);
|
||||
// Process the indexes
|
||||
res.insert(
|
||||
"indexes".to_owned(),
|
||||
process_arr(run.all_tb_indexes(opt.ns(), opt.db(), tb).await?),
|
||||
);
|
||||
// Process the live queries
|
||||
res.insert(
|
||||
"lives".to_owned(),
|
||||
process_arr(run.all_tb_lives(opt.ns(), opt.db(), tb).await?),
|
||||
);
|
||||
// Ok all good
|
||||
Value::from(res).ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,10 +352,15 @@ impl fmt::Display for InfoStatement {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Root => f.write_str("INFO FOR ROOT"),
|
||||
Self::RootStructure => f.write_str("INFO FOR ROOT STRUCTURE"),
|
||||
Self::Ns => f.write_str("INFO FOR NAMESPACE"),
|
||||
Self::NsStructure => f.write_str("INFO FOR NAMESPACE STRUCTURE"),
|
||||
Self::Db => f.write_str("INFO FOR DATABASE"),
|
||||
Self::DbStructure => f.write_str("INFO FOR DATABASE STRUCTURE"),
|
||||
Self::Sc(ref s) => write!(f, "INFO FOR SCOPE {s}"),
|
||||
Self::ScStructure(ref s) => write!(f, "INFO FOR SCOPE {s} STRUCTURE"),
|
||||
Self::Tb(ref t) => write!(f, "INFO FOR TABLE {t}"),
|
||||
Self::TbStructure(ref t) => write!(f, "INFO FOR TABLE {t} STRUCTURE"),
|
||||
Self::User(ref u, ref b) => match b {
|
||||
Some(ref b) => write!(f, "INFO FOR USER {u} ON {b}"),
|
||||
None => write!(f, "INFO FOR USER {u}"),
|
||||
|
@ -234,3 +368,30 @@ impl fmt::Display for InfoStatement {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(crate) trait InfoStructure {
|
||||
fn structure(self) -> Value;
|
||||
}
|
||||
|
||||
impl InfoStatement {
|
||||
pub(crate) fn structurize(self) -> Result<Self, ()> {
|
||||
let out = match self {
|
||||
InfoStatement::Root => InfoStatement::RootStructure,
|
||||
InfoStatement::Ns => InfoStatement::NsStructure,
|
||||
InfoStatement::Db => InfoStatement::DbStructure,
|
||||
InfoStatement::Sc(s) => InfoStatement::ScStructure(s),
|
||||
InfoStatement::Tb(t) => InfoStatement::TbStructure(t),
|
||||
_ => return Err(()),
|
||||
};
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
fn process_arr<T>(a: Arc<[T]>) -> Value
|
||||
where
|
||||
T: InfoStructure + Clone,
|
||||
{
|
||||
Value::Array(a.iter().cloned().map(InfoStructure::structure).collect())
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ use crate::err::{Error, LiveQueryCause};
|
|||
use crate::fflags::FFLAGS;
|
||||
use crate::iam::Auth;
|
||||
use crate::kvs::lq_structs::{LqEntry, TrackedResult};
|
||||
use crate::sql::{Cond, Fetchs, Fields, Table, Uuid, Value};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{Cond, Fetchs, Fields, Object, Table, Uuid, Value};
|
||||
use derive::Store;
|
||||
use futures::lock::MutexGuard;
|
||||
use revision::revisioned;
|
||||
|
@ -191,3 +192,30 @@ impl fmt::Display for LiveStatement {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for LiveStatement {
|
||||
fn structure(self) -> Value {
|
||||
let Self {
|
||||
expr,
|
||||
what,
|
||||
cond,
|
||||
fetch,
|
||||
..
|
||||
} = self;
|
||||
|
||||
let mut acc = Object::default();
|
||||
|
||||
acc.insert("expr".to_string(), expr.structure());
|
||||
|
||||
acc.insert("what".to_string(), what.structure());
|
||||
|
||||
if let Some(cond) = cond {
|
||||
acc.insert("cond".to_string(), cond.structure());
|
||||
}
|
||||
|
||||
if let Some(fetch) = fetch {
|
||||
acc.insert("fetch".to_string(), fetch.structure());
|
||||
}
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::Array;
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::fmt::Display;
|
||||
|
||||
use super::{Kind, Table};
|
||||
use super::{Kind, Object, Table, Value};
|
||||
|
||||
/// The type of records stored by a table
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Hash, Clone, Eq, PartialEq, PartialOrd)]
|
||||
|
@ -26,10 +28,10 @@ impl Display for TableType {
|
|||
TableType::Relation(rel) => {
|
||||
f.write_str(" RELATION")?;
|
||||
if let Some(Kind::Record(kind)) = &rel.from {
|
||||
write!(f, " IN {}", get_tables_from_kind(kind))?;
|
||||
write!(f, " IN {}", get_tables_from_kind(kind).join(" | "))?;
|
||||
}
|
||||
if let Some(Kind::Record(kind)) = &rel.to {
|
||||
write!(f, " OUT {}", get_tables_from_kind(kind))?;
|
||||
write!(f, " OUT {}", get_tables_from_kind(kind).join(" | "))?;
|
||||
}
|
||||
}
|
||||
TableType::Any => {
|
||||
|
@ -40,8 +42,42 @@ impl Display for TableType {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_tables_from_kind(tables: &[Table]) -> String {
|
||||
tables.iter().map(|t| t.0.as_str()).collect::<Vec<_>>().join(" | ")
|
||||
impl InfoStructure for TableType {
|
||||
fn structure(self) -> Value {
|
||||
let mut acc = Object::default();
|
||||
|
||||
match &self {
|
||||
TableType::Any => {
|
||||
acc.insert("kind".to_string(), "ANY".into());
|
||||
}
|
||||
TableType::Normal => {
|
||||
acc.insert("kind".to_string(), "NORMAL".into());
|
||||
}
|
||||
TableType::Relation(rel) => {
|
||||
acc.insert("kind".to_string(), "RELATION".into());
|
||||
|
||||
if let Some(Kind::Record(tables)) = &rel.from {
|
||||
acc.insert(
|
||||
"in".to_string(),
|
||||
Value::Array(Array::from(get_tables_from_kind(tables))),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(Kind::Record(tables)) = &rel.to {
|
||||
acc.insert(
|
||||
"out".to_string(),
|
||||
Value::Array(Array::from(get_tables_from_kind(tables))),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Value::Object(acc)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_tables_from_kind(tables: &[Table]) -> Vec<&str> {
|
||||
tables.iter().map(|t| t.0.as_str()).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Hash, Clone, Eq, PartialEq, PartialOrd)]
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::dbs::{Options, Transaction};
|
|||
use crate::doc::CursorDoc;
|
||||
use crate::err::Error;
|
||||
use crate::fnc::util::string::fuzzy::Fuzzy;
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{
|
||||
array::Uniq,
|
||||
fmt::{Fmt, Pretty},
|
||||
|
@ -2594,6 +2595,12 @@ impl fmt::Display for Value {
|
|||
}
|
||||
}
|
||||
|
||||
impl InfoStructure for Value {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
/// Check if we require a writeable transaction
|
||||
pub(crate) fn writeable(&self) -> bool {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::sql::{cond::Cond, field::Fields, group::Groups, table::Tables};
|
||||
use crate::sql::statements::info::InfoStructure;
|
||||
use crate::sql::{cond::Cond, field::Fields, group::Groups, table::Tables, Value};
|
||||
use revision::revisioned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
@ -26,3 +27,8 @@ impl fmt::Display for View {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
impl InfoStructure for View {
|
||||
fn structure(self) -> Value {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,6 +185,7 @@ pub(crate) static KEYWORDS: phf::Map<UniCase<&'static str>, TokenKind> = phf_map
|
|||
UniCase::ascii("SNOWBALL") => TokenKind::Keyword(Keyword::Snowball),
|
||||
UniCase::ascii("SPLIT") => TokenKind::Keyword(Keyword::Split),
|
||||
UniCase::ascii("START") => TokenKind::Keyword(Keyword::Start),
|
||||
UniCase::ascii("STRUCTURE") => TokenKind::Keyword(Keyword::Structure),
|
||||
UniCase::ascii("TABLE") => TokenKind::Keyword(Keyword::Table),
|
||||
UniCase::ascii("TB") => TokenKind::Keyword(Keyword::Table),
|
||||
UniCase::ascii("TERMS_CACHE") => TokenKind::Keyword(Keyword::TermsCache),
|
||||
|
|
|
@ -425,7 +425,7 @@ impl Parser<'_> {
|
|||
/// Expects `INFO` to already be consumed.
|
||||
pub(crate) fn parse_info_stmt(&mut self) -> ParseResult<InfoStatement> {
|
||||
expected!(self, t!("FOR"));
|
||||
let stmt = match self.next().kind {
|
||||
let mut stmt = match self.next().kind {
|
||||
t!("ROOT") => InfoStatement::Root,
|
||||
t!("NAMESPACE") => InfoStatement::Ns,
|
||||
t!("DATABASE") => InfoStatement::Db,
|
||||
|
@ -444,6 +444,18 @@ impl Parser<'_> {
|
|||
}
|
||||
x => unexpected!(self, x, "an info target"),
|
||||
};
|
||||
|
||||
if self.peek_kind() == t!("STRUCTURE") {
|
||||
stmt = match stmt.structurize() {
|
||||
Ok(s) => {
|
||||
self.pop_peek();
|
||||
s
|
||||
}
|
||||
Err(_) => {
|
||||
unexpected!(self, t!("STRUCTURE"), "not STRUCTURE")
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(stmt)
|
||||
}
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ keyword! {
|
|||
Snowball => "SNOWBALL",
|
||||
Split => "SPLIT",
|
||||
Start => "START",
|
||||
Structure => "STRUCTURE",
|
||||
Table => "TABLE",
|
||||
TermsCache => "TERMS_CACHE",
|
||||
TermsOrder => "TERMS_ORDER",
|
||||
|
|
Loading…
Reference in a new issue