Compare commits
7 commits
master
...
fluffyemil
Author | SHA1 | Date | |
---|---|---|---|
|
356b969356 | ||
|
0dfb712ef7 | ||
|
10e3d52902 | ||
|
5fbf17f4f9 | ||
|
6adb97c587 | ||
|
666580301f | ||
|
e83c4ef1ba |
30 changed files with 2918 additions and 49 deletions
25
.gitignore
vendored
25
.gitignore
vendored
|
@ -54,3 +54,28 @@ pom.xml.asc
|
||||||
/fixtures/*.db-shm
|
/fixtures/*.db-shm
|
||||||
/fixtures/*.db-wal
|
/fixtures/*.db-wal
|
||||||
/query-parser/out/
|
/query-parser/out/
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData
|
||||||
|
build.xcarchive
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
/sdks/swift/Mentat/*.xcodeproj/project.xcworkspace/xcuserdata
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.xccheckout
|
||||||
|
*.moved-aside
|
||||||
|
*.xcuserstate
|
||||||
|
*.xcscmblueprint
|
||||||
|
|
||||||
|
## Obj-C/Swift specific
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
|
@ -1,10 +1,15 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mentat_ffi"
|
name = "mentat_ffi"
|
||||||
version = "0.1.0"
|
version = "0.0.1"
|
||||||
authors = ["Emily Toop <etoop@mozilla.com>"]
|
authors = ["Emily Toop <etoop@mozilla.com>"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "mentat_ffi"
|
||||||
|
crate-type = ["lib", "staticlib", "cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2.32"
|
||||||
|
|
||||||
[dependencies.mentat]
|
[dependencies.mentat]
|
||||||
path = ".."
|
path = "../"
|
||||||
|
|
||||||
|
|
103
ffi/src/lib.rs
103
ffi/src/lib.rs
|
@ -42,6 +42,7 @@ pub use mentat::{
|
||||||
Syncable,
|
Syncable,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
TxObserver,
|
TxObserver,
|
||||||
|
TxReport,
|
||||||
Uuid,
|
Uuid,
|
||||||
ValueType,
|
ValueType,
|
||||||
Variable,
|
Variable,
|
||||||
|
@ -62,16 +63,23 @@ pub type TypedValueListIterator = vec::IntoIter<Vec<TypedValue>>;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ExternTxReport {
|
pub struct ExternTempId {
|
||||||
|
pub key: *const c_char,
|
||||||
|
pub value: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TransactionChange {
|
||||||
pub txid: Entid,
|
pub txid: Entid,
|
||||||
pub changes: Box<[Entid]>,
|
|
||||||
pub changes_len: usize,
|
pub changes_len: usize,
|
||||||
|
pub changes: Box<[Entid]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ExternTxReportList {
|
pub struct TxChangeList {
|
||||||
pub reports: Box<[ExternTxReport]>,
|
pub reports: Box<[TransactionChange]>,
|
||||||
pub len: usize,
|
pub len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +145,42 @@ pub extern "C" fn store_open(uri: *const c_char) -> *mut Store {
|
||||||
|
|
||||||
// TODO: begin_transaction
|
// TODO: begin_transaction
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn store_transact(store: *mut Store, transaction: *const c_char) -> *mut ExternResult {
|
||||||
|
let store = &mut*store;
|
||||||
|
let transaction = c_char_to_string(transaction);
|
||||||
|
let result = store.begin_transaction().and_then(|mut in_progress| {
|
||||||
|
in_progress.transact(&transaction).and_then(|tx_report| {
|
||||||
|
in_progress.commit()
|
||||||
|
.map(|_| tx_report)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
Box::into_raw(Box::new(result.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn tx_report_get_entid(tx_report: *mut TxReport) -> i64 {
|
||||||
|
let tx_report = &*tx_report;
|
||||||
|
tx_report.tx_id
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn tx_report_get_tx_instant(tx_report: *mut TxReport) -> i64 {
|
||||||
|
let tx_report = &*tx_report;
|
||||||
|
tx_report.tx_instant.timestamp()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn tx_report_entity_for_temp_id(tx_report: *mut TxReport, tempid: *const c_char) -> *mut i64 {
|
||||||
|
let tx_report = &*tx_report;
|
||||||
|
let key = c_char_to_string(tempid);
|
||||||
|
if let Some(entid) = tx_report.tempids.get(&key) {
|
||||||
|
Box::into_raw(Box::new(entid.clone()))
|
||||||
|
} else {
|
||||||
|
std::ptr::null_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: cache
|
// TODO: cache
|
||||||
|
|
||||||
// TODO: q_once
|
// TODO: q_once
|
||||||
|
@ -148,14 +192,6 @@ pub unsafe extern "C" fn store_query<'a>(store: *mut Store, query: *const c_char
|
||||||
Box::into_raw(Box::new(query_builder))
|
Box::into_raw(Box::new(query_builder))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn query_builder_bind_int(query_builder: *mut QueryBuilder, var: *const c_char, value: c_int) {
|
|
||||||
let var = c_char_to_string(var);
|
|
||||||
let query_builder = &mut*query_builder;
|
|
||||||
let value = value as i32;
|
|
||||||
query_builder.bind_value(&var, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn query_builder_bind_long(query_builder: *mut QueryBuilder, var: *const c_char, value: i64) {
|
pub unsafe extern "C" fn query_builder_bind_long(query_builder: *mut QueryBuilder, var: *const c_char, value: i64) {
|
||||||
let var = c_char_to_string(var);
|
let var = c_char_to_string(var);
|
||||||
|
@ -281,9 +317,9 @@ pub unsafe extern "C" fn typed_value_as_kw(typed_value: *mut TypedValue) -> *co
|
||||||
|
|
||||||
//as_boolean
|
//as_boolean
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn typed_value_as_boolean(typed_value: *mut TypedValue) -> bool {
|
pub unsafe extern "C" fn typed_value_as_boolean(typed_value: *mut TypedValue) -> i32 {
|
||||||
let typed_value = Box::from_raw(typed_value);
|
let typed_value = Box::from_raw(typed_value);
|
||||||
typed_value.into_boolean().expect("Typed value cannot be coerced into a Boolean")
|
if typed_value.into_boolean().expect("Typed value cannot be coerced into a Boolean") { 1 } else { 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
//as_double
|
//as_double
|
||||||
|
@ -297,7 +333,8 @@ pub unsafe extern "C" fn typed_value_as_double(typed_value: *mut TypedValue) ->
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn typed_value_as_timestamp(typed_value: *mut TypedValue) -> i64 {
|
pub unsafe extern "C" fn typed_value_as_timestamp(typed_value: *mut TypedValue) -> i64 {
|
||||||
let typed_value = Box::from_raw(typed_value);
|
let typed_value = Box::from_raw(typed_value);
|
||||||
let val = typed_value.into_timestamp().expect("Typed value cannot be coerced into a Timestamp");
|
let t = typed_value.value_type();
|
||||||
|
let val = typed_value.into_timestamp().expect(&format!("Typed value of type {:?} cannot be coerced into a Timestamp", t));
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +352,13 @@ pub unsafe extern "C" fn typed_value_as_uuid(typed_value: *mut TypedValue) -> *
|
||||||
string_to_c_char(typed_value.into_uuid_string().expect("Typed value cannot be coerced into a Uuid"))
|
string_to_c_char(typed_value.into_uuid_string().expect("Typed value cannot be coerced into a Uuid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//value_type
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn typed_value_value_type(typed_value: *mut TypedValue) -> ValueType {
|
||||||
|
let typed_value = &*typed_value;
|
||||||
|
typed_value.value_type()
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn row_at_index(rows: *mut Vec<Vec<TypedValue>>, index: c_int) -> *mut Vec<TypedValue> {
|
pub unsafe extern "C" fn row_at_index(rows: *mut Vec<Vec<TypedValue>>, index: c_int) -> *mut Vec<TypedValue> {
|
||||||
let result = &*rows;
|
let result = &*rows;
|
||||||
|
@ -340,9 +384,9 @@ pub unsafe extern "C" fn values_iter(values: *mut Vec<TypedValue>) -> *mut Type
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn values_iter_next(iter: *mut TypedValueIterator) -> *const TypedValue {
|
pub unsafe extern "C" fn values_iter_next(iter: *mut TypedValueIterator) -> *mut TypedValue {
|
||||||
let iter = &mut *iter;
|
let iter = &mut *iter;
|
||||||
iter.next().map_or(std::ptr::null_mut(), |v| &v as *const TypedValue)
|
iter.next().map_or(std::ptr::null_mut(), |v| Box::into_raw(Box::new(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
//as_long
|
//as_long
|
||||||
|
@ -383,7 +427,7 @@ pub unsafe extern "C" fn values_iter_next_as_double(iter: *mut TypedValueIterato
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn values_iter_next_as_timestamp(iter: *mut TypedValueIterator) -> *const i64 {
|
pub unsafe extern "C" fn values_iter_next_as_timestamp(iter: *mut TypedValueIterator) -> *const i64 {
|
||||||
let iter = &mut *iter;
|
let iter = &mut *iter;
|
||||||
iter.next().map_or(std::ptr::null_mut(), |v| v.into_timestamp().expect("Typed value cannot be coerced into a Timestamp") as *const i64)
|
iter.next().map_or(std::ptr::null_mut(), |v| { let t = v.value_type(); v.into_timestamp().expect(&format!("Typed value of type {:?} cannot be coerced into a Timestamp", t)) as *const i64 })
|
||||||
}
|
}
|
||||||
|
|
||||||
//as_string
|
//as_string
|
||||||
|
@ -469,12 +513,6 @@ pub unsafe extern "C" fn value_at_index_as_uuid(values: *mut Vec<TypedValue>, in
|
||||||
string_to_c_char(value.clone().into_uuid_string().expect("Typed value cannot be coerced into a Uuid"))
|
string_to_c_char(value.clone().into_uuid_string().expect("Typed value cannot be coerced into a Uuid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: q_prepare
|
|
||||||
|
|
||||||
// TODO: q_explain
|
|
||||||
|
|
||||||
// TODO: lookup_values_for_attribute
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn store_value_for_attribute(store: *mut Store, entid: i64, attribute: *const c_char) -> *mut ExternResult {
|
pub unsafe extern "C" fn store_value_for_attribute(store: *mut Store, entid: i64, attribute: *const c_char) -> *mut ExternResult {
|
||||||
let store = &*store;
|
let store = &*store;
|
||||||
|
@ -492,24 +530,24 @@ pub unsafe extern "C" fn store_register_observer(store: *mut Store,
|
||||||
key: *const c_char,
|
key: *const c_char,
|
||||||
attributes: *const Entid,
|
attributes: *const Entid,
|
||||||
attributes_len: usize,
|
attributes_len: usize,
|
||||||
callback: extern fn(key: *const c_char, reports: &ExternTxReportList)) {
|
callback: extern fn(key: *const c_char, reports: &TxChangeList)) {
|
||||||
let store = &mut*store;
|
let store = &mut*store;
|
||||||
let mut attribute_set = BTreeSet::new();
|
let mut attribute_set = BTreeSet::new();
|
||||||
let slice = slice::from_raw_parts(attributes, attributes_len);
|
let slice = slice::from_raw_parts(attributes, attributes_len);
|
||||||
attribute_set.extend(slice.iter());
|
attribute_set.extend(slice.iter());
|
||||||
let key = c_char_to_string(key);
|
let key = c_char_to_string(key);
|
||||||
let tx_observer = Arc::new(TxObserver::new(attribute_set, move |obs_key, batch| {
|
let tx_observer = Arc::new(TxObserver::new(attribute_set, move |obs_key, batch| {
|
||||||
let extern_reports: Vec<ExternTxReport> = batch.into_iter().map(|(tx_id, changes)| {
|
let extern_reports: Vec<TransactionChange> = batch.into_iter().map(|(tx_id, changes)| {
|
||||||
let changes: Vec<Entid> = changes.into_iter().map(|i|*i).collect();
|
let changes: Vec<Entid> = changes.into_iter().map(|i|*i).collect();
|
||||||
let len = changes.len();
|
let len = changes.len();
|
||||||
ExternTxReport {
|
TransactionChange {
|
||||||
txid: *tx_id,
|
txid: *tx_id,
|
||||||
changes: changes.into_boxed_slice(),
|
changes: changes.into_boxed_slice(),
|
||||||
changes_len: len,
|
changes_len: len,
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let len = extern_reports.len();
|
let len = extern_reports.len();
|
||||||
let reports = ExternTxReportList {
|
let reports = TxChangeList {
|
||||||
reports: extern_reports.into_boxed_slice(),
|
reports: extern_reports.into_boxed_slice(),
|
||||||
len: len,
|
len: len,
|
||||||
};
|
};
|
||||||
|
@ -536,7 +574,7 @@ pub unsafe extern "C" fn store_entid_for_attribute(store: *mut Store, attr: *con
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn tx_report_list_entry_at(tx_report_list: *mut ExternTxReportList, index: c_int) -> *const ExternTxReport {
|
pub unsafe extern "C" fn tx_change_list_entry_at(tx_report_list: *mut TxChangeList, index: c_int) -> *const TransactionChange {
|
||||||
let tx_report_list = &*tx_report_list;
|
let tx_report_list = &*tx_report_list;
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
let report = Box::new(tx_report_list.reports[index].clone());
|
let report = Box::new(tx_report_list.reports[index].clone());
|
||||||
|
@ -544,7 +582,7 @@ pub unsafe extern "C" fn tx_report_list_entry_at(tx_report_list: *mut ExternTxRe
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn changelist_entry_at(tx_report: *mut ExternTxReport, index: c_int) -> Entid {
|
pub unsafe extern "C" fn changelist_entry_at(tx_report: *mut TransactionChange, index: c_int) -> Entid {
|
||||||
let tx_report = &*tx_report;
|
let tx_report = &*tx_report;
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
tx_report.changes[index].clone()
|
tx_report.changes[index].clone()
|
||||||
|
@ -633,8 +671,7 @@ pub unsafe extern "C" fn store_set_uuid_for_attribute_on_entid(store: *mut Store
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn destroy(obj: *mut c_void) {
|
pub unsafe extern "C" fn destroy(obj: *mut c_void) {
|
||||||
if !obj.is_null() {
|
if !obj.is_null() {
|
||||||
let obj_to_release = Box::from_raw(obj);
|
let _ = Box::from_raw(obj);
|
||||||
println!("object to release {:?}", obj_to_release);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,6 +687,8 @@ define_destructor!(query_builder_destroy, QueryBuilder);
|
||||||
|
|
||||||
define_destructor!(store_destroy, Store);
|
define_destructor!(store_destroy, Store);
|
||||||
|
|
||||||
|
define_destructor!(tx_report_destroy, TxReport);
|
||||||
|
|
||||||
define_destructor!(typed_value_destroy, TypedValue);
|
define_destructor!(typed_value_destroy, TypedValue);
|
||||||
|
|
||||||
define_destructor!(typed_value_list_destroy, Vec<TypedValue>);
|
define_destructor!(typed_value_list_destroy, Vec<TypedValue>);
|
||||||
|
|
|
@ -45,12 +45,19 @@ impl ConjoiningClauses {
|
||||||
use self::FnArg::*;
|
use self::FnArg::*;
|
||||||
match arg {
|
match arg {
|
||||||
FnArg::Variable(var) => {
|
FnArg::Variable(var) => {
|
||||||
|
match self.bound_value(&var) {
|
||||||
|
// The type is already known if it's a bound variable….
|
||||||
|
Some(TypedValue::Long(v)) => Ok(QueryValue::TypedValue(TypedValue::Long(v))),
|
||||||
|
Some(TypedValue::Double(v)) => Ok(QueryValue::TypedValue(TypedValue::Double(v))),
|
||||||
|
_ => {
|
||||||
self.constrain_var_to_numeric(var.clone());
|
self.constrain_var_to_numeric(var.clone());
|
||||||
self.column_bindings
|
self.column_bindings
|
||||||
.get(&var)
|
.get(&var)
|
||||||
.and_then(|cols| cols.first().map(|col| QueryValue::Column(col.clone())))
|
.and_then(|cols| cols.first().map(|col| QueryValue::Column(col.clone())))
|
||||||
.ok_or_else(|| Error::from_kind(ErrorKind::UnboundVariable(var.name())))
|
.ok_or_else(|| Error::from_kind(ErrorKind::UnboundVariable(var.name())))
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
// Can't be an entid.
|
// Can't be an entid.
|
||||||
EntidOrInteger(i) => Ok(QueryValue::TypedValue(TypedValue::Long(i))),
|
EntidOrInteger(i) => Ok(QueryValue::TypedValue(TypedValue::Long(i))),
|
||||||
IdentOrKeyword(_) |
|
IdentOrKeyword(_) |
|
||||||
|
@ -73,12 +80,18 @@ impl ConjoiningClauses {
|
||||||
use self::FnArg::*;
|
use self::FnArg::*;
|
||||||
match arg {
|
match arg {
|
||||||
FnArg::Variable(var) => {
|
FnArg::Variable(var) => {
|
||||||
|
match self.bound_value(&var) {
|
||||||
|
// The type is already known if it's a bound variable….
|
||||||
|
Some(TypedValue::Instant(v)) => Ok(QueryValue::TypedValue(TypedValue::Instant(v))),
|
||||||
|
_ => {
|
||||||
self.constrain_var_to_type(var.clone(), ValueType::Instant);
|
self.constrain_var_to_type(var.clone(), ValueType::Instant);
|
||||||
self.column_bindings
|
self.column_bindings
|
||||||
.get(&var)
|
.get(&var)
|
||||||
.and_then(|cols| cols.first().map(|col| QueryValue::Column(col.clone())))
|
.and_then(|cols| cols.first().map(|col| QueryValue::Column(col.clone())))
|
||||||
.ok_or_else(|| Error::from_kind(ErrorKind::UnboundVariable(var.name())))
|
.ok_or_else(|| Error::from_kind(ErrorKind::UnboundVariable(var.name())))
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
Constant(NonIntegerConstant::Instant(v)) => {
|
Constant(NonIntegerConstant::Instant(v)) => {
|
||||||
Ok(QueryValue::TypedValue(TypedValue::Instant(v)))
|
Ok(QueryValue::TypedValue(TypedValue::Instant(v)))
|
||||||
},
|
},
|
||||||
|
@ -144,11 +157,17 @@ impl ConjoiningClauses {
|
||||||
use self::FnArg::*;
|
use self::FnArg::*;
|
||||||
match arg {
|
match arg {
|
||||||
FnArg::Variable(var) => {
|
FnArg::Variable(var) => {
|
||||||
|
match self.bound_value(&var) {
|
||||||
|
// The type is already known if it's a bound variable….
|
||||||
|
Some(v) => Ok(QueryValue::TypedValue(v)),
|
||||||
|
None => {
|
||||||
self.column_bindings
|
self.column_bindings
|
||||||
.get(&var)
|
.get(&var)
|
||||||
.and_then(|cols| cols.first().map(|col| QueryValue::Column(col.clone())))
|
.and_then(|cols| cols.first().map(|col| QueryValue::Column(col.clone())))
|
||||||
.ok_or_else(|| Error::from_kind(ErrorKind::UnboundVariable(var.name())))
|
.ok_or_else(|| Error::from_kind(ErrorKind::UnboundVariable(var.name())))
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
EntidOrInteger(i) => Ok(QueryValue::PrimitiveLong(i)),
|
EntidOrInteger(i) => Ok(QueryValue::PrimitiveLong(i)),
|
||||||
IdentOrKeyword(_) => unimplemented!(), // TODO
|
IdentOrKeyword(_) => unimplemented!(), // TODO
|
||||||
Constant(NonIntegerConstant::Boolean(val)) => Ok(QueryValue::TypedValue(TypedValue::Boolean(val))),
|
Constant(NonIntegerConstant::Boolean(val)) => Ok(QueryValue::TypedValue(TypedValue::Boolean(val))),
|
||||||
|
|
|
@ -17,7 +17,10 @@ mod utils;
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
Attribute,
|
Attribute,
|
||||||
|
DateTime,
|
||||||
Schema,
|
Schema,
|
||||||
|
TypedValue,
|
||||||
|
Utc,
|
||||||
ValueType,
|
ValueType,
|
||||||
ValueTypeSet,
|
ValueTypeSet,
|
||||||
};
|
};
|
||||||
|
@ -32,11 +35,13 @@ use mentat_query_algebrizer::{
|
||||||
EmptyBecause,
|
EmptyBecause,
|
||||||
ErrorKind,
|
ErrorKind,
|
||||||
Known,
|
Known,
|
||||||
|
QueryInputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
use utils::{
|
use utils::{
|
||||||
add_attribute,
|
add_attribute,
|
||||||
alg,
|
alg,
|
||||||
|
alg_with_inputs,
|
||||||
associate_ident,
|
associate_ident,
|
||||||
bails,
|
bails,
|
||||||
};
|
};
|
||||||
|
@ -45,6 +50,7 @@ fn prepopulated_schema() -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "date"), 65);
|
associate_ident(&mut schema, NamespacedKeyword::new("foo", "date"), 65);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "double"), 66);
|
associate_ident(&mut schema, NamespacedKeyword::new("foo", "double"), 66);
|
||||||
|
associate_ident(&mut schema, NamespacedKeyword::new("foo", "long"), 67);
|
||||||
add_attribute(&mut schema, 65, Attribute {
|
add_attribute(&mut schema, 65, Attribute {
|
||||||
value_type: ValueType::Instant,
|
value_type: ValueType::Instant,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
@ -55,6 +61,11 @@ fn prepopulated_schema() -> Schema {
|
||||||
multival: false,
|
multival: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
add_attribute(&mut schema, 67, Attribute {
|
||||||
|
value_type: ValueType::Long,
|
||||||
|
multival: false,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,3 +127,60 @@ fn test_instant_predicates_require_instants() {
|
||||||
assert_eq!(cc.known_type(&Variable::from_valid_name("?t")).expect("?t is known"),
|
assert_eq!(cc.known_type(&Variable::from_valid_name("?t")).expect("?t is known"),
|
||||||
ValueType::Double);
|
ValueType::Double);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_instant_predicates_accepts_var() {
|
||||||
|
let schema = prepopulated_schema();
|
||||||
|
let known = Known::for_schema(&schema);
|
||||||
|
|
||||||
|
let instant_var = Variable::from_valid_name("?time");
|
||||||
|
let instant_value = TypedValue::Instant(DateTime::parse_from_rfc3339("2018-04-11T19:17:00.000Z")
|
||||||
|
.map(|t| t.with_timezone(&Utc))
|
||||||
|
.expect("expected valid date"));
|
||||||
|
|
||||||
|
let query = r#"[:find ?e
|
||||||
|
:in ?time
|
||||||
|
:where
|
||||||
|
[?e :foo/date ?t]
|
||||||
|
[(< ?t ?time)]]"#;
|
||||||
|
let cc = alg_with_inputs(known, query, QueryInputs::with_value_sequence(vec![(instant_var.clone(), instant_value.clone())]));
|
||||||
|
assert_eq!(cc.known_type(&instant_var).expect("?time is known"),
|
||||||
|
ValueType::Instant);
|
||||||
|
|
||||||
|
let query = r#"[:find ?e
|
||||||
|
:in ?time
|
||||||
|
:where
|
||||||
|
[?e :foo/date ?t]
|
||||||
|
[(> ?time, ?t)]]"#;
|
||||||
|
let cc = alg_with_inputs(known, query, QueryInputs::with_value_sequence(vec![(instant_var.clone(), instant_value.clone())]));
|
||||||
|
assert_eq!(cc.known_type(&instant_var).expect("?time is known"),
|
||||||
|
ValueType::Instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_numeric_predicates_accepts_var() {
|
||||||
|
let schema = prepopulated_schema();
|
||||||
|
let known = Known::for_schema(&schema);
|
||||||
|
|
||||||
|
let numeric_var = Variable::from_valid_name("?long");
|
||||||
|
let numeric_value = TypedValue::Long(1234567);
|
||||||
|
|
||||||
|
// You can't use a string for an inequality: this is a straight-up error.
|
||||||
|
let query = r#"[:find ?e
|
||||||
|
:in ?long
|
||||||
|
:where
|
||||||
|
[?e :foo/long ?t]
|
||||||
|
[(> ?t ?long)]]"#;
|
||||||
|
let cc = alg_with_inputs(known, query, QueryInputs::with_value_sequence(vec![(numeric_var.clone(), numeric_value.clone())]));
|
||||||
|
assert_eq!(cc.known_type(&numeric_var).expect("?long is known"),
|
||||||
|
ValueType::Long);
|
||||||
|
|
||||||
|
let query = r#"[:find ?e
|
||||||
|
:in ?long
|
||||||
|
:where
|
||||||
|
[?e :foo/long ?t]
|
||||||
|
[(> ?long, ?t)]]"#;
|
||||||
|
let cc = alg_with_inputs(known, query, QueryInputs::with_value_sequence(vec![(numeric_var.clone(), numeric_value.clone())]));
|
||||||
|
assert_eq!(cc.known_type(&numeric_var).expect("?long is known"),
|
||||||
|
ValueType::Long);
|
||||||
|
}
|
||||||
|
|
|
@ -98,3 +98,8 @@ pub fn alg(known: Known, input: &str) -> ConjoiningClauses {
|
||||||
let parsed = parse_find_string(input).expect("query input to have parsed");
|
let parsed = parse_find_string(input).expect("query input to have parsed");
|
||||||
algebrize(known, parsed).expect("algebrizing to have succeeded").cc
|
algebrize(known, parsed).expect("algebrizing to have succeeded").cc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn alg_with_inputs(known: Known, input: &str, inputs: QueryInputs) -> ConjoiningClauses {
|
||||||
|
let parsed = parse_find_string(input).expect("query input to have parsed");
|
||||||
|
algebrize_with_inputs(known, parsed, 0, inputs).expect("algebrizing to have succeeded").cc
|
||||||
|
}
|
||||||
|
|
593
sdks/swift/Mentat/Mentat.xcodeproj/project.pbxproj
Normal file
593
sdks/swift/Mentat/Mentat.xcodeproj/project.pbxproj
Normal file
|
@ -0,0 +1,593 @@
|
||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 50;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
7BDB96942077C299009D0651 /* Mentat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BDB968A2077C299009D0651 /* Mentat.framework */; };
|
||||||
|
7BDB96992077C299009D0651 /* MentatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96982077C299009D0651 /* MentatTests.swift */; };
|
||||||
|
7BDB969B2077C299009D0651 /* Mentat.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDB968D2077C299009D0651 /* Mentat.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
7BDB96AF2077C38E009D0651 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96A62077C38D009D0651 /* Query.swift */; };
|
||||||
|
7BDB96B02077C38E009D0651 /* Mentat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96A72077C38D009D0651 /* Mentat.swift */; };
|
||||||
|
7BDB96B12077C38E009D0651 /* store.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDB96A82077C38E009D0651 /* store.h */; };
|
||||||
|
7BDB96B22077C38E009D0651 /* RelResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96A92077C38E009D0651 /* RelResult.swift */; };
|
||||||
|
7BDB96B32077C38E009D0651 /* RustObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96AA2077C38E009D0651 /* RustObject.swift */; };
|
||||||
|
7BDB96B42077C38E009D0651 /* OptionalRustObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96AB2077C38E009D0651 /* OptionalRustObject.swift */; };
|
||||||
|
7BDB96B52077C38E009D0651 /* TupleResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96AC2077C38E009D0651 /* TupleResult.swift */; };
|
||||||
|
7BDB96B72077C38E009D0651 /* TypedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96AE2077C38E009D0651 /* TypedValue.swift */; };
|
||||||
|
7BDB96C22077CD98009D0651 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BDB96C12077CD98009D0651 /* libresolv.tbd */; };
|
||||||
|
7BDB96C62077D347009D0651 /* Date+Int64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96C52077D346009D0651 /* Date+Int64.swift */; };
|
||||||
|
7BDB96C9207B735A009D0651 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 7BDB96C8207B735A009D0651 /* fixtures */; };
|
||||||
|
7BDB96CC207B7684009D0651 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96CB207B7684009D0651 /* Errors.swift */; };
|
||||||
|
7BEB7D2C207D03DA000369AD /* TxReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BEB7D2B207D03DA000369AD /* TxReport.swift */; };
|
||||||
|
7BEB7D2D207F6B73000369AD /* libmentat_ffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BEB7D23207BE2AF000369AD /* libmentat_ffi.a */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
7BDB96952077C299009D0651 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 7BDB96812077C299009D0651 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 7BDB96892077C299009D0651;
|
||||||
|
remoteInfo = Mentat;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
7BDB968A2077C299009D0651 /* Mentat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mentat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
7BDB968D2077C299009D0651 /* Mentat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Mentat.h; sourceTree = "<group>"; };
|
||||||
|
7BDB968E2077C299009D0651 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
7BDB96932077C299009D0651 /* MentatTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MentatTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
7BDB96982077C299009D0651 /* MentatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentatTests.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB969A2077C299009D0651 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
7BDB96A62077C38D009D0651 /* Query.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Query.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB96A72077C38D009D0651 /* Mentat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mentat.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB96A82077C38E009D0651 /* store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = store.h; sourceTree = "<group>"; };
|
||||||
|
7BDB96A92077C38E009D0651 /* RelResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelResult.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB96AA2077C38E009D0651 /* RustObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RustObject.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB96AB2077C38E009D0651 /* OptionalRustObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionalRustObject.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB96AC2077C38E009D0651 /* TupleResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TupleResult.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB96AE2077C38E009D0651 /* TypedValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypedValue.swift; sourceTree = "<group>"; };
|
||||||
|
7BDB96BF2077CD7A009D0651 /* libmentat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmentat.a; path = ../../../target/universal/release/libmentat.a; sourceTree = "<group>"; };
|
||||||
|
7BDB96C12077CD98009D0651 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
|
||||||
|
7BDB96C32077D090009D0651 /* module.map */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.map; sourceTree = "<group>"; };
|
||||||
|
7BDB96C52077D346009D0651 /* Date+Int64.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Int64.swift"; sourceTree = "<group>"; };
|
||||||
|
7BDB96C8207B735A009D0651 /* fixtures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = fixtures; path = ../../../../fixtures; sourceTree = "<group>"; };
|
||||||
|
7BDB96CB207B7684009D0651 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
|
||||||
|
7BEB7D21207BDDEF000369AD /* libtoodle.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtoodle.a; path = ../../../target/universal/release/libtoodle.a; sourceTree = "<group>"; };
|
||||||
|
7BEB7D23207BE2AF000369AD /* libmentat_ffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmentat_ffi.a; path = ../../../target/universal/release/libmentat_ffi.a; sourceTree = "<group>"; };
|
||||||
|
7BEB7D2B207D03DA000369AD /* TxReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TxReport.swift; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
7BDB96862077C299009D0651 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7BDB96C22077CD98009D0651 /* libresolv.tbd in Frameworks */,
|
||||||
|
7BEB7D2D207F6B73000369AD /* libmentat_ffi.a in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
7BDB96902077C299009D0651 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7BDB96942077C299009D0651 /* Mentat.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
7BDB96802077C299009D0651 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB968C2077C299009D0651 /* Mentat */,
|
||||||
|
7BDB96972077C299009D0651 /* MentatTests */,
|
||||||
|
7BDB968B2077C299009D0651 /* Products */,
|
||||||
|
7BDB96BE2077CD7A009D0651 /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB968B2077C299009D0651 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB968A2077C299009D0651 /* Mentat.framework */,
|
||||||
|
7BDB96932077C299009D0651 /* MentatTests.xctest */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB968C2077C299009D0651 /* Mentat */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB96CA207B7672009D0651 /* Errors */,
|
||||||
|
7BDB96C42077D346009D0651 /* Extensions */,
|
||||||
|
7BDB96BA2077C42B009D0651 /* Core */,
|
||||||
|
7BDB96A42077C301009D0651 /* Query */,
|
||||||
|
7BDB96B92077C403009D0651 /* Rust */,
|
||||||
|
7BDB96A82077C38E009D0651 /* store.h */,
|
||||||
|
7BDB96A72077C38D009D0651 /* Mentat.swift */,
|
||||||
|
7BEB7D26207BE5BB000369AD /* Transact */,
|
||||||
|
7BDB968D2077C299009D0651 /* Mentat.h */,
|
||||||
|
7BDB968E2077C299009D0651 /* Info.plist */,
|
||||||
|
7BDB96C32077D090009D0651 /* module.map */,
|
||||||
|
);
|
||||||
|
path = Mentat;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB96972077C299009D0651 /* MentatTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB96C8207B735A009D0651 /* fixtures */,
|
||||||
|
7BDB96982077C299009D0651 /* MentatTests.swift */,
|
||||||
|
7BDB969A2077C299009D0651 /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = MentatTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB96A42077C301009D0651 /* Query */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB96A62077C38D009D0651 /* Query.swift */,
|
||||||
|
7BDB96A92077C38E009D0651 /* RelResult.swift */,
|
||||||
|
7BDB96AC2077C38E009D0651 /* TupleResult.swift */,
|
||||||
|
);
|
||||||
|
path = Query;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB96B92077C403009D0651 /* Rust */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB96AB2077C38E009D0651 /* OptionalRustObject.swift */,
|
||||||
|
7BDB96AA2077C38E009D0651 /* RustObject.swift */,
|
||||||
|
);
|
||||||
|
path = Rust;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB96BA2077C42B009D0651 /* Core */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB96AE2077C38E009D0651 /* TypedValue.swift */,
|
||||||
|
);
|
||||||
|
path = Core;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB96BE2077CD7A009D0651 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BEB7D23207BE2AF000369AD /* libmentat_ffi.a */,
|
||||||
|
7BEB7D21207BDDEF000369AD /* libtoodle.a */,
|
||||||
|
7BDB96C12077CD98009D0651 /* libresolv.tbd */,
|
||||||
|
7BDB96BF2077CD7A009D0651 /* libmentat.a */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB96C42077D346009D0651 /* Extensions */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB96C52077D346009D0651 /* Date+Int64.swift */,
|
||||||
|
);
|
||||||
|
path = Extensions;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BDB96CA207B7672009D0651 /* Errors */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BDB96CB207B7684009D0651 /* Errors.swift */,
|
||||||
|
);
|
||||||
|
path = Errors;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7BEB7D26207BE5BB000369AD /* Transact */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7BEB7D2B207D03DA000369AD /* TxReport.swift */,
|
||||||
|
);
|
||||||
|
path = Transact;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
|
7BDB96872077C299009D0651 /* Headers */ = {
|
||||||
|
isa = PBXHeadersBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7BDB96B12077C38E009D0651 /* store.h in Headers */,
|
||||||
|
7BDB969B2077C299009D0651 /* Mentat.h in Headers */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXHeadersBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
7BDB96892077C299009D0651 /* Mentat */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 7BDB969E2077C299009D0651 /* Build configuration list for PBXNativeTarget "Mentat" */;
|
||||||
|
buildPhases = (
|
||||||
|
7BDB96852077C299009D0651 /* Sources */,
|
||||||
|
7BDB96862077C299009D0651 /* Frameworks */,
|
||||||
|
7BDB96872077C299009D0651 /* Headers */,
|
||||||
|
7BDB96882077C299009D0651 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = Mentat;
|
||||||
|
productName = Mentat;
|
||||||
|
productReference = 7BDB968A2077C299009D0651 /* Mentat.framework */;
|
||||||
|
productType = "com.apple.product-type.framework";
|
||||||
|
};
|
||||||
|
7BDB96922077C299009D0651 /* MentatTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 7BDB96A12077C299009D0651 /* Build configuration list for PBXNativeTarget "MentatTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
7BDB968F2077C299009D0651 /* Sources */,
|
||||||
|
7BDB96902077C299009D0651 /* Frameworks */,
|
||||||
|
7BDB96912077C299009D0651 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
7BDB96962077C299009D0651 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = MentatTests;
|
||||||
|
productName = MentatTests;
|
||||||
|
productReference = 7BDB96932077C299009D0651 /* MentatTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
7BDB96812077C299009D0651 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastSwiftUpdateCheck = 0930;
|
||||||
|
LastUpgradeCheck = 0930;
|
||||||
|
ORGANIZATIONNAME = Mozilla;
|
||||||
|
TargetAttributes = {
|
||||||
|
7BDB96892077C299009D0651 = {
|
||||||
|
CreatedOnToolsVersion = 9.3;
|
||||||
|
LastSwiftMigration = 0930;
|
||||||
|
};
|
||||||
|
7BDB96922077C299009D0651 = {
|
||||||
|
CreatedOnToolsVersion = 9.3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 7BDB96842077C299009D0651 /* Build configuration list for PBXProject "Mentat" */;
|
||||||
|
compatibilityVersion = "Xcode 9.3";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
);
|
||||||
|
mainGroup = 7BDB96802077C299009D0651;
|
||||||
|
productRefGroup = 7BDB968B2077C299009D0651 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
7BDB96892077C299009D0651 /* Mentat */,
|
||||||
|
7BDB96922077C299009D0651 /* MentatTests */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
7BDB96882077C299009D0651 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
7BDB96912077C299009D0651 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7BDB96C9207B735A009D0651 /* fixtures in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
7BDB96852077C299009D0651 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7BDB96B32077C38E009D0651 /* RustObject.swift in Sources */,
|
||||||
|
7BDB96C62077D347009D0651 /* Date+Int64.swift in Sources */,
|
||||||
|
7BEB7D2C207D03DA000369AD /* TxReport.swift in Sources */,
|
||||||
|
7BDB96B42077C38E009D0651 /* OptionalRustObject.swift in Sources */,
|
||||||
|
7BDB96B22077C38E009D0651 /* RelResult.swift in Sources */,
|
||||||
|
7BDB96AF2077C38E009D0651 /* Query.swift in Sources */,
|
||||||
|
7BDB96CC207B7684009D0651 /* Errors.swift in Sources */,
|
||||||
|
7BDB96B02077C38E009D0651 /* Mentat.swift in Sources */,
|
||||||
|
7BDB96B72077C38E009D0651 /* TypedValue.swift in Sources */,
|
||||||
|
7BDB96B52077C38E009D0651 /* TupleResult.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
7BDB968F2077C299009D0651 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
7BDB96992077C299009D0651 /* MentatTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
7BDB96962077C299009D0651 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 7BDB96892077C299009D0651 /* Mentat */;
|
||||||
|
targetProxy = 7BDB96952077C299009D0651 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
7BDB969C2077C299009D0651 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.3;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Mentat";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
7BDB969D2077C299009D0651 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 11.3;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Mentat";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
7BDB969F2077C299009D0651 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = 8BHJ767F4Y;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = Mentat/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../../../target/universal/release";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.Mentat;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Mentat";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
7BDB96A02077C299009D0651 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DEVELOPMENT_TEAM = 8BHJ767F4Y;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
ENABLE_TESTABILITY = NO;
|
||||||
|
INFOPLIST_FILE = Mentat/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../../../target/universal/release";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.Mentat;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Mentat";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
7BDB96A22077C299009D0651 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 8BHJ767F4Y;
|
||||||
|
INFOPLIST_FILE = MentatTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.MentatTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
7BDB96A32077C299009D0651 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 8BHJ767F4Y;
|
||||||
|
INFOPLIST_FILE = MentatTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@loader_path/Frameworks",
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.MentatTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
7BDB96842077C299009D0651 /* Build configuration list for PBXProject "Mentat" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
7BDB969C2077C299009D0651 /* Debug */,
|
||||||
|
7BDB969D2077C299009D0651 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
7BDB969E2077C299009D0651 /* Build configuration list for PBXNativeTarget "Mentat" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
7BDB969F2077C299009D0651 /* Debug */,
|
||||||
|
7BDB96A02077C299009D0651 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
7BDB96A12077C299009D0651 /* Build configuration list for PBXNativeTarget "MentatTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
7BDB96A22077C299009D0651 /* Debug */,
|
||||||
|
7BDB96A32077C299009D0651 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 7BDB96812077C299009D0651 /* Project object */;
|
||||||
|
}
|
7
sdks/swift/Mentat/Mentat.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
sdks/swift/Mentat/Mentat.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:Mentat.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0930"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96922077C299009D0651"
|
||||||
|
BuildableName = "MentatTests.xctest"
|
||||||
|
BlueprintName = "MentatTests"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "0930"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96922077C299009D0651"
|
||||||
|
BuildableName = "MentatTests.xctest"
|
||||||
|
BlueprintName = "MentatTests"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "7BDB96892077C299009D0651"
|
||||||
|
BuildableName = "Mentat.framework"
|
||||||
|
BlueprintName = "Mentat"
|
||||||
|
ReferencedContainer = "container:Mentat.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>SchemeUserState</key>
|
||||||
|
<dict>
|
||||||
|
<key>Mentat Debug.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<key>Mentat.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict>
|
||||||
|
<key>7BDB96892077C299009D0651</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>7BDB96922077C299009D0651</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
75
sdks/swift/Mentat/Mentat/Core/TypedValue.swift
Normal file
75
sdks/swift/Mentat/Mentat/Core/TypedValue.swift
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
class TypedValue: OptionalRustObject {
|
||||||
|
|
||||||
|
var valueType: ValueType {
|
||||||
|
return typed_value_value_type(self.raw!)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asLong() -> Int64 {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
return typed_value_as_long(self.raw!)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asEntid() -> Int64 {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
return typed_value_as_entid(self.raw!)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asKeyword() -> String {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
return String(cString: typed_value_as_kw(self.raw!))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asBool() -> Bool {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
let v = typed_value_as_boolean(self.raw!)
|
||||||
|
return v > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func asDouble() -> Double {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
return typed_value_as_double(self.raw!)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asDate() -> Date {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
let timestamp = typed_value_as_timestamp(self.raw!)
|
||||||
|
return Date(timeIntervalSince1970: TimeInterval(timestamp))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asString() -> String {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
return String(cString: typed_value_as_string(self.raw!))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asUUID() -> UUID? {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
return UUID(uuidString: String(cString: typed_value_as_uuid(self.raw!)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
typed_value_destroy(pointer)
|
||||||
|
}
|
||||||
|
}
|
20
sdks/swift/Mentat/Mentat/Errors/Errors.swift
Normal file
20
sdks/swift/Mentat/Mentat/Errors/Errors.swift
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum QueryError: Error {
|
||||||
|
case builderConsumed
|
||||||
|
case invalidKeyword(message: String)
|
||||||
|
case executionFailed(message: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum QueryResultError: Error {
|
||||||
|
case resultsConsumed
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct MentatError: Error {
|
||||||
|
let message: String
|
||||||
|
}
|
11
sdks/swift/Mentat/Mentat/Extensions/Date+Int64.swift
Normal file
11
sdks/swift/Mentat/Mentat/Extensions/Date+Int64.swift
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
///* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// * License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Date {
|
||||||
|
func toMicroseconds() -> Int64 {
|
||||||
|
return Int64(self.timeIntervalSince1970 * 1_000_000)
|
||||||
|
}
|
||||||
|
}
|
24
sdks/swift/Mentat/Mentat/Info.plist
Normal file
24
sdks/swift/Mentat/Mentat/Info.plist
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
14
sdks/swift/Mentat/Mentat/Mentat.h
Normal file
14
sdks/swift/Mentat/Mentat/Mentat.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
//! Project version number for Mentat.
|
||||||
|
FOUNDATION_EXPORT double MentatVersionNumber;
|
||||||
|
|
||||||
|
//! Project version string for Mentat.
|
||||||
|
FOUNDATION_EXPORT const unsigned char MentatVersionString[];
|
||||||
|
|
||||||
|
// In this header, you should import all the public headers of your framework using statements like #import <Mentat/PublicHeader.h>
|
||||||
|
|
188
sdks/swift/Mentat/Mentat/Mentat.swift
Normal file
188
sdks/swift/Mentat/Mentat/Mentat.swift
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
protocol Observing {
|
||||||
|
// define functions for store observation
|
||||||
|
func transactionDidOccur(key: String, reports: [TransactionChange])
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol Observable {
|
||||||
|
func register(key: String, observer: Observing, attributes: [String])
|
||||||
|
func unregister(key: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mentat: RustObject {
|
||||||
|
fileprivate static var observers = [String: Observing]()
|
||||||
|
|
||||||
|
required override init(raw: OpaquePointer) {
|
||||||
|
super.init(raw: raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(storeURI: String = "") {
|
||||||
|
self.init(raw: store_open(storeURI))
|
||||||
|
}
|
||||||
|
|
||||||
|
func transact(transaction: String) throws -> TxReport {
|
||||||
|
let result = store_transact(self.raw, transaction).pointee
|
||||||
|
guard let success = result.ok else {
|
||||||
|
if let error = result.err {
|
||||||
|
throw MentatError(message: String(cString: error))
|
||||||
|
}
|
||||||
|
throw MentatError(message: "Unspecified Error")
|
||||||
|
}
|
||||||
|
return TxReport(raw: success)
|
||||||
|
}
|
||||||
|
|
||||||
|
func entidForAttribute(attribute: String) -> Int64 {
|
||||||
|
return Int64(store_entid_for_attribute(self.raw, attribute))
|
||||||
|
}
|
||||||
|
|
||||||
|
func sync_now() -> Bool {
|
||||||
|
let err = store_sync(self.raw, "00000000-0000-0000-0000-000000000117", "http://mentat.dev.lcip.org/mentatsync/0.1")
|
||||||
|
if let error = err.pointee.err {
|
||||||
|
let str = String(cString: error)
|
||||||
|
print("Sync error \(str)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func query(query: String) -> Query {
|
||||||
|
return Query(raw: store_query(self.raw, query))
|
||||||
|
}
|
||||||
|
|
||||||
|
func value(forAttribute attribute: String, ofEntity entid: Int64) -> TypedValue? {
|
||||||
|
let result = store_value_for_attribute(self.raw, entid, attribute).pointee
|
||||||
|
guard let success = result.ok else {
|
||||||
|
if let error = result.err {
|
||||||
|
let str = String(cString: error)
|
||||||
|
print("Error: \(str)")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TypedValue(raw: success)
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(date value: Date, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_timestamp_for_attribute_on_entid(self.intoRaw(), entid, attribute, value.toMicroseconds())
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(long value: Int64, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_long_for_attribute_on_entid(self.intoRaw(), entid, attribute, value)
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(reference value: Int64, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_entid_for_attribute_on_entid(self.intoRaw(), entid, attribute, value)
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setKeywordReference(value: String, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_kw_ref_for_attribute_on_entid(self.intoRaw(), entid, attribute, value)
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(boolean value: Bool, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_boolean_for_attribute_on_entid(self.intoRaw(), entid, attribute, value ? 1 : 0)
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(double value: Double, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_double_for_attribute_on_entid(self.intoRaw(), entid, attribute, value)
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(string value: String, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_string_for_attribute_on_entid(self.intoRaw(), entid, attribute, value)
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(uuid value: UUID, forAttribute attribute: String, onEntity entid: Int64) throws {
|
||||||
|
let result = store_set_uuid_for_attribute_on_entid(self.intoRaw(), entid, attribute, value.uuidString)
|
||||||
|
guard let err = result.pointee.err else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw QueryError.executionFailed(message: String(cString: err))
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
store_destroy(pointer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Mentat: Observable {
|
||||||
|
func register(key: String, observer: Observing, attributes: [String]) {
|
||||||
|
let attrEntIds = attributes.map({ (kw) -> Int64 in
|
||||||
|
let entid = Int64(self.entidForAttribute(attribute: kw));
|
||||||
|
return entid
|
||||||
|
})
|
||||||
|
|
||||||
|
let ptr = UnsafeMutablePointer<Int64>.allocate(capacity: attrEntIds.count)
|
||||||
|
let entidPointer = UnsafeMutableBufferPointer(start: ptr, count: attrEntIds.count)
|
||||||
|
var _ = entidPointer.initialize(from: attrEntIds)
|
||||||
|
|
||||||
|
guard let firstElement = entidPointer.baseAddress else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Mentat.observers[key] = observer
|
||||||
|
store_register_observer(self.raw, key, firstElement, Int64(attributes.count), transactionObserverCallback)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func unregister(key: String) {
|
||||||
|
store_unregister_observer(self.raw, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func transactionObserverCallback(key: UnsafePointer<CChar>, reports: UnsafePointer<TxChangeList>) {
|
||||||
|
// needs to be done in the same thread as the calling thread otherwise the TxReportList might be released before
|
||||||
|
// we can reference it.
|
||||||
|
let key = String(cString: key)
|
||||||
|
guard let observer = Mentat.observers[key] else { return }
|
||||||
|
|
||||||
|
// let len = Int(reports.pointee.len)
|
||||||
|
// var txReports = [TxReport]()
|
||||||
|
// for i in 0..<len {
|
||||||
|
// guard let report = tx_report_list_entry_at(reports, i)?.pointee else { continue }
|
||||||
|
// txReports.append(TxReport(raw: report))
|
||||||
|
// }
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
observer.transactionDidOccur(key: key, reports: [TransactionChange]())
|
||||||
|
}
|
||||||
|
}
|
218
sdks/swift/Mentat/Mentat/Query/Query.swift
Normal file
218
sdks/swift/Mentat/Mentat/Query/Query.swift
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
class Query: OptionalRustObject {
|
||||||
|
|
||||||
|
func bind(varName: String, toLong value: Int64) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_long(r, varName, value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toReference value: Int64) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_ref(r, varName, value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toReference value: String) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_ref_kw(r, varName, value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toKeyword value: String) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_kw(r, varName, value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toBoolean value: Bool) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_boolean(r, varName, value ? 1 : 0)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toDouble value: Double) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_double(r, varName, value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toDate value: Date) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_timestamp(r, varName, value.toMicroseconds())
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toString value: String) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_string(r, varName, value)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(varName: String, toUuid value: UUID) throws -> Query {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
query_builder_bind_uuid(r, varName, value.uuidString)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeMap(map: @escaping (TupleResult?, QueryError?) -> Void) throws {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
let result = query_builder_execute(r)
|
||||||
|
self.raw = nil
|
||||||
|
|
||||||
|
if let err = result.pointee.err {
|
||||||
|
let message = String(cString: err)
|
||||||
|
map(nil, QueryError.executionFailed(message: message))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let rowsPtr = result.pointee.ok else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let rows = RelResult(raw: rowsPtr)
|
||||||
|
for row in rows {
|
||||||
|
map(row, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func execute(callback: @escaping (RelResult?, QueryError?) -> Void) throws {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
let result = query_builder_execute(r)
|
||||||
|
self.raw = nil
|
||||||
|
|
||||||
|
if let err = result.pointee.err {
|
||||||
|
let message = String(cString: err)
|
||||||
|
callback(nil, QueryError.executionFailed(message: message))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let results = result.pointee.ok else {
|
||||||
|
callback(nil, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback(RelResult(raw: results), nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeScalar(callback: @escaping (TypedValue?, QueryError?) -> Void) throws {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
let result = query_builder_execute_scalar(r)
|
||||||
|
self.raw = nil
|
||||||
|
|
||||||
|
if let err = result.pointee.err {
|
||||||
|
let message = String(cString: err)
|
||||||
|
callback(nil, QueryError.executionFailed(message: message))
|
||||||
|
}
|
||||||
|
guard let results = result.pointee.ok else {
|
||||||
|
callback(nil, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback(TypedValue(raw: OpaquePointer(results)), nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeColl(callback: @escaping (ColResult?, QueryError?) -> Void) throws {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
let result = query_builder_execute_coll(r)
|
||||||
|
self.raw = nil
|
||||||
|
|
||||||
|
if let err = result.pointee.err {
|
||||||
|
let message = String(cString: err)
|
||||||
|
callback(nil, QueryError.executionFailed(message: message))
|
||||||
|
}
|
||||||
|
guard let results = result.pointee.ok else {
|
||||||
|
callback(nil, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback(ColResult(raw: results), nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeCollMap(map: @escaping (TypedValue?, QueryError?) -> Void) throws {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
let result = query_builder_execute(r)
|
||||||
|
self.raw = nil
|
||||||
|
|
||||||
|
if let err = result.pointee.err {
|
||||||
|
let message = String(cString: err)
|
||||||
|
map(nil, QueryError.executionFailed(message: message))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let cols = result.pointee.ok else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let rowList = ColResult(raw: cols)
|
||||||
|
for row in rowList {
|
||||||
|
map(row, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeTuple(callback: @escaping (TupleResult?, QueryError?) -> Void) throws {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryError.builderConsumed
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
let result = query_builder_execute_tuple(r)
|
||||||
|
self.raw = nil
|
||||||
|
|
||||||
|
if let err = result.pointee.err {
|
||||||
|
let message = String(cString: err)
|
||||||
|
callback(nil, QueryError.executionFailed(message: message))
|
||||||
|
}
|
||||||
|
guard let results = result.pointee.ok else {
|
||||||
|
callback(nil, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback(TupleResult(raw: OpaquePointer(results)), nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
query_builder_destroy(pointer)
|
||||||
|
}
|
||||||
|
}
|
58
sdks/swift/Mentat/Mentat/Query/RelResult.swift
Normal file
58
sdks/swift/Mentat/Mentat/Query/RelResult.swift
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
class RelResult: OptionalRustObject {
|
||||||
|
private func getRaw() throws -> OpaquePointer {
|
||||||
|
guard let r = self.raw else {
|
||||||
|
throw QueryResultError.resultsConsumed
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func row(index: Int32) throws -> TupleResult? {
|
||||||
|
guard let row = row_at_index(try self.getRaw(), index) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TupleResult(raw: row)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
destroy(UnsafeMutableRawPointer(pointer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RelResultIterator: OptionalRustObject, IteratorProtocol {
|
||||||
|
typealias Element = TupleResult
|
||||||
|
|
||||||
|
init(iter: OpaquePointer?) {
|
||||||
|
super.init(raw: iter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func next() -> Element? {
|
||||||
|
guard let iter = self.raw,
|
||||||
|
let rowPtr = rows_iter_next(iter) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TupleResult(raw: rowPtr)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
typed_value_result_set_iter_destroy(pointer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RelResult: Sequence {
|
||||||
|
func makeIterator() -> RelResultIterator {
|
||||||
|
do {
|
||||||
|
let rowIter = rows_iter(try self.getRaw())
|
||||||
|
self.raw = nil
|
||||||
|
return RelResultIterator(iter: rowIter)
|
||||||
|
} catch {
|
||||||
|
return RelResultIterator(iter: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
sdks/swift/Mentat/Mentat/Query/TupleResult.swift
Normal file
85
sdks/swift/Mentat/Mentat/Query/TupleResult.swift
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
class TupleResult: OptionalRustObject {
|
||||||
|
|
||||||
|
func get(index: Int) -> TypedValue {
|
||||||
|
return TypedValue(raw: value_at_index(self.raw!, Int32(index)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asLong(index: Int) -> Int64 {
|
||||||
|
return value_at_index_as_long(self.raw!, Int32(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asEntid(index: Int) -> Int64 {
|
||||||
|
return value_at_index_as_entid(self.raw!, Int32(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asKeyword(index: Int) -> String {
|
||||||
|
return String(cString: value_at_index_as_kw(self.raw!, Int32(index)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asBool(index: Int) -> Bool {
|
||||||
|
return value_at_index_as_boolean(self.raw!, Int32(index)) == 0 ? false : true
|
||||||
|
}
|
||||||
|
|
||||||
|
func asDouble(index: Int) -> Double {
|
||||||
|
return value_at_index_as_double(self.raw!, Int32(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asDate(index: Int) -> Date {
|
||||||
|
return Date(timeIntervalSince1970: TimeInterval(value_at_index_as_timestamp(self.raw!, Int32(index))))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asString(index: Int) -> String {
|
||||||
|
return String(cString: value_at_index_as_string(self.raw!, Int32(index)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asUUID(index: Int) -> UUID? {
|
||||||
|
return UUID(uuidString: String(cString: value_at_index_as_uuid(self.raw!, Int32(index))))
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
typed_value_list_destroy(pointer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColResult: TupleResult {
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColResultIterator: OptionalRustObject, IteratorProtocol {
|
||||||
|
typealias Element = TypedValue
|
||||||
|
|
||||||
|
init(iter: OpaquePointer?) {
|
||||||
|
super.init(raw: iter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func next() -> Element? {
|
||||||
|
guard let iter = self.raw,
|
||||||
|
let rowPtr = values_iter_next(iter) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return TypedValue(raw: rowPtr)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
typed_value_list_iter_destroy(pointer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ColResult: Sequence {
|
||||||
|
func makeIterator() -> ColResultIterator {
|
||||||
|
defer {
|
||||||
|
self.raw = nil
|
||||||
|
}
|
||||||
|
guard let raw = self.raw else {
|
||||||
|
return ColResultIterator(iter: nil)
|
||||||
|
}
|
||||||
|
let rowIter = values_iter(raw)
|
||||||
|
return ColResultIterator(iter: rowIter)
|
||||||
|
}
|
||||||
|
}
|
35
sdks/swift/Mentat/Mentat/Rust/OptionalRustObject.swift
Normal file
35
sdks/swift/Mentat/Mentat/Rust/OptionalRustObject.swift
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
class OptionalRustObject: Destroyable {
|
||||||
|
var raw: OpaquePointer?
|
||||||
|
lazy var uniqueId: ObjectIdentifier = {
|
||||||
|
ObjectIdentifier(self)
|
||||||
|
}()
|
||||||
|
|
||||||
|
init(raw: UnsafeMutableRawPointer) {
|
||||||
|
self.raw = OpaquePointer(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(raw: OpaquePointer?) {
|
||||||
|
self.raw = raw
|
||||||
|
}
|
||||||
|
|
||||||
|
func intoRaw() -> OpaquePointer? {
|
||||||
|
return self.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
guard let raw = self.raw else { return }
|
||||||
|
self.cleanup(pointer: raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanup(pointer: OpaquePointer) {
|
||||||
|
fatalError("\(cleanup) is not implemented.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
45
sdks/swift/Mentat/Mentat/Rust/RustObject.swift
Normal file
45
sdks/swift/Mentat/Mentat/Rust/RustObject.swift
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
protocol Destroyable {
|
||||||
|
func cleanup(pointer: OpaquePointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RustObject: Destroyable {
|
||||||
|
var raw: OpaquePointer
|
||||||
|
|
||||||
|
lazy var uniqueId: ObjectIdentifier = {
|
||||||
|
ObjectIdentifier(self)
|
||||||
|
}()
|
||||||
|
|
||||||
|
init(raw: OpaquePointer) {
|
||||||
|
self.raw = raw
|
||||||
|
}
|
||||||
|
|
||||||
|
init(raw: UnsafeMutableRawPointer) {
|
||||||
|
self.raw = OpaquePointer(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
init?(raw: OpaquePointer?) {
|
||||||
|
guard let r = raw else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
self.raw = r
|
||||||
|
}
|
||||||
|
|
||||||
|
func intoRaw() -> OpaquePointer {
|
||||||
|
return self.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.cleanup(pointer: self.raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanup(pointer: OpaquePointer) {
|
||||||
|
fatalError("\(cleanup) is not implemented.")
|
||||||
|
}
|
||||||
|
}
|
30
sdks/swift/Mentat/Mentat/Transact/TxReport.swift
Normal file
30
sdks/swift/Mentat/Mentat/Transact/TxReport.swift
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
import Mentatlib
|
||||||
|
|
||||||
|
class TxReport: RustObject {
|
||||||
|
|
||||||
|
public var txId: Int64 {
|
||||||
|
return tx_report_get_entid(self.raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
public var txInstant: Date {
|
||||||
|
return Date(timeIntervalSince1970: TimeInterval(tx_report_get_tx_instant(self.raw)))
|
||||||
|
}
|
||||||
|
|
||||||
|
public func entidForTmpId(tmpId: String) -> Int64? {
|
||||||
|
guard let entidPtr = tx_report_entity_for_temp_id(self.raw, tmpId) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return entidPtr.pointee
|
||||||
|
}
|
||||||
|
|
||||||
|
override func cleanup(pointer: OpaquePointer) {
|
||||||
|
tx_report_destroy(pointer)
|
||||||
|
}
|
||||||
|
}
|
4
sdks/swift/Mentat/Mentat/module.map
Normal file
4
sdks/swift/Mentat/Mentat/module.map
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module Mentatlib [system][extern_c] {
|
||||||
|
header "store.h"
|
||||||
|
export *
|
||||||
|
}
|
151
sdks/swift/Mentat/Mentat/store.h
Normal file
151
sdks/swift/Mentat/Mentat/store.h
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef store_h
|
||||||
|
#define store_h
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Foundation/NSObjCRuntime.h>
|
||||||
|
|
||||||
|
struct TransactionChange {
|
||||||
|
int64_t txid;
|
||||||
|
int64_t*_Nonnull* _Nonnull changes;
|
||||||
|
uint64_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TxChangeList {
|
||||||
|
struct TransactionChange*_Nonnull* _Nonnull reports;
|
||||||
|
uint64_t len;
|
||||||
|
};
|
||||||
|
typedef struct TxChangeList TxChangeList;
|
||||||
|
|
||||||
|
struct Result {
|
||||||
|
void* _Nullable ok;
|
||||||
|
char* _Nullable err;
|
||||||
|
};
|
||||||
|
typedef struct Result Result;
|
||||||
|
|
||||||
|
struct Option {
|
||||||
|
void* _Nullable value;
|
||||||
|
};
|
||||||
|
typedef struct Option Option;
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, ValueType) {
|
||||||
|
ValueTypeRef = 1,
|
||||||
|
ValueTypeBoolean,
|
||||||
|
ValueTypeInstant,
|
||||||
|
ValueTypeLong,
|
||||||
|
ValueTypeDouble,
|
||||||
|
ValueTypeString,
|
||||||
|
ValueTypeKeyword,
|
||||||
|
ValueTypeUuid
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Query;
|
||||||
|
struct QueryResultRow;
|
||||||
|
struct QueryResultRows;
|
||||||
|
struct QueryRowsIterator;
|
||||||
|
struct QueryRowIterator;
|
||||||
|
struct Store;
|
||||||
|
struct TxReport;
|
||||||
|
struct TypedValue;
|
||||||
|
|
||||||
|
// Store
|
||||||
|
struct Store*_Nonnull store_open(const char*_Nonnull uri);
|
||||||
|
|
||||||
|
void destroy(void* _Nullable obj);
|
||||||
|
void query_builder_destroy(struct Query* _Nullable obj);
|
||||||
|
void store_destroy(struct Store* _Nonnull obj);
|
||||||
|
void tx_report_destroy(struct TxReport* _Nonnull obj);
|
||||||
|
void typed_value_destroy(struct TypedValue* _Nullable obj);
|
||||||
|
void typed_value_list_destroy(struct QueryResultRow* _Nullable obj);
|
||||||
|
void typed_value_list_iter_destroy(struct QueryRowIterator* _Nullable obj);
|
||||||
|
void typed_value_result_set_destroy(struct QueryResultRows* _Nullable obj);
|
||||||
|
void typed_value_result_set_iter_destroy(struct QueryRowsIterator* _Nullable obj);
|
||||||
|
|
||||||
|
// transact
|
||||||
|
struct Result*_Nonnull store_transact(struct Store*_Nonnull store, const char* _Nonnull transaction);
|
||||||
|
const int64_t* _Nullable tx_report_entity_for_temp_id(const struct TxReport* _Nonnull report, const char* _Nonnull tempid);
|
||||||
|
int64_t tx_report_get_entid(const struct TxReport* _Nonnull report);
|
||||||
|
int64_t tx_report_get_tx_instant(const struct TxReport* _Nonnull report);
|
||||||
|
|
||||||
|
// Sync
|
||||||
|
struct Result*_Nonnull store_sync(struct Store*_Nonnull store, const char* _Nonnull user_uuid, const char* _Nonnull server_uri);
|
||||||
|
|
||||||
|
// Observers
|
||||||
|
void store_register_observer(struct Store*_Nonnull store, const char* _Nonnull key, const int64_t* _Nonnull attributes, const int64_t len, void (*_Nonnull callback_fn)(const char* _Nonnull key, const struct TxChangeList* _Nonnull reports));
|
||||||
|
void store_unregister_observer(struct Store*_Nonnull store, const char* _Nonnull key);
|
||||||
|
int64_t store_entid_for_attribute(struct Store*_Nonnull store, const char*_Nonnull attr);
|
||||||
|
int64_t changelist_entry_at(const struct TransactionChange* _Nonnull report, size_t index);
|
||||||
|
|
||||||
|
// Query
|
||||||
|
struct Query*_Nonnull store_query(struct Store*_Nonnull store, const char* _Nonnull query);
|
||||||
|
struct Result*_Nonnull store_value_for_attribute(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute);
|
||||||
|
|
||||||
|
// Query Variable Binding
|
||||||
|
void query_builder_bind_int(struct Store*_Nonnull store, const char* _Nonnull var, const int32_t value);
|
||||||
|
void query_builder_bind_long(struct Query*_Nonnull query, const char* _Nonnull var, const int64_t value);
|
||||||
|
void query_builder_bind_ref(struct Query*_Nonnull query, const char* _Nonnull var, const int64_t value);
|
||||||
|
void query_builder_bind_ref_kw(struct Query*_Nonnull query, const char* _Nonnull var, const char* _Nonnull value);
|
||||||
|
void query_builder_bind_kw(struct Query*_Nonnull query, const char* _Nonnull var, const char* _Nonnull value);
|
||||||
|
void query_builder_bind_boolean(struct Query*_Nonnull query, const char* _Nonnull var, const int32_t value);
|
||||||
|
void query_builder_bind_double(struct Query*_Nonnull query, const char* _Nonnull var, const double value);
|
||||||
|
void query_builder_bind_timestamp(struct Query*_Nonnull query, const char* _Nonnull var, const int64_t value);
|
||||||
|
void query_builder_bind_string(struct Query*_Nonnull query, const char* _Nonnull var, const char* _Nonnull value);
|
||||||
|
void query_builder_bind_uuid(struct Query*_Nonnull query, const char* _Nonnull var, const char* _Nonnull value);
|
||||||
|
|
||||||
|
// Query execution
|
||||||
|
struct Result*_Nonnull query_builder_execute(struct Query*_Nonnull query);
|
||||||
|
struct Result*_Nonnull query_builder_execute_scalar(struct Query*_Nonnull query);
|
||||||
|
struct Result*_Nonnull query_builder_execute_coll(struct Query*_Nonnull query);
|
||||||
|
struct Result*_Nonnull query_builder_execute_tuple(struct Query*_Nonnull query);
|
||||||
|
|
||||||
|
// Query Result Processing
|
||||||
|
int64_t typed_value_as_long(struct TypedValue*_Nonnull value);
|
||||||
|
int64_t typed_value_as_entid(struct TypedValue*_Nonnull value);
|
||||||
|
const char* _Nonnull typed_value_as_kw(struct TypedValue*_Nonnull value);
|
||||||
|
int32_t typed_value_as_boolean(struct TypedValue*_Nonnull value);
|
||||||
|
double typed_value_as_double(struct TypedValue*_Nonnull value);
|
||||||
|
int64_t typed_value_as_timestamp(struct TypedValue*_Nonnull value);
|
||||||
|
const char* _Nonnull typed_value_as_string(struct TypedValue*_Nonnull value);
|
||||||
|
const char* _Nonnull typed_value_as_uuid(struct TypedValue*_Nonnull value);
|
||||||
|
enum ValueType typed_value_value_type(struct TypedValue*_Nonnull value);
|
||||||
|
|
||||||
|
struct QueryResultRow* _Nullable row_at_index(struct QueryResultRows* _Nonnull rows, const int32_t index);
|
||||||
|
struct QueryRowsIterator* _Nonnull rows_iter(struct QueryResultRows* _Nonnull rows);
|
||||||
|
struct QueryResultRow* _Nullable rows_iter_next(struct QueryRowsIterator* _Nonnull iter);
|
||||||
|
struct QueryRowIterator* _Nonnull values_iter(struct QueryResultRow* _Nonnull row);
|
||||||
|
struct TypedValue* _Nullable values_iter_next(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const int64_t* _Nullable values_iter_next_as_long(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const int64_t* _Nullable values_iter_next_as_entid(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const char* _Nullable values_iter_next_as_kw(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const int32_t* _Nullable values_iter_next_as_boolean(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const double* _Nullable values_iter_next_as_double(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const int64_t* _Nullable values_iter_next_as_timestamp(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const char* _Nullable values_iter_next_as_string(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
const char* _Nullable values_iter_next_as_uuid(struct QueryRowIterator* _Nonnull iter);
|
||||||
|
|
||||||
|
struct TypedValue* _Nonnull value_at_index(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
int64_t value_at_index_as_long(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
int64_t value_at_index_as_entid(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
const char* _Nonnull value_at_index_as_kw(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
int32_t value_at_index_as_boolean(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
double value_at_index_as_double(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
int64_t value_at_index_as_timestamp(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
const char* _Nonnull value_at_index_as_string(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
const char* _Nonnull value_at_index_as_uuid(struct QueryResultRow* _Nonnull row, const int32_t index);
|
||||||
|
|
||||||
|
// Set single values
|
||||||
|
struct Result*_Nonnull store_set_long_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const int64_t value);
|
||||||
|
struct Result*_Nonnull store_set_entid_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const int64_t value);
|
||||||
|
struct Result*_Nonnull store_set_kw_ref_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const char* _Nonnull value);
|
||||||
|
struct Result*_Nonnull store_set_boolean_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const int32_t value);
|
||||||
|
struct Result*_Nonnull store_set_double_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const double value);
|
||||||
|
struct Result*_Nonnull store_set_timestamp_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const int64_t value);
|
||||||
|
struct Result*_Nonnull store_set_string_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const char* _Nonnull value);
|
||||||
|
struct Result*_Nonnull store_set_uuid_for_attribute_on_entid(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, const char* _Nonnull value);
|
||||||
|
|
||||||
|
// Transaction change lists
|
||||||
|
const struct TransactionChange* _Nullable tx_change_list_entry_at(const struct TxChangeList* _Nonnull list, size_t index);
|
||||||
|
|
||||||
|
#endif /* store_h */
|
22
sdks/swift/Mentat/MentatTests/Info.plist
Normal file
22
sdks/swift/Mentat/MentatTests/Info.plist
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
836
sdks/swift/Mentat/MentatTests/MentatTests.swift
Normal file
836
sdks/swift/Mentat/MentatTests/MentatTests.swift
Normal file
|
@ -0,0 +1,836 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import Mentat
|
||||||
|
|
||||||
|
class MentatTests: XCTestCase {
|
||||||
|
|
||||||
|
var schema: String?
|
||||||
|
var edn: String?
|
||||||
|
var store: Mentat?
|
||||||
|
|
||||||
|
override func setUp() {
|
||||||
|
super.setUp()
|
||||||
|
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDown() {
|
||||||
|
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||||
|
super.tearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
// test that a store can be opened in memory
|
||||||
|
func testOpenInMemoryStore() {
|
||||||
|
XCTAssertNotNil(Mentat().intoRaw())
|
||||||
|
}
|
||||||
|
|
||||||
|
// test that a store can be opened in a specific location
|
||||||
|
func testOpenStoreInLocation() {
|
||||||
|
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
||||||
|
let documentsURL = paths[0]
|
||||||
|
let storeURI = documentsURL.appendingPathComponent("test.db", isDirectory: false).absoluteString
|
||||||
|
XCTAssertNotNil(Mentat(storeURI: storeURI).intoRaw())
|
||||||
|
}
|
||||||
|
|
||||||
|
func readSchema() throws -> String {
|
||||||
|
guard let schema = self.schema else {
|
||||||
|
let bundle = Bundle(for: type(of: self))
|
||||||
|
let schemaUrl = bundle.url(forResource: "cities", withExtension: "schema", subdirectory: "fixtures")!
|
||||||
|
let schema = try String(contentsOf: schemaUrl)
|
||||||
|
self.schema = schema
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
|
func readEdn() throws -> String {
|
||||||
|
guard let edn = self.edn else {
|
||||||
|
let bundle = Bundle(for: type(of: self))
|
||||||
|
let ednUrl = bundle.url(forResource: "all_seattle", withExtension: "edn", subdirectory: "fixtures")!
|
||||||
|
let edn = try String(contentsOf: ednUrl)
|
||||||
|
self.edn = edn
|
||||||
|
return edn
|
||||||
|
}
|
||||||
|
|
||||||
|
return edn
|
||||||
|
}
|
||||||
|
|
||||||
|
func transactSchema(mentat: Mentat) throws -> TxReport {
|
||||||
|
let vocab = try readSchema()
|
||||||
|
let report = try mentat.transact(transaction: vocab)
|
||||||
|
return report
|
||||||
|
}
|
||||||
|
|
||||||
|
func transactEdn(mentat: Mentat) throws -> TxReport {
|
||||||
|
let edn = try readEdn()
|
||||||
|
let report = try mentat.transact(transaction: edn)
|
||||||
|
return report
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStore() -> Mentat {
|
||||||
|
guard let mentat = self.store else {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let _ = try! self.transactSchema(mentat: mentat)
|
||||||
|
let _ = try! self.transactEdn(mentat: mentat)
|
||||||
|
self.store = mentat
|
||||||
|
return mentat
|
||||||
|
}
|
||||||
|
|
||||||
|
return mentat
|
||||||
|
}
|
||||||
|
|
||||||
|
func populateWithTypesSchema(mentat: Mentat) -> TxReport? {
|
||||||
|
do {
|
||||||
|
let schema = """
|
||||||
|
[
|
||||||
|
[:db/add "b" :db/ident :foo/boolean]
|
||||||
|
[:db/add "b" :db/valueType :db.type/boolean]
|
||||||
|
[:db/add "b" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "l" :db/ident :foo/long]
|
||||||
|
[:db/add "l" :db/valueType :db.type/long]
|
||||||
|
[:db/add "l" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "r" :db/ident :foo/ref]
|
||||||
|
[:db/add "r" :db/valueType :db.type/ref]
|
||||||
|
[:db/add "r" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "i" :db/ident :foo/instant]
|
||||||
|
[:db/add "i" :db/valueType :db.type/instant]
|
||||||
|
[:db/add "i" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "d" :db/ident :foo/double]
|
||||||
|
[:db/add "d" :db/valueType :db.type/double]
|
||||||
|
[:db/add "d" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "s" :db/ident :foo/string]
|
||||||
|
[:db/add "s" :db/valueType :db.type/string]
|
||||||
|
[:db/add "s" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "k" :db/ident :foo/keyword]
|
||||||
|
[:db/add "k" :db/valueType :db.type/keyword]
|
||||||
|
[:db/add "k" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "u" :db/ident :foo/uuid]
|
||||||
|
[:db/add "u" :db/valueType :db.type/uuid]
|
||||||
|
[:db/add "u" :db/cardinality :db.cardinality/one]
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
let report = try mentat.transact(transaction: schema)
|
||||||
|
let stringEntid = report.entidForTmpId(tmpId: "s")!
|
||||||
|
|
||||||
|
let data = """
|
||||||
|
[
|
||||||
|
[:db/add "a" :foo/boolean true]
|
||||||
|
[:db/add "a" :foo/long 25]
|
||||||
|
[:db/add "a" :foo/instant #inst "2017-01-01T11:00:00.000Z"]
|
||||||
|
[:db/add "a" :foo/double 11.23]
|
||||||
|
[:db/add "a" :foo/string "The higher we soar the smaller we appear to those who cannot fly."]
|
||||||
|
[:db/add "a" :foo/keyword :foo/string]
|
||||||
|
[:db/add "a" :foo/uuid #uuid "550e8400-e29b-41d4-a716-446655440000"]
|
||||||
|
[:db/add "b" :foo/boolean false]
|
||||||
|
[:db/add "b" :foo/ref \(stringEntid)]
|
||||||
|
[:db/add "b" :foo/long 50]
|
||||||
|
[:db/add "b" :foo/instant #inst "2018-01-01T11:00:00.000Z"]
|
||||||
|
[:db/add "b" :foo/double 22.46]
|
||||||
|
[:db/add "b" :foo/string "Silence is worse; all truths that are kept silent become poisonous."]
|
||||||
|
[:db/add "b" :foo/uuid #uuid "4cb3f828-752d-497a-90c9-b1fd516d5644"]
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
return try mentat.transact(transaction: data)
|
||||||
|
} catch {
|
||||||
|
assertionFailure(error.localizedDescription)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func test1TransactVocabulary() {
|
||||||
|
do {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = try transactSchema(mentat: mentat)
|
||||||
|
XCTAssertNotNil(report)
|
||||||
|
assert(report.txId > 0)
|
||||||
|
} catch {
|
||||||
|
assertionFailure(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func test2TransactEntities() {
|
||||||
|
do {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let _ = try self.transactSchema(mentat: mentat)
|
||||||
|
let report = try self.transactEdn(mentat: mentat)
|
||||||
|
XCTAssertNotNil(report)
|
||||||
|
assert(report.txId > 0)
|
||||||
|
let entid = report.entidForTmpId(tmpId: "a17592186045438")
|
||||||
|
assert(entid == 65566)
|
||||||
|
} catch {
|
||||||
|
assertionFailure(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testQueryScalar() {
|
||||||
|
let mentat = newStore()
|
||||||
|
let query = "[:find ?n . :in ?name :where [(fulltext $ :community/name ?name) [[?e ?n]]]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query).bind(varName: "?name", toString: "Wallingford").executeScalar(callback: { (scalarResult, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
guard let result = scalarResult?.asString() else {
|
||||||
|
return assertionFailure("No String value received")
|
||||||
|
}
|
||||||
|
assert(result == "KOMO Communities - Wallingford")
|
||||||
|
expect.fulfill()
|
||||||
|
})
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testQueryColl() {
|
||||||
|
let mentat = newStore()
|
||||||
|
let query = "[:find [?when ...] :where [_ :db/txInstant ?when] :order (asc ?when)]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query).executeColl(callback: { (collResult, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
guard let rows = collResult else {
|
||||||
|
return assertionFailure("No results received")
|
||||||
|
}
|
||||||
|
// we are expecting 3 results
|
||||||
|
for i in 0..<3 {
|
||||||
|
let _ = rows.asDate(index: i)
|
||||||
|
assert(true)
|
||||||
|
}
|
||||||
|
expect.fulfill()
|
||||||
|
})
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testQueryCollResultIterator() {
|
||||||
|
let mentat = newStore()
|
||||||
|
let query = "[:find [?when ...] :where [_ :db/txInstant ?when] :order (asc ?when)]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query).executeColl(callback: { (collResult, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
guard let rows = collResult else {
|
||||||
|
return assertionFailure("No results received")
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.forEach({ (value) in
|
||||||
|
assert(value.valueType.rawValue == 2)
|
||||||
|
})
|
||||||
|
expect.fulfill()
|
||||||
|
})
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testQueryTuple() {
|
||||||
|
let mentat = newStore()
|
||||||
|
let query = """
|
||||||
|
[:find [?name ?cat]
|
||||||
|
:where
|
||||||
|
[?c :community/name ?name]
|
||||||
|
[?c :community/type :community.type/website]
|
||||||
|
[(fulltext $ :community/category "food") [[?c ?cat]]]]
|
||||||
|
"""
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query).executeTuple(callback: { (tupleResult, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
guard let tuple = tupleResult else {
|
||||||
|
return assertionFailure("expecting a result")
|
||||||
|
}
|
||||||
|
let name = tuple.asString(index: 0)
|
||||||
|
let category = tuple.asString(index: 1)
|
||||||
|
assert(name == "Community Harvest of Southwest Seattle")
|
||||||
|
assert(category == "sustainable food")
|
||||||
|
expect.fulfill()
|
||||||
|
})
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testQueryRel() {
|
||||||
|
let mentat = newStore()
|
||||||
|
let query = """
|
||||||
|
[:find ?name ?cat
|
||||||
|
:where
|
||||||
|
[?c :community/name ?name]
|
||||||
|
[?c :community/type :community.type/website]
|
||||||
|
[(fulltext $ :community/category "food") [[?c ?cat]]]]
|
||||||
|
"""
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
let expectedResults = [("InBallard", "food"),
|
||||||
|
("Seattle Chinatown Guide", "food"),
|
||||||
|
("Community Harvest of Southwest Seattle", "sustainable food"),
|
||||||
|
("University District Food Bank", "food bank")]
|
||||||
|
try! mentat.query(query: query).execute(callback: { (relResult, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
guard let rows = relResult else {
|
||||||
|
return assertionFailure("No results received")
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, row) in rows.enumerated() {
|
||||||
|
let (name, category) = expectedResults[i]
|
||||||
|
assert( row.asString(index: 0) == name)
|
||||||
|
assert(row.asString(index: 1) == category)
|
||||||
|
}
|
||||||
|
expect.fulfill()
|
||||||
|
})
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testQueryRelResultIterator() {
|
||||||
|
let mentat = newStore()
|
||||||
|
let query = """
|
||||||
|
[:find ?name ?cat
|
||||||
|
:where
|
||||||
|
[?c :community/name ?name]
|
||||||
|
[?c :community/type :community.type/website]
|
||||||
|
[(fulltext $ :community/category "food") [[?c ?cat]]]]
|
||||||
|
"""
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
let expectedResults = [("InBallard", "food"),
|
||||||
|
("Seattle Chinatown Guide", "food"),
|
||||||
|
("Community Harvest of Southwest Seattle", "sustainable food"),
|
||||||
|
("University District Food Bank", "food bank")]
|
||||||
|
try! mentat.query(query: query).execute(callback: { (relResult, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
guard let rows = relResult else {
|
||||||
|
return assertionFailure("No results received")
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
rows.forEach({ (row) in
|
||||||
|
let (name, category) = expectedResults[i]
|
||||||
|
i += 1
|
||||||
|
assert(row.asString(index: 0) == name)
|
||||||
|
assert(row.asString(index: 1) == category)
|
||||||
|
})
|
||||||
|
assert(i == 4)
|
||||||
|
expect.fulfill()
|
||||||
|
})
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindLong() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")
|
||||||
|
let query = "[:find ?e . :in ?bool :where [?e :foo/boolean ?bool]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?bool", toBoolean: true)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == aEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindRef() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let stringEntid = mentat.entidForAttribute(attribute: ":foo/string")
|
||||||
|
let bEntid = report.entidForTmpId(tmpId: "b")
|
||||||
|
let query = "[:find ?e . :in ?ref :where [?e :foo/ref ?ref]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?ref", toReference: stringEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == bEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindKwRef() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let bEntid = report.entidForTmpId(tmpId: "b")
|
||||||
|
let query = "[:find ?e . :in ?ref :where [?e :foo/ref ?ref]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?ref", toReference: ":foo/string")
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == bEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindKw() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")
|
||||||
|
let query = "[:find ?e . :in ?kw :where [?e :foo/keyword ?kw]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?kw", toKeyword: ":foo/string")
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == aEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindDate() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")
|
||||||
|
let query = "[:find [?e ?d] :in ?now :where [?e :foo/instant ?d] [(< ?d ?now)]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?now", toDate: Date())
|
||||||
|
.executeTuple { (row, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(row)
|
||||||
|
assert(row?.asEntid(index: 0) == aEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func testBindString() {
|
||||||
|
let mentat = newStore()
|
||||||
|
let query = "[:find ?n . :in ?name :where [(fulltext $ :community/name ?name) [[?e ?n]]]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?name", toString: "Wallingford")
|
||||||
|
.executeScalar(callback: { (scalarResult, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
guard let result = scalarResult?.asString() else {
|
||||||
|
return assertionFailure("No String value received")
|
||||||
|
}
|
||||||
|
assert(result == "KOMO Communities - Wallingford")
|
||||||
|
expect.fulfill()
|
||||||
|
})
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindUuid() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")
|
||||||
|
let query = "[:find ?e . :in ?uuid :where [?e :foo/uuid ?uuid]]"
|
||||||
|
let uuid = UUID(uuidString: "550e8400-e29b-41d4-a716-446655440000")!
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?uuid", toUuid: uuid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == aEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindBoolean() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")
|
||||||
|
let query = "[:find ?e . :in ?bool :where [?e :foo/boolean ?bool]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?bool", toBoolean: true)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == aEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBindDouble() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")
|
||||||
|
let query = "[:find ?e . :in ?double :where [?e :foo/double ?double]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?double", toDouble: 11.23)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == aEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsLong() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?v . :in ?e :where [?e :foo/long ?v]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?e", toReference: aEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asLong() == 25)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsRef() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?e . :where [?e :foo/long 25]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asEntid() == aEntid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsKw() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?v . :in ?e :where [?e :foo/keyword ?v]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?e", toReference: aEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asKeyword() == ":foo/string")
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsBoolean() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?v . :in ?e :where [?e :foo/boolean ?v]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?e", toReference: aEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asBool() == true)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsDouble() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?v . :in ?e :where [?e :foo/double ?v]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?e", toReference: aEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asDouble() == 11.23)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsDate() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?v . :in ?e :where [?e :foo/instant ?v]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
|
||||||
|
let expectedDate = formatter.date(from: "2017-01-01T11:00:00+00:00")
|
||||||
|
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?e", toReference: aEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asDate() == expectedDate)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsString() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?v . :in ?e :where [?e :foo/string ?v]]"
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?e", toReference: aEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asString() == "The higher we soar the smaller we appear to those who cannot fly.")
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTypedValueAsUuid() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let query = "[:find ?v . :in ?e :where [?e :foo/uuid ?v]]"
|
||||||
|
let expectedUuid = UUID(uuidString: "550e8400-e29b-41d4-a716-446655440000")!
|
||||||
|
let expect = expectation(description: "Query is executed")
|
||||||
|
try! mentat.query(query: query)
|
||||||
|
.bind(varName: "?e", toReference: aEntid)
|
||||||
|
.executeScalar { (value, error) in
|
||||||
|
assert(error == nil, "Unexpected error: \(String(describing: error))")
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asUUID() == expectedUuid)
|
||||||
|
expect.fulfill()
|
||||||
|
}
|
||||||
|
waitForExpectations(timeout: 1) { error in
|
||||||
|
if let error = error {
|
||||||
|
assertionFailure("waitForExpectationsWithTimeout errored: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testValueForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let value = mentat.value(forAttribute: ":foo/long", ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(value)
|
||||||
|
assert(value?.asLong() == 25)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEntidForAttribute() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let _ = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let entid = mentat.entidForAttribute(attribute: ":foo/long")
|
||||||
|
assert(entid == 65540)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetLongForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let attr = ":foo/long"
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(pre)
|
||||||
|
assert(pre?.asLong() == 25)
|
||||||
|
XCTAssertNoThrow(try mentat.set(long: 100, forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
assert(post?.asLong() == 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetBooleanForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let attr = ":foo/boolean"
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(pre)
|
||||||
|
assert(pre?.asBool() == true)
|
||||||
|
XCTAssertNoThrow(try mentat.set(boolean: false, forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
let p = post?.asBool()
|
||||||
|
assert(p == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetRefForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let bEntid = report.entidForTmpId(tmpId: "b")!
|
||||||
|
let attr = ":foo/ref"
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNil(pre)
|
||||||
|
XCTAssertNoThrow(try mentat.set(reference: bEntid, forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
assert(post?.asEntid() == bEntid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetRefKwForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let attr = ":foo/ref"
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNil(pre)
|
||||||
|
XCTAssertNoThrow(try mentat.setKeywordReference(value: ":foo/long", forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
assert(post?.asEntid() == 65540)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetDateForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let attr = ":foo/instant"
|
||||||
|
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
|
||||||
|
let previousDate = formatter.date(from: "2017-01-01T11:00:00+00:00")
|
||||||
|
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(pre)
|
||||||
|
assert(pre?.asDate() == previousDate)
|
||||||
|
|
||||||
|
let now = Date()
|
||||||
|
XCTAssertNoThrow(try mentat.set(date: now, forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
let p = post?.asDate()
|
||||||
|
|
||||||
|
assert(formatter.string(from: p!) == formatter.string(from: now))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetDoubleForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let attr = ":foo/double"
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(pre)
|
||||||
|
assert(pre?.asDouble() == 11.23)
|
||||||
|
XCTAssertNoThrow(try mentat.set(double: 22.0, forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
assert(post?.asDouble() == 22.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetStringForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let attr = ":foo/string"
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(pre)
|
||||||
|
assert(pre?.asString() == "The higher we soar the smaller we appear to those who cannot fly.")
|
||||||
|
XCTAssertNoThrow(try mentat.set(string: "Become who you are!", forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
assert(post?.asString() == "Become who you are!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetUuidForAttributeOfEntity() {
|
||||||
|
let mentat = Mentat()
|
||||||
|
let report = self.populateWithTypesSchema(mentat: mentat)!
|
||||||
|
let aEntid = report.entidForTmpId(tmpId: "a")!
|
||||||
|
let previousUuid = UUID(uuidString: "550e8400-e29b-41d4-a716-446655440000")!
|
||||||
|
let attr = ":foo/uuid"
|
||||||
|
let pre = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(pre)
|
||||||
|
assert(pre?.asUUID() == previousUuid)
|
||||||
|
|
||||||
|
let newUuid = UUID()
|
||||||
|
XCTAssertNoThrow(try mentat.set(uuid: newUuid, forAttribute: attr, onEntity: aEntid))
|
||||||
|
let post = mentat.value(forAttribute: attr, ofEntity: aEntid)
|
||||||
|
XCTAssertNotNil(post)
|
||||||
|
assert(post?.asUUID() == newUuid)
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,6 +54,7 @@ pub use mentat_query::{
|
||||||
pub use mentat_db::{
|
pub use mentat_db::{
|
||||||
CORE_SCHEMA_VERSION,
|
CORE_SCHEMA_VERSION,
|
||||||
DB_SCHEMA_CORE,
|
DB_SCHEMA_CORE,
|
||||||
|
AttributeSet,
|
||||||
TxObserver,
|
TxObserver,
|
||||||
TxReport,
|
TxReport,
|
||||||
new_connection,
|
new_connection,
|
||||||
|
|
|
@ -14,9 +14,11 @@ use std::collections::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
|
DateTime,
|
||||||
Entid,
|
Entid,
|
||||||
NamespacedKeyword,
|
NamespacedKeyword,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
|
Utc,
|
||||||
ValueType,
|
ValueType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,6 +74,11 @@ impl<'a> QueryBuilder<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bind_date_time(&mut self, var: &str, value: DateTime<Utc>) -> &mut Self {
|
||||||
|
self.values.insert(Variable::from_valid_name(var), TypedValue::Instant(value));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bind_type(&mut self, var: &str, value_type: ValueType) -> &mut Self {
|
pub fn bind_type(&mut self, var: &str, value_type: ValueType) -> &mut Self {
|
||||||
self.types.insert(Variable::from_valid_name(var), value_type);
|
self.types.insert(Variable::from_valid_name(var), value_type);
|
||||||
self
|
self
|
||||||
|
@ -114,6 +121,11 @@ mod test {
|
||||||
Store,
|
Store,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use mentat_core::{
|
||||||
|
DateTime,
|
||||||
|
Utc,
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_scalar_query() {
|
fn test_scalar_query() {
|
||||||
let mut store = Store::open("").expect("store connection");
|
let mut store = Store::open("").expect("store connection");
|
||||||
|
@ -386,4 +398,45 @@ mod test {
|
||||||
assert_eq!(results.get(0).map_or(None, |t| t.to_owned().into_boolean()).expect("boolean"), true);
|
assert_eq!(results.get(0).map_or(None, |t| t.to_owned().into_boolean()).expect("boolean"), true);
|
||||||
assert_eq!(results.get(1).map_or(None, |t| t.to_owned().into_long()).expect("long"), 25);
|
assert_eq!(results.get(1).map_or(None, |t| t.to_owned().into_long()).expect("long"), 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bind_date() {
|
||||||
|
let mut store = Store::open("").expect("store connection");
|
||||||
|
store.transact(r#"[
|
||||||
|
[:db/add "s" :db/ident :foo/boolean]
|
||||||
|
[:db/add "s" :db/valueType :db.type/boolean]
|
||||||
|
[:db/add "s" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "t" :db/ident :foo/long]
|
||||||
|
[:db/add "t" :db/valueType :db.type/long]
|
||||||
|
[:db/add "t" :db/cardinality :db.cardinality/one]
|
||||||
|
[:db/add "i" :db/ident :foo/instant]
|
||||||
|
[:db/add "i" :db/valueType :db.type/instant]
|
||||||
|
[:db/add "i" :db/cardinality :db.cardinality/one]
|
||||||
|
]"#).expect("successful transaction");
|
||||||
|
|
||||||
|
let report = store.transact(r#"[
|
||||||
|
[:db/add "l" :foo/boolean true]
|
||||||
|
[:db/add "l" :foo/long 25]
|
||||||
|
[:db/add "m" :foo/boolean false]
|
||||||
|
[:db/add "m" :foo/long 26]
|
||||||
|
[:db/add "n" :foo/boolean true]
|
||||||
|
[:db/add "n" :foo/long 27]
|
||||||
|
[:db/add "p" :foo/boolean false]
|
||||||
|
[:db/add "p" :foo/long 28]
|
||||||
|
[:db/add "p" :foo/instant #inst "2018-04-11T15:08:00.000Z"]
|
||||||
|
]"#).expect("successful transaction");
|
||||||
|
|
||||||
|
let p_entid = report.tempids.get("p").expect("found it").clone();
|
||||||
|
|
||||||
|
let time = DateTime::parse_from_rfc3339("2018-04-11T19:17:00.000Z")
|
||||||
|
.map(|t| t.with_timezone(&Utc))
|
||||||
|
.expect("expected valid date");
|
||||||
|
let results = QueryBuilder::new(&mut store, r#"[:find [?e ?d] :in ?now :where [?e :foo/instant ?d] [(< ?d ?now)]]"#)
|
||||||
|
.bind_date_time("?now", time)
|
||||||
|
.execute_tuple().expect("TupleResult")
|
||||||
|
.unwrap_or(vec![]);
|
||||||
|
assert_eq!(results.get(0).map_or(None, |t| t.to_owned().into_entid()).expect("entid"), p_entid);
|
||||||
|
let instant = results.get(1).map_or(None, |t| t.to_owned().into_timestamp()).expect("instant");
|
||||||
|
assert_eq!(instant, 1523459280);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue