Skip to content

Commit

Permalink
Fix broken SQL query for counting tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
ad-si committed Mar 17, 2024
1 parent 698943c commit 24a57b3
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 23 deletions.
11 changes: 4 additions & 7 deletions tasklite-core/source/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ import FullTask (
selectQuery,
)
import Note (Note (body, ulid))
import SqlUtils (quoteKeyword)
import Task (
DerivedState (IsOpen),
Task,
Expand Down Expand Up @@ -2160,13 +2161,9 @@ countTasks conf connection filterExpression = do
case filterMay of
Nothing -> do
[NumRows taskCount] <-
query
connection
[sql|
SELECT count(1)
FROM ?
|]
(Only $ tableName conf)
query_ connection $
Query $
"SELECT count(1) FROM " <> quoteKeyword conf.tableName

pure $ pretty taskCount
Just (filterExps, _) -> do
Expand Down
37 changes: 30 additions & 7 deletions tasklite-core/source/SqlUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,10 @@ import Protolude as P (
unwords,
words,
($),
(&),
)

import Data.Text as T (
intercalate,
isSuffixOf,
pack,
unlines,
unpack,
)
import Data.Text qualified as T
import Database.SQLite.Simple as Sql (
Connection,
Query (..),
Expand Down Expand Up @@ -195,6 +190,34 @@ fromAs tableName aliasName =
(alias aliasName)


-- | Escape double quotes in SQL strings
escDoubleQuotes :: Text -> Text
escDoubleQuotes =
T.replace "\"" "\"\""


-- | Quote a keyword in an SQL query
quoteKeyword :: Text -> Text
quoteKeyword keyword =
keyword
& escDoubleQuotes
& (\word -> "\"" <> word <> "\"")


-- | Escape single quotes in SQL strings
escSingleQuotes :: Text -> Text
escSingleQuotes =
T.replace "'" "''"


-- | Quote literal text in an SQL query
quoteText :: Text -> Text
quoteText keyword =
keyword
& escSingleQuotes
& (\word -> "'" <> word <> "'")


getValue :: (Show a) => a -> Text
getValue value =
"'" <> show value <> "'"
Expand Down
2 changes: 2 additions & 0 deletions tasklite-core/tasklite-core.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ test-suite tasklite-test
main-is: Spec.hs
other-modules:
CliSpec
LibSpec
TestUtils
Paths_tasklite_core
autogen-modules:
Paths_tasklite_core
Expand Down
57 changes: 57 additions & 0 deletions tasklite-core/test/LibSpec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module LibSpec where

import Protolude (
Maybe (..),
Text,
pure,
show,
($),
)
import Protolude qualified as P

import Config (defaultConfig)
import Test.Hspec (
Spec,
describe,
it,
shouldBe,
)

import Lib (countTasks, insertTags, insertTask)
import Task (Task (body, ulid), zeroTask)
import TestUtils (withMemoryDb)


spec :: Spec
spec = do
describe "Lib" $ do
it "counts tasks" $ do
withMemoryDb defaultConfig $ \memConn -> do
let
task1 =
zeroTask
{ ulid = "01hs68z7mdg4ktpxbv0yfafznq"
, body = "New task"
}
task2 =
zeroTask
{ ulid = "01hs690f9hkzk9z7zews9j2k1d"
, body = "New task"
}

count0 <- countTasks defaultConfig memConn P.mempty
show count0 `shouldBe` ("0" :: Text)

insertTask memConn task1
count1 <- countTasks defaultConfig memConn P.mempty
show count1 `shouldBe` ("1" :: Text)

insertTask memConn task2
count2 <- countTasks defaultConfig memConn P.mempty
show count2 `shouldBe` ("2" :: Text)

insertTags memConn Nothing task2 ["test"]
countWithTag <- countTasks defaultConfig memConn (Just ["+test"])
show countWithTag `shouldBe` ("1" :: Text)

pure ()
14 changes: 5 additions & 9 deletions tasklite-core/test/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import Lib (
setReadyUtc,
updateTask,
)
import LibSpec qualified
import Migrations (runMigrations)
import Note (Note)
import Task (
Expand All @@ -87,16 +88,10 @@ import TaskToNote (TaskToNote)
import TaskToNote qualified
import TaskToTag (TaskToTag)
import TaskToTag qualified
import TestUtils (withMemoryDb)
import Utils (parseUlidText, parseUlidUtcSection, parseUtc, ulid2utc)


withMemoryDb :: Config -> (Sql.Connection -> IO a) -> IO a
withMemoryDb conf action =
Sql.withConnection ":memory:" $ \memConn -> do
_ <- runMigrations conf memConn
action memConn


exampleTask :: Task
exampleTask =
zeroTask
Expand All @@ -112,8 +107,6 @@ exampleTask =

testSuite :: Config -> DateTime -> SpecWith ()
testSuite conf now = do
CliSpec.spec

describe "Utils" $ do
it "correctly parses beginning of UNIX epoch" $
do
Expand Down Expand Up @@ -449,6 +442,9 @@ testSuite conf now = do
ulid2utc updatedTask.ulid `shouldBe` Just utcFromUlid
_ -> P.die "More than one task found"

LibSpec.spec
CliSpec.spec


main :: IO ()
main = do
Expand Down
18 changes: 18 additions & 0 deletions tasklite-core/test/TestUtils.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module TestUtils where

import Protolude (
IO,
($),
)

import Database.SQLite.Simple qualified as Sql

import Config (Config (..))
import Migrations (runMigrations)


withMemoryDb :: Config -> (Sql.Connection -> IO a) -> IO a
withMemoryDb conf action =
Sql.withConnection ":memory:" $ \memConn -> do
_ <- runMigrations conf memConn
action memConn

0 comments on commit 24a57b3

Please sign in to comment.