2011-03-09 4 views
1

J'ai écrit un petit script pour extraire des données d'Oracle en utilisant Takusen:Takusen: Erreur troncature

{-# 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 et c3 sont CLOB-s Lorsque je tente de l'exécuter, je reçois le message d'erreur suivant:

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

Il est avéré que c3 est la problématique. Lorsque je l'exclure de la requête, cela fonctionne très bien. A en juger par l'erreur, j'ai besoin d'augmenter la taille du tampon pour c3 pour éviter la troncature mais je ne trouve rien de tel dans la documentation de Takusen.

Une aide?

Répondre

2

Je contacté les auteurs de Takusen et a obtenu la réponse suivante (Oleg):

bindBuffer est en effet pas pertinente au problème à portée de main: bindBuffers sont utilisés lorsque la liaison de données à la requête de variables, qui est, le déplacement des données en la base de données. L'allocation de mémoire tampon pour les données à partir de est effectuée dans les instances de la classe DBType dans la base de données . Il y a plusieurs cas dans .../takusen/Base de données/Oracle/Enumerator.lhs L'un correspondant, pour la colonne de type chaîne Peut-être, est

exemple DBType (Peut-être que String) Interrogation ColumnBuffer où allocBufferFor _ qn = allocBuffer q (16000, oci_SQLT_CHR) n fetchCol q tampon = tampon bufferToString

Il semble que le tampon alloué soit de 16000 octets. Peut-être que ce nombre devrait être augmenté.

L'augmentation de ce tampon a résolu mon problème.

Un grand merci à Oleg et al.

1

Une navigation rapide à travers le code takusen révèle une :-(constante hardcoded

De: assez pour travailler autour, ou serait 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 

Mais c'est facile si OracleBind était une classe exportée

newtype SomeHugeString = SomeHugeString {getHugeString :: String} 
instance OracleBind SomeHugeString where ... 

, je pense qu'en tant est que vous devrez simplement créer votre propre fourchette du fichier /Oracle/Enumerator.lhs.

+1

Il semble étrange, mais je l'ai monté à 524288 et il jette encore la même erreur :-( – sandre