Permalink
Browse files

Add support for SQL_NO_TOTAL for large text fields

  • Loading branch information...
1 parent 391ab6d commit 8134f715c18a0d60cc7b0329c7c2dbfee3e3e932 @vagifverdi committed May 13, 2012
Showing with 31 additions and 2 deletions.
  1. +31 −2 Database/HDBC/ODBC/Statement.hsc
@@ -1,7 +1,7 @@
-- -*- mode: haskell; -*-
{-# CFILES hdbc-odbc-helper.c #-}
-- Above line for hugs
-{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE DoAndIfThenElse, EmptyDataDecls #-}
module Database.HDBC.ODBC.Statement (
fGetQueryInfo,
@@ -342,6 +342,35 @@ getBindCols sstate cstmt = do
Just bindCols -> do
return (mBindCols, bindCols)
+-- This is only for String data. For binary fix should be very easy. Just check the column type and use buflen instead of buflen - 1
+getLongColData cstmt bindCol = do
+ let (BindColString buf bufLen col) = bindCol
+ l $ "buflen: " ++ show bufLen
+ bs <- B.packCStringLen (buf, fromIntegral (bufLen - 1))
+ l $ "sql_no_total col " ++ show (BUTF8.toString bs)
+ bs2 <- getRestLongColData cstmt #{const SQL_CHAR} col bs
+ return $ SqlByteString bs2
+
+
+getRestLongColData cstmt cBinding icol acc = do
+ l "getLongColData"
+ alloca $ \plen ->
+ allocaBytes colBufSizeMaximum $ \buf ->
+ do res <- sqlGetData cstmt (fromIntegral icol) cBinding
+ buf (fromIntegral colBufSizeMaximum) plen
+ if res == #{const SQL_SUCCESS} || res == #{const SQL_SUCCESS_WITH_INFO} then do
+ len <- peek plen
+ if len == #{const SQL_NO_DATA} then return acc
+ else do
+ let bufmax = fromIntegral $ colBufSizeMaximum - 1
+ bs <- B.packCStringLen (buf, fromIntegral (if len == #{const SQL_NO_TOTAL} || len > bufmax then bufmax else len))
+ l $ "sql_no_total col is: " ++ show (BUTF8.toString bs)
+ let newacc = B.append acc bs
+ if len /= #{const SQL_NO_TOTAL} && len <= bufmax then
+ return newacc
+ else getRestLongColData cstmt cBinding icol newacc
+ else raiseError "sqlGetData" res (StmtHandle cstmt)
+
-- TODO: This code does not deal well with data that is extremely large,
-- where multiple fetches are required.
getColData cstmt cBinding icol = do
@@ -743,7 +772,7 @@ bindColToSqlValue pcstmt (bindCol, pStrLen) = do
strLen <- peek pStrLen
case strLen of
#{const SQL_NULL_DATA} -> return SqlNull
- #{const SQL_NO_TOTAL} -> fail $ "Unexpected SQL_NO_TOTAL"
+ #{const SQL_NO_TOTAL} -> getLongColData pcstmt bindCol
_ -> bindColToSqlValue' pcstmt bindCol strLen
-- | This is a worker function for `bindcolToSqlValue`. Note that the case

1 comment on commit 8134f71

@zenzike

Thanks for the pull request. In principle, this patch seems fine, but I think it shouldn't be too difficult to change the indenting so that the DoAndIfThenElse extension isn't required. I'd rather avoid bringing in more language extensions if it can be avoided. Would you mind changing this so that I can merge in?

Please sign in to comment.