Introduce ValueRc as an abstraction over Rc/Arc choice.
This commit is contained in:
parent
9292867dc9
commit
1918388ddf
9 changed files with 64 additions and 39 deletions
|
@ -56,11 +56,13 @@ mod sql_types;
|
||||||
|
|
||||||
pub use types::{
|
pub use types::{
|
||||||
Entid,
|
Entid,
|
||||||
|
FromRc,
|
||||||
KnownEntid,
|
KnownEntid,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
Binding,
|
Binding,
|
||||||
ValueType,
|
ValueType,
|
||||||
ValueTypeTag,
|
ValueTypeTag,
|
||||||
|
ValueRc,
|
||||||
now,
|
now,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,11 @@ impl<T> FromRc<T> for Arc<T> where T: Sized + Clone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use Rc for values.
|
||||||
|
//
|
||||||
|
pub type ValueRc<T> = Rc<T>;
|
||||||
|
|
||||||
/// Represents one entid in the entid space.
|
/// Represents one entid in the entid space.
|
||||||
///
|
///
|
||||||
/// Per https://www.sqlite.org/datatype3.html (see also http://stackoverflow.com/a/8499544), SQLite
|
/// Per https://www.sqlite.org/datatype3.html (see also http://stackoverflow.com/a/8499544), SQLite
|
||||||
|
@ -208,8 +213,8 @@ pub enum TypedValue {
|
||||||
Double(OrderedFloat<f64>),
|
Double(OrderedFloat<f64>),
|
||||||
Instant(DateTime<Utc>), // Use `into()` to ensure truncation.
|
Instant(DateTime<Utc>), // Use `into()` to ensure truncation.
|
||||||
// TODO: &str throughout?
|
// TODO: &str throughout?
|
||||||
String(Rc<String>),
|
String(ValueRc<String>),
|
||||||
Keyword(Rc<NamespacedKeyword>),
|
Keyword(ValueRc<NamespacedKeyword>),
|
||||||
Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone.
|
Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +233,8 @@ pub enum TypedValue {
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum Binding {
|
pub enum Binding {
|
||||||
Scalar(TypedValue),
|
Scalar(TypedValue),
|
||||||
Vec(Rc<Vec<Binding>>),
|
Vec(ValueRc<Vec<Binding>>),
|
||||||
Map(Rc<StructuredMap>),
|
Map(ValueRc<StructuredMap>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<T> for Binding where T: Into<TypedValue> {
|
impl<T> From<T> for Binding where T: Into<TypedValue> {
|
||||||
|
@ -258,7 +263,7 @@ impl Binding {
|
||||||
/// We entirely support the former, and partially support the latter -- you can alias
|
/// We entirely support the former, and partially support the latter -- you can alias
|
||||||
/// using a different keyword only.
|
/// using a different keyword only.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct StructuredMap(IndexMap<Rc<NamespacedKeyword>, Binding>);
|
pub struct StructuredMap(IndexMap<ValueRc<NamespacedKeyword>, Binding>);
|
||||||
|
|
||||||
impl Binding {
|
impl Binding {
|
||||||
/// Returns true if the provided type is `Some` and matches this value's type, or if the
|
/// Returns true if the provided type is `Some` and matches this value's type, or if the
|
||||||
|
@ -311,14 +316,14 @@ impl TypedValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new `TypedValue::Keyword` instance by cloning the provided
|
/// Construct a new `TypedValue::Keyword` instance by cloning the provided
|
||||||
/// values and wrapping them in a new `Rc`. This is expensive, so this might
|
/// values and wrapping them in a new `ValueRc`. This is expensive, so this might
|
||||||
/// be best limited to tests.
|
/// be best limited to tests.
|
||||||
pub fn typed_ns_keyword(ns: &str, name: &str) -> TypedValue {
|
pub fn typed_ns_keyword(ns: &str, name: &str) -> TypedValue {
|
||||||
NamespacedKeyword::new(ns, name).into()
|
NamespacedKeyword::new(ns, name).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new `TypedValue::String` instance by cloning the provided
|
/// Construct a new `TypedValue::String` instance by cloning the provided
|
||||||
/// value and wrapping it in a new `Rc`. This is expensive, so this might
|
/// value and wrapping it in a new `ValueRc`. This is expensive, so this might
|
||||||
/// be best limited to tests.
|
/// be best limited to tests.
|
||||||
pub fn typed_string(s: &str) -> TypedValue {
|
pub fn typed_string(s: &str) -> TypedValue {
|
||||||
s.into()
|
s.into()
|
||||||
|
@ -381,31 +386,43 @@ impl From<Uuid> for TypedValue {
|
||||||
|
|
||||||
impl<'a> From<&'a str> for TypedValue {
|
impl<'a> From<&'a str> for TypedValue {
|
||||||
fn from(value: &'a str) -> TypedValue {
|
fn from(value: &'a str) -> TypedValue {
|
||||||
TypedValue::String(Rc::new(value.to_string()))
|
TypedValue::String(ValueRc::new(value.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Arc<String>> for TypedValue {
|
||||||
|
fn from(value: Arc<String>) -> TypedValue {
|
||||||
|
TypedValue::String(ValueRc::from_arc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<String>> for TypedValue {
|
impl From<Rc<String>> for TypedValue {
|
||||||
fn from(value: Rc<String>) -> TypedValue {
|
fn from(value: Rc<String>) -> TypedValue {
|
||||||
TypedValue::String(value.clone())
|
TypedValue::String(ValueRc::from_rc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for TypedValue {
|
impl From<String> for TypedValue {
|
||||||
fn from(value: String) -> TypedValue {
|
fn from(value: String) -> TypedValue {
|
||||||
TypedValue::String(Rc::new(value))
|
TypedValue::String(ValueRc::new(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Arc<NamespacedKeyword>> for TypedValue {
|
||||||
|
fn from(value: Arc<NamespacedKeyword>) -> TypedValue {
|
||||||
|
TypedValue::Keyword(ValueRc::from_arc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<NamespacedKeyword>> for TypedValue {
|
impl From<Rc<NamespacedKeyword>> for TypedValue {
|
||||||
fn from(value: Rc<NamespacedKeyword>) -> TypedValue {
|
fn from(value: Rc<NamespacedKeyword>) -> TypedValue {
|
||||||
TypedValue::Keyword(value.clone())
|
TypedValue::Keyword(ValueRc::from_rc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NamespacedKeyword> for TypedValue {
|
impl From<NamespacedKeyword> for TypedValue {
|
||||||
fn from(value: NamespacedKeyword) -> TypedValue {
|
fn from(value: NamespacedKeyword) -> TypedValue {
|
||||||
TypedValue::Keyword(Rc::new(value))
|
TypedValue::Keyword(ValueRc::new(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +459,7 @@ impl TypedValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_kw(self) -> Option<Rc<NamespacedKeyword>> {
|
pub fn into_kw(self) -> Option<ValueRc<NamespacedKeyword>> {
|
||||||
match self {
|
match self {
|
||||||
TypedValue::Keyword(v) => Some(v),
|
TypedValue::Keyword(v) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -484,7 +501,7 @@ impl TypedValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_string(self) -> Option<Rc<String>> {
|
pub fn into_string(self) -> Option<ValueRc<String>> {
|
||||||
match self {
|
match self {
|
||||||
TypedValue::String(v) => Some(v),
|
TypedValue::String(v) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -521,7 +538,7 @@ impl Binding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_kw(self) -> Option<Rc<NamespacedKeyword>> {
|
pub fn into_kw(self) -> Option<ValueRc<NamespacedKeyword>> {
|
||||||
match self {
|
match self {
|
||||||
Binding::Scalar(TypedValue::Keyword(v)) => Some(v),
|
Binding::Scalar(TypedValue::Keyword(v)) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -563,7 +580,7 @@ impl Binding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_string(self) -> Option<Rc<String>> {
|
pub fn into_string(self) -> Option<ValueRc<String>> {
|
||||||
match self {
|
match self {
|
||||||
Binding::Scalar(TypedValue::String(v)) => Some(v),
|
Binding::Scalar(TypedValue::String(v)) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -68,8 +68,6 @@ use std::iter::{
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
|
@ -85,6 +83,7 @@ use mentat_core::{
|
||||||
Schema,
|
Schema,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
UpdateableCache,
|
UpdateableCache,
|
||||||
|
ValueRc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::util::{
|
use mentat_core::util::{
|
||||||
|
@ -190,7 +189,7 @@ pub type Aev = (Entid, Entid, TypedValue);
|
||||||
|
|
||||||
pub struct AevFactory {
|
pub struct AevFactory {
|
||||||
// Our own simple string-interning system.
|
// Our own simple string-interning system.
|
||||||
strings: HashSet<Rc<String>>,
|
strings: HashSet<ValueRc<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AevFactory {
|
impl AevFactory {
|
||||||
|
|
|
@ -19,7 +19,6 @@ use std::fmt::Display;
|
||||||
use std::iter::{once, repeat};
|
use std::iter::{once, repeat};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use itertools;
|
use itertools;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -51,7 +50,9 @@ use mentat_core::{
|
||||||
TypedValue,
|
TypedValue,
|
||||||
ToMicros,
|
ToMicros,
|
||||||
ValueType,
|
ValueType,
|
||||||
|
ValueRc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use errors::{ErrorKind, Result, ResultExt};
|
use errors::{ErrorKind, Result, ResultExt};
|
||||||
use metadata;
|
use metadata;
|
||||||
use schema::{
|
use schema::{
|
||||||
|
@ -872,7 +873,7 @@ impl MentatStoring for rusqlite::Connection {
|
||||||
let chunks: itertools::IntoChunks<_> = entities.into_iter().chunks(max_vars / bindings_per_statement);
|
let chunks: itertools::IntoChunks<_> = entities.into_iter().chunks(max_vars / bindings_per_statement);
|
||||||
|
|
||||||
// From string to (searchid, value_type_tag).
|
// From string to (searchid, value_type_tag).
|
||||||
let mut seen: HashMap<Rc<String>, (i64, i32)> = HashMap::with_capacity(entities.len());
|
let mut seen: HashMap<ValueRc<String>, (i64, i32)> = HashMap::with_capacity(entities.len());
|
||||||
|
|
||||||
// We'd like to flat_map here, but it's not obvious how to flat_map across Result.
|
// We'd like to flat_map here, but it's not obvious how to flat_map across Result.
|
||||||
let results: Result<Vec<()>> = chunks.into_iter().map(|chunk| -> Result<()> {
|
let results: Result<Vec<()>> = chunks.into_iter().map(|chunk| -> Result<()> {
|
||||||
|
|
|
@ -25,6 +25,10 @@ use std::fmt::{
|
||||||
Formatter,
|
Formatter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::ops::{
|
||||||
|
Deref,
|
||||||
|
};
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
Attribute,
|
Attribute,
|
||||||
Entid,
|
Entid,
|
||||||
|
@ -97,13 +101,13 @@ pub use self::inputs::QueryInputs;
|
||||||
use Known;
|
use Known;
|
||||||
|
|
||||||
// We do this a lot for errors.
|
// We do this a lot for errors.
|
||||||
trait RcCloned<T> {
|
trait Cloned<T> {
|
||||||
fn cloned(&self) -> T;
|
fn cloned(&self) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> RcCloned<T> for ::std::rc::Rc<T> {
|
impl<T: Clone> Cloned<T> for ::mentat_core::ValueRc<T> {
|
||||||
fn cloned(&self) -> T {
|
fn cloned(&self) -> T {
|
||||||
self.as_ref().clone()
|
self.deref().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ use mentat_query::{
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::RcCloned;
|
use super::Cloned;
|
||||||
|
|
||||||
use clauses::{
|
use clauses::{
|
||||||
ConjoiningClauses,
|
ConjoiningClauses,
|
||||||
|
|
|
@ -15,11 +15,10 @@ use std::fmt::{
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
Entid,
|
Entid,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
|
ValueRc,
|
||||||
ValueType,
|
ValueType,
|
||||||
ValueTypeSet,
|
ValueTypeSet,
|
||||||
};
|
};
|
||||||
|
@ -709,7 +708,7 @@ pub enum EvolvedValuePlace {
|
||||||
Entid(Entid),
|
Entid(Entid),
|
||||||
Value(TypedValue),
|
Value(TypedValue),
|
||||||
EntidOrInteger(i64),
|
EntidOrInteger(i64),
|
||||||
IdentOrKeyword(Rc<NamespacedKeyword>),
|
IdentOrKeyword(ValueRc<NamespacedKeyword>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum PlaceOrEmpty<T> {
|
pub enum PlaceOrEmpty<T> {
|
||||||
|
|
|
@ -55,7 +55,9 @@ pub use edn::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
|
FromRc,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
|
ValueRc,
|
||||||
ValueType,
|
ValueType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,7 +207,7 @@ pub enum NonIntegerConstant {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
BigInteger(BigInt),
|
BigInteger(BigInt),
|
||||||
Float(OrderedFloat<f64>),
|
Float(OrderedFloat<f64>),
|
||||||
Text(Rc<String>),
|
Text(ValueRc<String>),
|
||||||
Instant(DateTime<Utc>),
|
Instant(DateTime<Utc>),
|
||||||
Uuid(Uuid),
|
Uuid(Uuid),
|
||||||
}
|
}
|
||||||
|
@ -225,13 +227,13 @@ impl NonIntegerConstant {
|
||||||
|
|
||||||
impl<'a> From<&'a str> for NonIntegerConstant {
|
impl<'a> From<&'a str> for NonIntegerConstant {
|
||||||
fn from(val: &'a str) -> NonIntegerConstant {
|
fn from(val: &'a str) -> NonIntegerConstant {
|
||||||
NonIntegerConstant::Text(Rc::new(val.to_string()))
|
NonIntegerConstant::Text(ValueRc::new(val.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for NonIntegerConstant {
|
impl From<String> for NonIntegerConstant {
|
||||||
fn from(val: String) -> NonIntegerConstant {
|
fn from(val: String) -> NonIntegerConstant {
|
||||||
NonIntegerConstant::Text(Rc::new(val))
|
NonIntegerConstant::Text(ValueRc::new(val))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,18 +326,18 @@ pub enum PatternNonValuePlace {
|
||||||
Placeholder,
|
Placeholder,
|
||||||
Variable(Variable),
|
Variable(Variable),
|
||||||
Entid(i64), // Will always be +ve. See #190.
|
Entid(i64), // Will always be +ve. See #190.
|
||||||
Ident(Rc<NamespacedKeyword>),
|
Ident(ValueRc<NamespacedKeyword>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<NamespacedKeyword>> for PatternNonValuePlace {
|
impl From<Rc<NamespacedKeyword>> for PatternNonValuePlace {
|
||||||
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
||||||
PatternNonValuePlace::Ident(value.clone())
|
PatternNonValuePlace::Ident(ValueRc::from_rc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NamespacedKeyword> for PatternNonValuePlace {
|
impl From<NamespacedKeyword> for PatternNonValuePlace {
|
||||||
fn from(value: NamespacedKeyword) -> Self {
|
fn from(value: NamespacedKeyword) -> Self {
|
||||||
PatternNonValuePlace::Ident(Rc::new(value))
|
PatternNonValuePlace::Ident(ValueRc::new(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +389,7 @@ impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum IdentOrEntid {
|
pub enum IdentOrEntid {
|
||||||
Ident(Rc<NamespacedKeyword>),
|
Ident(NamespacedKeyword),
|
||||||
Entid(i64),
|
Entid(i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,19 +401,19 @@ pub enum PatternValuePlace {
|
||||||
Placeholder,
|
Placeholder,
|
||||||
Variable(Variable),
|
Variable(Variable),
|
||||||
EntidOrInteger(i64),
|
EntidOrInteger(i64),
|
||||||
IdentOrKeyword(Rc<NamespacedKeyword>),
|
IdentOrKeyword(ValueRc<NamespacedKeyword>),
|
||||||
Constant(NonIntegerConstant),
|
Constant(NonIntegerConstant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<NamespacedKeyword>> for PatternValuePlace {
|
impl From<Rc<NamespacedKeyword>> for PatternValuePlace {
|
||||||
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
||||||
PatternValuePlace::IdentOrKeyword(value.clone())
|
PatternValuePlace::IdentOrKeyword(ValueRc::from_rc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NamespacedKeyword> for PatternValuePlace {
|
impl From<NamespacedKeyword> for PatternValuePlace {
|
||||||
fn from(value: NamespacedKeyword) -> Self {
|
fn from(value: NamespacedKeyword) -> Self {
|
||||||
PatternValuePlace::IdentOrKeyword(Rc::new(value))
|
PatternValuePlace::IdentOrKeyword(ValueRc::new(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ use ordered_float::OrderedFloat;
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
ToMicros,
|
ToMicros,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
|
ValueRc,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use rusqlite::types::Value;
|
pub use rusqlite::types::Value;
|
||||||
|
@ -103,7 +104,7 @@ pub struct SQLiteQueryBuilder {
|
||||||
// Instead we track byte and String arguments separately, mapping them to their argument name,
|
// Instead we track byte and String arguments separately, mapping them to their argument name,
|
||||||
// in order to dedupe. We'll add these to the regular argument vector later.
|
// in order to dedupe. We'll add these to the regular argument vector later.
|
||||||
byte_args: HashMap<Vec<u8>, String>, // From value to argument name.
|
byte_args: HashMap<Vec<u8>, String>, // From value to argument name.
|
||||||
string_args: HashMap<Rc<String>, String>, // From value to argument name.
|
string_args: HashMap<ValueRc<String>, String>, // From value to argument name.
|
||||||
args: Vec<(String, Rc<rusqlite::types::Value>)>, // (arg, value).
|
args: Vec<(String, Rc<rusqlite::types::Value>)>, // (arg, value).
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue