Skip to content

Commit 9787b6d

Browse files
committed
Add parser for the required types.
Added parsers and serializers for all but the following types: * Lambda 100 * Projection 104 * Unary Primitive 101 * Exception -128 * GUID The remaining types should be easy to express, but I want to try to write a parser for q itself, now. closes #2
1 parent 7638e5f commit 9787b6d

File tree

24 files changed

+2826
-303
lines changed

24 files changed

+2826
-303
lines changed

.ghci

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,58 @@
1+
import Data.List
2+
13
:{
2-
:def test const (
3-
do putStrLn "Press any key to run tests, q to stop..."
4+
:def test (\args ->
5+
do let createPattern p = if (null p)
6+
then "**"
7+
else if "*" `isSuffixOf` p
8+
then p
9+
else "**" ++ p ++ "**"
10+
pattern = createPattern args
11+
cmd p = unlines [ ":reload"
12+
, ":main --pattern " ++ p
13+
, ":test " ++ p
14+
]
15+
putStrLn $ "Going to run: " ++ pattern
16+
putStrLn "Press any key to run tests, q to stop, anything else changes the test pattern..."
417
x <- getLine
518
return $ if (x == "q")
619
then ""
7-
else ":reload \n :main \n :test"
20+
else if null x
21+
then cmd pattern
22+
else let pattern' = createPattern x
23+
in cmd $ createPattern x
824
)
25+
:}
26+
27+
-- -*- mode: haskell; -*-
28+
-- Begin copied material.
29+
-- <http://www.cs.kent.ac.uk/people/staff/cr3/toolbox/haskell/dot-squashed.ghci641>
30+
:{
31+
:def redir \varcmd -> return $
32+
case break Data.Char.isSpace varcmd of
33+
(var,_:cmd) -> unlines
34+
[":set -fno-print-bind-result"
35+
,"tmp <- System.Directory.getTemporaryDirectory"
36+
,"(f,h) <- System.IO.openTempFile tmp \"ghci\""
37+
,"sto <- GHC.Handle.hDuplicate System.IO.stdout"
38+
,"GHC.Handle.hDuplicateTo h System.IO.stdout"
39+
,"System.IO.hClose h"
40+
,cmd
41+
,"GHC.Handle.hDuplicateTo sto System.IO.stdout"
42+
,"let readFileNow f = readFile f >>= \\t->Data.List.length t `seq` return t"
43+
,var++" <- readFileNow f"
44+
,"System.Directory.removeFile f"
45+
]
46+
_ -> "putStrLn \"usage: :redir <var> <cmd>\""
47+
:}
48+
49+
--- Integration with the hlint code style tool
50+
:{
51+
:def hlint \extra -> return $ unlines
52+
[":unset +t +s"
53+
,":set -w"
54+
,":redir hlintvar1 :show modules"
55+
,":cmd return $ \":! hlint \" ++ unwords (map (takeWhile (/=',') . drop 2 . dropWhile (/= '(')) $ lines hlintvar1) ++ \" \" ++ " ++ show extra
56+
,":set +t +s -Wall"
57+
]
958
:}

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ cabal.sandbox.config
1111
*.log
1212
.#*
1313
*.iml
14-
q/
1514
.idea
1615
out/
1716
report.html

.travis.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
language: haskell
2+
ghc: 7.8.3
3+
4+
cache:
5+
directories:
6+
- ~/.cabal
27

38
before_install:
4-
- cabal install --only-dependencies --enable-tests
9+
- sudo apt-get update -qq
10+
- sudo apt-get install -qq --force-yes libgd2-xpm ia32-libs ia32-libs-multiarch
11+
- sed -f use-stackage.sed ~/.cabal/config > ~/.cabal/config.tmp
12+
- rm ~/.cabal/config
13+
- mv ~/.cabal/config.tmp ~/.cabal/config
14+
- cat ~/.cabal/config
15+
- cabal update
516
- cabal install hpc-coveralls --avoid-reinstalls
617

718
script:
8-
- cat cabal.config >> ~/.cabal/config # use stackage - find a better way to do this
9-
- cabal update
1019
- cabal install --only-dependencies --enable-tests
1120
- cabal configure --enable-tests --enable-library-coverage
1221
- cabal build
1322
- run-cabal-test --show-details=always
23+
# - hlint src
24+
# - hlint tests
25+
# - hlint benchmarks
1426

1527
after_script:
1628
- hpc-coveralls --exclude-dir=tests kdb-haskell-tests

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CABALSANDBOX := ".cabal-sandbox"
55
all: install hpc bench haddock run
66

77
bench: install
8+
cabal configure --enable-benchmarks
89
cabal build
910
cabal bench --benchmark-options="-o report.html"
1011

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ kdb-haskell
66

77
A repository that (in the future) will hold a kdb+ driver in Haskell.
88

9+
Status:
10+
* Parser and serializer for most kdb+ types is implemented with good test coverage.
11+
912
* [Download free kdb+](http://kx.com/software-download.php)
1013
* [Useful working driver](http://code.kx.com/wsvn/code/contrib/sagrawal/kx/haskell/kx.hs)
1114
* https://blog.engineyard.com/2014/the-second-contributor

benchmarks/Benchmark.hs

Lines changed: 80 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@
1212
module Main where
1313

1414
import Criterion.Main
15+
import Criterion.Measurement
16+
import Data.ByteString ()
17+
import Data.Fixed (Pico)
18+
import Data.Ratio
1519
import Data.Int (Int16)
16-
import Database.Kdb.Internal.Types (Value(..), cV, s, li)
20+
import Data.Monoid ((<>))
21+
import Database.Kdb.Internal.Types
1722
import Foreign.C.Types (CChar)
1823
import Text.Printf (printf)
19-
import qualified Control.Monad as CM (forM_)
24+
import Test.QuickCheck (Gen, arbitrary, listOf1, choose, generate, vectorOf, suchThat)
25+
import qualified Control.Monad as CM
2026
import qualified Data.ByteString.Char8 as C
27+
import qualified Data.Time as Time
2128
import qualified Data.Vector as V
2229
import qualified Data.Vector.Storable as SV
2330
import qualified Data.Vector.Storable.Mutable as MSV
@@ -31,42 +38,29 @@ import System.IO.Unsafe (unsafePerformIO)
3138
import Network.Socket hiding (recv)
3239
import Network.Socket.ByteString (recv, sendAll)
3340

34-
fillS :: [[CChar]] -> Value
35-
fillS x = let (x',y') = createS x
36-
in SV x' y'
37-
{-# INLINE fillS #-}
38-
39-
createS :: [[CChar]] -> (Int, SV.Vector CChar)
40-
createS cl = unsafePerformIO $ do
41-
v <- MSV.new (Prelude.length . Prelude.concat $ cl)
42-
fill v 0 $ Prelude.concat cl
43-
SV.unsafeFreeze v >>= \x -> return (Prelude.length cl,x)
44-
where
45-
fill _ _ [] = return ()
46-
fill v i (x:xs) = MSV.unsafeWrite v i x >> fill v (i + 1) xs
47-
48-
-- | Constructor for T - a Q table - we must always build it using this function
49-
-- 2 bytes for table header - 1 additional byte for dict type header
50-
fillT :: V.Vector Value -> Value
51-
fillT !xs = T (V.foldl' (\x y -> x + KT.size y) 3 xs) xs
52-
{-# INLINE fillT #-}
53-
5441
-- function to convert list of bytestring into hex digits - useful for debugging kx IPC bytes
5542
bprint :: C.ByteString -> String
5643
bprint x = ("0x" ++ ) $ foldl (++) "" $ fmap (printf "%02x") $ C.unpack x
5744

58-
main :: IO ()
59-
main = do
60-
let shortv = HV (SV.fromList[1..10]) -- short list - for benchmark testing
61-
il1 = IV $ SV.enumFromN 1 5000000 -- list of int
62-
il2 = IV $ SV.enumFromN 1 5000000 -- list of int
63-
il3 = IV $ SV.enumFromN 1 5000000 -- list of int
64-
l1 = L (V.fromList [il1,il2,il3]) -- general list of int
65-
sl1 = fillS [[97,0],[98,0],[99,0]] -- symbol list: `a`b`c
66-
t = fillT (V.fromList [sl1,l1]) -- table t:([] a:til 5000000;b:til 5000000;c:til 5000000)
67-
sl2 = s "t" -- atomic symbol `t
68-
cl1 = cV "insert" -- string ".u.insert"
69-
gl1 = li [cl1,sl2,t] -- general list (".u.insert";`t;t). t is the table from above
45+
-- test:([]kbool:();kbyte:();kshort:();kint:();klong:();
46+
-- kreal:();kfloat:();kchar:();ksymbol:();kboolv:();kbytev:();kshortv:();kintv:();
47+
-- klongv:();krealv:();kfloatv:();kcharv:();ksymbolv:())
48+
49+
-- .u.upd:{[t;x] if not -16=type first first x;a:.z.n; x:$[0>type first x;a,x;(enlist(count first x)#a),x]]; t insert x}
50+
-- write schema statement: simply send a char vector
51+
52+
main1 :: IO ()
53+
main1 = do
54+
-- let shortv = KShortV (SV.fromList[1..10]) -- short list - for benchmark testing
55+
-- il1 = V . KIntV $ SV.enumFromN 1 5000000 -- list of int
56+
-- il2 = V . KIntV $ SV.enumFromN 1 5000000 -- list of int
57+
-- il3 = V . KIntV $ SV.enumFromN 1 5000000 -- list of int
58+
-- l1 = KList (V.fromList [il1,il2,il3]) -- general list of int
59+
-- sl1 = symV ["a", "b", "c"]
60+
-- t = KT.table' (V.fromList [sl1,l1]) -- table t:([] a:til 5000000;b:til 5000000;c:til 5000000)
61+
-- sl2 = s "t" -- atomic symbol `t
62+
-- cl1 = charV "insert" -- string ".u.insert"
63+
-- gl1 = list [cl1,sl2,t] -- general list (".u.insert";`t;t). t is the table from above
7064
{--
7165
defaultMain [
7266
bench "ShortV" $ whnf SV.fromList ([1..10]::[Int16])
@@ -84,8 +78,58 @@ main = do
8478
connect sock (addrAddress serveraddr)
8579
sendAll sock "user:pwd\1\0"
8680
msg <- recv sock 1024
87-
print "Received authentication"
81+
putStrLn "Received authentication"
8882
print $ bprint msg
89-
CM.forM_ [1..1] $ \x -> sendAll sock $ IPC.asyncIPC gl1
83+
84+
-- send the schema
85+
sendAll sock . IPC.asyncIPC $ charV schema
86+
87+
-- Gen the rows
88+
rows <- setupEnv 100
89+
90+
-- Send the rows
91+
CM.forM_ rows $ \x -> sendAll sock $ IPC.asyncIPC x
92+
93+
-- Close the socket
9094
sClose sock
9195

96+
setupEnv :: Int -> IO [KT.Value]
97+
setupEnv count = CM.replicateM count (generate randomRow)
98+
99+
benchmark :: IO ()
100+
benchmark = defaultMain [
101+
env (setupEnv 1000000) $ \ ~rows ->
102+
bgroup "bla" [
103+
bench "length" $ nf (map IPC.asyncIPC) rows
104+
]
105+
]
106+
107+
--benchmark2 :: IO ()
108+
--benchmark2 = do
109+
-- (m, time) <- flip measure 1 $ env setupEnv $ \ ~rows ->
110+
-- bgroup "bla" [
111+
-- bench "length" $ nf (map IPC.asyncIPC) rows
112+
-- ]
113+
-- return ()
114+
115+
main2 :: IO ()
116+
main2 = do
117+
addrinfos <- getAddrInfo Nothing (Just "127.0.0.1") (Just "7777")
118+
let serveraddr = head addrinfos
119+
sock <- socket (addrFamily serveraddr) Stream defaultProtocol
120+
connect sock (addrAddress serveraddr)
121+
122+
-- Login
123+
sendAll sock "user:pwd\1\0"
124+
msg <- recv sock 1024
125+
putStrLn "Received authentication"
126+
print $ bprint msg
127+
128+
-- Send the schema
129+
sendAll sock . IPC.asyncIPC $ charV schema
130+
131+
sClose sock
132+
133+
main :: IO ()
134+
main = main1
135+

cabal.config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
-- Lock the package database
2-
remote-repo: stackage:http://www.stackage.org/stackage/7cbdc905d399a45de2128a2d8e67e22636f309a1
1+
-- Stackage build for GHC 7.8 + Haskell Platform, 2014-09-24, inclusive
2+
remote-repo: stackage:http://www.stackage.org/stackage/92c5686ff52b79d727431993e2f21b1b7b869d1b

kdb-haskell.cabal

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
name: kdb-haskell
32
version: 0.1.0
43
synopsis: Haskell bindings for KDB+.
@@ -33,19 +32,21 @@ library
3332
exposed-modules:
3433
other-modules: Database.Kdb.Internal.Types
3534
, Database.Kdb.Internal.IPC
35+
, Database.Kdb.Internal.DateTimeTypes
3636
default-language: Haskell2010
3737
build-depends: base >= 4 && < 5
38-
, mtl
38+
, deepseq
39+
, cpu
40+
, time
41+
, attoparsec
3942
, bytestring
43+
-- see if possible to get rid of: necessary for the
44+
-- conversions between Word32/Word64 and Float/Double.
45+
, array
4046
, vector
41-
, text
42-
, containers
43-
, binary
44-
, lens
4547
, QuickCheck
46-
, directory
4748
hs-source-dirs: src
48-
ghc-options: -Wall
49+
ghc-options: -Wall
4950
-fwarn-incomplete-patterns
5051
-funbox-strict-fields
5152

@@ -55,37 +56,73 @@ test-suite kdb-haskell-tests
5556
main-is: Test.hs
5657
type: exitcode-stdio-1.0
5758
build-depends: base
59+
, deepseq
60+
, deepseq-generics
61+
, cpu
5862
, bytestring
63+
, array
5964
, base16-bytestring
6065
, containers
6166
, vector
67+
, attoparsec
6268
, text
6369
, time
70+
, timezone-series >= 0.1.3
71+
, timezone-olson
72+
, tzdata == 0.1.20140612.0
6473
, binary
6574
, mtl
6675
, lens
6776
-- Testing
6877
, tasty
6978
, tasty-quickcheck
79+
--, tasty-smallcheck
7080
, tasty-hunit
7181
, QuickCheck
82+
, quickcheck-io
83+
, network
84+
, process
85+
, directory
86+
, system-filepath
87+
, resourcet
88+
, transformers
89+
, retry
7290
, Cabal
73-
Ghc-Options: -Wall
91+
-- This needs to be disabled for now, until I figure out
92+
-- why this fails to build.
93+
--, hlint
94+
ghc-options: -Wall
7495
-O0
75-
-funbox-strict-fields
96+
-funbox-strict-fields
7697

7798
benchmark kdb-haskell-benchmark
7899
type: exitcode-stdio-1.0
79100
hs-source-dirs: src
101+
, tests
80102
, benchmarks
81103
main-is: Benchmark.hs
82104
build-depends: base
83-
, mtl
84-
, vector
105+
, deepseq
106+
, deepseq-generics
107+
, cpu
85108
, bytestring
109+
, array
110+
, base16-bytestring
111+
, containers
112+
, vector
113+
, attoparsec
114+
, text
115+
, time
116+
, timezone-series >= 0.1.3
117+
, binary
118+
, mtl
119+
, lens
120+
-- Benchmark deps
86121
, network
122+
, time
87123
, criterion
88-
, random
124+
, QuickCheck
89125
ghc-options: -Wall
90126
-O2
91127
-funbox-strict-fields
128+
-rtsopts

0 commit comments

Comments
 (0)