我写了一个小脚本,用Takusen从Oracle中提取数据:
{-# LANGUAGE ScopedTypeVariables #-}
module Test where
import Database.Oracle.Enumerator
import Control.Monad.Trans (liftIO)
import Connections (watDevDb, watProdDb)
import System.Environment
import Data.Char
main :: IO ()
main = do
[fn] <- getArgs
sqls <- readFile fn
flip catchDB reportRethrow (withSession watProdDb $ do
let iter (c1::Maybe String) (c2::Maybe String) (c3::Maybe String) (r::Maybe String) = result' c3
rslt <- doQuery (sql sqls) iter (Nothing::Maybe String)
liftIO (putStrLn . show $ rslt))
test = withArgs ["extract.sql"] main
c2
和c3
是CLOB-s
当我尝试执行它时,我收到以下错误消息:
*** Exception: DBError ("01","000") 1406 " : ORA-01406: fetched column value was truncated\n"
事实证明c3
是有问题的。当我从查询中排除它时,它工作得很好。
从错误判断,我需要增加c3
的缓冲区大小以避免截断,但我在Takusen文档中找不到类似的东西。
任何帮助?
答案 0 :(得分:2)
我联系了Takusen的作者并得到了以下回复(Oleg):
bindBuffer确实与手头的问题无关:bindBuffers 在将数据绑定到查询变量(即移动数据)时使用 进入数据库。来自数据库的数据的缓冲区分配是 在类DBType的实例中完成。有几个例子 在 ... / takusen /数据库/ ORACLE / Enumerator.lhs 对于列类型Maybe String,相关的是
instance DBType(Maybe String)查询ColumnBuffer在哪里 allocBufferFor _ q n = allocBuffer q(16000,oci_SQLT_CHR)n fetchCol q buffer = bufferToString buffer
分配的缓冲区似乎是16000字节。也许这个数字 应该增加。
这个缓冲区的增加解决了我的问题。
非常感谢Oleg等人
答案 1 :(得分:1)
快速浏览takusen代码会显示一个硬编码常量: - (
来自:http://code.haskell.org/takusen/Database/Oracle/Enumerator.lhs
instance OracleBind String where
-- FIXME should these be withUTF8String{Len} ?
bindWithValue v a = withCString v (\p -> a (castPtr p))
bindWriteBuffer b s = withCStringLen s (\(p,l) ->
copyBytes (castPtr b) p (1+l))
bindDataSize s = fromIntegral (length s)
bindBufferSize _ = 32000
bindType _ = oci_SQLT_CHR
但这很容易解决,或者如果OracleBind是导出的类
newtype SomeHugeString = SomeHugeString {getHugeString :: String}
instance OracleBind SomeHugeString where ...
按原样,我认为你必须只创建自己的/Oracle/Enumerator.lhs文件的分支。