summaryrefslogtreecommitdiff
path: root/rbejdb
diff options
context:
space:
mode:
authorFedor Yudanov <fedwiz@academ.org>2013-04-17 15:28:29 +0700
committerFedor Yudanov <fedwiz@academ.org>2013-04-17 15:28:29 +0700
commit2af2f0446d09f2691f5404b91f01321026aa8404 (patch)
treec9b8b925a0837e3fc83e41697ba6573c052ffd3e /rbejdb
parenta874bd4909694b666cd020e84558c63841fc8b70 (diff)
downloadejdb-2af2f0446d09f2691f5404b91f01321026aa8404.tar.gz
ejdb-2af2f0446d09f2691f5404b91f01321026aa8404.tar.bz2
ejdb-2af2f0446d09f2691f5404b91f01321026aa8404.zip
#50 - documentation using RDoc + update method tuning
Diffstat (limited to 'rbejdb')
-rw-r--r--rbejdb/src/rbejdb.c128
-rw-r--r--rbejdb/test/t2.rb7
2 files changed, 111 insertions, 24 deletions
diff --git a/rbejdb/src/rbejdb.c b/rbejdb/src/rbejdb.c
index 485c6aa..1426b25 100644
--- a/rbejdb/src/rbejdb.c
+++ b/rbejdb/src/rbejdb.c
@@ -34,6 +34,7 @@ typedef struct {
typedef struct {
TCLIST* results;
TCLIST* results_raw;
+ int count;
TCXSTR* log;
} RBEJDB_RESULTS;
@@ -45,7 +46,7 @@ typedef struct {
} RBEJDB_QUERY;
-VALUE create_EJDB_query_results(TCLIST* qres, TCXSTR *log);
+VALUE create_EJDB_query_results(TCLIST* qres, int count, TCXSTR *log);
VALUE ejdbClass;
@@ -251,13 +252,12 @@ VALUE EJDB_drop_collection(int argc, VALUE* argv, VALUE self) {
*
* NOTE: Field names of passed objects may not contain $ and . characters, error condition will be fired in this case.
* - +collName+ (String) - name of collection
- * - +obj+ (Hash or Object) - zero or more objects to save
+ * - +obj+ (Hash or Object) - one or more objects to save
* - +merge+ (Hash or Object) - if true a saved objects will be merged with who's
*
* <br/>
* Returns:
- * - nil, if no objects provided in arguments
- * - oid of saved object, as String if one object provided in arguments
+ * - oid of saved object, as string, if single object provided in arguments
* - array of oids, in other case
*/
VALUE EJDB_save(int argc, VALUE *argv, VALUE self) {
@@ -453,7 +453,7 @@ VALUE EJDB_find_internal(VALUE self, VALUE collName, VALUE queryWrap, VALUE q, V
coll = ejdbcreatecoll(ejdb, StringValuePtr(collName), NULL);
}
if (!coll) {
- return !onlycount ? create_EJDB_query_results(tclistnew2(1), NULL) : INT2NUM(0);
+ return !onlycount || explain ? create_EJDB_query_results(tclistnew2(1), 0, NULL) : INT2NUM(0);
}
}
@@ -465,7 +465,7 @@ VALUE EJDB_find_internal(VALUE self, VALUE collName, VALUE queryWrap, VALUE q, V
TCLIST* qres = ejdbqryexecute(coll, ejq, &count, qflags, log);
- return !onlycount ? create_EJDB_query_results(qres, log) : INT2NUM(count);
+ return !onlycount || explain ? create_EJDB_query_results(qres, count, log) : INT2NUM(count);
}
VALUE EJDB_find_internal_wrapper(VALUE args) {
@@ -482,7 +482,7 @@ VALUE EJDB_find_ensure(VALUE queryWrap, VALUE exception) {
/*
* call-seq:
- * ejdb.find(collName, [q = {}, orarr = [], hints = {}]) -> nil
+ * ejdb.find(collName, [q = {}, orarr = [], hints = {}]) -> EJDBResults or Number
*
* Execute query on collection. EJDB queries inspired by MongoDB (mongodb.org) and follows same philosophy.
* Both in query and in +hints+ strings or symbols may be used as keys (f. e. "fpath" and :fpath are equal).
@@ -551,16 +551,16 @@ VALUE EJDB_find_ensure(VALUE queryWrap, VALUE exception) {
* [:orderby] Sorting order of query fields.
* [:onlycount] If `true` only count of matching records will be returned without placing records in result set.
* [:fields] Set subset of fetched fields
- * If a field presented in $orderby clause it will be forced to include in resulting records.<br/>
+ * If a field presented in +:orderby+ clause it will be forced to include in resulting records.<br/>
* Example:<br/>
- * hints: {
- * "$orderby" : { //ORDER BY field1 ASC, field2 DESC
- * "field1" : 1,
- * "field2" : -1
+ * hints = {
+ * :orderby => { //ORDER BY field1 ASC, field2 DESC
+ * "field1" => 1,
+ * "field2" => -1
* },
- * "$fields" : { //SELECT ONLY {_id, field1, field2}
- * "field1" : 1,
- * "field2" : 1
+ * :fields => { //SELECT ONLY {_id, field1, field2}
+ * "field1" => 1,
+ * "field2" => 1
* }
* }
*
@@ -571,6 +571,12 @@ VALUE EJDB_find_ensure(VALUE queryWrap, VALUE exception) {
* - +orarr+ (Array) - array of additional OR query objects (joined with OR predicate). If 3rd argument is not array it
* will be recognized as +hints+ argument
* - +hints+ (Hash or Object) - object with query hints
+ *
+ * <br/>
+ * Returns:
+ * - EJDBResults object, if no +:onlycount+ hint specified or :explain hint specified
+ * - results count as Number, otherwise
+ *
*/
VALUE EJDB_find(int argc, VALUE* argv, VALUE self) {
VALUE collName;
@@ -600,7 +606,6 @@ VALUE EJDB_find(int argc, VALUE* argv, VALUE self) {
rbquery->orarrbson = NULL;
rbquery->orarrlng = 0;
-
VALUE params = rb_ary_new();
rb_ary_push(params, self);
rb_ary_push(params, collName);
@@ -613,10 +618,29 @@ VALUE EJDB_find(int argc, VALUE* argv, VALUE self) {
return rb_ensure(EJDB_find_internal_wrapper, params, EJDB_find_ensure, queryWrap);
}
-static VALUE EJDB_block_true(VALUE yielded_object, VALUE context, int argc, VALUE argv[]){
+VALUE EJDB_block_true(VALUE yielded_object, VALUE context, int argc, VALUE argv[]){
return Qtrue;
}
+
+/*
+ * call-seq:
+ * ejdb.find_one(collName, oid) -> Hash or Number or nil
+ *
+ * Same as +find+ but retrieves only one matching object.
+ *
+ * - +collName+ (String) - name of collection
+ * - +q+ (Hash or Object) - query object. In most cases it will be easier to use hash to specify EJDB queries
+ * - +orarr+ (Array) - array of additional OR query objects (joined with OR predicate). If 3rd argument is not array it
+ * will be recognized as +hints+ argument
+ * - +hints+ (Hash or Object) - object with query hints
+ *
+ * <br/>
+ * Returns:
+ * - found object as hash, if no +:onlycount+ hint specified
+ * - nil, if no +:onlycount+ hint specified and nothing found
+ * - results count as Number, otherwise
+ */
VALUE EJDB_find_one(int argc, VALUE* argv, VALUE self) {
VALUE results = EJDB_find(argc, argv, self);
if (TYPE(results) == T_DATA) {
@@ -625,8 +649,60 @@ VALUE EJDB_find_one(int argc, VALUE* argv, VALUE self) {
return results;
}
-void EJDB_update(int argc, VALUE* argv, VALUE self) {
- EJDB_find(argc, argv, self);
+
+/*
+ * call-seq:
+ * ejdb.update(collName, oid) -> EJDBResults or Number
+ *
+ * Convenient method to execute update queries.
+ *
+ * - $set Field set operation:
+ * - {some fields for selection, "$set" => {"field1" => obj, ..., "fieldN" => obj}}
+ * - $upsert Atomic upsert. If matching records are found it will be "$set" operation, otherwise new record will be inserted with fields specified by argment object.
+ * - {.., "$upsert" => {"field1" => val1, "fieldN" => valN}}
+ * - $inc Increment operation. Only number types are supported.
+ * - {some fields for selection, "$inc" => {"field1" => number, ..., "fieldN" => number}
+ * - $dropall In-place record removal operation.
+ * - {some fields for selection, "$dropall" => true}
+ * - $addToSet | $addToSetAll Atomically adds value to the array only if its not in the array already. If containing array is missing it will be created.
+ * - {.., "$addToSet" => {"fpath" => val1, "fpathN" => valN, ...}}
+ * - $pull | pullAll Atomically removes all occurrences of value from field, if field is an array.
+ * - {.., "$pull" => {"fpath" => val1, "fpathN" => valN, ...}}
+ *
+ * <br/>
+ * - +collName+ (String) - name of collection
+ * - +q+ (Hash or Object) - query object. In most cases it will be easier to use hash to specify EJDB queries
+ * - +orarr+ (Array) - array of additional OR query objects (joined with OR predicate). If 3rd argument is not array it
+ * will be recognized as +hints+ argument
+ * - +hints+ (Hash or Object) - object with query hints
+ *
+ * <br/>
+ * Returns:
+ * Returns:
+ * - EJDBResults object, with only +count+ and +log+ methods available if :explain hint specified
+ * - updated objects count as Number, otherwise
+ */
+VALUE EJDB_update(int argc, VALUE* argv, VALUE self) {
+
+ VALUE collName;
+ VALUE q;
+ VALUE orarr;
+ VALUE hints;
+
+ VALUE p3;
+ VALUE p4;
+
+ rb_scan_args(argc, argv, "13", &collName, &q, &p3, &p4);
+
+ orarr = TYPE(p3) == T_ARRAY ? p3 : rb_ary_new();
+ hints = TYPE(p3) != T_ARRAY ? p3 : p4;
+ hints = !NIL_P(hints) ? hints : rb_hash_new();
+
+ Check_Type(hints, T_HASH);
+ rb_hash_aset(hints, rb_str_new2("onlycount"), Qtrue);
+
+ VALUE findargs[4] = {collName, q, orarr, hints};
+ return EJDB_find(4, findargs, self);
}
@@ -860,7 +936,7 @@ void EJDB_results_free(RBEJDB_RESULTS* rbres) {
ruby_xfree(rbres);
}
-VALUE create_EJDB_query_results(TCLIST* qres, TCXSTR *log) {
+VALUE create_EJDB_query_results(TCLIST* qres, int count, TCXSTR *log) {
VALUE resultsWrap = Data_Wrap_Struct(ejdbResultsClass, NULL, EJDB_results_free, ruby_xmalloc(sizeof(RBEJDB_RESULTS)));
RBEJDB_RESULTS* rbresults;
Data_Get_Struct(resultsWrap, RBEJDB_RESULTS, rbresults);
@@ -876,6 +952,7 @@ VALUE create_EJDB_query_results(TCLIST* qres, TCXSTR *log) {
rbresults->results = results;
rbresults->results_raw = qres;
+ rbresults->count = count;
rbresults->log = log;
return resultsWrap;
@@ -896,6 +973,16 @@ void EJDB_results_each(VALUE self) {
rb_yield(bson_to_ruby(bsonval));
}
}
+VALUE EJDB_results_count(VALUE self) {
+ RBEJDB_RESULTS* rbresults;
+ Data_Get_Struct(self, RBEJDB_RESULTS, rbresults);
+
+ if (!rbresults) {
+ rb_raise(rb_eRuntimeError, "count() method called on invalid ejdb query results");
+ }
+
+ return INT2NUM(rbresults->count);
+}
VALUE EJDB_results_log(VALUE self) {
RBEJDB_RESULTS* rbresults;
@@ -998,6 +1085,7 @@ Init_rbejdb() {
rb_define_singleton_method(ejdbResultsClass, "new", RUBY_METHOD_FUNC(private_new_method_stub), 0);
rb_include_module(ejdbResultsClass, rb_mEnumerable);
rb_define_method(ejdbResultsClass, "each", RUBY_METHOD_FUNC(EJDB_results_each), 0);
+ rb_define_method(ejdbResultsClass, "count", RUBY_METHOD_FUNC(EJDB_results_count), 0);
rb_define_method(ejdbResultsClass, "log", RUBY_METHOD_FUNC(EJDB_results_log), 0);
rb_define_method(ejdbResultsClass, "close", RUBY_METHOD_FUNC(EJDB_results_close), 0);
diff --git a/rbejdb/test/t2.rb b/rbejdb/test/t2.rb
index 1e63631..616d752 100644
--- a/rbejdb/test/t2.rb
+++ b/rbejdb/test/t2.rb
@@ -308,8 +308,7 @@ class EJDBTestUnit < Test::Unit::TestCase
assert_equal(1, obj["extra1"])
q = {"_id" => {"$in" => [id]}, "$set" => {"stime" => Time.now}}
- result = $jb.update("parrots", q)
- assert_equal(1, result.count)
+ assert_equal(1, $jb.update("parrots", q))
puts __method__.inspect + " has passed successfull"
end
@@ -430,8 +429,7 @@ class EJDBTestUnit < Test::Unit::TestCase
assert_not_nil $jb
assert $jb.open?
- results = $jb.update("upsertcoll", {:foo => "bar", "$upsert" => {:foo => "bar"}})
- assert_equal(1, results.count)
+ assert_equal(1, $jb.update("upsertcoll", {:foo => "bar", "$upsert" => {:foo => "bar"}}))
obj = $jb.find_one("upsertcoll", {:foo => "bar"})
assert_equal("bar", obj["foo"])
@@ -612,6 +610,7 @@ class EJDBTestUnit < Test::Unit::TestCase
assert_not_nil results.to_a[0]
assert_not_equal(:chupacabra, results.to_a[0]["name"])
+ assert_nil $jb.find_one("monsters", {:name => "Sauron"})
puts __method__.inspect + " has passed successfull"
end