hssqlppp-0.4.2: src-extra/tests/Database/HsSqlPpp/Tests/ParameterizedStatementTests.lhs
Tests for the infrastructure to create type safe access to databases -
the information needed is gathered during typechecking and exposed in
the StatementType annotation, so these are really just a subset of the
type checking tests.
> module Database.HsSqlPpp.Tests.ParameterizedStatementTests (parameterizedStatementTests) where
>
> import Test.HUnit
> import Test.Framework
> import Test.Framework.Providers.HUnit
> --import Debug.Trace
> import Data.Generics
> import Data.Generics.Uniplate.Data
>
>
> import Database.HsSqlPpp.Types
> import Database.HsSqlPpp.Annotation
> import Database.HsSqlPpp.Parser
> import Database.HsSqlPpp.TypeChecker
> import Database.HsSqlPpp.Catalog
>
> data Item = Group String [Item]
> | Statements [(String, [CatalogUpdate], Maybe ParameterizedStatementType)]
>
> parameterizedStatementTests :: Test.Framework.Test
> parameterizedStatementTests =
> testGroup "parameterized statement tests" $ itemToTft testData
>
> testData :: Item
> testData =
> Group "parameterized statement tests" [
> Group "simple selects" [ Statements [
> ("select test();"
> ,[CatCreateFunction FunName "test" [] (Pseudo Void) False]
> ,Just ([],[]))
> ,("select adnum,adbin from pg_attrdef;"
> ,[]
> ,Just ([],[("adnum", ScalarType "int2")
> ,("adbin", ScalarType "pg_node_tree")]))
> ,("select adnum,adbin from pg_attrdef where adnum= ?;"
> ,[]
> ,Just ([ScalarType "int2"],[("adnum", ScalarType "int2")
> ,("adbin", ScalarType "pg_node_tree")]))
> ,("select count(1) from pg_attrdef;"
> ,[]
> ,Just ([],[("count", ScalarType "int8")]))
> {-,("select test($1);"
> ,[CatCreateFunction FunName "test" [ScalarType "int4"] (ScalarType "text") False]
> ,StatementType [ScalarType "int4"] [("test",ScalarType "text")])
> ,-}
> ,("select test(?);"
> ,[CatCreateFunction FunName "test" [ScalarType "int4"] (ScalarType "text") False]
> ,Just ([ScalarType "int4"],[("test",ScalarType "text")]))
> ]
> ]
> ,Group "simple dml" [ Statements [
> ("insert into testt values (1, 'test');"
> ,[CatCreateTable "testt" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,Just ([],[]))
> ,("insert into testt (c1,c2) values (?, ?);"
> ,[CatCreateTable "testt" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,Just ([typeInt, ScalarType "text"],[]))
> ,("insert into testt (c1,c2) values (1, 'test') returning c1;"
> ,[CatCreateTable "testt" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,Just ([],[("c1",typeInt)]))
> ,("insert into testt (c1,c2) values (?, ?) returning c1 as d1, c2;"
> ,[CatCreateTable "testt" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,Just ([typeInt, ScalarType "text"],[("d1", typeInt)
> ,("c2", ScalarType "text")]))
> {-,("insert into testt (c1,c2) values (?, ?) returning *;"
> ,[CatCreateTable "testt" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,StatementType [typeInt, ScalarType "text"] [("c1", typeInt)
> ,("c2", ScalarType "text")])-}
> ,("update testt set c1= ?,c2= ? where c1= ? returning c2;"
> ,[CatCreateTable "testt" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,Just ([typeInt, ScalarType "text", typeInt],[("c2", ScalarType "text")]))
> ,("update testt set (c1,c2) = (?,?);"
> ,[CatCreateTable "testt" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,Just ([typeInt, ScalarType "text"],[]))
> ,("delete from blah where c1= ? returning c2;"
> ,[CatCreateTable "blah" [("c1", typeInt)
> ,("c2", ScalarType "text")] []]
> ,Just ([typeInt],[("c2", ScalarType "text")]))
> ]
> ]
> ]
~~~~
select a,b from c where d=e group by f having g=h orderby i limit j offset k;
select function(a,b);
insert into a (b,c) values (d,e) returning f,g
update a set b=c,d=e where f=g returning h,i
delete from t where a=b returning c,d
rough list of grammar elements to possibly add inference support to:
where top level - >maybeboolexpr
having
limit, offset
values for table literal or insert
set clause
rowsetclause
onexpr, joinon?
windowfn
liftoperator
selectitem?
castexpression
caseexpression
funcall
inpredicate
TODO: add support in each of these places for position args only when
doing typecheckPS
do typecheck error if come across ? when not doing typecheckPS
make sure ? fails type check if not in a valid place in the ast
~~~~
-------------------------------------------------------------------------------
> testStatementType :: String -> [CatalogUpdate] -> Maybe ParameterizedStatementType -> Test.Framework.Test
> testStatementType src eu st = testCase ("typecheck " ++ src) $
> let ast = case parseStatements "" src of
> Left e -> error $ show e
> Right l -> l
> in case typeCheckParameterizedStatement makeCat (head ast) of
> Left e -> error $ show e
> Right aast -> --trace (ppShow aast) $
> let is = getTopLevelInfo aast
> er = getTypeErrors aast
> in case is of
> _ | not (null er) -> assertFailure $ show er
> is1 -> assertEqual ("typecheck " ++ src) st is1
> -- _ -> assertFailure ("expected onne statementinfo, got " ++ show is)
> where
> getTypeErrors :: Data a => a -> [TypeError]
> getTypeErrors = universeBi
> getTopLevelInfo a = stType $ getAnnotation a
> makeCat = case updateCatalog defaultTemplate1Catalog eu of
> Left x -> error $ show x
> Right e -> e
>
> itemToTft :: Item -> [Test.Framework.Test]
> itemToTft (Statements es) = map (\(a,b,c) -> testStatementType a b c) es
> itemToTft (Group s is) = [testGroup s $ concatMap itemToTft is]