packages feed

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