Comments (7)
For the record, if we wanted to go heavyweight we could roll in my separate project language-sqlite, which is (I believe) a complete parser and generator for the SQLite syntax. But then it would have to be kept up to date...
from direct-sqlite.
The underlying sqlite implementation already parses the query string, adding another on top of it sounds like a lot of added complexity.
What I had mind in for this particular issue was a lot simpler. In fact, it should be simple enough that I'll post a pull request..
from direct-sqlite.
Can't send a pull request right now, but here's the idea in a patch. Instead of using 'fail', it'd be nicer to use exception types. The below code now uses deprecated fail coming in from Prelude, so it gives a compiler warning.
commit 9d18e815c739ff6065349d5f10adf458a844406b
Author: Janne Hellsten <[email protected]>
Date: Thu Aug 16 09:17:58 2012 +0300
Throw an error if # of bind params doesn't the query (#2)
Fail with an error rather than let sqlite convert missing
parameters to NULLs.
diff --git a/Database/SQLite3.hsc b/Database/SQLite3.hsc
index 2026392..4220438 100644
--- a/Database/SQLite3.hsc
+++ b/Database/SQLite3.hsc
@@ -30,6 +30,7 @@ module Database.SQLite3 (
)
where
+import Control.Monad
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BSI
import qualified Data.Text as T
@@ -393,6 +394,10 @@ bindText statement parameterIndex text = do
bind :: Statement -> [SQLData] -> IO ()
bind statement sqlData = do
+ nParams <- bindParameterCount statement
+ when (nParams /= length sqlData) $
+ fail ("mismatched parameter count for bind. Prepared statement "++
+ "needs "++ show nParams ++ ", " ++ show (length sqlData) ++" given")
mapM (\(parameterIndex, datum) -> do
case datum of
SQLInteger int64 -> bindInt64 statement parameterIndex int64
diff --git a/test/Main.hs b/test/Main.hs
index 83384da..d956bb6 100644
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,4 +1,5 @@
+import Prelude
import Control.Exception (bracket)
import Control.Monad (when)
import System.Exit (exitFailure)
@@ -18,10 +19,17 @@ data TestEnv =
tests :: [TestEnv -> Test]
tests =
[ TestLabel "Simple" . testSimplest
+ , TestLabel "Params" . testBind
, TestLabel "Params" . testBindParamCounts
, TestLabel "Params" . testBindParamName
+ , TestLabel "Params" . testBindErrorValidation
]
+assertBindErrorCaught :: IO a -> Assertion
+assertBindErrorCaught action = do
+ catch (action >> return False) (\_ -> return True) >>=
+ assertBool "assertExceptionCaught"
+
-- Simplest SELECT
testSimplest :: TestEnv -> Test
testSimplest TestEnv{..} = TestCase $ do
@@ -32,6 +40,27 @@ testSimplest TestEnv{..} = TestCase $ do
finalize stmt
assertEqual "1+1" (SQLInteger 2) res
+testBind :: TestEnv -> Test
+testBind TestEnv{..} = TestCase $ do
+ bracket (prepare conn "SELECT ?") finalize testBind1
+ bracket (prepare conn "SELECT ?+?") finalize testBind2
+ where
+ testBind1 stmt = do
+ let params = [SQLInteger 3]
+ bind stmt params
+ Row <- step stmt
+ res <- columns stmt
+ Done <- step stmt
+ assertEqual "single param" params res
+
+ testBind2 stmt = do
+ let params = [SQLInteger 1, SQLInteger 1]
+ bind stmt params
+ Row <- step stmt
+ res <- columns stmt
+ Done <- step stmt
+ assertEqual "two params param" [SQLInteger 2] res
+
-- Test bindParameterCount
testBindParamCounts :: TestEnv -> Test
testBindParamCounts TestEnv{..} = TestCase $ do
@@ -58,6 +87,16 @@ testBindParamName TestEnv{..} = TestCase $ do
name <- bindParameterName stmt ndx
assertEqual "name match" expecting name) $ zip [1..] names
+testBindErrorValidation :: TestEnv -> Test
+testBindErrorValidation TestEnv{..} = TestCase $ do
+ bracket (prepare conn "SELECT ?") finalize (\stmt -> assertBindErrorCaught (testException1 stmt))
+ bracket (prepare conn "SELECT ?") finalize (\stmt -> assertBindErrorCaught (testException2 stmt))
+ where
+ -- Invalid use, one param in q string, none given
+ testException1 stmt = bind stmt []
+ -- Invalid use, one param in q string, 2 given
+ testException2 stmt = bind stmt [SQLInteger 1, SQLInteger 2]
+
-- | Action for connecting to the database that will be used for
-- testing.
--
from direct-sqlite.
The above patch will conflict with Joey's #7 - I can send a pull request if/when the other change goes in.
from direct-sqlite.
Yes, I'll wait for Joey's changes to go in and then ask you to resubmit, I think. Shouldn't be long.
from direct-sqlite.
I've merged Joey's patch (it was a lot easier to read than I expected :D).
So you know.
On Thu, Aug 16, 2012 at 5:50 AM, Janne Hellsten [email protected]:
The above patch will conflict with Joey's
#7 - I can send a pull
request if/when the other change goes in.—
Reply to this email directly or view it on GitHubhttps://github.com//issues/2#issuecomment-7781095.
-- Irene Knapp
from direct-sqlite.
Pull request here #9
from direct-sqlite.
Related Issues (20)
- Enable math functions HOT 3
- Add built-tool-depends hsc2hs? HOT 2
- Expose setting sqlite3_busy_timeout
- Test suite failure with GHC 8
- How to add FTS5? HOT 5
- Any need to apply stat64 workaround? HOT 4
- Unreliable sqlErrorDetails in parallelized environments HOT 5
- Inaccurate version bound / build failure for GHC < 7.10 HOT 1
- Upgrading SQLite to v3.27.2
- Add a flag for compiling sqlite in Multi-thread mode HOT 3
- Upgrade embedded SQLite library HOT 2
- Test failure with system sqlite 3.34.1 HOT 1
- Nondeterministic `ErrorMisuse` on multiple runs of the same application test HOT 9
- Add Bindings to sqlite3_status and sqlite3_status64 HOT 1
- Slowness on `stepNoCB` HOT 1
- Updating test case for upgrading SQLite HOT 1
- Allow semigroup-0.20 HOT 1
- ICU extension flag HOT 3
- Allow opening sqllite from bytestring via sqllite3_deserialize directive HOT 4
- Can't use URI HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from direct-sqlite.