Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'feature/ReplicaSetSupport' into develop

  • Loading branch information...
commit 7c00db2aea586aff5d627fb5e89e1f9858f86f86 2 parents ae8d9c9 + 0cbcebf
@mtowers mtowers authored
View
9 Makefile
@@ -8,16 +8,13 @@ OUTLIB=mongo.so
LDFLAGS= $(LIBS)
-OBJS = main.o mongo_bsontypes.o mongo_connection.o mongo_cursor.o mongo_gridfile.o mongo_gridfs.o mongo_gridfschunk.o mongo_query.o utils.o
+OBJS = main.o mongo_bsontypes.o mongo_dbclient.o mongo_replicaset.o mongo_connection.o mongo_cursor.o mongo_gridfile.o mongo_gridfs.o mongo_gridfschunk.o mongo_query.o utils.o
all: luamongo
clean:
$(RM) $(OBJS) $(OUTLIB)
-old: CFLAGS := $(CFLAGS) -DMONGO_PRE_1_5
-old: luamongo
-
luamongo: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(OUTLIB) $(LDFLAGS)
@@ -31,6 +28,8 @@ echo:
main.o: main.cpp utils.h
$(CC) -c -o $@ $< $(CFLAGS)
+mongo_dbclient.o: mongo_dbclient.cpp common.h utils.h
+ $(CC) -c -o $@ $< $(CFLAGS)
mongo_connection.o: mongo_connection.cpp common.h utils.h
$(CC) -c -o $@ $< $(CFLAGS)
mongo_cursor.o: mongo_cursor.cpp common.h utils.h
@@ -43,6 +42,8 @@ mongo_gridfschunk.o: mongo_gridfschunk.cpp common.h utils.h
$(CC) -c -o $@ $< $(CFLAGS)
mongo_query.o: mongo_query.cpp common.h utils.h
$(CC) -c -o $@ $< $(CFLAGS)
+mongo_replicaset.o: mongo_replicaset.cpp common.h utils.h
+ $(CC) -c -o $@ $< $(CFLAGS)
mongo_bsontypes.o: mongo_bsontypes.cpp common.h
$(CC) -c -o $@ $< $(CFLAGS)
utils.o: utils.cpp common.h utils.h
View
19 common.h
@@ -1,12 +1,17 @@
-#define LUAMONGO_ROOT "mongo"
-#define LUAMONGO_CONNECTION "mongo.Connection"
-#define LUAMONGO_CURSOR "mongo.Cursor"
-#define LUAMONGO_QUERY "mongo.Query"
+#define LUAMONGO_ROOT "mongo"
+#define LUAMONGO_CONNECTION "mongo.Connection"
+#define LUAMONGO_REPLICASET "mongo.ReplicaSet"
+#define LUAMONGO_CURSOR "mongo.Cursor"
+#define LUAMONGO_QUERY "mongo.Query"
#define LUAMONGO_GRIDFS "mongo.GridFS"
#define LUAMONGO_GRIDFILE "mongo.GridFile"
#define LUAMONGO_GRIDFSCHUNK "mongo.GridFSChunk"
+// not an actual class, pseudo-base for error messages
+#define LUAMONGO_DBCLIENT "mongo.DBClient"
+
#define LUAMONGO_ERR_CONNECTION_FAILED "Connection failed: %s"
+#define LUAMONGO_ERR_REPLICASET_FAILED "ReplicaSet.New failed: %s"
#define LUAMONGO_ERR_GRIDFS_FAILED "GridFS failed: %s"
#define LUAMONGO_ERR_GRIDFSCHUNK_FAILED "GridFSChunk failed: %s"
#define LUAMONGO_ERR_QUERY_FAILED "Query failed: %s"
@@ -22,8 +27,4 @@
#define LUAMONGO_NOT_IMPLEMENTED "Not implemented: %s.%s"
#define LUAMONGO_ERR_CALLING "Error calling %s.%s: %s"
-#if defined(MONGO_PRE_1_5)
- #define CHUNK Chunk
-#else
- #define CHUNK GridFSChunk
-#endif
+
View
2  main.cpp
@@ -38,6 +38,7 @@ extern "C" {
extern int mongo_bsontypes_register(lua_State *L);
extern int mongo_connection_register(lua_State *L);
+extern int mongo_replicaset_register(lua_State *L);
extern int mongo_cursor_register(lua_State *L);
extern int mongo_query_register(lua_State *L);
extern int mongo_gridfs_register(lua_State *L);
@@ -55,6 +56,7 @@ extern "C" {
LM_EXPORT int luaopen_mongo(lua_State *L) {
mongo_bsontypes_register(L);
mongo_connection_register(L);
+ mongo_replicaset_register(L);
mongo_cursor_register(L);
mongo_query_register(L);
View
681 mongo_connection.cpp
@@ -1,4 +1,3 @@
-#include <iostream>
#include <client/dbclient.h>
extern "C" {
@@ -11,26 +10,19 @@ extern "C" {
#endif
};
-#include "utils.h"
#include "common.h"
using namespace mongo;
-extern int cursor_create(lua_State *L, DBClientConnection *connection, const char *ns,
- const Query &query, int nToReturn, int nToSkip,
- const BSONObj *fieldsToReturn, int queryOptions, int batchSize);
-
-extern void lua_to_bson(lua_State *L, int stackpos, BSONObj &obj);
-extern void bson_to_lua(lua_State *L, const BSONObj &obj);
-extern void lua_push_value(lua_State *L, const BSONElement &elem);
+extern const luaL_Reg dbclient_methods[];
namespace {
inline DBClientConnection* userdata_to_connection(lua_State* L, int index) {
- void *ud = 0;
- ud = luaL_checkudata(L, index, LUAMONGO_CONNECTION);
+ void *ud = luaL_checkudata(L, index, LUAMONGO_CONNECTION);
DBClientConnection *connection = *((DBClientConnection **)ud);
return connection;
}
+
} // anonymous namespace
/*
@@ -58,11 +50,7 @@ static int connection_new(lua_State *L) {
}
DBClientConnection **connection = (DBClientConnection **)lua_newuserdata(L, sizeof(DBClientConnection *));
-#if defined(MONGO_PRE_1_5)
- *connection = new DBClientConnection(auto_reconnect, 0);
-#else
*connection = new DBClientConnection(auto_reconnect, 0, rw_timeout);
-#endif
luaL_getmetatable(L, LUAMONGO_CONNECTION);
lua_setmetatable(L, -2);
@@ -75,8 +63,9 @@ static int connection_new(lua_State *L) {
return resultcount;
}
+
/*
- * ok,err = db:connect(connection_str)
+ * ok,err = connection:connect(connection_str)
*/
static int connection_connect(lua_State *L) {
DBClientConnection *connection = userdata_to_connection(L, 1);
@@ -94,640 +83,6 @@ static int connection_connect(lua_State *L) {
return 1;
}
-/*
- * created = db:ensure_index(ns, json_str or lua_table[, unique[, name]])
- */
-static int connection_ensure_index(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
- BSONObj fields;
-
- try {
- int type = lua_type(L, 3);
- if (type == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 3);
- fields = fromjson(jsonstr);
- } else if (type == LUA_TTABLE) {
- lua_to_bson(L, 3, fields);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "ensure_index", e.what());
- return 2;
- } catch (const char *err) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, err);
- return 2;
- }
-
- bool unique = lua_toboolean(L, 4);
- const char *name = luaL_optstring(L, 5, "");
-
- bool res = connection->ensureIndex(ns, fields, unique, name);
-
- lua_pushboolean(L, res);
- return 1;
-}
-
-/*
- * ok,err = db:auth({})
- * accepts a table of parameters:
- * dbname database to authenticate (required)
- * username username to authenticate against (required)
- * password password to authenticate against (required)
- * digestPassword set to true if password is pre-digested (default = true)
- *
- */
-static int connection_auth(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
-
- luaL_checktype(L, 2, LUA_TTABLE);
- lua_getfield(L, 2, "dbname");
- const char *dbname = luaL_checkstring(L, -1);
- lua_getfield(L, 2, "username");
- const char *username = luaL_checkstring(L, -1);
- lua_getfield(L, 2, "password");
- const char *password = luaL_checkstring(L, -1);
- lua_getfield(L, 2, "digestPassword");
- bool digestPassword = lua_isnil(L, -1) ? true : lua_toboolean(L, -1);
- lua_pop(L, 4);
-
- std::string errmsg;
- bool success = connection->auth(dbname, username, password, errmsg, digestPassword);
- if (!success) {
- lua_pushnil(L);
- lua_pushfstring(L, LUAMONGO_ERR_CONNECTION_FAILED, errmsg.c_str());
- return 2;
- }
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * is_failed = db:is_failed()
- */
-static int connection_is_failed(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
-
- bool is_failed = connection->isFailed();
- lua_pushboolean(L, is_failed);
- return 1;
-}
-
-/*
- * addr = db:get_server_address()
- */
-static int connection_get_server_address(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
-
- std::string address = connection->getServerAddress();
- lua_pushstring(L, address.c_str());
- return 1;
-}
-
-/*
- * count,err = db:count(ns)
- */
-static int connection_count(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- int count = 0;
- try {
- count = connection->count(ns);
- } catch (std::exception &e) {
- lua_pushnil(L);
- lua_pushfstring(L, LUAMONGO_ERR_COUNT_FAILED, e.what());
- return 2;
- }
-
- lua_pushinteger(L, count);
- return 1;
-}
-
-/*
- * ok,err = db:insert(ns, lua_table or json_str)
- */
-static int connection_insert(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- try {
- int type = lua_type(L, 3);
- if (type == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 3);
- connection->insert(ns, fromjson(jsonstr));
- } else if (type == LUA_TTABLE) {
- BSONObj data;
- lua_to_bson(L, 3, data);
-
- connection->insert(ns, data);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_INSERT_FAILED, e.what());
- return 2;
- } catch (const char *err) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, err);
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * ok,err = db:insert_batch(ns, lua_array_of_tables)
- */
-static int connection_insert_batch(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
- luaL_checktype(L, 3, LUA_TTABLE);
-
- try {
- std::vector<BSONObj> vdata;
- size_t tlen = lua_objlen(L, 3) + 1;
- for (size_t i = 1; i < tlen; ++i) {
- vdata.push_back(BSONObj());
- lua_rawgeti(L, 3, i);
- lua_to_bson(L, 4, vdata.back());
- lua_pop(L, 1);
- }
- connection->insert(ns, vdata);
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_INSERT_FAILED, e.what());
- return 2;
- } catch (const char *err) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, err);
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * cursor,err = db:query(ns, lua_table or json_str or query_obj, limit, skip, lua_table or json_str, options, batchsize)
- */
-static int connection_query(lua_State *L) {
- int n = lua_gettop(L);
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- Query query;
- if (!lua_isnoneornil(L, 3)) {
- try {
- int type = lua_type(L, 3);
- if (type == LUA_TSTRING) {
- query = fromjson(luaL_checkstring(L, 3));
- } else if (type == LUA_TTABLE) {
- BSONObj obj;
- lua_to_bson(L, 3, obj);
- query = obj;
- } else if (type == LUA_TUSERDATA) {
- void *uq = 0;
-
- uq = luaL_checkudata(L, 3, LUAMONGO_QUERY);
- query = *(*((Query **)uq));
- } else {
- throw(LUAMONGO_REQUIRES_QUERY);
- }
- } catch (std::exception &e) {
- lua_pushnil(L);
- lua_pushfstring(L, LUAMONGO_ERR_QUERY_FAILED, e.what());
- return 2;
- } catch (const char *err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- }
-
- int nToReturn = luaL_optint(L, 4, 0);
- int nToSkip = luaL_optint(L, 5, 0);
-
- const BSONObj *fieldsToReturn = NULL;
- if (!lua_isnoneornil(L, 6)) {
- fieldsToReturn = new BSONObj();
-
- int type = lua_type(L, 6);
-
- if (type == LUA_TSTRING) {
- fieldsToReturn = new BSONObj(luaL_checkstring(L, 6));
- } else if (type == LUA_TTABLE) {
- BSONObj obj;
- lua_to_bson(L, 6, obj);
- fieldsToReturn = new BSONObj(obj);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
- }
-
- int queryOptions = luaL_optint(L, 7, 0);
- int batchSize = luaL_optint(L, 8, 0);
-
- int res = cursor_create(L, connection, ns, query, nToReturn, nToSkip,
- fieldsToReturn, queryOptions, batchSize);
-
- if (fieldsToReturn) {
- delete fieldsToReturn;
- }
-
- return res;
-}
-
-/*
- * ok,err = db:remove(ns, lua_table or json_str or query_obj)
- */
-static int connection_remove(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- try {
- int type = lua_type(L, 3);
- bool justOne = lua_toboolean(L, 4);
-
- if (type == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 3);
- connection->remove(ns, fromjson(jsonstr), justOne);
- } else if (type == LUA_TTABLE) {
- BSONObj data;
- lua_to_bson(L, 3, data);
-
- connection->remove(ns, data, justOne);
- } else if (type == LUA_TUSERDATA) {
- Query query;
- void *uq = 0;
-
- uq = luaL_checkudata(L, 3, LUAMONGO_QUERY);
- query = *(*((Query **)uq));
-
- connection->remove(ns, query, justOne);
- } else {
- throw(LUAMONGO_REQUIRES_QUERY);
- }
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_REMOVE_FAILED, e.what());
- return 2;
- } catch (const char *err) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, err);
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * ok,err = db:update(ns, lua_table or json_str or query_obj, lua_table or json_str, upsert, multi)
- */
-static int connection_update(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- try {
- int type_query = lua_type(L, 3);
- int type_obj = lua_type(L, 4);
-
- bool upsert = lua_toboolean(L, 5);
- bool multi = lua_toboolean(L, 6);
-
- Query query;
- BSONObj obj;
-
- if (type_query == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 3);
- query = fromjson(jsonstr);
- } else if (type_query == LUA_TTABLE) {
- BSONObj q;
-
- lua_to_bson(L, 3, q);
- query = q;
- } else if (type_query == LUA_TUSERDATA) {
- void *uq = 0;
-
- uq = luaL_checkudata(L, 3, LUAMONGO_QUERY);
- query = *(*((Query **)uq));
- } else {
- throw(LUAMONGO_REQUIRES_QUERY);
- }
-
- if (type_obj == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 4);
- obj = fromjson(jsonstr);
- } else if (type_obj == LUA_TTABLE) {
- lua_to_bson(L, 4, obj);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
-
- connection->update(ns, query, obj, upsert, multi);
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_UPDATE_FAILED, e.what());
- return 2;
- } catch (const char *err) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, err);
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * ok,err = db:drop_collection(ns)
- */
-static int connection_drop_collection(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- try {
- connection->dropCollection(ns);
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_collection", e.what());
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * ok,err = db:drop_index_by_fields(ns, json_str or lua_table)
- */
-static int connection_drop_index_by_fields(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- BSONObj keys;
-
- try {
- int type = lua_type(L, 3);
- if (type == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 3);
- keys = fromjson(jsonstr);
- } else if (type == LUA_TTABLE) {
- lua_to_bson(L, 3, keys);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
-
- connection->dropIndex(ns, keys);
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_index_by_fields", e.what());
- return 2;
- } catch (const char *err) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, err);
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * ok,err = db:drop_index_by_name(ns, index_name)
- */
-static int connection_drop_index_by_name(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- try {
- connection->dropIndex(ns, luaL_checkstring(L, 3));
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_index_by_name", e.what());
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * ok,err = db:drop_indexes(ns)
- */
-static int connection_drop_indexes(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- try {
- connection->dropIndexes(ns);
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_indexes", e.what());
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * res,err = (dbname, jscode[, args_table])
- */
-static int connection_eval(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *dbname = luaL_checkstring(L, 2);
- const char *jscode = luaL_checkstring(L, 3);
-
- BSONObj info;
- BSONElement retval;
- BSONObj *args = NULL;
- if (!lua_isnoneornil(L, 4)) {
- try {
- int type = lua_type(L, 4);
-
- if (type == LUA_TSTRING) {
- args = new BSONObj(luaL_checkstring(L, 4));
- } else if (type == LUA_TTABLE) {
- BSONObj obj;
- lua_to_bson(L, 4, obj);
-
- args = new BSONObj(obj);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
- } catch (std::exception &e) {
- lua_pushnil(L);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "eval", e.what());
- return 2;
- } catch (const char *err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- }
-
- bool res = connection->eval(dbname, jscode, info, retval, args);
-
- if (!res) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "eval", info["errmsg"].str().c_str());
-
- return 2;
- }
-
- if (args) {
- delete args;
- }
-
- lua_push_value(L, retval);
- return 1;
-}
-
-/*
- * bool = db:exists(ns)
- */
-static int connection_exists(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- bool res = connection->exists(ns);
-
- lua_pushboolean(L, res);
-
- return 1;
-}
-
-/*
- * name = db:gen_index_name(json_str or lua_table)
- */
-static int connection_gen_index_name(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
-
- string name = "";
-
- try {
- int type = lua_type(L, 2);
- if (type == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 2);
- name = connection->genIndexName(fromjson(jsonstr));
- } else if (type == LUA_TTABLE) {
- BSONObj data;
- lua_to_bson(L, 2, data);
-
- name = connection->genIndexName(data);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
- } catch (std::exception &e) {
- lua_pushnil(L);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "gen_index_name", e.what());
- return 2;
- } catch (const char *err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
-
- lua_pushstring(L, name.c_str());
- return 1;
-}
-
-/*
- * cursor = db:get_indexes(ns)
- */
-static int connection_get_indexes(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- auto_ptr<DBClientCursor> autocursor = connection->getIndexes(ns);
-
- DBClientCursor **cursor = (DBClientCursor **)lua_newuserdata(L, sizeof(DBClientCursor *));
- *cursor = autocursor.get();
- autocursor.release();
-
- luaL_getmetatable(L, LUAMONGO_CURSOR);
- lua_setmetatable(L, -2);
-
- return 1;
-}
-
-/*
- * res,err = db:mapreduce(jsmapfunc, jsreducefunc[, query[, output]])
- */
-static int connection_mapreduce(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
- const char *jsmapfunc = luaL_checkstring(L, 3);
- const char *jsreducefunc = luaL_checkstring(L, 4);
-
- BSONObj query;
- if (!lua_isnoneornil(L, 5)) {
- try {
- int type = lua_type(L, 5);
- if (type == LUA_TSTRING) {
- const char *jsonstr = luaL_checkstring(L, 5);
- query = fromjson(jsonstr);
- } else if (type == LUA_TTABLE) {
- lua_to_bson(L, 5, query);
- } else {
- throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
- }
- } catch (std::exception &e) {
- lua_pushnil(L);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "mapreduce", e.what());
- return 2;
- } catch (const char *err) {
- lua_pushnil(L);
- lua_pushstring(L, err);
- return 2;
- }
- }
-
- const char *output = luaL_optstring(L, 6, "");
-
- BSONObj res = connection->mapreduce(ns, jsmapfunc, jsreducefunc, query, output);
-
- bson_to_lua(L, res);
-
- return 1;
-}
-
-/*
- * ok,err = db:reindex(ns);
- */
-static int connection_reindex(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
- const char *ns = luaL_checkstring(L, 2);
-
- try {
- connection->reIndex(ns);
- } catch (std::exception &e) {
- lua_pushboolean(L, 0);
- lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "reindex", e.what());
- return 2;
- }
-
- lua_pushboolean(L, 1);
- return 1;
-}
-
-/*
- * db:reset_index_cache()
- */
-static int connection_reset_index_cache(lua_State *L) {
- DBClientConnection *connection = userdata_to_connection(L, 1);
-
- connection->resetIndexCache();
-
- return 0;
-}
/*
* __gc
@@ -744,35 +99,13 @@ static int connection_gc(lua_State *L) {
static int connection_tostring(lua_State *L) {
DBClientConnection *connection = userdata_to_connection(L, 1);
lua_pushfstring(L, "%s: %s", LUAMONGO_CONNECTION, connection->toString().c_str());
-
return 1;
}
int mongo_connection_register(lua_State *L) {
static const luaL_Reg connection_methods[] = {
- {"auth", connection_auth},
{"connect", connection_connect},
- {"count", connection_count},
- {"drop_collection", connection_drop_collection},
- {"drop_index_by_fields", connection_drop_index_by_fields},
- {"drop_index_by_name", connection_drop_index_by_name},
- {"drop_indexes", connection_drop_indexes},
- {"ensure_index", connection_ensure_index},
- {"eval", connection_eval},
- {"exists", connection_exists},
- {"gen_index_name", connection_gen_index_name},
- {"get_indexes", connection_get_indexes},
- {"get_server_address", connection_get_server_address},
- {"insert", connection_insert},
- {"insert_batch", connection_insert_batch},
- {"is_failed", connection_is_failed},
- {"mapreduce", connection_mapreduce},
- {"query", connection_query},
- {"reindex", connection_reindex},
- {"remove", connection_remove},
- {"reset_index_cache", connection_reset_index_cache},
- {"update", connection_update},
{NULL, NULL}
};
@@ -782,7 +115,8 @@ int mongo_connection_register(lua_State *L) {
};
luaL_newmetatable(L, LUAMONGO_CONNECTION);
- luaL_register(L, 0, connection_methods);
+ luaL_register(L, NULL, dbclient_methods);
+ luaL_register(L, NULL, connection_methods);
lua_pushvalue(L,-1);
lua_setfield(L, -2, "__index");
@@ -796,3 +130,4 @@ int mongo_connection_register(lua_State *L) {
return 1;
}
+
View
7 mongo_cursor.cpp
@@ -30,7 +30,7 @@ inline DBClientCursor* userdata_to_cursor(lua_State* L, int index) {
/*
* cursor,err = db:query(ns, query)
*/
-int cursor_create(lua_State *L, DBClientConnection *connection, const char *ns,
+int cursor_create(lua_State *L, DBClientBase *connection, const char *ns,
const Query &query, int nToReturn, int nToSkip,
const BSONObj *fieldsToReturn, int queryOptions, int batchSize) {
int resultcount = 1;
@@ -96,15 +96,12 @@ static int cursor_results(lua_State *L) {
static int cursor_has_more(lua_State *L) {
DBClientCursor *cursor = userdata_to_cursor(L, 1);
-#if defined(MONGO_1_5)
bool in_current_batch = lua_toboolean(L, 2);
if (in_current_batch)
lua_pushboolean(L, cursor->moreInCurrentBatch());
else
lua_pushboolean(L, cursor->more());
-#else
- lua_pushboolean(L, cursor->more());
-#endif // defined(MONGO_1_5)
+
return 1;
}
View
735 mongo_dbclient.cpp
@@ -0,0 +1,735 @@
+#include <client/dbclient.h>
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+
+#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
+#include <compat-5.1.h>
+#endif
+};
+
+#include "utils.h"
+#include "common.h"
+
+using namespace mongo;
+
+extern int cursor_create(lua_State *L, DBClientBase *connection, const char *ns,
+ const Query &query, int nToReturn, int nToSkip,
+ const BSONObj *fieldsToReturn, int queryOptions, int batchSize);
+
+extern void lua_to_bson(lua_State *L, int stackpos, BSONObj &obj);
+extern void bson_to_lua(lua_State *L, const BSONObj &obj);
+extern void lua_push_value(lua_State *L, const BSONElement &elem);
+
+
+DBClientBase* userdata_to_dbclient(lua_State *L, int stackpos)
+{
+ // adapted from http://www.lua.org/source/5.1/lauxlib.c.html#luaL_checkudata
+ void *ud = lua_touserdata(L, stackpos);
+ if (ud == NULL)
+ luaL_typerror(L, stackpos, "userdata");
+
+ // try Connection
+ lua_getfield(L, LUA_REGISTRYINDEX, LUAMONGO_CONNECTION);
+ if (lua_getmetatable(L, stackpos))
+ {
+ if (lua_rawequal(L, -1, -2))
+ {
+ DBClientConnection *connection = *((DBClientConnection **)ud);
+ lua_pop(L, 2);
+ return connection;
+ }
+ lua_pop(L, 2);
+ }
+ else
+ lua_pop(L, 1);
+
+ // try ReplicaSet
+ lua_getfield(L, LUA_REGISTRYINDEX, LUAMONGO_REPLICASET); // get correct metatable
+ if (lua_getmetatable(L, stackpos))
+ {
+ if (lua_rawequal(L, -1, -2))
+ {
+ DBClientReplicaSet *replicaset = *((DBClientReplicaSet **)ud);
+ lua_pop(L, 2); // remove both metatables
+ return replicaset;
+ }
+ lua_pop(L, 2);
+ }
+ else
+ lua_pop(L, 1);
+
+ luaL_typerror(L, stackpos, LUAMONGO_DBCLIENT);
+ return NULL; // should never get here
+}
+
+
+/***********************************************************************/
+// The following methods are common to all DBClients
+// (DBClientConnection and DBClientReplicaSet)
+/***********************************************************************/
+
+
+/*
+ * created = db:ensure_index(ns, json_str or lua_table[, unique[, name]])
+ */
+static int dbclient_ensure_index(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+ BSONObj fields;
+
+ try {
+ int type = lua_type(L, 3);
+ if (type == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 3);
+ fields = fromjson(jsonstr);
+ } else if (type == LUA_TTABLE) {
+ lua_to_bson(L, 3, fields);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "ensure_index", e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, err);
+ return 2;
+ }
+
+ bool unique = lua_toboolean(L, 4);
+ const char *name = luaL_optstring(L, 5, "");
+
+ bool res = dbclient->ensureIndex(ns, fields, unique, name);
+
+ lua_pushboolean(L, res);
+ return 1;
+}
+
+/*
+ * ok,err = db:auth({})
+ * accepts a table of parameters:
+ * dbname database to authenticate (required)
+ * username username to authenticate against (required)
+ * password password to authenticate against (required)
+ * digestPassword set to true if password is pre-digested (default = true)
+ *
+ */
+static int dbclient_auth(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_getfield(L, 2, "dbname");
+ const char *dbname = luaL_checkstring(L, -1);
+ lua_getfield(L, 2, "username");
+ const char *username = luaL_checkstring(L, -1);
+ lua_getfield(L, 2, "password");
+ const char *password = luaL_checkstring(L, -1);
+ lua_getfield(L, 2, "digestPassword");
+ bool digestPassword = lua_isnil(L, -1) ? true : lua_toboolean(L, -1);
+ lua_pop(L, 4);
+
+ std::string errmsg;
+ bool success = dbclient->auth(dbname, username, password, errmsg, digestPassword);
+ if (!success) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_CONNECTION_FAILED, errmsg.c_str());
+ return 2;
+ }
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * is_failed = db:is_failed()
+ */
+static int dbclient_is_failed(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+
+ bool is_failed = dbclient->isFailed();
+ lua_pushboolean(L, is_failed);
+ return 1;
+}
+
+/*
+ * addr = db:get_server_address()
+ */
+static int dbclient_get_server_address(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+
+ std::string address = dbclient->getServerAddress();
+ lua_pushstring(L, address.c_str());
+ return 1;
+}
+
+/*
+ * count,err = db:count(ns)
+ */
+static int dbclient_count(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ int count = 0;
+ try {
+ count = dbclient->count(ns);
+ } catch (std::exception &e) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_COUNT_FAILED, e.what());
+ return 2;
+ }
+
+ lua_pushinteger(L, count);
+ return 1;
+}
+
+/*
+ * ok,err = db:insert(ns, lua_table or json_str)
+ */
+static int dbclient_insert(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ try {
+ int type = lua_type(L, 3);
+ if (type == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 3);
+ dbclient->insert(ns, fromjson(jsonstr));
+ } else if (type == LUA_TTABLE) {
+ BSONObj data;
+ lua_to_bson(L, 3, data);
+
+ dbclient->insert(ns, data);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_INSERT_FAILED, e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, err);
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * ok,err = db:insert_batch(ns, lua_array_of_tables)
+ */
+static int dbclient_insert_batch(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+ luaL_checktype(L, 3, LUA_TTABLE);
+
+ try {
+ std::vector<BSONObj> vdata;
+ size_t tlen = lua_objlen(L, 3) + 1;
+ for (size_t i = 1; i < tlen; ++i) {
+ vdata.push_back(BSONObj());
+ lua_rawgeti(L, 3, i);
+ lua_to_bson(L, 4, vdata.back());
+ lua_pop(L, 1);
+ }
+ dbclient->insert(ns, vdata);
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_INSERT_FAILED, e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, err);
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * cursor,err = db:query(ns, lua_table or json_str or query_obj, limit, skip, lua_table or json_str, options, batchsize)
+ */
+static int dbclient_query(lua_State *L) {
+ int n = lua_gettop(L);
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ Query query;
+ if (!lua_isnoneornil(L, 3)) {
+ try {
+ int type = lua_type(L, 3);
+ if (type == LUA_TSTRING) {
+ query = fromjson(luaL_checkstring(L, 3));
+ } else if (type == LUA_TTABLE) {
+ BSONObj obj;
+ lua_to_bson(L, 3, obj);
+ query = obj;
+ } else if (type == LUA_TUSERDATA) {
+ void *uq = 0;
+
+ uq = luaL_checkudata(L, 3, LUAMONGO_QUERY);
+ query = *(*((Query **)uq));
+ } else {
+ throw(LUAMONGO_REQUIRES_QUERY);
+ }
+ } catch (std::exception &e) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_QUERY_FAILED, e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ }
+
+ int nToReturn = luaL_optint(L, 4, 0);
+ int nToSkip = luaL_optint(L, 5, 0);
+
+ const BSONObj *fieldsToReturn = NULL;
+ if (!lua_isnoneornil(L, 6)) {
+ fieldsToReturn = new BSONObj();
+
+ int type = lua_type(L, 6);
+
+ if (type == LUA_TSTRING) {
+ fieldsToReturn = new BSONObj(luaL_checkstring(L, 6));
+ } else if (type == LUA_TTABLE) {
+ BSONObj obj;
+ lua_to_bson(L, 6, obj);
+ fieldsToReturn = new BSONObj(obj);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+ }
+
+ int queryOptions = luaL_optint(L, 7, 0);
+ int batchSize = luaL_optint(L, 8, 0);
+
+ int res = cursor_create(L, dbclient, ns, query, nToReturn, nToSkip,
+ fieldsToReturn, queryOptions, batchSize);
+
+ if (fieldsToReturn) {
+ delete fieldsToReturn;
+ }
+
+ return res;
+}
+
+/*
+ * ok,err = db:remove(ns, lua_table or json_str or query_obj)
+ */
+static int dbclient_remove(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ try {
+ int type = lua_type(L, 3);
+ bool justOne = lua_toboolean(L, 4);
+
+ if (type == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 3);
+ dbclient->remove(ns, fromjson(jsonstr), justOne);
+ } else if (type == LUA_TTABLE) {
+ BSONObj data;
+ lua_to_bson(L, 3, data);
+
+ dbclient->remove(ns, data, justOne);
+ } else if (type == LUA_TUSERDATA) {
+ Query query;
+ void *uq = 0;
+
+ uq = luaL_checkudata(L, 3, LUAMONGO_QUERY);
+ query = *(*((Query **)uq));
+
+ dbclient->remove(ns, query, justOne);
+ } else {
+ throw(LUAMONGO_REQUIRES_QUERY);
+ }
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_REMOVE_FAILED, e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, err);
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * ok,err = db:update(ns, lua_table or json_str or query_obj, lua_table or json_str, upsert, multi)
+ */
+static int dbclient_update(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ try {
+ int type_query = lua_type(L, 3);
+ int type_obj = lua_type(L, 4);
+
+ bool upsert = lua_toboolean(L, 5);
+ bool multi = lua_toboolean(L, 6);
+
+ Query query;
+ BSONObj obj;
+
+ if (type_query == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 3);
+ query = fromjson(jsonstr);
+ } else if (type_query == LUA_TTABLE) {
+ BSONObj q;
+
+ lua_to_bson(L, 3, q);
+ query = q;
+ } else if (type_query == LUA_TUSERDATA) {
+ void *uq = 0;
+
+ uq = luaL_checkudata(L, 3, LUAMONGO_QUERY);
+ query = *(*((Query **)uq));
+ } else {
+ throw(LUAMONGO_REQUIRES_QUERY);
+ }
+
+ if (type_obj == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 4);
+ obj = fromjson(jsonstr);
+ } else if (type_obj == LUA_TTABLE) {
+ lua_to_bson(L, 4, obj);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+
+ dbclient->update(ns, query, obj, upsert, multi);
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_UPDATE_FAILED, e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, err);
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * ok,err = db:drop_collection(ns)
+ */
+static int dbclient_drop_collection(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ try {
+ dbclient->dropCollection(ns);
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_collection", e.what());
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * ok,err = db:drop_index_by_fields(ns, json_str or lua_table)
+ */
+static int dbclient_drop_index_by_fields(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ BSONObj keys;
+
+ try {
+ int type = lua_type(L, 3);
+ if (type == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 3);
+ keys = fromjson(jsonstr);
+ } else if (type == LUA_TTABLE) {
+ lua_to_bson(L, 3, keys);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+
+ dbclient->dropIndex(ns, keys);
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_index_by_fields", e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, err);
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * ok,err = db:drop_index_by_name(ns, index_name)
+ */
+static int dbclient_drop_index_by_name(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ try {
+ dbclient->dropIndex(ns, luaL_checkstring(L, 3));
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_index_by_name", e.what());
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * ok,err = db:drop_indexes(ns)
+ */
+static int dbclient_drop_indexes(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ try {
+ dbclient->dropIndexes(ns);
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "drop_indexes", e.what());
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * res,err = (dbname, jscode[, args_table])
+ */
+static int dbclient_eval(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *dbname = luaL_checkstring(L, 2);
+ const char *jscode = luaL_checkstring(L, 3);
+
+ BSONObj info;
+ BSONElement retval;
+ BSONObj *args = NULL;
+ if (!lua_isnoneornil(L, 4)) {
+ try {
+ int type = lua_type(L, 4);
+
+ if (type == LUA_TSTRING) {
+ args = new BSONObj(luaL_checkstring(L, 4));
+ } else if (type == LUA_TTABLE) {
+ BSONObj obj;
+ lua_to_bson(L, 4, obj);
+
+ args = new BSONObj(obj);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+ } catch (std::exception &e) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "eval", e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ }
+
+ bool res = dbclient->eval(dbname, jscode, info, retval, args);
+
+ if (!res) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "eval", info["errmsg"].str().c_str());
+
+ return 2;
+ }
+
+ if (args) {
+ delete args;
+ }
+
+ lua_push_value(L, retval);
+ return 1;
+}
+
+/*
+ * bool = db:exists(ns)
+ */
+static int dbclient_exists(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ bool res = dbclient->exists(ns);
+
+ lua_pushboolean(L, res);
+
+ return 1;
+}
+
+/*
+ * name = db:gen_index_name(json_str or lua_table)
+ */
+static int dbclient_gen_index_name(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+
+ string name = "";
+
+ try {
+ int type = lua_type(L, 2);
+ if (type == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 2);
+ name = dbclient->genIndexName(fromjson(jsonstr));
+ } else if (type == LUA_TTABLE) {
+ BSONObj data;
+ lua_to_bson(L, 2, data);
+
+ name = dbclient->genIndexName(data);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+ } catch (std::exception &e) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "gen_index_name", e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+
+ lua_pushstring(L, name.c_str());
+ return 1;
+}
+
+/*
+ * cursor = db:get_indexes(ns)
+ */
+static int dbclient_get_indexes(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ auto_ptr<DBClientCursor> autocursor = dbclient->getIndexes(ns);
+
+ DBClientCursor **cursor = (DBClientCursor **)lua_newuserdata(L, sizeof(DBClientCursor *));
+ *cursor = autocursor.get();
+ autocursor.release();
+
+ luaL_getmetatable(L, LUAMONGO_CURSOR);
+ lua_setmetatable(L, -2);
+
+ return 1;
+}
+
+/*
+ * res,err = db:mapreduce(jsmapfunc, jsreducefunc[, query[, output]])
+ */
+static int dbclient_mapreduce(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+ const char *jsmapfunc = luaL_checkstring(L, 3);
+ const char *jsreducefunc = luaL_checkstring(L, 4);
+
+ BSONObj query;
+ if (!lua_isnoneornil(L, 5)) {
+ try {
+ int type = lua_type(L, 5);
+ if (type == LUA_TSTRING) {
+ const char *jsonstr = luaL_checkstring(L, 5);
+ query = fromjson(jsonstr);
+ } else if (type == LUA_TTABLE) {
+ lua_to_bson(L, 5, query);
+ } else {
+ throw(LUAMONGO_REQUIRES_JSON_OR_TABLE);
+ }
+ } catch (std::exception &e) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "mapreduce", e.what());
+ return 2;
+ } catch (const char *err) {
+ lua_pushnil(L);
+ lua_pushstring(L, err);
+ return 2;
+ }
+ }
+
+ const char *output = luaL_optstring(L, 6, "");
+
+ BSONObj res = dbclient->mapreduce(ns, jsmapfunc, jsreducefunc, query, output);
+
+ bson_to_lua(L, res);
+
+ return 1;
+}
+
+/*
+ * ok,err = db:reindex(ns);
+ */
+static int dbclient_reindex(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+ const char *ns = luaL_checkstring(L, 2);
+
+ try {
+ dbclient->reIndex(ns);
+ } catch (std::exception &e) {
+ lua_pushboolean(L, 0);
+ lua_pushfstring(L, LUAMONGO_ERR_CALLING, LUAMONGO_CONNECTION, "reindex", e.what());
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/*
+ * db:reset_index_cache()
+ */
+static int dbclient_reset_index_cache(lua_State *L) {
+ DBClientBase *dbclient = userdata_to_dbclient(L, 1);
+
+ dbclient->resetIndexCache();
+
+ return 0;
+}
+
+// Method registration table for DBClients
+extern const luaL_Reg dbclient_methods[] = {
+ {"auth", dbclient_auth},
+ {"count", dbclient_count},
+ {"drop_collection", dbclient_drop_collection},
+ {"drop_index_by_fields", dbclient_drop_index_by_fields},
+ {"drop_index_by_name", dbclient_drop_index_by_name},
+ {"drop_indexes", dbclient_drop_indexes},
+ {"ensure_index", dbclient_ensure_index},
+ {"eval", dbclient_eval},
+ {"exists", dbclient_exists},
+ {"gen_index_name", dbclient_gen_index_name},
+ {"get_indexes", dbclient_get_indexes},
+ {"get_server_address", dbclient_get_server_address},
+ {"insert", dbclient_insert},
+ {"insert_batch", dbclient_insert_batch},
+ {"is_failed", dbclient_is_failed},
+ {"mapreduce", dbclient_mapreduce},
+ {"query", dbclient_query},
+ {"reindex", dbclient_reindex},
+ {"remove", dbclient_remove},
+ {"reset_index_cache", dbclient_reset_index_cache},
+ {"update", dbclient_update},
+ {NULL, NULL}
+};
+
+
View
6 mongo_gridfile.cpp
@@ -52,10 +52,10 @@ static int gridfile_chunk(lua_State *L) {
int resultcount = 1;
try {
- CHUNK c = gridfile->getChunk(num);
- CHUNK *chunk_ptr = new CHUNK(c);
+ GridFSChunk c = gridfile->getChunk(num);
+ GridFSChunk *chunk_ptr = new GridFSChunk(c);
- CHUNK **chunk = (CHUNK **)lua_newuserdata(L, sizeof(CHUNK *));
+ GridFSChunk **chunk = (GridFSChunk **)lua_newuserdata(L, sizeof(GridFSChunk *));
*chunk = chunk_ptr;
luaL_getmetatable(L, LUAMONGO_GRIDFSCHUNK);
View
9 mongo_gridfs.cpp
@@ -20,6 +20,7 @@ using namespace mongo;
extern void lua_to_bson(lua_State *L, int stackpos, BSONObj &obj);
extern void bson_to_lua(lua_State *L, const BSONObj &obj);
extern int gridfile_create(lua_State *L, GridFile gf);
+extern DBClientBase* userdata_to_dbclient(lua_State *L, int stackpos);
namespace {
inline GridFS* userdata_to_gridfs(lua_State* L, int index) {
@@ -30,7 +31,7 @@ namespace {
return gridfs;
}
-}
+} // anonymous namespace
/*
* gridfs, err = mongo.GridFS.New(connection, dbname[, prefix])
@@ -40,11 +41,7 @@ static int gridfs_new(lua_State *L) {
int resultcount = 1;
try {
- void *ud = 0;
-
- ud = luaL_checkudata(L, 1, LUAMONGO_CONNECTION);
- DBClientConnection *connection = *((DBClientConnection **)ud);
-
+ DBClientBase *connection = userdata_to_dbclient(L, 1);
const char *dbname = lua_tostring(L, 2);
GridFS **gridfs = (GridFS **)lua_newuserdata(L, sizeof(GridFS *));
View
12 mongo_gridfschunk.cpp
@@ -18,11 +18,11 @@ extern "C" {
using namespace mongo;
namespace {
- inline CHUNK* userdata_to_gridfschunk(lua_State* L, int index) {
+ inline GridFSChunk* userdata_to_gridfschunk(lua_State* L, int index) {
void *ud = 0;
ud = luaL_checkudata(L, index, LUAMONGO_GRIDFSCHUNK);
- CHUNK *chunk = *((CHUNK **)ud);
+ GridFSChunk *chunk = *((GridFSChunk **)ud);
return chunk;
}
@@ -32,7 +32,7 @@ namespace {
* str = chunk:data()
*/
static int gridfschunk_data(lua_State *L) {
- CHUNK *chunk = userdata_to_gridfschunk(L, 1);
+ GridFSChunk *chunk = userdata_to_gridfschunk(L, 1);
int len;
const char *data = chunk->data(len);
@@ -47,7 +47,7 @@ static int gridfschunk_data(lua_State *L) {
* __len
*/
static int gridfschunk_len(lua_State *L) {
- CHUNK *chunk = userdata_to_gridfschunk(L, 1);
+ GridFSChunk *chunk = userdata_to_gridfschunk(L, 1);
int len = chunk->len();
@@ -61,7 +61,7 @@ static int gridfschunk_len(lua_State *L) {
* __gc
*/
static int gridfschunk_gc(lua_State *L) {
- CHUNK *chunk = userdata_to_gridfschunk(L, 1);
+ GridFSChunk *chunk = userdata_to_gridfschunk(L, 1);
delete chunk;
@@ -72,7 +72,7 @@ static int gridfschunk_gc(lua_State *L) {
* __tostring
*/
static int gridfschunk_tostring(lua_State *L) {
- CHUNK *chunk = userdata_to_gridfschunk(L, 1);
+ GridFSChunk *chunk = userdata_to_gridfschunk(L, 1);
lua_pushfstring(L, "%s: %p", LUAMONGO_GRIDFSCHUNK, chunk);
View
132 mongo_replicaset.cpp
@@ -0,0 +1,132 @@
+#include <client/dbclient.h>
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
+#include <compat-5.1.h>
+#endif
+};
+
+#include "common.h"
+
+using namespace mongo;
+
+extern const luaL_Reg dbclient_methods[];
+
+namespace {
+inline DBClientReplicaSet* userdata_to_replicaset(lua_State* L, int index) {
+ void *ud = luaL_checkudata(L, index, LUAMONGO_REPLICASET);
+ DBClientReplicaSet *replicaset = *((DBClientReplicaSet **)ud);
+ return replicaset;
+}
+
+} // anonymous namespace
+
+
+/*
+ * db,err = mongo.ReplicaSet.New(name, {hostAndPort1, ...)
+ */
+static int replicaset_new(lua_State *L) {
+ luaL_checktype(L, 1, LUA_TSTRING);
+ luaL_checktype(L, 2, LUA_TTABLE);
+
+ int resultcount = 1;
+ try {
+ const char *rs_name = luaL_checkstring(L, 1);
+
+ std::vector<mongo::HostAndPort> rs_servers;
+ int i = 1;
+ while (1) {
+ lua_pushinteger(L, i++);
+ lua_gettable(L, 2);
+ const char* hostAndPort = lua_tostring(L, -1);
+ lua_pop(L, 1);
+ if (!hostAndPort)
+ break;
+ HostAndPort hp(hostAndPort);
+ rs_servers.push_back(hp);
+ }
+
+ DBClientReplicaSet **replicaset = (DBClientReplicaSet **)lua_newuserdata(L, sizeof(DBClientReplicaSet *));
+ *replicaset = new DBClientReplicaSet(rs_name, rs_servers);
+
+ luaL_getmetatable(L, LUAMONGO_REPLICASET);
+ lua_setmetatable(L, -2);
+ } catch (std::exception &e) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_REPLICASET_FAILED, e.what());
+ resultcount = 2;
+ }
+
+ return resultcount;
+}
+
+/*
+ * ok,err = replicaset:connect()
+ */
+static int replicaset_connect(lua_State *L) {
+ DBClientReplicaSet *replicaset = userdata_to_replicaset(L, 1);
+
+ try {
+ replicaset->connect();
+ } catch (std::exception &e) {
+ lua_pushnil(L);
+ lua_pushfstring(L, LUAMONGO_ERR_CONNECT_FAILED, LUAMONGO_REPLICASET, e.what());
+ return 2;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+
+/*
+ * __gc
+ */
+static int replicaset_gc(lua_State *L) {
+ DBClientReplicaSet *replicaset = userdata_to_replicaset(L, 1);
+ delete replicaset;
+ return 0;
+}
+
+/*
+ * __tostring
+ */
+static int replicaset_tostring(lua_State *L) {
+ DBClientReplicaSet *replicaset = userdata_to_replicaset(L, 1);
+ lua_pushfstring(L, "%s: %s", LUAMONGO_REPLICASET, replicaset->toString().c_str());
+ return 1;
+}
+
+
+int mongo_replicaset_register(lua_State *L) {
+ static const luaL_Reg replicaset_methods[] = {
+ {"connect", replicaset_connect},
+ {NULL, NULL}
+ };
+
+ static const luaL_Reg replicaset_class_methods[] = {
+ {"New", replicaset_new},
+ {NULL, NULL}
+ };
+
+ luaL_newmetatable(L, LUAMONGO_REPLICASET);
+ luaL_register(L, NULL, dbclient_methods);
+ luaL_register(L, NULL, replicaset_methods);
+ lua_pushvalue(L,-1);
+ lua_setfield(L, -2, "__index");
+
+ lua_pushcfunction(L, replicaset_gc);
+ lua_setfield(L, -2, "__gc");
+
+ lua_pushcfunction(L, replicaset_tostring);
+ lua_setfield(L, -2, "__tostring");
+
+ luaL_register(L, LUAMONGO_REPLICASET, replicaset_class_methods);
+
+ return 1;
+}
+
View
64 tests/connection.lua
@@ -0,0 +1,64 @@
+#!/usr/bin/lua
+-- Tests DB connection bindings
+--
+-- Configuration can be set with the following environment variables:
+-- TEST_SERVER ('localhost')
+-- TEST_DB ('test')
+-- TEST_USER (nil, no auth will be done)
+-- TEST_PASS ('')
+
+require 'mongo'
+require 'os'
+
+require 'tests/lunity'
+module( 'LUAMONGO_TEST_CONNECTION', lunity )
+
+function setup()
+ test_server = os.getenv('TEST_SERVER') or 'localhost'
+ test_user = os.getenv('TEST_USER') or nil
+ test_password = os.getenv('TEST_PASS') or ''
+ test_db = os.getenv('TEST_DB') or 'test'
+ test_ns = test_db .. '.conn_values'
+end
+
+function teardown()
+end
+
+function test_ReplicaSet()
+ -- Create a Connection object
+ local db = mongo.Connection.New()
+ assertNotNil( db, 'unable to create mongo.Connection' )
+ assert( db:connect(test_server), 'unable to forcefully connect to mongo instance' )
+
+ -- test data
+ local data = { a = 10, b = 'str1' }
+ local data_as_json = "{'a': 10, 'b': 'str1'}"
+
+ -- auth if we need to
+ if test_user then
+ assertTrue( db:auth{dbname=test_db, username=test_user, password=test_password}, "unable to auth to db" )
+ end
+
+ -- drop existing data
+ assertTrue( db:drop_collection(test_ns) )
+
+ -- insert a value into the namespace 'test.values'
+ assertTrue( db:insert(test_ns, data), 'unable to insert table-based data' )
+
+ -- insert the same using a JSON string
+ assertTrue( db:insert(test_ns, data_as_json), 'unable to insert JSON-based data' )
+
+ -- check the data
+ assertEqual( 2, db:count(test_ns) )
+
+ -- query all the values in the namespace, ensuring the values are equal to the inserted values
+ local q = db:query( test_ns, {} )
+ assertNotNil( q, 'unable to create Query object' )
+ for result in q:results() do
+ assertEqual( result.a, data.a )
+ assertEqual( result.b, data.b )
+ end
+end
+
+
+runTests()
View
366 tests/lunity.lua
@@ -0,0 +1,366 @@
+--[=========================================================================[
+ Lunity v0.9 by Gavin Kistner
+
+ This work is licensed under the Creative Commons Attribution 3.0
+ United States License. To view a copy of this license, visit
+ http://creativecommons.org/licenses/by/3.0/us/ or send a letter to
+ Creative Commons
+ 171 Second Street, Suite 300
+ San Francisco, California, 94105, USA
+
+ Usage:
+ require 'my_own_code'
+ require 'lunity'
+ module( 'TEST_RUNTIME', lunity )
+
+ function setup()
+ -- code here will be run before each test
+ end
+
+ function teardown()
+ -- code here will be run after each test
+ end
+
+ function test1_foo()
+ -- Tests to run must either start with or end with 'test'
+ assertTrue( 42 == 40 + 2 )
+ assertFalse( 42 == 40 )
+ assertEqual( 42, 40 + 2 )
+ assertNotEqual( 42, 40, "These better not be the same!" )
+ assertTableEquals( { a=42 }, { ["a"]=6*7 } )
+ -- See library for more assertions available
+ end
+
+ function test2_bar()
+ -- Tests will be run in alphabetical order of the entire function name
+ end
+
+ function utility()
+ -- You can define functions for your tests to call with impunity
+ end
+
+ runTests( )
+ -- or runTests{ useANSI = false }
+ -- or runTests{ useHTML = true }
+--]=========================================================================]
+
+local setmetatable=setmetatable
+local _G=_G
+module( 'lunity' )
+
+VERSION = "0.9"
+
+local lunity = _M
+setmetatable( lunity, {
+ __index = _G,
+ __call = function( self, testSuite )
+ setmetatable( testSuite, {
+ __index = function( testSuite, value )
+ if value == 'runTests' then
+ return function( options ) lunity.__runAllTests( testSuite, options ) end
+ elseif lunity[value] then
+ return lunity[value]
+ else
+ return nil
+ end
+ end
+ } )
+ end
+} )
+
+function __assertionSucceeded()
+ lunity.__assertsPassed = lunity.__assertsPassed + 1
+ io.write('.')
+ return true
+end
+
+function fail( msg )
+ if not msg then msg = "(test failure)" end
+ error( msg, 2 )
+end
+
+function assert( testCondition, msg )
+ if not testCondition then
+ if not msg then msg = "assert() failed: value was "..tostring(testCondition) end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertEqual( actual, expected, msg )
+ if actual~=expected then
+ if not msg then
+ msg = string.format( "assertEqual() failed: expected %s, was %s",
+ tostring(expected),
+ tostring(actual)
+ )
+ end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertTableEquals( actual, expected, msg, keyPath )
+ -- Easy out
+ if actual == expected then
+ if not keyPath then
+ return __assertionSucceeded()
+ else
+ return true
+ end
+ end
+
+ if not keyPath then keyPath = {} end
+
+ if type(actual) ~= 'table' then
+ if not msg then
+ msg = "Value passed to assertTableEquals() was not a table."
+ end
+ error( msg, 2 + #keyPath )
+ end
+
+ -- Ensure all keys in t1 match in t2
+ for key,expectedValue in pairs( expected ) do
+ keyPath[#keyPath+1] = tostring(key)
+ local actualValue = actual[key]
+ if type(expectedValue)=='table' then
+ if type(actualValue)~='table' then
+ if not msg then
+ msg = "Tables not equal; expected "..table.concat(keyPath,'.').." to be a table, but was a "..type(actualValue)
+ end
+ error( msg, 1 + #keyPath )
+ elseif expectedValue ~= actualValue then
+ assertTableEquals( actualValue, expectedValue, msg, keyPath )
+ end
+ else
+ if actualValue ~= expectedValue then
+ if not msg then
+ if actualValue == nil then
+ msg = "Tables not equal; missing key '"..table.concat(keyPath,'.').."'."
+ else
+ msg = "Tables not equal; expected '"..table.concat(keyPath,'.').."' to be "..tostring(expectedValue)..", but was "..tostring(actualValue)
+ end
+ end
+ error( msg, 1 + #keyPath )
+ end
+ end
+ keyPath[#keyPath] = nil
+ end
+
+ -- Ensure actual doesn't have keys that aren't expected
+ for k,_ in pairs(actual) do
+ if expected[k] == nil then
+ if not msg then
+ msg = "Tables not equal; found unexpected key '"..table.concat(keyPath,'.').."."..tostring(k).."'"
+ end
+ error( msg, 2 + #keyPath )
+ end
+ end
+
+ return __assertionSucceeded()
+end
+
+function assertNotEqual( actual, expected, msg )
+ if actual==expected then
+ if not msg then
+ msg = string.format( "assertNotEqual() failed: value not allowed to be %s",
+ tostring(actual)
+ )
+ end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertTrue( actual, msg )
+ if actual ~= true then
+ if not msg then
+ msg = string.format( "assertTrue() failed: value was %s, expected true",
+ tostring(actual)
+ )
+ end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertFalse( actual, msg )
+ if actual ~= false then
+ if not msg then
+ msg = string.format( "assertFalse() failed: value was %s, expected false",
+ tostring(actual)
+ )
+ end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertNil( actual, msg )
+ if actual ~= nil then
+ if not msg then
+ msg = string.format( "assertNil() failed: value was %s, expected nil",
+ tostring(actual)
+ )
+ end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertNotNil( actual, msg )
+ if actual == nil then
+ if not msg then msg = "assertNotNil() failed: value was nil" end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertType( actual, expectedType, msg )
+ if type(actual) ~= expectedType then
+ if not msg then
+ msg = string.format( "assertType() failed: value %s is a %s, expected to be a %s",
+ tostring(actual),
+ type(actual),
+ expectedType
+ )
+ end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+-- Ensures that the value is a function OR may be called as one
+function assertInvokable( value, msg )
+ local meta = getmetatable(value)
+ if (type(value) ~= 'function') and not ( meta and meta.__call and (type(meta.__call)=='function') ) then
+ if not msg then
+ msg = string.format( "assertInvokable() failed: '%s' can not be called as a function",
+ tostring(value)
+ )
+ end
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertErrors( invokable, ... )
+ assertInvokable( invokable )
+ if pcall(invokable,...) then
+ local msg = string.format( "assertErrors() failed: %s did not raise an error",
+ tostring(invokable)
+ )
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function assertDoesNotError( invokable, ... )
+ assertInvokable( invokable )
+ if not pcall(invokable,...) then
+ local msg = string.format( "assertDoesNotError() failed: %s raised an error",
+ tostring(invokable)
+ )
+ error( msg, 2 )
+ end
+ return __assertionSucceeded()
+end
+
+function is_nil( value ) return type(value)=='nil' end
+function is_boolean( value ) return type(value)=='boolean' end
+function is_number( value ) return type(value)=='number' end
+function is_string( value ) return type(value)=='string' end
+function is_table( value ) return type(value)=='table' end
+function is_function( value ) return type(value)=='function' end
+function is_thread( value ) return type(value)=='thread' end
+function is_userdata( value ) return type(value)=='userdata' end
+
+function __runAllTests( testSuite, options )
+ if not options then options = {} end
+ lunity.__assertsPassed = 0
+
+ local useHTML, useANSI
+ if options.useHTML ~= nil then
+ useHTML = options.useHTML
+ else
+ useHTML = lunity.useHTML
+ end
+
+ if not useHTML then
+ if options.useANSI ~= nil then
+ useANSI = options.useANSI
+ elseif lunity.useANSI ~= nil then
+ useANSI = lunity.useANSI
+ else
+ useANSI = true
+ end
+ end
+
+ if useHTML then
+ print( "<h2 style='background:#000; color:#fff; margin:1em 0 0 0; padding:0.1em 0.4em; font-size:120%'>"..testSuite._NAME.."</h2><pre style='margin:0; padding:0.2em 1em; background:#ffe; border:1px solid #eed; overflow:auto'>" )
+ else
+ print( string.rep('=',78) )
+ print( testSuite._NAME )
+ print( string.rep('=',78) )
+ end
+ io.stdout:flush()
+
+ local theTestNames = {}
+ for testName,test in pairs(testSuite) do
+ if type(test)=='function' and type(testName)=='string' and (testName:find("^test") or testName:find("test$")) then
+ theTestNames[#theTestNames+1] = testName
+ end
+ end
+ table.sort(theTestNames)
+
+ local theSuccessCount = 0
+ for _,testName in ipairs(theTestNames) do
+ local testScratchpad = {}
+ io.write( testName..": " )
+ if testSuite.setup then testSuite.setup(testScratchpad) end
+ local successFlag, errorMessage = pcall( testSuite[testName], testScratchpad )
+ if successFlag then
+ print( "pass" )
+ theSuccessCount = theSuccessCount + 1
+ else
+ if useANSI then
+ print( "\27[31m\27[1mFAIL!\27[0m" )
+ print( "\27[31m"..errorMessage.."\27[0m" )
+ elseif useHTML then
+ print("<b style='color:red'>FAIL!</b>")
+ print( "<span style='color:red'>"..errorMessage.."</span>" )
+ else
+ print("FAIL!")
+ print( errorMessage )
+ end
+ end
+ io.stdout:flush()
+ if testSuite.teardown then testSuite.teardown( testScratchpad ) end
+ end
+ if useHTML then
+ print( "</pre>" )
+ else
+ print( string.rep( '-', 78 ) )
+ end
+
+ print( string.format( "%d/%d tests passed (%0.1f%%)",
+ theSuccessCount,
+ #theTestNames,
+ 100 * theSuccessCount / #theTestNames
+ ) )
+
+ if useHTML then
+ print( "<br>" )
+ end
+
+ print( string.format( "%d total successful assertion%s",
+ lunity.__assertsPassed,
+ lunity.__assertsPassed == 1 and "" or "s"
+ ) )
+
+ if not useHTML then
+ print( "" )
+ end
+ io.stdout:flush()
+
+end
View
64 tests/replicaset.lua
@@ -0,0 +1,64 @@
+#!/usr/bin/lua
+-- Tests ReplicaSet bindings
+--
+-- Configuration can be set with the following environment variables:
+-- TEST_SERVER ('localhost')
+-- TEST_DB ('test')
+-- TEST_USER (nil, no auth will be done)
+-- TEST_PASS ('')
+
+require 'mongo'
+require 'os'
+
+require 'tests/lunity'
+module( 'LUAMONGO_TEST_REPLICASET', lunity )
+
+function setup()
+ test_server = os.getenv('TEST_SERVER') or 'localhost'
+ test_user = os.getenv('TEST_USER') or nil
+ test_password = os.getenv('TEST_PASS') or ''
+ test_db = os.getenv('TEST_DB') or 'test'
+ test_ns = test_db .. '.rs_values'
+end
+
+function teardown()
+end
+
+function test_ReplicaSet()
+ -- Create a ReplicaSet object
+ local db = mongo.ReplicaSet.New( 'rsname', { test_server } )
+ assertNotNil( db, 'unable to create mongo.ReplicaSet' )
+ assert( db:connect(), 'unable to forcefully connect to ReplicaSet' )
+
+ -- test data
+ local data = { a = 10, b = 'str1' }
+ local data_as_json = "{'a': 10, 'b': 'str1'}"
+
+ -- auth if we need to
+ if test_user then
+ assertTrue( db:auth{dbname=test_db, username=test_user, password=test_password}, "unable to auth to db" )
+ end
+
+ -- drop existing data
+ assertTrue( db:drop_collection(test_ns) )
+
+ -- insert a value into the namespace 'test.values'
+ assertTrue( db:insert(test_ns, data), 'unable to insert table-based data' )
+
+ -- insert the same using a JSON string
+ assertTrue( db:insert(test_ns, data_as_json), 'unable to insert JSON-based data' )
+
+ -- check the data
+ assertEqual( 2, db:count(test_ns) )
+
+ -- query all the values in the namespace, ensuring the values are equal to the inserted values
+ local q = db:query( test_ns, {} )
+ assertNotNil( q, 'unable to create Query object' )
+ for result in q:results() do
+ assertEqual( result.a, data.a )
+ assertEqual( result.b, data.b )
+ end
+end
+
+
+runTests()
View
5 utils.cpp
@@ -270,10 +270,9 @@ void lua_to_bson(lua_State *L, int stackpos, BSONObj &obj) {
lua_pushnil(L);
while (lua_next(L, stackpos) != 0) {
- if (lua_isnumber(L, -2)) {
- stringstream ss;
+ if (lua_type(L, -2) == LUA_TNUMBER) {
+ ostringstream ss;
ss << lua_tonumber(L, -2);
-
lua_append_bson(L, ss.str().c_str(), -1, &builder);
} else {
const char *k = lua_tostring(L, -2);
Please sign in to comment.
Something went wrong with that request. Please try again.