X-Git-Url: http://nitlanguage.org diff --git a/lib/mongodb/native_mongodb.nit b/lib/mongodb/native_mongodb.nit index 3bcf3f8..692d08a 100644 --- a/lib/mongodb/native_mongodb.nit +++ b/lib/mongodb/native_mongodb.nit @@ -48,12 +48,12 @@ extern class NativeBSON `{ bson_t * `} # by parsing the JSON found in `data`. # Only a single JSON object may exist in data or an error will be set and # `NULL` returned. - new from_json_string(data: NativeString) import set_mongoc_error `{ + new from_json_string(data: CString) import set_mongoc_error `{ bson_error_t error; bson_t *bson; - bson = bson_new_from_json(data, -1, &error); + bson = bson_new_from_json((uint8_t *)data, -1, &error); if(!bson) { - NativeBSON_set_mongoc_error(recv, &error); + NativeBSON_set_mongoc_error(bson, &error); return NULL; } return bson; @@ -64,7 +64,7 @@ extern class NativeBSON `{ bson_t * `} # The `bson_as_json()` function shall encode bson as a JSON encoded UTF-8 string. # The caller is responsible for freeing the resulting UTF-8 encoded string # by calling `bson_free()` with the result. - fun to_native_string: NativeString `{ return bson_as_json(self, NULL); `} + fun to_native_string: CString `{ return bson_as_json(self, NULL); `} # Wrapper for `bson_destroy()`. # @@ -100,7 +100,37 @@ extern class BSONError `{ bson_error_t * `} # Wrapper for `error.message`. # # The `error.message` field contains a human printable error message. - fun message: NativeString `{ return self->message; `} + fun message: CString `{ return self->message; `} +end + +# Wrapper for `bson_oid_t`. +# +# The `bson_oid_t` structure contains the 12-byte ObjectId notation defined by the +# [BSON ObjectID specificiation](http://docs.mongodb.org/manual/reference/object-id/). +# +# ObjectId is a 12-byte BSON type, constructed using: +# * a 4-byte value representing the seconds since the Unix epoch (in Big Endian) +# * a 3-byte machine identifier +# * a 2-byte process id (Big Endian), and +# * a 3-byte counter (Big Endian), starting with a random value. +extern class BSONObjectId `{ bson_oid_t * `} + + # Generates a new `bson_oid_t`. + new `{ + bson_oid_t *self = malloc(sizeof(bson_oid_t)); + bson_oid_init(self, NULL); + return self; + `} + + # Object id. + fun id: String import CString.to_s_with_copy `{ + char str[25]; + bson_oid_to_string(self, str); + return CString_to_s_with_copy(str); + `} + + # Destroy `self`. + fun destroy `{ free(self); `} end redef class Sys @@ -108,11 +138,16 @@ redef class Sys # # See `MongoClient::last_error`. var last_mongoc_error: nullable BSONError = null + + # Last auto generated id if any. + # + # See `MongoCollection::insert`. + var last_mongoc_id: nullable BSONObjectId = null is writable end # Wrapper for `char**`. # -# Used to handle array of NativeString returned by MongoDB. +# Used to handle array of CString returned by MongoDB. redef class NativeCStringArray # Frees `self`. # @@ -132,7 +167,7 @@ extern class NativeMongoClient `{ mongoc_client_t * `} # Wrapper for `mongoc_client_new()`. # # Creates a new `mongoc_client_t` using the `uri` string provided. - new(uri: NativeString) `{ + new(uri: CString) `{ mongoc_init(); return mongoc_client_new(uri); `} @@ -159,7 +194,7 @@ extern class NativeMongoClient `{ mongoc_client_t * `} import set_mongoc_error, NativeCStringArray, NativeCStringArray.as nullable `{ bson_error_t error; char **strv; - if(strv = mongoc_client_get_database_names(self, &error)) { + if((strv = mongoc_client_get_database_names(self, &error))) { return NativeCStringArray_as_nullable(strv); } NativeMongoClient_set_mongoc_error(self, &error); @@ -194,7 +229,7 @@ extern class NativeMongoDb `{ mongoc_database_t * `} # Database are automatically created on the MongoDB server upon insertion of # the first document into a collection. # There is no need to create a database manually. - new(client: NativeMongoClient, db_name: NativeString) `{ + new(client: NativeMongoClient, db_name: CString) `{ return mongoc_client_get_database(client, db_name); `} @@ -206,7 +241,7 @@ extern class NativeMongoDb `{ mongoc_database_t * `} import set_mongoc_error, NativeCStringArray, NativeCStringArray.as nullable `{ bson_error_t error; char **strv; - if(strv = mongoc_database_get_collection_names(self, &error)) { + if((strv = mongoc_database_get_collection_names(self, &error))) { return NativeCStringArray_as_nullable(strv); } NativeMongoDb_set_mongoc_error(self, &error); @@ -217,7 +252,7 @@ extern class NativeMongoDb `{ mongoc_database_t * `} # # Allocates a new `mongoc_collection_t` structure for the collection named # `name` in database. - fun collection(name: NativeString): NativeMongoCollection `{ + fun collection(name: CString): NativeMongoCollection `{ return mongoc_database_get_collection(self, name); `} @@ -225,7 +260,7 @@ extern class NativeMongoDb `{ mongoc_database_t * `} # # This function checks to see if a collection exists on the MongoDB server # within database. - fun has_collection(name: NativeString): Bool import set_mongoc_error `{ + fun has_collection(name: CString): Bool import set_mongoc_error `{ bson_error_t error; if(!mongoc_database_has_collection(self, name, &error)) { NativeMongoDb_set_mongoc_error(self, &error); @@ -277,7 +312,7 @@ extern class NativeMongoCollection `{ mongoc_collection_t * `} # Collections are automatically created on the MongoDB server upon insertion # of the first document. # There is no need to create a collection manually. - new(client: NativeMongoClient, db, collection: NativeString) `{ + new(client: NativeMongoClient, db, collection: CString) `{ return mongoc_client_get_collection(client, db, collection); `} @@ -287,10 +322,16 @@ extern class NativeMongoCollection `{ mongoc_collection_t * `} # If no `_id` element is found in document, then a `bson_oid_t` will be # generated locally and added to the document. # - # You can retrieve a generated `_id` from `mongoc_collection_get_last_error()`. - fun insert(doc: NativeBSON): Bool import set_mongoc_error `{ + # You can retrieve a generated `_id` from `sys.last_mongoc_id`. + fun insert(document: NativeBSON): Bool import set_mongoc_error, set_mongoc_last_id `{ + bson_oid_t oid; + if(!bson_has_field(document, "_id")) { + bson_oid_init (&oid, NULL); + BSON_APPEND_OID (document, "_id", &oid); + NativeMongoCollection_set_mongoc_last_id(self, &oid); + } bson_error_t error; - if(!mongoc_collection_insert(self, MONGOC_INSERT_NONE, doc, NULL, &error)) { + if(!mongoc_collection_insert(self, MONGOC_INSERT_NONE, document, NULL, &error)) { NativeMongoCollection_set_mongoc_error(self, &error); return false; } @@ -302,7 +343,15 @@ extern class NativeMongoCollection `{ mongoc_collection_t * `} # This function shall save a document into the collection. # If the document has an `_id` field it will be updated. # Otherwise it will be inserted. - fun save(document: NativeBSON): Bool import set_mongoc_error `{ + # + # You can retrieve a generated `_id` from `sys.last_mongoc_id`. + fun save(document: NativeBSON): Bool import set_mongoc_error, set_mongoc_last_id `{ + bson_oid_t oid; + if(!bson_has_field(document, "_id")) { + bson_oid_init (&oid, NULL); + BSON_APPEND_OID (document, "_id", &oid); + NativeMongoCollection_set_mongoc_last_id(self, &oid); + } bson_error_t error; if(!mongoc_collection_save(self, document, NULL, &error)) { NativeMongoCollection_set_mongoc_error(self, &error); @@ -383,17 +432,33 @@ extern class NativeMongoCollection `{ mongoc_collection_t * `} # # If you would like to specify options such as a sort order, # the query must be placed inside of `{"$query": {}}`. - fun find(query: NativeBSON): nullable NativeMongoCursor import + fun find(query: NativeBSON, skip, limit: Int): nullable NativeMongoCursor import NativeMongoCursor.as nullable, set_mongoc_error `{ bson_error_t error; mongoc_cursor_t *cursor; - cursor = mongoc_collection_find(self, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); - + cursor = mongoc_collection_find(self, MONGOC_QUERY_NONE, skip, limit, 0, query, NULL, NULL); if (mongoc_cursor_error(cursor, &error)) { NativeMongoCollection_set_mongoc_error(self, &error); return null_NativeMongoCursor(); } + return NativeMongoCursor_as_nullable(cursor); + `} + # Wrapper for `mongoc_collection_aggregate()`. + # + # This function shall execute an aggregation `pipeline` on the underlying collection. + # + # The `pipeline` parameter should contain a field named `pipeline` containing + # a BSON array of pipeline stages. + fun aggregate(pipeline: NativeBSON): nullable NativeMongoCursor import + NativeMongoCursor.as nullable, set_mongoc_error `{ + bson_error_t error; + mongoc_cursor_t *cursor; + cursor = mongoc_collection_aggregate(self, MONGOC_QUERY_NONE, pipeline, NULL, NULL); + if (mongoc_cursor_error(cursor, &error)) { + NativeMongoCollection_set_mongoc_error(self, &error); + return null_NativeMongoCursor(); + } return NativeMongoCursor_as_nullable(cursor); `} @@ -429,7 +494,7 @@ extern class NativeMongoCollection `{ mongoc_collection_t * `} # The name of the collection will also be updated internally so it is safe # to continue using this collection after the rename. # Additional operations will occur on renamed collection. - fun rename(new_database, new_name: NativeString): Bool `{ + fun rename(new_database, new_name: CString): Bool `{ bson_error_t error; if(!mongoc_collection_rename(self, new_database, new_name, false, &error)){ NativeMongoCollection_set_mongoc_error(self, &error); @@ -443,6 +508,9 @@ extern class NativeMongoCollection `{ mongoc_collection_t * `} # This instance should not be used beyond this point! fun destroy `{ mongoc_collection_destroy(self); `} + # Utility method to set `Sys.last_mongoc_last_id`. + fun set_mongoc_last_id(id: BSONObjectId) do sys.last_mongoc_id = id + # Utility method to set `Sys.last_mongoc_error`. fun set_mongoc_error(err: BSONError) do sys.last_mongoc_error = err end @@ -467,7 +535,12 @@ extern class NativeMongoCursor `{ mongoc_cursor_t* `} # Wrapper for `mongoc_cursor_current()`. # # Fetches the cursors current document or NULL if there has been an error. - fun current: NativeBSON `{ return (bson_t*) mongoc_cursor_current(self); `} + fun current: NativeBSON `{ + // As said in documentation, BSON objects should not be freed manually. + bson_t* bson = (bson_t*) mongoc_cursor_current(self); + // Copy BSON so we can let the GC free it automatically. + return bson_copy(bson); + `} # Wrapper for `mongoc_cursor_next()`. # @@ -480,11 +553,6 @@ extern class NativeMongoCursor `{ mongoc_cursor_t* `} return mongoc_cursor_next(self, &doc); `} - # Wrapper for `mongoc_cursor_more()`. - # - # This function shall indicate if there is more data to be read from the cursor. - fun more: Bool `{ return mongoc_cursor_more(self); `} - # Wrapper for `mongoc_cursor_destroy()`. # # This instance should not be used beyond this point!