Fre*_*son 5 sql sqlite haskell generated-code hdbc
我在Haskell中生成SQL查询并使用HDBC将它们提交到SQLite(3)数据库.现在,此函数返回一个查询:
import Database.HDBC.Sqlite3
import Database.HDBC
data UmeQuery = UmeQuery String [SqlValue] deriving Show
tRunUmeQuery :: UmeQuery -> FilePath -> IO [[SqlValue]]
tRunUmeQuery (UmeQuery q args) dbFile = do
conn <- connectSqlite3 dbFile
stat <- prepare conn q
s <- execute stat args
res <- fetchAllRows' stat
disconnect conn
return $ res
selectPos targetlt parentlt op pos = let
q= "select TARGET.* from levels tl, labeltypes tlt, segments TARGET,
(select TARGET.session_id session_id,SECONDARY.labeltype_id labeltype_id,
SECONDARY.label_id label_id,min(TARGET.label_id) min_childlabel_id from
levels tl, labeltypes tlt, segments TARGET, segments SECONDARY, labeltypes slt,
levels sl where TARGET.session_id = SECONDARY.session_id and ((SECONDARY.start
<= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start <= SECONDARY.start
and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ? and SECONDARY.label '
!= '' and tl.id = tlt.level_id and sl.id = slt.level_id and tlt.id = TARGET.labeltype_id
and slt.id = SECONDARY.labeltype_id group by TARGET.session_id, TARGET.labeltype_id,
SECONDARY.label_id) SUMMARY, segments SECONDARY, labeltypes slt, levels sl where
TARGET.session_id = SECONDARY.session_id and TARGET.session_id = SUMMARY.session_id
and ((SECONDARY.start <= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start
<= SECONDARY.start and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ?
and tl.id = tlt.level_id and tlt.id = TARGET.labeltype_id and SUMMARY.labeltype_id =
SECONDARY.labeltype_id and SUMMARY.label_id = SECONDARY.label_id and sl.id = slt.level_id
and slt.id = SECONDARY.labeltype_id and (TARGET.label_id - SUMMARY.min_childlabel_id +1) = 2 "
a = [toSql targetlt, toSql parentlt, toSql targetlt, toSql parentlt ]
in UmeQuery q a
Run Code Online (Sandbox Code Playgroud)
当应用于数据库时返回正确的东西:
> let a =selectPos "Word" "Utterance" "=" 2
> let b = tRunUmeQuery a testdb
> b
Run Code Online (Sandbox Code Playgroud)
产出:
[[SqlByteString"1",SqlByteString"2",SqlByteString"3",SqlByteString"0.149383838383838",SqlByteString"0.312777777777778",SqlByteString"second"],[SqlByteString"1",SqlByteString"2",SqlByteString"6",SqlByteString "0.507488888888889",SqlByteString"0.655905050505051",SqlByteString"第四",[SqlByteString"2",SqlByteString"2",SqlByteString"3",SqlByteString"0.149383838383838",SqlByteString"0.312777777777778",SqlByteString"second"],[SqlByteString" 2",SqlByteString"2",SqlByteString"6",SqlByteString"0.507488888888889",SqlByteString"0.655905050505051",SqlByteString"第四",[SqlByteString"3",SqlByteString"2",SqlByteString"3",SqlByteString"0.149383838383838", SqlByteString"0.312777777777778",SqlByteString"second"],[SqlByteString"3",SqlByteString"2",SqlByteString"6",SqlByteString"0.507488888888889",SqlByteString"0.655905050505051",SqlByteString"4th"]]
现在,当我需要在查询中插入几个小的动态部分时,就像这样(抱歉,你必须滚动到字符串的末尾才能看到这个):
selectPos targetlt parentlt op pos = let
q= "select TARGET.* from levels tl, labeltypes tlt, segments TARGET,
(select TARGET.session_id session_id,SECONDARY.labeltype_id labeltype_id,
SECONDARY.label_id label_id,min(TARGET.label_id) min_childlabel_id from
levels tl, labeltypes tlt, segments TARGET, segments SECONDARY, labeltypes slt,
levels sl where TARGET.session_id = SECONDARY.session_id and ((SECONDARY.start
<= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start <= SECONDARY.start
and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ? and SECONDARY.label
!= '' and tl.id = tlt.level_id and sl.id = slt.level_id and tlt.id = TARGET.labeltype_id
and slt.id = SECONDARY.labeltype_id group by TARGET.session_id, TARGET.labeltype_id,
SECONDARY.label_id) SUMMARY, segments SECONDARY, labeltypes slt, levels sl where
TARGET.session_id = SECONDARY.session_id and TARGET.session_id = SUMMARY.session_id
and ((SECONDARY.start <= TARGET.start and TARGET.end <= SECONDARY.end) or (TARGET.start
<= SECONDARY.start and SECONDARY.end <= TARGET.end)) and tl.name = ? and sl.name = ?
and tl.id = tlt.level_id and tlt.id = TARGET.labeltype_id and SUMMARY.labeltype_id =
SECONDARY.labeltype_id and SUMMARY.label_id = SECONDARY.label_id and sl.id = slt.level_id
and slt.id = SECONDARY.labeltype_id and (TARGET.label_id - SUMMARY.min_childlabel_id +1) "
++ op ++ " ? "
a = [toSql targetlt, toSql parentlt, toSql targetlt, toSql parentlt , toSql pos]
in UmeQuery q a
Run Code Online (Sandbox Code Playgroud)
并做同样的事情,我得到:
> let a =selectPos "Word" "Utterance" "=" 2
> let b = tRunUmeQuery a testdb
> b
Run Code Online (Sandbox Code Playgroud)
[]
为什么第二个查询没有返回任何东西(或者实际上是同一个东西)?
有任何想法吗?
编辑:
我进一步调查了这一点,认为这可能与懒惰有某种关系.好了,现在已经重塑了这个:
selectPos :: String -> String -> String -> Integer -> [[SqlValue]]
selectPos targetlt parentlt op pos = let
q= foldl' (++) [] ["select TARGET.* from levels tl, labeltypes tlt, segments TARGET,
(select TARGET.session_id session_id,SECONDARY.labeltype_id labeltype_id,SECONDARY.label_id
label_id,min(TARGET.label_id) min_childlabel_id from levels tl, labeltypes tlt, segments
TARGET, segments SECONDARY, labeltypes slt, levels sl where TARGET.session_id = SECONDARY.session_id "
,matchstring , " and tl.name = ? and sl.name = ? and SECONDARY.label != '' and tl.id = tlt.level_id
and sl.id = slt.level_id and tlt.id = TARGET.labeltype_id and slt.id = SECONDARY.labeltype_id
group by TARGET.session_id, TARGET.labeltype_id, SECONDARY.label_id) SUMMARY, segments SECONDARY,
labeltypes slt, levels sl where TARGET.session_id = SECONDARY.session_id and TARGET.session_id =
SUMMARY.session_id " , matchstring , " and tl.name = ? and sl.name = ? and tl.id = tlt.level_id
and tlt.id = TARGET.labeltype_id and SUMMARY.labeltype_id = SECONDARY.labeltype_id and SUMMARY.label_id
= SECONDARY.label_id and sl.id = slt.level_id and slt.id = SECONDARY.labeltype_id and
(TARGET.label_id - SUMMARY.min_childlabel_id +1) " , op , " ? "]
a = [toSql targetlt, toSql parentlt, toSql targetlt, toSql parentlt , toSql (pos :: Integer)]
in UmeQuery q a
Run Code Online (Sandbox Code Playgroud)
不幸的是,这对问题没有帮助(当我:在ghci中sprint函数的返回值时,它仍然没有评估).所以,懒惰可能是某种方式的问题,但我不知道如何使这充分评估..?请问,有什么想法吗?
所以...只是陈述事实:
如果所有这些都是真的,那么我就会相信查询一定是有效的,但却是错误的。检查数据?转储查询,手动运行它。让我知道。
要尝试的事情:
pos
到工作查询(使用op
硬编码)并查看是否有效op
到工作查询(使用pos
硬编码)并查看是否有效出于某种原因,我一直认为这可能是转换或其他问题的数据类型问题,但我从未使用过 Haskell,所以我无法真正猜测还会发生什么。
其他建议:
sqlite> select * from temp;
temp_id temp_name
---------- ----------
1 one
2 two
3 three
Run Code Online (Sandbox Code Playgroud)
import Database.HDBC.Sqlite3
import Database.HDBC
testdb = "C:\\Users\\Kim!\\test.db"
data UmeQuery = UmeQuery String [SqlValue] deriving Show
tRunUmeQuery :: UmeQuery -> FilePath -> IO [[SqlValue]]
tRunUmeQuery (UmeQuery q args) dbFile = do
conn <- connectSqlite3 dbFile
stat <- prepare conn q
s <- execute stat args
res <- fetchAllRows' stat
disconnect conn
return $ res
selectPos temp_id op = let
q = "select temp_id, temp_name from temp where temp_id = " ++ op ++ " ?";
a = [ toSql temp_id ]
in UmeQuery q a
Run Code Online (Sandbox Code Playgroud)
> let a = selectPos (1::Int) "="
> let b = tRunUmeQuery a testdb
> b
[[SqlByteString "1",SqlByteString "one"]]
> let a = selectPos (1::Int) ">"
> let b = tRunUmeQuery a testdb
> b
[[SqlByteString "2",SqlByteString "two"],[SqlByteString "3",SqlByteString "three"]]
Run Code Online (Sandbox Code Playgroud)
快速说明:今天之前我从未接触过 Haskell 或 SQLite。我正在 Windows 7 Professional 64 位上使用 SQLite3 - sqlite-dll-win64-x64-201409301904.zip运行 Haskell Platform 2014.2.0.0 。
编辑:这也有效...(查询也有一点不同)
import Data.List
selectPos temp_id op temp_name = let
q = foldl' (++) [] [
"select temp_id, temp_name " ++
"from temp " ++
"where temp_id " , op , " ? or " ++
" temp_name = ? "]
a = [ toSql (temp_id::Int), toSql temp_name ]
in UmeQuery q a
> let a = selectPos 1 ">" "one"
> let b = tRunUmeQuery a testdb
> b
[[SqlByteString "1",SqlByteString "one"],[SqlByteString "2",SqlByteString "two"],[SqlByteString "3",SqlByteString "three"]]
Run Code Online (Sandbox Code Playgroud)
编辑:这有效......
sqlite> insert into temp values (4, "Word");
sqlite> insert into temp values (5, "Utterance");
selectPos targetlt parentlt op pos = let
q = " select temp_id, temp_name \
\ from temp \
\ where temp_name = ? or \
\ temp_name = ? or \
\ temp_name = ? or \
\ temp_name = ? or \
\ temp_id "++op++" ? "
a = [toSql targetlt, toSql parentlt,
toSql targetlt, toSql parentlt,
toSql (pos::Int) ]
in UmeQuery q a
> let a = selectPos "Word" "Utterance" "=" 2
> let b = tRunUmeQuery a testdb
> b
[[SqlByteString "2",SqlByteString "two"],[SqlByteString "4",SqlByteString "Word"],[SqlByteString "5",SqlByteString "Utterance"]]
Run Code Online (Sandbox Code Playgroud)
所以...在您在问题中发布的查询中...也存在意想不到的差异...这与变量无关。这是一个单引号。不确定是否只是复制和粘贴中的拼写错误或什么。我显然无法运行您的查询,因为这正是因为需要提供大量的模拟表和数据......
编辑:哈...我又回到了这个问题。selectPos
我注意到你在最后一个示例上方有一行我没有使用的额外行。我必须这样做才能让它工作......[[SqlValue]]
或者IO [[SqlValue]]
因为最后一个值对我不起作用;错误(我只是在尝试,我不知道这些值是否真正有意义)。
selectPos :: String -> String -> String -> Integer -> UmeQuery
selectPos targetlt parentlt op pos = let
q = " select temp_id, temp_name \
\ from temp \
\ where temp_name = ? or \
\ temp_name = ? or \
\ temp_name = ? or \
\ temp_name != ? or \
\ temp_id "++op++" ? "
a = [toSql targetlt, toSql parentlt,
toSql targetlt, toSql parentlt,
toSql pos ]
in UmeQuery q a
> let a = selectPos "Word" "Utterance" "=" 2
> let b = tRunUmeQuery a testdb
> b
[[SqlByteString "1",SqlByteString "one"],[SqlByteString "2",SqlByteString "two"],[SqlByteString "3",SqlByteString "three"],[SqlByteString "4",SqlByteString "Word"],[SqlByteString "5",SqlByteString "Utterance"]]
Run Code Online (Sandbox Code Playgroud)
不管怎样...我很高兴今天能编写我的第一个 Haskell 程序...!
归档时间: |
|
查看次数: |
196 次 |
最近记录: |