我正在使用Haskell的direct-sqlite
包来查询SQLite数据库。我需要REGEXP匹配,所以我构建了一个实现功能的Haskell函数,并将其插入到数据库连接中。
import Text.Regex.Base.RegexLike
import qualified Text.Regex.PCRE.ByteString as PCRE
import Database.SQLite3
data UmeQuery = UmeQuery Text [SQLData] deriving Show
data Segment = Segment SegmentLabel SegmentStart SegmentEnd Session LabelType Checksum deriving (Show)
runUmeQuery :: UmeQuery -> FilePath -> IO [Segment]
runUmeQuery eq dbFile = do
conn <- open $ pack dbFile
res <- runUmeQuery' eq conn
return res
runUmeQuery' :: UmeQuery -> Database -> IO [Segment]
runUmeQuery' (UmeQuery q args) conn = do
statement <- prepare conn q
createFunction conn "regexp" (Just 2) True sqlRegexp
bind statement args
res <- fmap reverse $ getRows statement []
Database.SQLite3.finalize statement
close conn
return res
getRows :: Statement -> [Segment] -> IO [Segment]
getRows stmt acc = do
r <- step stmt
case r of
Done -> return acc
Row -> do
sess <- columnText stmt 0
lt <- columnText stmt 1
start <- columnDouble stmt 3
end <- columnDouble stmt 4
label <- columnText stmt 5
checksum <- columnText stmt 6
getRows stmt ((Segment label start end sess lt checksum):acc)
sqlRegexp :: FuncContext -> FuncArgs -> IO ()
sqlRegexp ctx args = do
reg <- fmap encodeUtf8 $ funcArgText args 0
text <- fmap encodeUtf8 $ funcArgText args 1
res <- pcreRegex reg text
funcResultInt64 ctx res
where
pcreRegex reg b = do
reC <- pcreCompile reg
re <- case reC of
(Right r) -> return r
(Left (_,e) ) -> fail e
reE <- PCRE.execute re b
case reE of
(Right (Just _)) -> return (1 :: Int64)
(Right (Nothing)) -> return (0 :: Int64)
(Left (_,e)) -> fail e -- Not a good idea maybe, but I have no use for error messages.
where pcreCompile = PCRE.compile defaultCompOpt defaultExecOpt
因此,基本上,查询函数打开一个连接,插入一个“regexp”函数并执行一个查询(在数据类型中)。这是根据手册:
REGEXP运算符是regexp()用户的特殊语法 功能。默认情况下没有定义regexp()用户函数,因此请使用 REGEXP运算符通常会导致错误消息。如果 在运行时添加名为“regexp”的应用程序定义的SQL函数, 然后“X REGEXP Y”运算符将被实现为调用 “正则表达式(Y,X)”。 https://www.sqlite.org/lang_expr.html#like
现在,问题是该功能在查询中不可用:
> let b = UmeQuery (pack "select * from segments where label REGEXP '.*';") []
*Phonetic.Database.UmeQuery
> out <- runUmeQuery b "./umecore-hs/testdata/umetest.umedb"
*** Exception: SQLite3 returned ErrorError while attempting to perform prepare "select * from segments where label REGEXP '.*';": no such function: REGEXP
如何使其可用?
答案 0 :(得分:0)
我不知道Haskell,但这段代码看起来好像是在准备Haskell 安装函数前的语句。 - CL。 24分钟前
傻傻的我。