added whereClause, tidied code

This commit is contained in:
Rick Richardson 2010-02-05 08:31:01 -05:00
parent e606b1bc1f
commit 58fbd2005f
3 changed files with 41 additions and 11 deletions

View file

@ -46,6 +46,8 @@ module Database.MongoDB
save, save,
-- * Convenience collection operations -- * Convenience collection operations
find, findOne, quickFind, quickFind', find, findOne, quickFind, quickFind',
-- * Query Helpers
whereClause,
-- * Cursor -- * Cursor
Cursor, Cursor,
allDocs, allDocs', finish, nextDoc, allDocs, allDocs', finish, nextDoc,
@ -82,7 +84,9 @@ import System.IO.Unsafe
import System.Random import System.Random
-- | A list of handles to database connections -- | A list of handles to database connections
data Connection = Connection { cHandles :: [Handle], cIndex :: IORef Int, cRand :: IORef [Int] } data Connection = Connection { cHandles :: [Handle]
,cIndex :: IORef Int
,cRand :: IORef [Int] }
-- | Establish a connection to a MongoDB server -- | Establish a connection to a MongoDB server
connect :: HostName -> IO Connection connect :: HostName -> IO Connection
@ -542,33 +546,48 @@ update c col flags sel obj = do
cPut c msg cPut c msg
return reqID return reqID
-- | log into the mongodb /Database/ attached to the /Connection/
login :: Connection -> Database -> String -> String -> IO BsonDoc login :: Connection -> Database -> String -> String -> IO BsonDoc
login c db user pass = do login c db user pass = do
doc <- runCommand c db (toBsonDoc [("getnonce", toBson (1 :: Int))]) doc <- runCommand c db (toBsonDoc [("getnonce", toBson (1 :: Int))])
let nonce = fromBson $ fromLookup $ BSON.lookup "nonce" doc :: String let nonce = fromBson $ fromLookup $ BSON.lookup "nonce" doc :: String
digest = md5sum $ pack $ nonce ++ user ++ ( md5sum $ pack (user ++ ":mongo:" ++ pass)) digest = md5sum $ pack $ nonce ++ user ++
( md5sum $ pack (user ++ ":mongo:" ++ pass))
request = toBsonDoc [("authenticate", toBson (1 :: Int)), request = toBsonDoc [("authenticate", toBson (1 :: Int)),
("user", toBson user), ("user", toBson user),
("nonce", toBson nonce), ("nonce", toBson nonce),
("key", toBson digest)] ("key", toBson digest)]
in runCommand c db request in runCommand c db request
addUser :: Connection -> String -> String -> String -> IO BsonDoc -- | create a new user in the current /Database/
addUser :: Connection -> Database -> String -> String -> IO BsonDoc
addUser c db user pass = do addUser c db user pass = do
let userDoc = toBsonDoc [(s2L"user", toBson user)] let userDoc = toBsonDoc [(s2L"user", toBson user)]
fdb = s2L (db ++ ".system.users") fdb = L.append db (s2L ".system.users")
doc <- liftM (maybe userDoc id) (findOne c fdb userDoc) doc <- liftM (maybe userDoc id) (findOne c fdb userDoc)
let doc' = Map.insert (s2L "pwd") (toBson ( md5sum $ pack (user ++ ":mongo:" ++ pass))) doc let doc' = Map.insert (s2L "pwd")
(toBson ( md5sum $ pack (user ++ ":mongo:" ++ pass))) doc
_ <- save c fdb doc' _ <- save c fdb doc'
return doc' return doc'
-- | Conveniently stores the /BsonDoc/ to the /FullCollection/
-- | if there is an _id present in the /BsonDoc/ then it already has
-- | a place in the DB, so we update it using the _id, otherwise
-- | we insert it
save :: Connection -> FullCollection -> BsonDoc -> IO RequestID save :: Connection -> FullCollection -> BsonDoc -> IO RequestID
save c fc doc = save c fc doc =
case Map.lookup (s2L "_id") doc of case Map.lookup (s2L "_id") doc of
Nothing -> insert c fc doc Nothing -> insert c fc doc
Just obj -> update c fc [UFUpsert] (toBsonDoc [("_id", obj)]) doc Just obj -> update c fc [UFUpsert] (toBsonDoc [("_id", obj)]) doc
-- | Use this in the place of the query portion of a select type query
-- | This uses javascript and a scope supplied by a /BsonDoc/ to evaluate
-- | documents in the database for retrieval.
-- | Example:
-- | > findOne conn mycoll $ whereClause "this.name == (name1 + name2)"
-- | > (toBsonDoc [("name1", toBson "mar"), ("name2", toBson "tha")])
whereClause :: String -> BsonDoc -> BsonDoc
whereClause qry scope = toBsonDoc [("$where", (BsonCodeWScope (s2L qry) scope))]
data Hdr = Hdr { data Hdr = Hdr {
hMsgLen :: Int32, hMsgLen :: Int32,

View file

@ -73,6 +73,7 @@ data BsonValue
| BsonSymbol L8.ByteString | BsonSymbol L8.ByteString
| BsonInt32 Int32 | BsonInt32 Int32
| BsonInt64 Int64 | BsonInt64 Int64
| BsonCodeWScope L8.ByteString BsonDoc
| BsonMinKey | BsonMinKey
| BsonMaxKey | BsonMaxKey
deriving (Show, Eq, Ord) deriving (Show, Eq, Ord)
@ -195,7 +196,11 @@ getVal DataSymbol = do
sLen1 <- getI32 sLen1 <- getI32
(_sLen2, s) <- getS (_sLen2, s) <- getS
return (fromIntegral $ 4 + sLen1, BsonString s) return (fromIntegral $ 4 + sLen1, BsonString s)
getVal DataCodeWScope = fail "DataCodeWScope not yet supported" -- TODO getVal DataCodeWScope = do
sLen1 <- getI32
(_, qry) <- getS
(_, scope) <- getDoc
return (fromIntegral sLen1, BsonCodeWScope qry scope)
getVal DataInt = liftM ((,) 4 . BsonInt32 . fromIntegral) getI32 getVal DataInt = liftM ((,) 4 . BsonInt32 . fromIntegral) getI32
getVal DataTimestamp = fail "DataTimestamp not yet supported" -- TODO getVal DataTimestamp = fail "DataTimestamp not yet supported" -- TODO
@ -240,7 +245,7 @@ putType BsonRegex{} = putDataType DataRegex
-- putType = putDataType DataRef -- putType = putDataType DataRef
-- putType = putDataType DataCode -- putType = putDataType DataCode
putType BsonSymbol{} = putDataType DataSymbol putType BsonSymbol{} = putDataType DataSymbol
-- putType = putDataType DataCodeWScope putType BsonCodeWScope{} = putDataType DataCodeWScope
putType BsonInt32 {} = putDataType DataInt putType BsonInt32 {} = putDataType DataInt
putType BsonInt64 {} = putDataType DataLong putType BsonInt64 {} = putDataType DataLong
-- putType = putDataType DataTimestamp -- putType = putDataType DataTimestamp
@ -249,7 +254,7 @@ putType BsonMaxKey = putDataType DataMaxKey
putVal :: BsonValue -> Put putVal :: BsonValue -> Put
putVal (BsonDouble d) = putFloat64le d putVal (BsonDouble d) = putFloat64le d
putVal (BsonString s) = putI32 (fromIntegral $ 1 + L8.length s) >> putS s putVal (BsonString s) = putStrSz s
putVal (BsonObject o) = putObj o putVal (BsonObject o) = putObj o
putVal (BsonArray es) = putOutterObj bs putVal (BsonArray es) = putOutterObj bs
where bs = runPut $ forM_ (List.zip [(0::Int) .. ] es) $ \(i, e) -> where bs = runPut $ forM_ (List.zip [(0::Int) .. ] es) $ \(i, e) ->
@ -270,6 +275,9 @@ putVal (BsonRegex r opt)= do putS r
putVal (BsonSymbol s) = putI32 (fromIntegral $ 1 + L8.length s) >> putS s putVal (BsonSymbol s) = putI32 (fromIntegral $ 1 + L8.length s) >> putS s
putVal (BsonInt32 i) = putI32 i putVal (BsonInt32 i) = putI32 i
putVal (BsonInt64 i) = putI64 i putVal (BsonInt64 i) = putI64 i
putVal (BsonCodeWScope q s) =
let bytes = runPut (putStrSz q >> putObj s)
in (putI32 $ (+4) $ fromIntegral $ L.length bytes) >> putLazyByteString bytes
putVal BsonMinKey = putNothing putVal BsonMinKey = putNothing
putVal BsonMaxKey = putNothing putVal BsonMaxKey = putNothing

View file

@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
module Database.MongoDB.Util module Database.MongoDB.Util
( (
putI8, putI32, putI64, putNothing, putNull, putS, putI8, putI32, putI64, putNothing, putNull, putS,
getI8, getI32, getI64, getC, getS, getNull, getI8, getI32, getI64, getC, getS, getNull, putStrSz,
) )
where where
import Control.Exception (assert) import Control.Exception (assert)
@ -75,3 +75,6 @@ putNull = putI8 (0::Int)
putS :: L8.ByteString -> Put putS :: L8.ByteString -> Put
putS s = putLazyByteString s >> putNull putS s = putLazyByteString s >> putNull
putStrSz :: L.ByteString -> Put
putStrSz s = putI32 (fromIntegral $ 1 + L8.length s) >> putS s