Takusen-0.7: Database/Sqlite/Test/SqliteFunctions.lhs
|
Module : Database.Sqlite.Test.SqliteFunctions
Copyright : (c) 2004 Oleg Kiselyov, Alistair Bayley
License : BSD-style
Maintainer : oleg@pobox.com, alistair@abayley.org
Stability : experimental
Portability : non-portable
> {-# OPTIONS -fglasgow-exts #-}
> module Database.Sqlite.Test.SqliteFunctions (runTest) where
> import Foreign
> import Foreign.C
> import Foreign.C.UTF8
> import Control.Monad
> import Control.Exception
> import Data.Dynamic
> import Database.Sqlite.SqliteFunctions
> import System.Environment (getArgs)
> import Test.MiniUnit
> runTest :: String -> IO ()
> runTest dbname = do
> testOpen dbname
> db <- openDb dbname
> createFixture db
> runTestTT "Sqlite low-level tests" (testlist db)
> destroyFixture db
> closeDb db
> --testlist db = TestList $ map (\t -> TestCase (t db))
> testlist db = map (\t -> t db)
> [ testSelectInts
> , testSelectDouble
> , testSelectInt64
> , testSelectStringNull
> , testSelectStringEmpty
> , testSelectNoRows
> , testSelectManyRows
> , testUnion
> , testBindString
> , testBindDouble
> , testFetchAfterFinalise
> , testConstraintError
> , testSelectUTF8Text
> ]
> ignoreError action =
> catchSqlite action (\e -> return undefined)
> printIgnoreError action = catchSqlite action
> (\e -> do
> putStrLn (show e)
> return undefined
> )
> printPropagateError action = catchSqlite action
> (\e -> do
> putStrLn (show e)
> throwSqlite e
> return undefined
> )
> ddlExec db stmt = do
> _ <- stmtExec db stmt
> return ()
> testOpen dbname = do
> h <- openDb dbname
> closeDb h
> createFixture db = do
> ignoreError $ ddlExec db "drop table tdual"
> ignoreError $ ddlExec db "drop table t_natural"
> ignoreError $ ddlExec db "drop table t_blob"
> printPropagateError $
> ddlExec db "create table tdual (dummy text)"
> printPropagateError $
> ddlExec db "insert into tdual (dummy) values ('X')"
> printPropagateError $ ddlExec db "create table t_natural (n integer primary key)"
> mapM_ (insertNatural db) [1..10]
> printPropagateError $
> ddlExec db "create table t_blob (b blob)"
> printPropagateError $
> ddlExec db "insert into t_blob values ('blobtest')"
> insertNatural db n = do
> ddlExec db $ "insert into t_natural values (" ++ (show n) ++ ")"
> destroyFixture db = do
> printPropagateError $ ddlExec db "drop table tdual"
> printPropagateError $ ddlExec db "drop table t_natural"
> printPropagateError $ ddlExec db "drop table t_blob"
> testCreateDual db = do
> ignoreError ( do
> ddlExec db "create table tdual (dummy integer primary key)"
> assertFailure "SqliteException not thrown when table already exists"
> )
> printPropagateError $ ddlExec db "insert into tdual values (1)"
> testSelectInts db = do
> stmt <- printPropagateError $
> stmtPrepare db "select n from t_natural where n < 3 order by n;"
> rc <- stmtFetch db stmt
> n <- colValInt stmt 1
> assertEqual "testSelectInts: 1" 1 n
> rc <- stmtFetch db stmt
> n <- colValInt stmt 1
> assertEqual "testSelectInts: 2" 2 n
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> assertEqual "testSelectInts: done" sqliteDONE rc
> testSelectInt64 db = do
> stmt <- printPropagateError $
> stmtPrepare db "select 20041225235959"
> --stmtPrepare db "select -1 union select 1 union select 2*1000*1000*1000 order by 1"
> rc <- stmtFetch db stmt
> n <- colValInt64 stmt 1
> assertEqual "testSelectInt64: 20041225235959" 20041225235959 n
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> assertEqual "testSelectInt64: done" sqliteDONE rc
> testSelectDouble db = do
> stmt <- printPropagateError $
> stmtPrepare db "select 1.2"
> rc <- stmtFetch db stmt
> n <- colValDouble stmt 1
> assertEqual "testSelectDouble: 1.2" 1.2 n
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> assertEqual "testSelectDouble: done" sqliteDONE rc
> testSelectStringNull db = do
> stmt <- printPropagateError $
> stmtPrepare db "select null"
> rc <- stmtFetch db stmt
> n <- colValString stmt 1
> assertEqual "testSelectString: Nothing" Nothing n
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> assertEqual "testSelectString: done" sqliteDONE rc
> testSelectStringEmpty db = do
> stmt <- printPropagateError $
> stmtPrepare db "select ''"
> rc <- stmtFetch db stmt
> -- what is rc after row fetch? sqliteOK or sqliteROW?
> assertEqual "testSelectString: row 1" sqliteROW rc
> n <- colValString stmt 1
> assertEqual "testSelectString: ''" (Just "") n
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> assertEqual "testSelectString: done" sqliteDONE rc
> testUnion db = do
> stmt <- printPropagateError $
> stmtPrepare db "select 'h1' from tdual union select 'h2' from tdual union select 'h3' from tdual"
> rc <- stmtFetch db stmt
> Just s <- colValString stmt 1
> assertEqual "testUnion: h1" "h1" s
> rc <- stmtFetch db stmt
> Just s <- colValString stmt 1
> assertEqual "testUnion: h2" "h2" s
> rc <- stmtFetch db stmt
> Just s <- colValString stmt 1
> assertEqual "testUnion: h3" "h3" s
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> assertEqual "testUnion: done" sqliteDONE rc
> testSelectNoRows db = do
> stmt <- printPropagateError $
> stmtPrepare db "select 'h1' from tdual where dummy = '2'"
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> assertEqual "testSelectNoRows: done" sqliteDONE rc
> manyRows :: String
> manyRows =
> "select 1 from"
> ++ " ( select 1 from tdual union select 0 from tdual)"
> ++ ", ( select 2 from tdual union select 0 from tdual)"
> ++ ", ( select 3 from tdual union select 0 from tdual)"
> ++ ", ( select 4 from tdual union select 0 from tdual)"
> ++ ", ( select 5 from tdual union select 0 from tdual)"
> ++ ", ( select 6 from tdual union select 0 from tdual)"
> ++ ", ( select 7 from tdual union select 0 from tdual)"
> ++ ", ( select 8 from tdual union select 0 from tdual)"
> ++ ", ( select 9 from tdual union select 0 from tdual)"
> ++ ", ( select 10 from tdual union select 0 from tdual)"
> countRows :: DBHandle -> StmtHandle -> Int -> IO Int
> countRows db stmt n = do
> rc <- printPropagateError $ stmtFetch db stmt
> _ <- colValInt stmt 1
> if rc == sqliteDONE
> then return n
> else countRows db stmt (n+1)
> testSelectManyRows db = do
> stmt <- printPropagateError $ stmtPrepare db manyRows
> n <- countRows db stmt 0
> stmtFinalise db stmt
> assertEqual "testSelectManyRows: done" 1024 n
> testBindString db = do
> stmt <- printPropagateError $
> stmtPrepare db "select ? from tdual"
> bindString db stmt 1 "h1"
> rc <- stmtFetch db stmt
> Just n <- colValString stmt 1
> assertEqual "testBindString: h1" "h1" n
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
> testBindDouble db = do
> stmt <- printPropagateError $
> stmtPrepare db "select ? from tdual where ? = ?"
> bindDouble db stmt 1 2.3
> bindInt db stmt 2 2001
> bindInt64 db stmt 3 2001
> rc <- stmtFetch db stmt
> n <- colValDouble stmt 1
> assertEqual "testBindDouble: 2.3" 2.3 n
> rc <- stmtFetch db stmt
> stmtFinalise db stmt
This test reveals that library misuse (error number 21)
is reported by sqlite_errcode as error code zero.
> testFetchAfterFinalise db = do
> stmt <- printPropagateError $ stmtPrepare db manyRows
> stmtFinalise db stmt
> rc <- sqliteStep stmt
> assertEqual "testFetchAfterFinalise: rc" 21 rc
> ex@(SqliteException e m) <- getError db
> -- Is this a bug in Sqlite?)
> assertEqual "testFetchAfterFinalise: errcode" 0 e
> assertEqual "testFetchAfterFinalise: errmsg" "not an error" m
This test confirms that a constraint error (19)
is correctly reported by sqlite_errcode.
> testConstraintError db = do
> withUTF8String "insert into t_natural values (1)" $ \cstr -> do
> rc <- sqliteExec db cstr nullFunPtr nullPtr nullPtr
> assertEqual "testConstraintError: rc" 19 rc
> ex@(SqliteException e m) <- getError db
> assertEqual "testConstraintError: errcode" 19 e
> assertEqual "testConstraintError: errmsg" "PRIMARY KEY must be unique" m
> testSelectUTF8Text db = do
> -- GREEK SMALL LETTER PHI
> -- unicode code-point 966
> -- UTF8: CF86 (207,134)
> -- UTF16: 03C6
> let expect = ['\966']
> stmt <- printPropagateError $
> stmtPrepare db "select ?"
> bindString db stmt 1 expect
> rc <- stmtFetch db stmt
> Just n <- colValString stmt 1
> assertEqual "testSelectUTF8Text" expect n
> stmtFinalise db stmt