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::{
|
||||
Entid,
|
||||
FromRc,
|
||||
KnownEntid,
|
||||
TypedValue,
|
||||
Binding,
|
||||
ValueType,
|
||||
ValueTypeTag,
|
||||
ValueRc,
|
||||
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.
|
||||
///
|
||||
/// 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>),
|
||||
Instant(DateTime<Utc>), // Use `into()` to ensure truncation.
|
||||
// TODO: &str throughout?
|
||||
String(Rc<String>),
|
||||
Keyword(Rc<NamespacedKeyword>),
|
||||
String(ValueRc<String>),
|
||||
Keyword(ValueRc<NamespacedKeyword>),
|
||||
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)]
|
||||
pub enum Binding {
|
||||
Scalar(TypedValue),
|
||||
Vec(Rc<Vec<Binding>>),
|
||||
Map(Rc<StructuredMap>),
|
||||
Vec(ValueRc<Vec<Binding>>),
|
||||
Map(ValueRc<StructuredMap>),
|
||||
}
|
||||
|
||||
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
|
||||
/// using a different keyword only.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct StructuredMap(IndexMap<Rc<NamespacedKeyword>, Binding>);
|
||||
pub struct StructuredMap(IndexMap<ValueRc<NamespacedKeyword>, Binding>);
|
||||
|
||||
impl Binding {
|
||||
/// 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
|
||||
/// 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.
|
||||
pub fn typed_ns_keyword(ns: &str, name: &str) -> TypedValue {
|
||||
NamespacedKeyword::new(ns, name).into()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn typed_string(s: &str) -> TypedValue {
|
||||
s.into()
|
||||
|
@ -381,31 +386,43 @@ impl From<Uuid> for TypedValue {
|
|||
|
||||
impl<'a> From<&'a str> for 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 {
|
||||
fn from(value: Rc<String>) -> TypedValue {
|
||||
TypedValue::String(value.clone())
|
||||
TypedValue::String(ValueRc::from_rc(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for 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 {
|
||||
fn from(value: Rc<NamespacedKeyword>) -> TypedValue {
|
||||
TypedValue::Keyword(value.clone())
|
||||
TypedValue::Keyword(ValueRc::from_rc(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NamespacedKeyword> for 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 {
|
||||
TypedValue::Keyword(v) => Some(v),
|
||||
_ => 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 {
|
||||
TypedValue::String(v) => Some(v),
|
||||
_ => 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 {
|
||||
Binding::Scalar(TypedValue::Keyword(v)) => Some(v),
|
||||
_ => 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 {
|
||||
Binding::Scalar(TypedValue::String(v)) => Some(v),
|
||||
_ => None,
|
||||
|
|
|
@ -68,8 +68,6 @@ use std::iter::{
|
|||
|
||||
use std::mem;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use std::iter::Peekable;
|
||||
|
@ -85,6 +83,7 @@ use mentat_core::{
|
|||
Schema,
|
||||
TypedValue,
|
||||
UpdateableCache,
|
||||
ValueRc,
|
||||
};
|
||||
|
||||
use mentat_core::util::{
|
||||
|
@ -190,7 +189,7 @@ pub type Aev = (Entid, Entid, TypedValue);
|
|||
|
||||
pub struct AevFactory {
|
||||
// Our own simple string-interning system.
|
||||
strings: HashSet<Rc<String>>,
|
||||
strings: HashSet<ValueRc<String>>,
|
||||
}
|
||||
|
||||
impl AevFactory {
|
||||
|
|
|
@ -19,7 +19,6 @@ use std::fmt::Display;
|
|||
use std::iter::{once, repeat};
|
||||
use std::ops::Range;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
use itertools;
|
||||
use itertools::Itertools;
|
||||
|
@ -51,7 +50,9 @@ use mentat_core::{
|
|||
TypedValue,
|
||||
ToMicros,
|
||||
ValueType,
|
||||
ValueRc,
|
||||
};
|
||||
|
||||
use errors::{ErrorKind, Result, ResultExt};
|
||||
use metadata;
|
||||
use schema::{
|
||||
|
@ -872,7 +873,7 @@ impl MentatStoring for rusqlite::Connection {
|
|||
let chunks: itertools::IntoChunks<_> = entities.into_iter().chunks(max_vars / bindings_per_statement);
|
||||
|
||||
// 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.
|
||||
let results: Result<Vec<()>> = chunks.into_iter().map(|chunk| -> Result<()> {
|
||||
|
|
|
@ -25,6 +25,10 @@ use std::fmt::{
|
|||
Formatter,
|
||||
};
|
||||
|
||||
use std::ops::{
|
||||
Deref,
|
||||
};
|
||||
|
||||
use mentat_core::{
|
||||
Attribute,
|
||||
Entid,
|
||||
|
@ -97,13 +101,13 @@ pub use self::inputs::QueryInputs;
|
|||
use Known;
|
||||
|
||||
// We do this a lot for errors.
|
||||
trait RcCloned<T> {
|
||||
trait Cloned<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 {
|
||||
self.as_ref().clone()
|
||||
self.deref().clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ use mentat_query::{
|
|||
Variable,
|
||||
};
|
||||
|
||||
use super::RcCloned;
|
||||
use super::Cloned;
|
||||
|
||||
use clauses::{
|
||||
ConjoiningClauses,
|
||||
|
|
|
@ -15,11 +15,10 @@ use std::fmt::{
|
|||
Result,
|
||||
};
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use mentat_core::{
|
||||
Entid,
|
||||
TypedValue,
|
||||
ValueRc,
|
||||
ValueType,
|
||||
ValueTypeSet,
|
||||
};
|
||||
|
@ -709,7 +708,7 @@ pub enum EvolvedValuePlace {
|
|||
Entid(Entid),
|
||||
Value(TypedValue),
|
||||
EntidOrInteger(i64),
|
||||
IdentOrKeyword(Rc<NamespacedKeyword>),
|
||||
IdentOrKeyword(ValueRc<NamespacedKeyword>),
|
||||
}
|
||||
|
||||
pub enum PlaceOrEmpty<T> {
|
||||
|
|
|
@ -55,7 +55,9 @@ pub use edn::{
|
|||
};
|
||||
|
||||
use mentat_core::{
|
||||
FromRc,
|
||||
TypedValue,
|
||||
ValueRc,
|
||||
ValueType,
|
||||
};
|
||||
|
||||
|
@ -205,7 +207,7 @@ pub enum NonIntegerConstant {
|
|||
Boolean(bool),
|
||||
BigInteger(BigInt),
|
||||
Float(OrderedFloat<f64>),
|
||||
Text(Rc<String>),
|
||||
Text(ValueRc<String>),
|
||||
Instant(DateTime<Utc>),
|
||||
Uuid(Uuid),
|
||||
}
|
||||
|
@ -225,13 +227,13 @@ impl NonIntegerConstant {
|
|||
|
||||
impl<'a> From<&'a str> for 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 {
|
||||
fn from(val: String) -> NonIntegerConstant {
|
||||
NonIntegerConstant::Text(Rc::new(val))
|
||||
NonIntegerConstant::Text(ValueRc::new(val))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,18 +326,18 @@ pub enum PatternNonValuePlace {
|
|||
Placeholder,
|
||||
Variable(Variable),
|
||||
Entid(i64), // Will always be +ve. See #190.
|
||||
Ident(Rc<NamespacedKeyword>),
|
||||
Ident(ValueRc<NamespacedKeyword>),
|
||||
}
|
||||
|
||||
impl From<Rc<NamespacedKeyword>> for PatternNonValuePlace {
|
||||
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
||||
PatternNonValuePlace::Ident(value.clone())
|
||||
PatternNonValuePlace::Ident(ValueRc::from_rc(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NamespacedKeyword> for PatternNonValuePlace {
|
||||
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)]
|
||||
pub enum IdentOrEntid {
|
||||
Ident(Rc<NamespacedKeyword>),
|
||||
Ident(NamespacedKeyword),
|
||||
Entid(i64),
|
||||
}
|
||||
|
||||
|
@ -399,19 +401,19 @@ pub enum PatternValuePlace {
|
|||
Placeholder,
|
||||
Variable(Variable),
|
||||
EntidOrInteger(i64),
|
||||
IdentOrKeyword(Rc<NamespacedKeyword>),
|
||||
IdentOrKeyword(ValueRc<NamespacedKeyword>),
|
||||
Constant(NonIntegerConstant),
|
||||
}
|
||||
|
||||
impl From<Rc<NamespacedKeyword>> for PatternValuePlace {
|
||||
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
||||
PatternValuePlace::IdentOrKeyword(value.clone())
|
||||
PatternValuePlace::IdentOrKeyword(ValueRc::from_rc(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NamespacedKeyword> for PatternValuePlace {
|
||||
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::{
|
||||
ToMicros,
|
||||
TypedValue,
|
||||
ValueRc,
|
||||
};
|
||||
|
||||
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,
|
||||
// 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.
|
||||
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).
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue