使用direct-sqlite为SQLite创建的“regexp”函数,但运算符REGEXP不可用

时间:2016-07-11 07:34:30

标签: regex sqlite haskell

我正在使用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

如何使其可用?

1 个答案:

答案 0 :(得分:0)

  

我不知道Haskell,但这段代码看起来好像是在准备Haskell   安装函数前的语句。 - CL。 24分钟前

傻傻的我。