Add unspecified resource (#4577)
This commit is contained in:
parent
07d834ef1c
commit
a9e6efd9b1
10 changed files with 128 additions and 18 deletions
|
@ -296,15 +296,27 @@ pub trait RpcContext {
|
||||||
// Return a single result?
|
// Return a single result?
|
||||||
let one = what.is_thing_single();
|
let one = what.is_thing_single();
|
||||||
// Specify the SQL query string
|
// Specify the SQL query string
|
||||||
let sql = "INSERT INTO $what $data RETURN AFTER";
|
|
||||||
// Specify the query parameters
|
let mut res = match what {
|
||||||
let var = Some(map! {
|
Value::None | Value::Null => {
|
||||||
String::from("what") => what.could_be_table(),
|
let sql = "INSERT $data RETURN AFTER";
|
||||||
String::from("data") => data,
|
let var = Some(map! {
|
||||||
=> &self.vars()
|
String::from("data") => data,
|
||||||
});
|
=> &self.vars()
|
||||||
// Execute the query on the database
|
});
|
||||||
let mut res = self.kvs().execute(sql, self.session(), var).await?;
|
self.kvs().execute(sql, self.session(), var).await?
|
||||||
|
}
|
||||||
|
what => {
|
||||||
|
let sql = "INSERT INTO $what $data RETURN AFTER";
|
||||||
|
let var = Some(map! {
|
||||||
|
String::from("what") => what.could_be_table(),
|
||||||
|
String::from("data") => data,
|
||||||
|
=> &self.vars()
|
||||||
|
});
|
||||||
|
self.kvs().execute(sql, self.session(), var).await?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Extract the first query result
|
// Extract the first query result
|
||||||
let res = match one {
|
let res = match one {
|
||||||
true => res.remove(0).result?.first(),
|
true => res.remove(0).result?.first(),
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub(crate) enum Command {
|
||||||
},
|
},
|
||||||
Insert {
|
Insert {
|
||||||
// inserts can only be on a table.
|
// inserts can only be on a table.
|
||||||
what: String,
|
what: Option<String>,
|
||||||
data: CoreValue,
|
data: CoreValue,
|
||||||
},
|
},
|
||||||
Patch {
|
Patch {
|
||||||
|
@ -197,9 +197,16 @@ impl Command {
|
||||||
what,
|
what,
|
||||||
data,
|
data,
|
||||||
} => {
|
} => {
|
||||||
let mut table = CoreTable::default();
|
let table = match what {
|
||||||
table.0 = what.clone();
|
Some(w) => {
|
||||||
let params = vec![CoreValue::from(what), data];
|
let mut tmp = CoreTable::default();
|
||||||
|
tmp.0 = w.clone();
|
||||||
|
CoreValue::from(tmp)
|
||||||
|
}
|
||||||
|
None => CoreValue::None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let params = vec![table, data];
|
||||||
|
|
||||||
RouterRequest {
|
RouterRequest {
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -600,7 +600,7 @@ async fn router(
|
||||||
let one = !data.is_array();
|
let one = !data.is_array();
|
||||||
let statement = {
|
let statement = {
|
||||||
let mut stmt = InsertStatement::default();
|
let mut stmt = InsertStatement::default();
|
||||||
stmt.into = Some(Table(what).into_core().into());
|
stmt.into = what.map(|w| Table(w).into_core().into());
|
||||||
stmt.data = Data::SingleExpression(data);
|
stmt.data = Data::SingleExpression(data);
|
||||||
stmt.output = Some(Output::After);
|
stmt.output = Some(Output::After);
|
||||||
stmt
|
stmt
|
||||||
|
|
|
@ -48,6 +48,7 @@ fn resource_to_values(r: Resource) -> CoreValues {
|
||||||
Resource::Array(x) => res.0 = Value::array_to_core(x),
|
Resource::Array(x) => res.0 = Value::array_to_core(x),
|
||||||
Resource::Edge(x) => res.0 = vec![x.into_inner().into()],
|
Resource::Edge(x) => res.0 = vec![x.into_inner().into()],
|
||||||
Resource::Range(x) => res.0 = vec![x.into_inner().into()],
|
Resource::Range(x) => res.0 = vec![x.into_inner().into()],
|
||||||
|
Resource::Unspecified => {}
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,13 @@ pub enum Error {
|
||||||
RangeOnEdges,
|
RangeOnEdges,
|
||||||
|
|
||||||
/// Tried to use a range query on an existing range
|
/// Tried to use a range query on an existing range
|
||||||
#[error("Tried to add a range to an resource which was already a range")]
|
#[error("Tried to add a range to a resource which was already a range")]
|
||||||
RangeOnRange,
|
RangeOnRange,
|
||||||
|
|
||||||
|
/// Tried to use a range query on an unspecified resource
|
||||||
|
#[error("Tried to add a range to an unspecified resource")]
|
||||||
|
RangeOnUnspecified,
|
||||||
|
|
||||||
/// Tried to use `table:id` syntax as a method parameter when `(table, id)` should be used instead
|
/// Tried to use `table:id` syntax as a method parameter when `(table, id)` should be used instead
|
||||||
#[error("Table name `{table}` contained a colon (:), this is dissallowed to avoid confusion with record-id's try `Table(\"{table}\")` instead.")]
|
#[error("Table name `{table}` contained a colon (:), this is dissallowed to avoid confusion with record-id's try `Table(\"{table}\")` instead.")]
|
||||||
TableColonId {
|
TableColonId {
|
||||||
|
@ -181,6 +185,10 @@ pub enum Error {
|
||||||
#[error("Live queries on edges not supported")]
|
#[error("Live queries on edges not supported")]
|
||||||
LiveOnEdges,
|
LiveOnEdges,
|
||||||
|
|
||||||
|
/// Tried to use a range query on an unspecified resource
|
||||||
|
#[error("Live queries on unspecified resource not supported")]
|
||||||
|
LiveOnUnspecified,
|
||||||
|
|
||||||
/// Tried to access a query statement as a live query when it isn't a live query
|
/// Tried to access a query statement as a live query when it isn't a live query
|
||||||
#[error("Query statement {0} is not a live query")]
|
#[error("Query statement {0} is not a live query")]
|
||||||
NotLiveQuery(usize),
|
NotLiveQuery(usize),
|
||||||
|
@ -209,6 +217,10 @@ pub enum Error {
|
||||||
#[error("Insert queries on ranges are not supported")]
|
#[error("Insert queries on ranges are not supported")]
|
||||||
InsertOnRange,
|
InsertOnRange,
|
||||||
|
|
||||||
|
/// Tried to insert on an unspecified resource with no data
|
||||||
|
#[error("Insert queries on unspecified resource with no data are not supported")]
|
||||||
|
InsertOnUnspecified,
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
InvalidNetTarget(#[from] ParseNetTargetError),
|
InvalidNetTarget(#[from] ParseNetTargetError),
|
||||||
|
|
||||||
|
|
|
@ -62,9 +62,10 @@ macro_rules! into_future {
|
||||||
Resource::Range {
|
Resource::Range {
|
||||||
..
|
..
|
||||||
} => return Err(Error::InsertOnRange.into()),
|
} => return Err(Error::InsertOnRange.into()),
|
||||||
|
Resource::Unspecified => return Err(Error::InsertOnUnspecified.into()),
|
||||||
};
|
};
|
||||||
let cmd = Command::Insert {
|
let cmd = Command::Insert {
|
||||||
what: table.to_string(),
|
what: Some(table.to_string()),
|
||||||
data: data.into(),
|
data: data.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ where
|
||||||
let mut data = to_core_value(data)?;
|
let mut data = to_core_value(data)?;
|
||||||
match self.resource? {
|
match self.resource? {
|
||||||
Resource::Table(table) => Ok(Command::Insert {
|
Resource::Table(table) => Ok(Command::Insert {
|
||||||
what: table,
|
what: Some(table),
|
||||||
data,
|
data,
|
||||||
}),
|
}),
|
||||||
Resource::RecordId(thing) => {
|
Resource::RecordId(thing) => {
|
||||||
|
@ -137,7 +138,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Command::Insert {
|
Ok(Command::Insert {
|
||||||
what: thing.tb,
|
what: Some(thing.tb),
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -146,6 +147,10 @@ where
|
||||||
Resource::Array(_) => Err(Error::InsertOnArray.into()),
|
Resource::Array(_) => Err(Error::InsertOnArray.into()),
|
||||||
Resource::Edge(_) => Err(Error::InsertOnEdges.into()),
|
Resource::Edge(_) => Err(Error::InsertOnEdges.into()),
|
||||||
Resource::Range(_) => Err(Error::InsertOnRange.into()),
|
Resource::Range(_) => Err(Error::InsertOnRange.into()),
|
||||||
|
Resource::Unspecified => Ok(Command::Insert {
|
||||||
|
what: None,
|
||||||
|
data,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ where
|
||||||
stmt.what = table.into();
|
stmt.what = table.into();
|
||||||
stmt.cond = range.to_cond();
|
stmt.cond = range.to_cond();
|
||||||
}
|
}
|
||||||
|
Resource::Unspecified => return Err(Error::LiveOnUnspecified.into()),
|
||||||
}
|
}
|
||||||
let query =
|
let query =
|
||||||
Query::new(client.clone(), vec![Statement::Live(stmt)], Default::default(), false);
|
Query::new(client.clone(), vec![Statement::Live(stmt)], Default::default(), false);
|
||||||
|
|
|
@ -845,6 +845,27 @@ where
|
||||||
/// },
|
/// },
|
||||||
/// ])
|
/// ])
|
||||||
/// .await?;
|
/// .await?;
|
||||||
|
///
|
||||||
|
/// // Insert multiple records into different tables
|
||||||
|
/// #[derive(Serialize)]
|
||||||
|
/// struct WithId<'a> {
|
||||||
|
/// id: sql::Thing,
|
||||||
|
/// name: &'a str,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let people: Vec<Person> = db.insert(())
|
||||||
|
/// .content(vec![
|
||||||
|
/// WithId {
|
||||||
|
/// id: sql::thing("person:tobie")?,
|
||||||
|
/// name: "Tobie",
|
||||||
|
/// },
|
||||||
|
/// WithId {
|
||||||
|
/// id: sql::thing("company:surrealdb")?,
|
||||||
|
/// name: "SurrealDB",
|
||||||
|
/// },
|
||||||
|
/// ])
|
||||||
|
/// .await?;
|
||||||
|
///
|
||||||
/// #
|
/// #
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
|
|
|
@ -74,6 +74,8 @@ pub enum Resource {
|
||||||
Edge(Edge),
|
Edge(Edge),
|
||||||
/// A range of id's on a table.
|
/// A range of id's on a table.
|
||||||
Range(QueryRange),
|
Range(QueryRange),
|
||||||
|
/// Unspecified resource
|
||||||
|
Unspecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource {
|
impl Resource {
|
||||||
|
@ -86,6 +88,7 @@ impl Resource {
|
||||||
Resource::Array(_) => Err(Error::RangeOnArray.into()),
|
Resource::Array(_) => Err(Error::RangeOnArray.into()),
|
||||||
Resource::Edge(_) => Err(Error::RangeOnEdges.into()),
|
Resource::Edge(_) => Err(Error::RangeOnEdges.into()),
|
||||||
Resource::Range(_) => Err(Error::RangeOnRange.into()),
|
Resource::Range(_) => Err(Error::RangeOnRange.into()),
|
||||||
|
Resource::Unspecified => Err(Error::RangeOnUnspecified.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +101,7 @@ impl Resource {
|
||||||
Resource::Array(x) => Value::array_to_core(x).into(),
|
Resource::Array(x) => Value::array_to_core(x).into(),
|
||||||
Resource::Edge(x) => x.into_inner().into(),
|
Resource::Edge(x) => x.into_inner().into(),
|
||||||
Resource::Range(x) => x.into_inner().into(),
|
Resource::Range(x) => x.into_inner().into(),
|
||||||
|
Resource::Unspecified => CoreValue::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,6 +183,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<()> for Resource {
|
||||||
|
fn from(_value: ()) -> Self {
|
||||||
|
Self::Unspecified
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Holds the `start` and `end` bounds of a range query
|
/// Holds the `start` and `end` bounds of a range query
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct KeyRange {
|
pub struct KeyRange {
|
||||||
|
@ -390,3 +400,9 @@ impl<R> IntoResource<Vec<R>> for &String {
|
||||||
Ok(self.into())
|
Ok(self.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<R> IntoResource<Vec<R>> for () {
|
||||||
|
fn into_resource(self) -> Result<Resource> {
|
||||||
|
Ok(Resource::Unspecified)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -540,6 +540,41 @@ async fn insert_thing() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test_log::test(tokio::test)]
|
||||||
|
async fn insert_unspecified() {
|
||||||
|
let (permit, db) = new_db().await;
|
||||||
|
db.use_ns(NS).use_db(Ulid::new().to_string()).await.unwrap();
|
||||||
|
drop(permit);
|
||||||
|
let tmp: Result<Vec<RecordId>, _> = db.insert(()).await;
|
||||||
|
tmp.unwrap_err();
|
||||||
|
let tmp: Result<Vec<RecordId>, _> = db.insert(()).content(json!({ "foo": "bar" })).await;
|
||||||
|
tmp.unwrap_err();
|
||||||
|
let tmp: Vec<ApiRecordId> = db
|
||||||
|
.insert(())
|
||||||
|
.content("{id: user:user1, foo: 'bar'}".parse::<Value>().unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
tmp,
|
||||||
|
vec![ApiRecordId {
|
||||||
|
id: "user:user1".parse::<RecordId>().unwrap(),
|
||||||
|
}]
|
||||||
|
);
|
||||||
|
|
||||||
|
let tmp: Result<Value, _> = db.insert(Resource::from(())).await;
|
||||||
|
tmp.unwrap_err();
|
||||||
|
let tmp: Result<Value, _> =
|
||||||
|
db.insert(Resource::from(())).content(json!({ "foo": "bar" })).await;
|
||||||
|
tmp.unwrap_err();
|
||||||
|
let tmp: Value = db
|
||||||
|
.insert(Resource::from(()))
|
||||||
|
.content("{id: user:user2, foo: 'bar'}".parse::<Value>().unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let val = "{id: user:user2, foo: 'bar'}".parse::<Value>().unwrap();
|
||||||
|
assert_eq!(tmp, val);
|
||||||
|
}
|
||||||
|
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn select_table() {
|
async fn select_table() {
|
||||||
let (permit, db) = new_db().await;
|
let (permit, db) = new_db().await;
|
||||||
|
|
Loading…
Reference in a new issue