on master help sign in
fixed a bug for nested SELECT queries
commit8011e703c265c2c1ea41e6ecefa009244046b4c5 authormelissam <mfm6@st-andrews.ac.uk> dateFri 10 Aug 2012, 11:44 (14 years ago) parentefb2fa1
5 files changed+54−36
contribs/lib/SQLite3/._sqlexpr.idr contribs/lib/SQLite3/._testunit.idr contribs/lib/SQLite3/sqlexpr.idr+9−9 contribs/lib/SQLite3/sqlite3.tex+12−10 contribs/lib/SQLite3/testunit.idr+33−17
contribs/lib/SQLite3/._sqlexpr.idr

Binary file not shown.

contribs/lib/SQLite3/._testunit.idr

Binary file not shown.

contribs/lib/SQLite3/sqlexpr.idr+9−9
@@ -157,23 +157,23 @@ listValType xs ((val, types, constr) :: vs) = let (str , newxs) = valString xs v
157157evalCond : List (Maybe(Int, Value)) -> Cond -> (String, List (Maybe(Int, Value)))
158158evalCond xs (Equals val1 val2) = let (restring , newxs ) = valString xs val1 in
159159 let (restring2, newxs') = valString newxs val2 in
160− (restring ++ " = " ++ restring2, (newxs'))
160+ (restring ++ " = " ++ restring2, newxs')
161161
162162evalCond xs (MkGT val1 val2) = let (restring , newxs ) = valString xs val1 in
163163 let (restring2, newxs') = valString newxs val2 in
164− (restring ++ " > " ++ restring2, (newxs'))
164+ (restring ++ " > " ++ restring2, newxs')
165165
166166evalCond xs (MkGTE val1 val2) = let (restring , newxs ) = valString xs val1 in
167167 let (restring2, newxs') = valString newxs val2 in
168− (restring ++ " >= " ++ restring2, ( newxs'))
168+ (restring ++ " >= " ++ restring2, newxs')
169169
170170evalCond xs (MkLT val1 val2) = let (restring , newxs ) = valString xs val1 in
171171 let (restring2, newxs') = valString newxs val2 in
172− (restring ++ " < " ++ restring2, (newxs'))
172+ (restring ++ " < " ++ restring2, newxs')
173173
174174evalCond xs (MkLTE val1 val2) = let (restring , newxs ) = valString xs val1 in
175175 let (restring2, newxs') = valString newxs val2 in
176− (restring ++ " =< " ++ restring2, ( newxs'))
176+ (restring ++ " =< " ++ restring2, newxs')
177177
178178evalCond xs (MkNULL val) = let (restring , newxs ) = valString xs val in
179179 (restring ++ " IS NULL " , newxs)
@@ -228,26 +228,26 @@ evalSQL xs (SELECT vars sql' c) = let (sqlstring, newxs) = evalSQL xs sql' in
228228 case c of
229229 Empty => case vars of
230230 (ALL ) => if complexType sql' then ("SELECT " ++ "*" ++ " FROM "
231− ++ (putBrackets sqlstring) ++ csstring, newxs')
231+ ++ (putBrackets sqlstring) ++ csstring, newxs)
232232
233233 else ("SELECT " ++ "*" ++ " FROM " ++ sqlstring
234234 ++ csstring, newxs')
235235
236236 (Cols selvar) => if complexType sql' then ("SELECT " ++ (unwords selvar) ++
237− " FROM " ++ (putBrackets sqlstring) ++ csstring, newxs')
237+ " FROM " ++ (putBrackets sqlstring) ++ csstring, newxs)
238238
239239 else ("SELECT " ++ (unwords selvar )++ " FROM " ++ sqlstring
240240 ++ csstring, newxs')
241241
242242 _ => case vars of
243243 (ALL ) => if complexType sql' then ("SELECT " ++ "*" ++ " FROM "
244− ++ " WHERE " ++ csstring , newxs')
244+ ++ " WHERE " ++ csstring , newxs)
245245 else ("SELECT " ++ "*" ++ " FROM " ++ sqlstring
246246 ++ " WHERE " ++ csstring , newxs')
247247
248248 (Cols selvar) => if complexType sql' then ("SELECT " ++ (unwords selvar) ++ " FROM " ++
249249 (putBrackets sqlstring) ++ " WHERE "
250− ++ csstring , newxs')
250+ ++ csstring , newxs)
251251
252252 else ("SELECT " ++ (unwords selvar) ++ " FROM " ++ sqlstring
253253 ++ " WHERE " ++ csstring , newxs')
contribs/lib/SQLite3/sqlite3.tex+12−10
@@ -11,25 +11,27 @@
1111 \begin{document}
1212 \section{Introduction}
1313\label{Introduction}
14−This document provides overview of how the library for SQLite works. The code base is written on top of the SQLite3 C/C++ Interface.
14+This document provides overview of how the library for SQLite works. The code base is written on top of the
15+SQLite3 C/C++ Interface.
1516This library supports some features of the low-level library, implemented in a higher level basis.
1617The library allows making use of data types as queries. The aim of this library is to avoid
1718SQL injections which are the most common security issues.
18−To avoid this we have defined a datatype which describes qqueries.
19+To avoid this we have defined a datatype which describes queries.
1920The queries are written using these data types and parsed as quoted string
2021while replacing values with indexed question mark to be binded with the statement.
2122\section{Using the library}
2223\label{Using the library}
23−Simple examples have been provided in the testunit.idr file.
24+Simple examples have been provided in the \emph{testunit.idr} file.
2425To open a database, use the open\_db function which takes the filename as a string.
25−This function implements the sqlite3\_open function .
26−This function returns a pointer to the database which can be used by other function to access the database object.
26+This function implements the sqlite3\_open function.
27+This function returns a pointer to the database which can be used by other function
28+to access the database object.
2729Whether or not an error occurs when it is opened,
2830resources should be released by passing it to close\_db when it is no longer required.
29−A query can then be builts using the supported data types .
31+A query can then be builts using the supported data types.
3032The library supports limited number of queries at the moment. The supported sql commands are :
3133\newline
32−\newline
34+
3335\textbf{SELECT,}
3436\textbf{INSERT,}
3537\textbf{UPDATE,}
@@ -39,7 +41,7 @@ The library supports limited number of queries at the moment. The supported sql
3941\label{Creating Queries}
4042
4143To create a query, use the evalSQL function which takes an empty list and the SQL query.
42−The routine evaluates the expression in a divide and conquer manner (or recursive?)
44+The routine evaluates the expression recrusively by dividing it into smaller parts,
4345filling up the list with the received values. For instance the following is a valid query:
4446
4547let sql = evalSQL [ ] ((SELECT ALL)(TBL ["tbl1"]) (MkCond (MkNULL (VCol "data"))))
@@ -49,12 +51,12 @@ let sql = evalSQL [ ] ((SELECT ALL)(TBL ["tbl1"]) (MkCond (MkNULL (VCol "data"))
4951
5052The evaluator returns a string and a list of indexed values.
5153The string part of the query could be parsed to prepare.
52−evalSQL parses the query as a string replacing values with ? and an index starting from one,
54+\emph{evalSQL} parses the query as a string replacing values with \emph{?} and an index starting from one,
5355storing them in the list given to it as an argument.
5456For example:
5557
5658
57−evalSQL [ ] (SELECT (Cols ["data"]) (SELECT (Cols["num","data"]) (TBL ["tbl1"]) (MkCond (Equals (VCol "num")(VInt 2))) ) Empty ) )
59+evalSQL [ ] (SELECT (Cols ["data"]) (SELECT (Cols["num","data"]) (TBL ["tbl1"])(MkCond(Equals(VCol "num")(VInt 2))))Empty))
5860
5961is passed to prepare as :
6062
contribs/lib/SQLite3/testunit.idr+33−17
@@ -5,21 +5,21 @@ import sqlite3
55testexpr : DB()
66testexpr = do db <- open_db "somedb.db"
77 let sql = (evalSQL [] ((SELECT ALL)(TBL ["tbl1"]) (OR (AND (MkCond (Equals (VCol "data")(VStr "data0"))) (MkCond (Equals (VCol "num")(VInt 1))) ) (MkCond (Equals (VCol "num")(VInt 2))))))
8− let x = (fst sql)
9− let list = (snd sql)
10− liftIO(print x)
11− stmt <- (prepare_db db x)
12− bindMulti stmt list
13− exec_db_v2 stmt
14− res <- toList_v1 db
15− liftIO(print res)
16− finalize_db stmt
17− close_db db
8+ let x = (fst sql) -- get the string
9+ let list = (snd sql) -- list of vals
10+ liftIO(print x) -- use liftIO to turn this into DB type
11+ stmt <- (prepare_db db x) -- prepare the statement
12+ bindMulti stmt list -- bind the values in the list
13+ exec_db_v2 stmt -- execute the prepared query
14+ res <- toList_v1 db -- toList_v1 to get the result
15+ liftIO(print res) -- print the result
16+ finalize_db stmt -- Statment pointer must be finalized in the end
17+ close_db db -- close the datbase
1818 return ()
1919
2020testupdate : DB()
2121testupdate = do db <- open_db "somedb.db"
22− let sql = (evalSQL [] (UPDATE (TBL ["tbl1"]) (WHERE (SET (MkCond (Equals(VCol "data") (VStr "data0"))) ) (MkCond (Equals (VCol "num") (VInt 2))) ) ))
22+ let sql = (evalSQL [] (UPDATE (TBL ["tbl1"]) (WHERE (SET (MkCond (Equals(VCol "data") (VStr "data600"))) ) (MkCond (Equals (VCol "num") (VInt 2))) ) ))
2323 let x = (fst sql)
2424 let list = (snd sql)
2525 liftIO(print x)
@@ -32,7 +32,7 @@ testupdate = do db <- open_db "somedb.db"
3232
3333testInsert : DB()
3434testInsert = do db <- open_db "somedb.db"
35− let sql = (evalSQL [] (INSERT (TBL ["tbl1"]) [(VInt 2),(VStr "histring2")]))
35+ let sql = (evalSQL [] (INSERT (TBL ["tbl1"]) [(VInt 3),(VStr "ham")]))
3636 let x = (fst sql)
3737 let list = (snd sql)
3838 liftIO(print x)
@@ -61,7 +61,7 @@ testNull = do db <- open_db "somedb.db"
6161
6262testInsertWithCond : DB()
6363testInsertWithCond = do db <- open_db "somedb.db"
64− let sql = (evalSQL [] (INSERTC (TBL ["tbl1"]) [(VCol "data"),(VCol "num")] [(VInt 201),(VStr "newinserted")]))
64+ let sql = (evalSQL [] (INSERTC (TBL ["tbl1"]) [(VCol "data"),(VCol "num")] [(VInt 30),(VStr "inserthere")]))
6565 let x = (fst sql)
6666 let list = (snd sql)
6767 liftIO(print x)
@@ -72,10 +72,10 @@ testInsertWithCond = do db <- open_db "somedb.db"
7272 close_db db
7373 return ()
7474
75−-- Nested queries need to have the same column as the outer queries !!!
75+-- Nested queries need to have the same column as the outer queries.
7676testNestedSel1 : DB()
7777testNestedSel1 = do db <- open_db "somedb.db"
78− let sql = (evalSQL [] (SELECT (Cols ["data"]) (SELECT (Cols["num","data"]) (TBL ["tbl1"]) (MkCond (Equals (VCol "num")(VInt 2))) ) Empty ) )
78+ let sql = (evalSQL [] (SELECT (Cols ["data"]) (SELECT (Cols["num","data"]) (TBL ["tbl1"]) (MkCond (MkGT (VCol "num")(VInt 2))))Empty))
7979 let x = (fst sql)
8080 let list = (snd sql)
8181 liftIO(print x)
@@ -102,6 +102,7 @@ testCreateTable = do db <- open_db "somedb.db"
102102 close_db db
103103 return ()
104104
105+-- This may be a bit slow
105106testMultiTable : DB ()
106107testMultiTable = do db <- open_db "somedb.db"
107108 let sql = (evalSQL [] ((SELECT ALL )(TBL ["mytable","tbl1"]) (Empty) ) )
@@ -117,8 +118,23 @@ testMultiTable = do db <- open_db "somedb.db"
117118 close_db db
118119 return ()
119120
121+testSelAll : DB ()
122+testSelAll = do db <- open_db "somedb.db"
123+ let sql = (evalSQL [] ((SELECT ALL )(TBL ["tbl1"]) (Empty) ) )
124+ let x = (fst sql)
125+ let list = (snd sql)
126+ liftIO(print x)
127+ stmt <- (prepare_db db x)
128+ bindMulti stmt list
129+ exec_db_v2 stmt
130+ res <- toList_v1 db
131+ liftIO(print res)
132+ finalize_db stmt
133+ close_db db
134+ return ()
135+
120136
121137main : IO ()
122−main = do x <- runDB (testexpr)
123− y <- runDB (testNestedSel1)
138+main = do x <- runDB (testMultiTable) -- runDB : DB a -> IO a
139+ --y <- runDB (testNestedSel1)
124140 return ()