2011-03-09 98 views
1

我寫了一個小腳本提取從Oracle數據使用Takusen:Takusen:截斷誤差

{-# 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 

c2c3是CLOB-S 當我嘗試執行它,我收到以下錯誤信息:

*** Exception: DBError ("01","000") 1406 " : ORA-01406: fetched column value was truncated\n"

原來c3是有問題的。當我從查詢中排除它時,它工作得很好。 根據錯誤判斷,我需要增加c3的緩衝區大小以避免截斷,但在Takusen文檔中找不到類似的東西。

任何幫助?

回答

2

我接觸Takusen的作者,得到了以下回應(奧列格):

bindBuffer確實是不相關的手頭的問題:bindBuffers 的數據綁定到查詢變量時使用,也就是說,移動數據 分成這個數據庫。數據的緩衝區分配數據庫是 在類DBType的實例中完成。有幾種情況 在 .../takusen /數據庫/ ORACLE/Enumerator.lhs 有關的一個,該列Maybe類型的字符串,是

實例DBTYPE(也許字符串)查詢ColumnBuffer其中 allocBufferFor _ QN = allocBuffer q(16000,oci_SQLT_CHR)n fetchCol q buffer = bufferToString buffer

似乎分配的緩衝區是16000字節。也許這個數字應該增加 。

緩衝區的增加解決了我的問題。

非常感謝Oleg等人。

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文件的叉。

+1

這似乎很奇怪,但我把它轉到524288,它仍然拋出相同的錯誤:-( – sandre 2011-03-09 23:19:13