updateToBson :: Text
             -> PersistValue
             -> Either PersistUpdate MongoUpdateOperation
             -> DB.Field
updateToBson fname v up =
#ifdef DEBUG
  debug (
#endif
    opName DB.:= DB.Doc [fname DB.:= opValue]
#ifdef DEBUG
    )
#endif
  where
    inc = "$inc"
    mul = "$mul"
    (opName, opValue) = case up of
      Left pup -> case (pup, v) of
        (Assign, PersistNull) -> ("$unset", DB.Int64 1)
        (Assign,a)    -> ("$set", DB.val a)
        (Add, a)      -> (inc, DB.val a)
        (Subtract, PersistInt64 i) -> (inc, DB.Int64 (-i))
        (Multiply, PersistInt64 i) -> (mul, DB.Int64 i)
        (Multiply, PersistDouble d) -> (mul, DB.Float d)
        (Subtract, _) -> error "expected PersistInt64 for a subtraction"
        (Multiply, _) -> error "expected PersistInt64 or PersistDouble for a subtraction"
        -- Obviously this could be supported for floats by multiplying with 1/x
        (Divide, _)   -> throw $ PersistMongoDBUnsupported "divide not supported"
        (BackendSpecificUpdate bsup, _) -> throw $ PersistMongoDBError $
          T.pack $ "did not expect BackendSpecificUpdate " ++ T.unpack bsup
      Right mup -> case mup of
        MongoEach op  -> case op of
           MongoPull -> ("$pullAll", DB.val v)
           _         -> (opToText op, DB.Doc ["$each" DB.:= DB.val v])
        MongoSimple x -> (opToText x, DB.val v)
updateToBson :: Text
             -> PersistValue
             -> Either PersistUpdate MongoUpdateOperation
             -> DB.Field
updateToBson fname v up =
#ifdef DEBUG
  debug (
#endif
    opName DB.:= DB.Doc [fname DB.:= opValue]
#ifdef DEBUG
    )
#endif
  where
    inc = "$inc"
    mul = "$mul"
    (opName, opValue) = case up of
      Left pup -> case (pup, v) of
        (Assign, PersistNull) -> ("$unset", DB.Int64 1)
        (Assign,a)    -> ("$set", DB.val a)
        (Add, a)      -> (inc, DB.val a)
        (Subtract, PersistInt64 i) -> (inc, DB.Int64 (-i))
        (Multiply, PersistInt64 i) -> (mul, DB.Int64 i)
        (Multiply, PersistDouble d) -> (mul, DB.Float d)
        (Subtract, _) -> error "expected PersistInt64 for a subtraction"
        (Multiply, _) -> error "expected PersistInt64 or PersistDouble for a subtraction"
        -- Obviously this could be supported for floats by multiplying with 1/x
        (Divide, _)   -> throw $ PersistMongoDBUnsupported "divide not supported"
        (BackendSpecificUpdate bsup, _) -> throw $ PersistMongoDBError $
          T.pack $ "did not expect BackendSpecificUpdate " ++ T.unpack bsup
      Right mup -> case mup of
        MongoEach op  -> case op of
           MongoPull -> ("$pullAll", DB.val v)
           _         -> (opToText op, DB.Doc ["$each" DB.:= DB.val v])
        MongoSimple x -> (opToText x, DB.val v)
updateToBson fname v up =
#ifdef DEBUG
  debug (
#endif
    opName DB.:= DB.Doc [fname DB.:= opValue]
#ifdef DEBUG
    )
#endif
  where
    inc = "$inc"
    mul = "$mul"
    (opName, opValue) = case up of
      Left pup -> case (pup, v) of
        (Assign, PersistNull) -> ("$unset", DB.Int64 1)
        (Assign,a)    -> ("$set", DB.val a)
        (Add, a)      -> (inc, DB.val a)
        (Subtract, PersistInt64 i) -> (inc, DB.Int64 (-i))
        (Multiply, PersistInt64 i) -> (mul, DB.Int64 i)
        (Multiply, PersistDouble d) -> (mul, DB.Float d)
        (Subtract, _) -> error "expected PersistInt64 for a subtraction"
        (Multiply, _) -> error "expected PersistInt64 or PersistDouble for a subtraction"
        -- Obviously this could be supported for floats by multiplying with 1/x
        (Divide, _)   -> throw $ PersistMongoDBUnsupported "divide not supported"
        (BackendSpecificUpdate bsup, _) -> throw $ PersistMongoDBError $
          T.pack $ "did not expect BackendSpecificUpdate " ++ T.unpack bsup
      Right mup -> case mup of
        MongoEach op  -> case op of
           MongoPull -> ("$pullAll", DB.val v)
           _         -> (opToText op, DB.Doc ["$each" DB.:= DB.val v])
        MongoSimple x -> (opToText x, DB.val v)