summaryrefslogtreecommitdiff
path: root/src/runtime/haskell-bind
diff options
context:
space:
mode:
authorkrasimir <krasimir@chalmers.se>2016-04-29 14:06:24 +0000
committerkrasimir <krasimir@chalmers.se>2016-04-29 14:06:24 +0000
commit3f0fe438cd37bd9f9ece835b6f3bc90ed5566110 (patch)
tree0a8cbe2fbfe5d5391a8c6359c8b0d7aadc3b3b57 /src/runtime/haskell-bind
parenta6b421226420e740b1b3d45817b9fc12cab13344 (diff)
a prototype for complex queries over expressions in libsg
Diffstat (limited to 'src/runtime/haskell-bind')
-rw-r--r--src/runtime/haskell-bind/SG.hsc93
-rw-r--r--src/runtime/haskell-bind/SG/FFI.hs21
2 files changed, 82 insertions, 32 deletions
diff --git a/src/runtime/haskell-bind/SG.hsc b/src/runtime/haskell-bind/SG.hsc
index b6707f031..c7600841c 100644
--- a/src/runtime/haskell-bind/SG.hsc
+++ b/src/runtime/haskell-bind/SG.hsc
@@ -1,4 +1,4 @@
-{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveDataTypeable, ExistentialQuantification #-}
#include <pgf/pgf.h>
#include <gu/exn.h>
@@ -7,13 +7,13 @@
module SG( SG, openSG, closeSG
, beginTrans, commit, rollback, inTransaction
, SgId
- , insertExpr, getExpr
+ , insertExpr, getExpr, queryExpr
, updateFtsIndex
, queryLinearization
, readTriple, showTriple
- , readTriples
, insertTriple, getTriple
, queryTriple
+ , prepareQuery
) where
import Foreign hiding (unsafePerformIO)
@@ -92,7 +92,7 @@ insertExpr :: SG -> Expr -> IO SgId
insertExpr (SG sg) (Expr expr _) =
withGuPool $ \tmpPl -> do
exn <- gu_new_exn tmpPl
- id <- sg_insert_expr sg expr exn
+ id <- sg_insert_expr sg expr 1 exn
handle_sg_exn exn
return id
@@ -109,6 +109,34 @@ getExpr (SG sg) id = do
return Nothing
else do return $ Just (Expr c_expr exprFPl)
+queryExpr :: SG -> Expr -> IO [(SgId,Expr)]
+queryExpr (SG sg) (Expr query _) =
+ withGuPool $ \tmpPl -> do
+ exn <- gu_new_exn tmpPl
+ res <- sg_query_expr sg query tmpPl exn
+ handle_sg_exn exn
+ fetchResults res exn
+ where
+ fetchResults res exn = do
+ exprPl <- gu_new_pool
+ (key,c_expr) <- alloca $ \pKey -> do
+ c_expr <- sg_query_next sg res pKey exprPl exn
+ key <- peek pKey
+ return (key,c_expr)
+ failed <- gu_exn_is_raised exn
+ if failed
+ then do gu_pool_free exprPl
+ sg_query_close sg res exn
+ handle_sg_exn exn
+ return []
+ else if c_expr == nullPtr
+ then do gu_pool_free exprPl
+ sg_query_close sg res exn
+ return []
+ else do exprFPl <- newForeignPtr gu_pool_finalizer exprPl
+ rest <- fetchResults res exn
+ return ((key,Expr c_expr exprFPl) : rest)
+
updateFtsIndex :: SG -> PGF -> IO ()
updateFtsIndex (SG sg) p = do
withGuPool $ \tmpPl -> do
@@ -177,33 +205,6 @@ showTriple (Expr expr1 _) (Expr expr2 _) (Expr expr3 _) =
s <- gu_string_buf_freeze sb tmpPl
peekCString s
-readTriples :: String -> Maybe [(Expr,Expr,Expr)]
-readTriples str =
- unsafePerformIO $
- do exprPl <- gu_new_pool
- withGuPool $ \tmpPl ->
- withCString str $ \c_str ->
- do guin <- gu_string_in c_str tmpPl
- exn <- gu_new_exn tmpPl
- seq <- pgf_read_expr_matrix guin 3 exprPl exn
- status <- gu_exn_is_raised exn
- if (seq /= nullPtr && not status)
- then do exprFPl <- newForeignPtr gu_pool_finalizer exprPl
- count <- (#peek GuSeq, len) seq
- ts <- peekTriples exprFPl (fromIntegral (count :: CInt)) (seq `plusPtr` (#offset GuSeq, data))
- return (Just ts)
- else do gu_pool_free exprPl
- return Nothing
- where
- peekTriples exprFPl count triple
- | count == 0 = return []
- | otherwise = do c_expr1 <- peekElemOff triple 0
- c_expr2 <- peekElemOff triple 1
- c_expr3 <- peekElemOff triple 2
- let t = (Expr c_expr1 exprFPl,Expr c_expr2 exprFPl,Expr c_expr3 exprFPl)
- ts <- peekTriples exprFPl (count-3) (triple `plusPtr` (3*sizeOf c_expr1))
- return (t:ts)
-
insertTriple :: SG -> Expr -> Expr -> Expr -> IO SgId
insertTriple (SG sg) (Expr expr1 _) (Expr expr2 _) (Expr expr3 _) =
withGuPool $ \tmpPl ->
@@ -281,6 +282,36 @@ queryTriple (SG sg) mb_expr1 mb_expr2 mb_expr3 =
,fromCExpr c_expr2 exprFPl mb_expr2
,fromCExpr c_expr3 exprFPl mb_expr3) : rest)
+
+data Query = forall a . Query {query :: Ptr SgQuery, queryMaster :: a}
+
+prepareQuery :: SG -> String -> IO (Maybe Query)
+prepareQuery (SG sg) str =
+ withGuPool $ \tmpPl ->
+ withCString str $ \c_str ->
+ do guin <- gu_string_in c_str tmpPl
+ exn <- gu_new_exn tmpPl
+ queryPl <- gu_new_pool
+ q <- do seq <- pgf_read_expr_matrix guin 3 queryPl exn
+ if seq /= nullPtr
+ then do count <- (#peek GuSeq, len) seq
+ sg_prepare_query sg (count `div` 3) (seq `plusPtr` (#offset GuSeq, data)) queryPl exn
+ else return nullPtr
+ failed <- gu_exn_is_raised exn
+ if failed
+ then do gu_pool_free queryPl
+ is_sgerr <- gu_exn_caught exn gu_exn_type_SgError
+ if is_sgerr
+ then do c_msg <- (#peek GuExn, data.data) exn
+ msg <- peekCString c_msg
+ throwIO (SGError msg)
+ else throwIO (SGError "Unknown database error")
+ else if q == nullPtr
+ then do gu_pool_free queryPl
+ return Nothing
+ else do queryFPl <- newForeignPtr gu_pool_finalizer queryPl
+ return (Just (Query q queryFPl))
+
-----------------------------------------------------------------------
-- Exceptions
diff --git a/src/runtime/haskell-bind/SG/FFI.hs b/src/runtime/haskell-bind/SG/FFI.hs
index 69e3efe3f..a6dce9494 100644
--- a/src/runtime/haskell-bind/SG/FFI.hs
+++ b/src/runtime/haskell-bind/SG/FFI.hs
@@ -8,7 +8,10 @@ import GHC.Ptr
import Data.Int
data SgSG
+data SgQueryExprResult
data SgTripleResult
+data SgQuery
+data SgQueryResult
type SgId = Int64
foreign import ccall "sg/sg.h sg_open"
@@ -27,11 +30,20 @@ foreign import ccall "sg/sg.h sg_rollback"
sg_rollback :: Ptr SgSG -> Ptr GuExn -> IO ()
foreign import ccall "sg/sg.h sg_insert_expr"
- sg_insert_expr :: Ptr SgSG -> PgfExpr -> Ptr GuExn -> IO SgId
+ sg_insert_expr :: Ptr SgSG -> PgfExpr -> CInt -> Ptr GuExn -> IO SgId
foreign import ccall "sg/sg.h sg_get_expr"
sg_get_expr :: Ptr SgSG -> SgId -> Ptr GuPool -> Ptr GuExn -> IO PgfExpr
+foreign import ccall "sg/sg.h sg_query_expr"
+ sg_query_expr :: Ptr SgSG -> PgfExpr -> Ptr GuPool -> Ptr GuExn -> IO (Ptr SgQueryExprResult)
+
+foreign import ccall "sg/sg.h sg_query_next"
+ sg_query_next :: Ptr SgSG -> Ptr SgQueryExprResult -> Ptr SgId -> Ptr GuPool -> Ptr GuExn -> IO PgfExpr
+
+foreign import ccall "sg/sg.h sg_query_close"
+ sg_query_close :: Ptr SgSG -> Ptr SgQueryExprResult -> Ptr GuExn -> IO ()
+
foreign import ccall "sg/sg.h sg_update_fts_index"
sg_update_fts_index :: Ptr SgSG -> Ptr PgfPGF -> Ptr GuExn -> IO ()
@@ -53,6 +65,13 @@ foreign import ccall "sg/sg.h sg_triple_result_fetch"
foreign import ccall "sg/sg.h sg_triple_result_close"
sg_triple_result_close :: Ptr SgTripleResult -> Ptr GuExn -> IO ()
+foreign import ccall "sg/sg.h sg_prepare_query"
+ sg_prepare_query :: Ptr SgSG -> CInt -> Ptr PgfExpr -> Ptr GuPool -> Ptr GuExn -> IO (Ptr SgQuery)
+
+foreign import ccall "sg/sg.h sg_query"
+ sg_query :: Ptr SgSG -> Ptr SgQuery -> Ptr GuExn -> IO (Ptr SgQueryResult)
+
+
type SgTriple = Ptr PgfExpr