{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE NamedFieldPuns #-}

module Database.DuckDB.Simple.Materialize (
    materializeValue,
) where

import Control.Exception (bracket, throwIO)
import Control.Monad (forM, when)
import Data.Array (Array, elems, listArray)
import Data.Bits (clearBit, shiftL, xor, (.|.))
import qualified Data.ByteString as BS
import Data.Int (Int16, Int32, Int64, Int8)
import qualified Data.Map.Strict as Map
import Data.Ratio ((%))
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as TextEncoding
import Data.Time.Calendar (Day, fromGregorian)
import Data.Time.Clock (UTCTime (..))
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import Data.Time.LocalTime (
    LocalTime (..),
    TimeOfDay (..),
    minutesToTimeZone,
    utc,
    utcToLocalTime,
 )
import qualified Data.UUID as UUID
import Data.Word (Word16, Word32, Word64, Word8)
import Database.DuckDB.FFI
import Database.DuckDB.Simple.FromField (
    BigNum (..),
    BitString (..),
    DecimalValue (..),
    FieldValue (..),
    IntervalValue (..),
    TimeWithZone (..),
    fromBigNumBytes,
 )
import Database.DuckDB.Simple.LogicalRep (
    LogicalTypeRep (..),
    StructField (..),
    StructValue (..),
    UnionMemberType (..),
    UnionValue (..),
    logicalTypeToRep,
 )
import Foreign.C.Types (CBool (..))
import Foreign.Marshal.Alloc (alloca)
import Foreign.Ptr (Ptr, castPtr, nullPtr, plusPtr)
import Foreign.Storable (Storable (..), peekByteOff, peekElemOff, pokeByteOff)

data DuckDBListEntry = DuckDBListEntry
    { DuckDBListEntry -> Word64
duckDBListEntryOffset :: !Word64
    , DuckDBListEntry -> Word64
duckDBListEntryLength :: !Word64
    }
    deriving (DuckDBListEntry -> DuckDBListEntry -> Bool
(DuckDBListEntry -> DuckDBListEntry -> Bool)
-> (DuckDBListEntry -> DuckDBListEntry -> Bool)
-> Eq DuckDBListEntry
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DuckDBListEntry -> DuckDBListEntry -> Bool
== :: DuckDBListEntry -> DuckDBListEntry -> Bool
$c/= :: DuckDBListEntry -> DuckDBListEntry -> Bool
/= :: DuckDBListEntry -> DuckDBListEntry -> Bool
Eq, Int -> DuckDBListEntry -> ShowS
[DuckDBListEntry] -> ShowS
DuckDBListEntry -> String
(Int -> DuckDBListEntry -> ShowS)
-> (DuckDBListEntry -> String)
-> ([DuckDBListEntry] -> ShowS)
-> Show DuckDBListEntry
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DuckDBListEntry -> ShowS
showsPrec :: Int -> DuckDBListEntry -> ShowS
$cshow :: DuckDBListEntry -> String
show :: DuckDBListEntry -> String
$cshowList :: [DuckDBListEntry] -> ShowS
showList :: [DuckDBListEntry] -> ShowS
Show)

instance Storable DuckDBListEntry where
    sizeOf :: DuckDBListEntry -> Int
sizeOf DuckDBListEntry
_ = Int
listEntryWordSize Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2
    alignment :: DuckDBListEntry -> Int
alignment DuckDBListEntry
_ = Word64 -> Int
forall a. Storable a => a -> Int
alignment (Word64
0 :: Word64)
    peek :: Ptr DuckDBListEntry -> IO DuckDBListEntry
peek Ptr DuckDBListEntry
ptr = do
        offset <- Ptr DuckDBListEntry -> Int -> IO Word64
forall b. Ptr b -> Int -> IO Word64
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr DuckDBListEntry
ptr Int
0
        len <- peekByteOff ptr listEntryWordSize
        pure DuckDBListEntry{duckDBListEntryOffset = offset, duckDBListEntryLength = len}
    poke :: Ptr DuckDBListEntry -> DuckDBListEntry -> IO ()
poke Ptr DuckDBListEntry
ptr DuckDBListEntry{Word64
duckDBListEntryOffset :: DuckDBListEntry -> Word64
duckDBListEntryOffset :: Word64
duckDBListEntryOffset, Word64
duckDBListEntryLength :: DuckDBListEntry -> Word64
duckDBListEntryLength :: Word64
duckDBListEntryLength} = do
        Ptr DuckDBListEntry -> Int -> Word64 -> IO ()
forall b. Ptr b -> Int -> Word64 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr DuckDBListEntry
ptr Int
0 Word64
duckDBListEntryOffset
        Ptr DuckDBListEntry -> Int -> Word64 -> IO ()
forall b. Ptr b -> Int -> Word64 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr DuckDBListEntry
ptr Int
listEntryWordSize Word64
duckDBListEntryLength

listEntryWordSize :: Int
listEntryWordSize :: Int
listEntryWordSize = Word64 -> Int
forall a. Storable a => a -> Int
sizeOf (Word64
0 :: Word64)

chunkIsRowValid :: Ptr Word64 -> DuckDBIdx -> IO Bool
chunkIsRowValid :: Ptr Word64 -> Word64 -> IO Bool
chunkIsRowValid Ptr Word64
validity Word64
rowIdx
    | Ptr Word64
validity Ptr Word64 -> Ptr Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr Word64
forall a. Ptr a
nullPtr = Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
    | Bool
otherwise = do
        CBool flag <- Ptr Word64 -> Word64 -> IO CBool
c_duckdb_validity_row_is_valid Ptr Word64
validity Word64
rowIdx
        pure (flag /= 0)

chunkDecodeText :: Ptr () -> DuckDBIdx -> IO Text
chunkDecodeText :: Ptr () -> Word64 -> IO Text
chunkDecodeText Ptr ()
dataPtr Word64
rowIdx = do
    let base :: Ptr Word8
base = Ptr () -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word8
        offset :: Int
offset = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
rowIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
duckdbStringTSize
        stringPtr :: Ptr DuckDBStringT
stringPtr = Ptr (ZonkAny 1) -> Ptr DuckDBStringT
forall a b. Ptr a -> Ptr b
castPtr (Ptr Word8
base Ptr Word8 -> Int -> Ptr (ZonkAny 1)
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
offset) :: Ptr DuckDBStringT
    len <- Ptr DuckDBStringT -> IO Word32
c_duckdb_string_t_length Ptr DuckDBStringT
stringPtr
    if len == 0
        then pure Text.empty
        else do
            cstr <- c_duckdb_string_t_data stringPtr
            bytes <- BS.packCStringLen (cstr, fromIntegral len)
            pure (TextEncoding.decodeUtf8 bytes)

chunkDecodeBlob :: Ptr () -> DuckDBIdx -> IO BS.ByteString
chunkDecodeBlob :: Ptr () -> Word64 -> IO ByteString
chunkDecodeBlob Ptr ()
dataPtr Word64
rowIdx = do
    let base :: Ptr Word8
base = Ptr () -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word8
        offset :: Int
offset = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
rowIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
duckdbStringTSize
        stringPtr :: Ptr DuckDBStringT
stringPtr = Ptr (ZonkAny 0) -> Ptr DuckDBStringT
forall a b. Ptr a -> Ptr b
castPtr (Ptr Word8
base Ptr Word8 -> Int -> Ptr (ZonkAny 0)
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
offset) :: Ptr DuckDBStringT
    len <- Ptr DuckDBStringT -> IO Word32
c_duckdb_string_t_length Ptr DuckDBStringT
stringPtr
    if len == 0
        then pure BS.empty
        else do
            ptr <- c_duckdb_string_t_data stringPtr
            BS.packCStringLen (ptr, fromIntegral len)

duckdbStringTSize :: Int
duckdbStringTSize :: Int
duckdbStringTSize = Int
16

materializeValue :: DuckDBType -> DuckDBVector -> Ptr () -> Ptr Word64 -> Int -> IO FieldValue
materializeValue :: DuckDBType
-> DuckDBVector -> Ptr () -> Ptr Word64 -> Int -> IO FieldValue
materializeValue DuckDBType
dtype DuckDBVector
vector Ptr ()
dataPtr Ptr Word64
validity Int
rowIdx = do
    let duckIdx :: Word64
duckIdx = Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
rowIdx :: DuckDBIdx
    valid <- Ptr Word64 -> Word64 -> IO Bool
chunkIsRowValid Ptr Word64
validity Word64
duckIdx
    if not valid
        then pure FieldNull
        else case dtype of
            DuckDBType
DuckDBTypeBoolean -> do
                raw <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word8) Int
rowIdx
                pure (FieldBool (raw /= 0))
            DuckDBType
DuckDBTypeTinyInt -> do
                raw <- Ptr Int8 -> Int -> IO Int8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int8) Int
rowIdx
                pure (FieldInt8 raw)
            DuckDBType
DuckDBTypeSmallInt -> do
                raw <- Ptr Int16 -> Int -> IO Int16
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int16
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int16) Int
rowIdx
                pure (FieldInt16 raw)
            DuckDBType
DuckDBTypeInteger -> do
                raw <- Ptr Int32 -> Int -> IO Int32
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int32
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int32) Int
rowIdx
                pure (FieldInt32 raw)
            DuckDBType
DuckDBTypeBigInt -> do
                raw <- Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int64
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int64) Int
rowIdx
                pure (FieldInt64 raw)
            DuckDBType
DuckDBTypeUTinyInt -> do
                raw <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word8) Int
rowIdx
                pure (FieldWord8 raw)
            DuckDBType
DuckDBTypeUSmallInt -> do
                raw <- Ptr Word16 -> Int -> IO Word16
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word16
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word16) Int
rowIdx
                pure (FieldWord16 raw)
            DuckDBType
DuckDBTypeUInteger -> do
                raw <- Ptr Word32 -> Int -> IO Word32
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word32
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word32) Int
rowIdx
                pure (FieldWord32 raw)
            DuckDBType
DuckDBTypeUBigInt -> do
                raw <- Ptr Word64 -> Int -> IO Word64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word64
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word64) Int
rowIdx
                pure (FieldWord64 raw)
            DuckDBType
DuckDBTypeFloat -> do
                raw <- Ptr Float -> Int -> IO Float
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Float
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Float) Int
rowIdx
                pure (FieldFloat raw)
            DuckDBType
DuckDBTypeDouble -> do
                raw <- Ptr Double -> Int -> IO Double
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Double
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Double) Int
rowIdx
                pure (FieldDouble raw)
            DuckDBType
DuckDBTypeVarchar -> Text -> FieldValue
FieldText (Text -> FieldValue) -> IO Text -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr () -> Word64 -> IO Text
chunkDecodeText Ptr ()
dataPtr Word64
duckIdx
            DuckDBType
DuckDBTypeUUID -> do
                DuckDBUHugeInt lower upperBiased <- Ptr DuckDBUHugeInt -> Int -> IO DuckDBUHugeInt
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBUHugeInt
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBUHugeInt) Int
rowIdx
                let upper = Word64
upperBiased Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`xor` (Word64
0x8000000000000000 :: Word64)
                pure (FieldUUID (UUID.fromWords64 (fromIntegral upper) lower))
            DuckDBType
DuckDBTypeBlob -> ByteString -> FieldValue
FieldBlob (ByteString -> FieldValue) -> IO ByteString -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr () -> Word64 -> IO ByteString
chunkDecodeBlob Ptr ()
dataPtr Word64
duckIdx
            DuckDBType
DuckDBTypeDate -> do
                raw <- Ptr Int32 -> Int -> IO Int32
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int32
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int32) Int
rowIdx
                FieldDate <$> decodeDuckDBDate (DuckDBDate raw)
            DuckDBType
DuckDBTypeTime -> do
                raw <- Ptr DuckDBTime -> Int -> IO DuckDBTime
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTime
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTime) Int
rowIdx
                FieldTime <$> decodeDuckDBTime raw
            DuckDBType
DuckDBTypeTimeNs -> do
                raw <- Ptr DuckDBTimeNs -> Int -> IO DuckDBTimeNs
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTimeNs
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTimeNs) Int
rowIdx
                pure (FieldTime (decodeDuckDBTimeNs raw))
            DuckDBType
DuckDBTypeTimeTz -> do
                raw <- Ptr DuckDBTimeTz -> Int -> IO DuckDBTimeTz
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTimeTz
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTimeTz) Int
rowIdx
                FieldTimeTZ <$> decodeDuckDBTimeTz raw
            DuckDBType
DuckDBTypeTimestamp -> do
                raw <- Ptr DuckDBTimestamp -> Int -> IO DuckDBTimestamp
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTimestamp
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTimestamp) Int
rowIdx
                FieldTimestamp <$> decodeDuckDBTimestamp raw
            DuckDBType
DuckDBTypeTimestampS -> do
                raw <- Ptr DuckDBTimestampS -> Int -> IO DuckDBTimestampS
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTimestampS
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTimestampS) Int
rowIdx
                FieldTimestamp <$> decodeDuckDBTimestampSeconds raw
            DuckDBType
DuckDBTypeTimestampMs -> do
                raw <- Ptr DuckDBTimestampMs -> Int -> IO DuckDBTimestampMs
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTimestampMs
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTimestampMs) Int
rowIdx
                FieldTimestamp <$> decodeDuckDBTimestampMilliseconds raw
            DuckDBType
DuckDBTypeTimestampNs -> do
                raw <- Ptr DuckDBTimestampNs -> Int -> IO DuckDBTimestampNs
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTimestampNs
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTimestampNs) Int
rowIdx
                FieldTimestamp <$> decodeDuckDBTimestampNanoseconds raw
            DuckDBType
DuckDBTypeTimestampTz -> do
                raw <- Ptr DuckDBTimestamp -> Int -> IO DuckDBTimestamp
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBTimestamp
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBTimestamp) Int
rowIdx
                FieldTimestampTZ <$> decodeDuckDBTimestampUTCTime raw
            DuckDBType
DuckDBTypeInterval -> do
                raw <- Ptr DuckDBInterval -> Int -> IO DuckDBInterval
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBInterval
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBInterval) Int
rowIdx
                pure (FieldInterval (intervalValueFromDuckDB raw))
            DuckDBType
DuckDBTypeDecimal ->
                IO DuckDBLogicalType
-> (DuckDBLogicalType -> IO ())
-> (DuckDBLogicalType -> IO FieldValue)
-> IO FieldValue
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
                    (DuckDBVector -> IO DuckDBLogicalType
c_duckdb_vector_get_column_type DuckDBVector
vector)
                    (\DuckDBLogicalType
lty -> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBLogicalType -> IO ()) -> IO ())
-> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBLogicalType
ptr -> Ptr DuckDBLogicalType -> DuckDBLogicalType -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr DuckDBLogicalType
ptr DuckDBLogicalType
lty IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr DuckDBLogicalType -> IO ()
c_duckdb_destroy_logical_type Ptr DuckDBLogicalType
ptr)
                    \DuckDBLogicalType
logical -> do
                        width <- DuckDBLogicalType -> IO Word8
c_duckdb_decimal_width DuckDBLogicalType
logical
                        scale <- c_duckdb_decimal_scale logical
                        internalTy <- c_duckdb_decimal_internal_type logical
                        rawValue <-
                            case internalTy of
                                DuckDBType
DuckDBTypeSmallInt ->
                                    Int16 -> Year
forall a. Integral a => a -> Year
toInteger (Int16 -> Year) -> IO Int16 -> IO Year
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Int16 -> Int -> IO Int16
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int16
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int16) Int
rowIdx
                                DuckDBType
DuckDBTypeInteger ->
                                    Int32 -> Year
forall a. Integral a => a -> Year
toInteger (Int32 -> Year) -> IO Int32 -> IO Year
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Int32 -> Int -> IO Int32
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int32
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int32) Int
rowIdx
                                DuckDBType
DuckDBTypeBigInt ->
                                    Int64 -> Year
forall a. Integral a => a -> Year
toInteger (Int64 -> Year) -> IO Int64 -> IO Year
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int64
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int64) Int
rowIdx
                                DuckDBType
DuckDBTypeHugeInt ->
                                    Year -> Year
forall a. Integral a => a -> Year
toInteger (Year -> Year) -> (DuckDBHugeInt -> Year) -> DuckDBHugeInt -> Year
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DuckDBHugeInt -> Year
duckDBHugeIntToInteger
                                        (DuckDBHugeInt -> Year) -> IO DuckDBHugeInt -> IO Year
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr DuckDBHugeInt -> Int -> IO DuckDBHugeInt
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBHugeInt
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBHugeInt) Int
rowIdx
                                DuckDBType
_ ->
                                    String -> IO Year
forall a. HasCallStack => String -> a
error String
"duckdb-simple: unsupported decimal internal storage type"
                        pure (FieldDecimal (DecimalValue width scale rawValue))
            DuckDBType
DuckDBTypeHugeInt -> do
                raw <- Ptr DuckDBHugeInt -> Int -> IO DuckDBHugeInt
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBHugeInt
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBHugeInt) Int
rowIdx
                pure (FieldHugeInt (duckDBHugeIntToInteger raw))
            DuckDBType
DuckDBTypeUHugeInt -> do
                raw <- Ptr DuckDBUHugeInt -> Int -> IO DuckDBUHugeInt
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBUHugeInt
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBUHugeInt) Int
rowIdx
                pure (FieldUHugeInt (duckDBUHugeIntToInteger raw))
            DuckDBType
DuckDBTypeBit -> do
                let base :: Ptr Word8
base = Ptr () -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word8
                    offset :: Int
offset = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
rowIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
duckdbStringTSize
                    stringPtr :: Ptr DuckDBStringT
stringPtr = Ptr (ZonkAny 2) -> Ptr DuckDBStringT
forall a b. Ptr a -> Ptr b
castPtr (Ptr Word8
base Ptr Word8 -> Int -> Ptr (ZonkAny 2)
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
offset) :: Ptr DuckDBStringT
                len <- Ptr DuckDBStringT -> IO Word32
c_duckdb_string_t_length Ptr DuckDBStringT
stringPtr
                ptr <- c_duckdb_string_t_data stringPtr
                bs <- BS.unpack <$> BS.packCStringLen (ptr, fromIntegral len)
                case bs of
                    [] -> FieldValue -> IO FieldValue
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BitString -> FieldValue
FieldBit (Word8 -> ByteString -> BitString
BitString Word8
0 ByteString
BS.empty))
                    [Word8
padding] -> FieldValue -> IO FieldValue
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BitString -> FieldValue
FieldBit (Word8 -> ByteString -> BitString
BitString Word8
padding ByteString
BS.empty))
                    (Word8
paddingByte : Word8
b : [Word8]
bits) -> do
                        let cleared :: Word8
cleared = (Word8 -> Int -> Word8) -> Word8 -> [Int] -> Word8
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
clearBit Word8
b [Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
paddingByte .. Int
7]
                        FieldValue -> IO FieldValue
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BitString -> FieldValue
FieldBit (Word8 -> ByteString -> BitString
BitString Word8
paddingByte ([Word8] -> ByteString
BS.pack (Word8
cleared Word8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
: [Word8]
bits))))
            DuckDBType
DuckDBTypeBigNum -> do
                let base :: Ptr Word8
base = Ptr () -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word8
                    offset :: Int
offset = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
rowIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
duckdbStringTSize
                    stringPtr :: Ptr DuckDBStringT
stringPtr = Ptr (ZonkAny 3) -> Ptr DuckDBStringT
forall a b. Ptr a -> Ptr b
castPtr (Ptr Word8
base Ptr Word8 -> Int -> Ptr (ZonkAny 3)
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
offset) :: Ptr DuckDBStringT
                len <- Ptr DuckDBStringT -> IO Word32
c_duckdb_string_t_length Ptr DuckDBStringT
stringPtr
                if len < 3
                    then pure (FieldBigNum (BigNum 0))
                    else do
                        ptr <- c_duckdb_string_t_data stringPtr
                        bytes <- BS.unpack <$> BS.packCStringLen (ptr, fromIntegral len)
                        pure (FieldBigNum (BigNum (fromBigNumBytes bytes)))
            DuckDBType
DuckDBTypeArray -> Array Int FieldValue -> FieldValue
FieldArray (Array Int FieldValue -> FieldValue)
-> IO (Array Int FieldValue) -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DuckDBVector -> Int -> IO (Array Int FieldValue)
decodeArrayElements DuckDBVector
vector Int
rowIdx
            DuckDBType
DuckDBTypeList -> [FieldValue] -> FieldValue
FieldList ([FieldValue] -> FieldValue) -> IO [FieldValue] -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DuckDBVector -> Ptr () -> Int -> IO [FieldValue]
decodeListElements DuckDBVector
vector Ptr ()
dataPtr Int
rowIdx
            DuckDBType
DuckDBTypeMap -> [(FieldValue, FieldValue)] -> FieldValue
FieldMap ([(FieldValue, FieldValue)] -> FieldValue)
-> IO [(FieldValue, FieldValue)] -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DuckDBVector -> Ptr () -> Int -> IO [(FieldValue, FieldValue)]
decodeMapPairs DuckDBVector
vector Ptr ()
dataPtr Int
rowIdx
            DuckDBType
DuckDBTypeStruct ->
                StructValue FieldValue -> FieldValue
FieldStruct (StructValue FieldValue -> FieldValue)
-> IO (StructValue FieldValue) -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DuckDBVector -> Int -> IO (StructValue FieldValue)
decodeStructValue DuckDBVector
vector Int
rowIdx
            DuckDBType
DuckDBTypeUnion ->
                UnionValue FieldValue -> FieldValue
FieldUnion (UnionValue FieldValue -> FieldValue)
-> IO (UnionValue FieldValue) -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DuckDBVector -> Ptr () -> Int -> IO (UnionValue FieldValue)
decodeUnionValue DuckDBVector
vector Ptr ()
dataPtr Int
rowIdx
            DuckDBType
DuckDBTypeEnum ->
                IO DuckDBLogicalType
-> (DuckDBLogicalType -> IO ())
-> (DuckDBLogicalType -> IO FieldValue)
-> IO FieldValue
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
                    (DuckDBVector -> IO DuckDBLogicalType
c_duckdb_vector_get_column_type DuckDBVector
vector)
                    (\DuckDBLogicalType
lty -> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBLogicalType -> IO ()) -> IO ())
-> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBLogicalType
ptr -> Ptr DuckDBLogicalType -> DuckDBLogicalType -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr DuckDBLogicalType
ptr DuckDBLogicalType
lty IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr DuckDBLogicalType -> IO ()
c_duckdb_destroy_logical_type Ptr DuckDBLogicalType
ptr)
                    \DuckDBLogicalType
logical -> do
                        enumInternal <- DuckDBLogicalType -> IO DuckDBType
c_duckdb_enum_internal_type DuckDBLogicalType
logical
                        case enumInternal of
                            DuckDBType
DuckDBTypeUTinyInt ->
                                Word32 -> FieldValue
FieldEnum (Word32 -> FieldValue) -> (Word8 -> Word32) -> Word8 -> FieldValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> FieldValue) -> IO Word8 -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word8) Int
rowIdx
                            DuckDBType
DuckDBTypeUSmallInt ->
                                Word32 -> FieldValue
FieldEnum (Word32 -> FieldValue)
-> (Word16 -> Word32) -> Word16 -> FieldValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> FieldValue) -> IO Word16 -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word16 -> Int -> IO Word16
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word16
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word16) Int
rowIdx
                            DuckDBType
DuckDBTypeUInteger ->
                                Word32 -> FieldValue
FieldEnum (Word32 -> FieldValue) -> IO Word32 -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word32 -> Int -> IO Word32
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Word32
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Word32) Int
rowIdx
                            DuckDBType
_ ->
                                String -> IO FieldValue
forall a. HasCallStack => String -> a
error String
"duckdb-simple: unsupported enum internal storage type"
            DuckDBType
DuckDBTypeSQLNull ->
                FieldValue -> IO FieldValue
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FieldValue
FieldNull
            DuckDBType
DuckDBTypeStringLiteral -> Text -> FieldValue
FieldText (Text -> FieldValue) -> IO Text -> IO FieldValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr () -> Word64 -> IO Text
chunkDecodeText Ptr ()
dataPtr Word64
duckIdx
            DuckDBType
DuckDBTypeIntegerLiteral -> do
                raw <- Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr Int64
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr Int64) Int
rowIdx
                pure (FieldInt64 raw)
            DuckDBType
DuckDBTypeInvalid ->
                String -> IO FieldValue
forall a. HasCallStack => String -> a
error String
"duckdb-simple: INVALID type in eager result"
            DuckDBType
DuckDBTypeAny ->
                String -> IO FieldValue
forall a. HasCallStack => String -> a
error String
"duckdb-simple: ANY columns should not appear in results"
            DuckDBType
other ->
                String -> IO FieldValue
forall a. HasCallStack => String -> a
error (String
"duckdb-simple: UNKNOWN type in eager result: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> DuckDBType -> String
forall a. Show a => a -> String
show DuckDBType
other)

decodeArrayElements :: DuckDBVector -> Int -> IO (Array Int FieldValue)
decodeArrayElements :: DuckDBVector -> Int -> IO (Array Int FieldValue)
decodeArrayElements DuckDBVector
vector Int
rowIdx = do
    arraySize <-
        IO DuckDBLogicalType
-> (DuckDBLogicalType -> IO ())
-> (DuckDBLogicalType -> IO Int)
-> IO Int
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
            (DuckDBVector -> IO DuckDBLogicalType
c_duckdb_vector_get_column_type DuckDBVector
vector)
            (\DuckDBLogicalType
logical -> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBLogicalType -> IO ()) -> IO ())
-> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBLogicalType
ptr -> Ptr DuckDBLogicalType -> DuckDBLogicalType -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr DuckDBLogicalType
ptr DuckDBLogicalType
logical IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr DuckDBLogicalType -> IO ()
c_duckdb_destroy_logical_type Ptr DuckDBLogicalType
ptr)
            \DuckDBLogicalType
logical -> do
                sizeRaw <- DuckDBLogicalType -> IO Word64
c_duckdb_array_type_array_size DuckDBLogicalType
logical
                let sizeWord = Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
sizeRaw :: Word64
                ensureWithinIntRange (Text.pack "array size") sizeWord
    childVec <- c_duckdb_array_vector_get_child vector
    when (childVec == nullPtr) $
        throwIO (userError "duckdb-simple: array child vector is null")
    childType <- vectorElementType childVec
    childData <- c_duckdb_vector_get_data childVec
    childValidity <- c_duckdb_vector_get_validity childVec
    let baseIdx = Int
rowIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
arraySize
    values <-
        forM [0 .. arraySize - 1] \Int
delta ->
            DuckDBType
-> DuckDBVector -> Ptr () -> Ptr Word64 -> Int -> IO FieldValue
materializeValue DuckDBType
childType DuckDBVector
childVec Ptr ()
childData Ptr Word64
childValidity (Int
baseIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
delta)
    pure $
        if arraySize <= 0
            then listArray (0, -1) []
            else listArray (0, arraySize - 1) values

decodeListElements :: DuckDBVector -> Ptr () -> Int -> IO [FieldValue]
decodeListElements :: DuckDBVector -> Ptr () -> Int -> IO [FieldValue]
decodeListElements DuckDBVector
vector Ptr ()
dataPtr Int
rowIdx = do
    entry <- Ptr DuckDBListEntry -> Int -> IO DuckDBListEntry
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBListEntry
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBListEntry) Int
rowIdx
    (baseIdx, len) <- listEntryBounds (Text.pack "list") entry
    childVec <- c_duckdb_list_vector_get_child vector
    when (childVec == nullPtr) $
        throwIO (userError "duckdb-simple: list child vector is null")
    childType <- vectorElementType childVec
    childData <- c_duckdb_vector_get_data childVec
    childValidity <- c_duckdb_vector_get_validity childVec
    forM [0 .. len - 1] \Int
delta ->
        DuckDBType
-> DuckDBVector -> Ptr () -> Ptr Word64 -> Int -> IO FieldValue
materializeValue DuckDBType
childType DuckDBVector
childVec Ptr ()
childData Ptr Word64
childValidity (Int
baseIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
delta)

decodeMapPairs :: DuckDBVector -> Ptr () -> Int -> IO [(FieldValue, FieldValue)]
decodeMapPairs :: DuckDBVector -> Ptr () -> Int -> IO [(FieldValue, FieldValue)]
decodeMapPairs DuckDBVector
vector Ptr ()
dataPtr Int
rowIdx = do
    entry <- Ptr DuckDBListEntry -> Int -> IO DuckDBListEntry
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr () -> Ptr DuckDBListEntry
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
dataPtr :: Ptr DuckDBListEntry) Int
rowIdx
    (baseIdx, len) <- listEntryBounds (Text.pack "map") entry
    structVec <- c_duckdb_list_vector_get_child vector
    when (structVec == nullPtr) $
        throwIO (userError "duckdb-simple: map struct vector is null")
    keyVec <- c_duckdb_struct_vector_get_child structVec 0
    valueVec <- c_duckdb_struct_vector_get_child structVec 1
    when (keyVec == nullPtr || valueVec == nullPtr) $
        throwIO (userError "duckdb-simple: map child vectors are null")
    keyType <- vectorElementType keyVec
    valueType <- vectorElementType valueVec
    keyData <- c_duckdb_vector_get_data keyVec
    valueData <- c_duckdb_vector_get_data valueVec
    keyValidity <- c_duckdb_vector_get_validity keyVec
    valueValidity <- c_duckdb_vector_get_validity valueVec
    forM [0 .. len - 1] \Int
delta -> do
        let childIdx :: Int
childIdx = Int
baseIdx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
delta
        keyValue <- DuckDBType
-> DuckDBVector -> Ptr () -> Ptr Word64 -> Int -> IO FieldValue
materializeValue DuckDBType
keyType DuckDBVector
keyVec Ptr ()
keyData Ptr Word64
keyValidity Int
childIdx
        valueValue <- materializeValue valueType valueVec valueData valueValidity childIdx
        pure (keyValue, valueValue)

decodeStructValue :: DuckDBVector -> Int -> IO (StructValue FieldValue)
decodeStructValue :: DuckDBVector -> Int -> IO (StructValue FieldValue)
decodeStructValue DuckDBVector
vector Int
rowIdx =
    IO DuckDBLogicalType
-> (DuckDBLogicalType -> IO ())
-> (DuckDBLogicalType -> IO (StructValue FieldValue))
-> IO (StructValue FieldValue)
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
        (DuckDBVector -> IO DuckDBLogicalType
c_duckdb_vector_get_column_type DuckDBVector
vector)
        (\DuckDBLogicalType
logical -> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBLogicalType -> IO ()) -> IO ())
-> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBLogicalType
ptr -> Ptr DuckDBLogicalType -> DuckDBLogicalType -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr DuckDBLogicalType
ptr DuckDBLogicalType
logical IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr DuckDBLogicalType -> IO ()
c_duckdb_destroy_logical_type Ptr DuckDBLogicalType
ptr)
        \DuckDBLogicalType
logical -> do
            structTypeRep <- DuckDBLogicalType -> IO LogicalTypeRep
logicalTypeToRep DuckDBLogicalType
logical
            structFields <-
                case structTypeRep of
                    LogicalTypeStruct Array Int (StructField LogicalTypeRep)
typeArray -> Array Int (StructField LogicalTypeRep)
-> IO (Array Int (StructField LogicalTypeRep))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Array Int (StructField LogicalTypeRep)
typeArray
                    LogicalTypeRep
other ->
                        IOError -> IO (Array Int (StructField LogicalTypeRep))
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO
                            ( String -> IOError
userError
                                ( String
"duckdb-simple: expected STRUCT logical type, but saw "
                                    String -> ShowS
forall a. Semigroup a => a -> a -> a
<> LogicalTypeRep -> String
forall a. Show a => a -> String
show LogicalTypeRep
other
                                )
                            )
            let typeList = Array Int (StructField LogicalTypeRep)
-> [StructField LogicalTypeRep]
forall i e. Array i e -> [e]
elems Array Int (StructField LogicalTypeRep)
structFields
                count = [StructField LogicalTypeRep] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [StructField LogicalTypeRep]
typeList
            valueFields <-
                forM (zip [0 .. count - 1] typeList) \(Int
childIdx, StructField{Text
structFieldName :: Text
structFieldName :: forall a. StructField a -> Text
structFieldName}) -> do
                    childVec <- DuckDBVector -> Word64 -> IO DuckDBVector
c_duckdb_struct_vector_get_child DuckDBVector
vector (Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
childIdx)
                    when (childVec == nullPtr) $
                        throwIO (userError "duckdb-simple: struct child vector is null")
                    childType <- vectorElementType childVec
                    childData <- c_duckdb_vector_get_data childVec
                    childValidity <- c_duckdb_vector_get_validity childVec
                    value <- materializeValue childType childVec childData childValidity rowIdx
                    pure StructField{structFieldName, structFieldValue = value}
            let fieldArray =
                    if Int
count Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
                        then (Int, Int)
-> [StructField FieldValue] -> Array Int (StructField FieldValue)
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, -Int
1) []
                        else (Int, Int)
-> [StructField FieldValue] -> Array Int (StructField FieldValue)
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [StructField FieldValue]
valueFields
                indexMap =
                    [(Text, Int)] -> Map Text Int
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([Text] -> [Int] -> [(Text, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((StructField LogicalTypeRep -> Text)
-> [StructField LogicalTypeRep] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map StructField LogicalTypeRep -> Text
forall a. StructField a -> Text
structFieldName [StructField LogicalTypeRep]
typeList) [Int
0 ..])
            pure
                StructValue
                    { structValueFields = fieldArray
                    , structValueTypes = structFields
                    , structValueIndex = indexMap
                    }

decodeUnionValue :: DuckDBVector -> Ptr () -> Int -> IO (UnionValue FieldValue)
decodeUnionValue :: DuckDBVector -> Ptr () -> Int -> IO (UnionValue FieldValue)
decodeUnionValue DuckDBVector
vector Ptr ()
_dataPtr Int
rowIdx =
    IO DuckDBLogicalType
-> (DuckDBLogicalType -> IO ())
-> (DuckDBLogicalType -> IO (UnionValue FieldValue))
-> IO (UnionValue FieldValue)
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
        (DuckDBVector -> IO DuckDBLogicalType
c_duckdb_vector_get_column_type DuckDBVector
vector)
        (\DuckDBLogicalType
logical -> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBLogicalType -> IO ()) -> IO ())
-> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBLogicalType
ptr -> Ptr DuckDBLogicalType -> DuckDBLogicalType -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr DuckDBLogicalType
ptr DuckDBLogicalType
logical IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr DuckDBLogicalType -> IO ()
c_duckdb_destroy_logical_type Ptr DuckDBLogicalType
ptr)
        \DuckDBLogicalType
logical -> do
            unionTypeRep <- DuckDBLogicalType -> IO LogicalTypeRep
logicalTypeToRep DuckDBLogicalType
logical
            membersArray <-
                case unionTypeRep of
                    LogicalTypeUnion Array Int UnionMemberType
members -> Array Int UnionMemberType -> IO (Array Int UnionMemberType)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Array Int UnionMemberType
members
                    LogicalTypeRep
other ->
                        IOError -> IO (Array Int UnionMemberType)
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO
                            ( String -> IOError
userError
                                ( String
"duckdb-simple: expected UNION logical type, but saw "
                                    String -> ShowS
forall a. Semigroup a => a -> a -> a
<> LogicalTypeRep -> String
forall a. Show a => a -> String
show LogicalTypeRep
other
                                )
                            )
            let membersList = Array Int UnionMemberType -> [UnionMemberType]
forall i e. Array i e -> [e]
elems Array Int UnionMemberType
membersArray
                memberCount = [UnionMemberType] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [UnionMemberType]
membersList
            tagVec <- c_duckdb_struct_vector_get_child vector 0
            when (tagVec == nullPtr) $
                throwIO (userError "duckdb-simple: union tag vector is null")
            tagType <- vectorElementType tagVec
            tagData <- c_duckdb_vector_get_data tagVec
            tagValidity <- c_duckdb_vector_get_validity tagVec
            tagValue <- materializeValue tagType tagVec tagData tagValidity rowIdx
            memberIdx <-
                case tagValue of
                    FieldWord8 Word8
tagWord -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
tagWord :: Int)
                    FieldWord16 Word16
tagWord -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
tagWord :: Int)
                    FieldWord32 Word32
tagWord ->
                        if Word32
tagWord Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word16 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16
forall a. Bounded a => a
maxBound :: Word16)
                            then Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
tagWord)
                            else IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag exceeds Word16 range")
                    FieldWord64 Word64
tagWord ->
                        if Word64
tagWord Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word16 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16
forall a. Bounded a => a
maxBound :: Word16)
                            then Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
tagWord)
                            else IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag exceeds Word16 range")
                    FieldInt8 Int8
tagInt
                        | Int8
tagInt Int8 -> Int8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int8
0 -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
tagInt)
                        | Bool
otherwise -> IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag negative")
                    FieldInt16 Int16
tagInt
                        | Int16
tagInt Int16 -> Int16 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int16
0 -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
tagInt)
                        | Bool
otherwise -> IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag negative")
                    FieldInt32 Int32
tagInt
                        | Int32
tagInt Int32 -> Int32 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int32
0 Bool -> Bool -> Bool
&& Int32
tagInt Int32 -> Int32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word16 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16
forall a. Bounded a => a
maxBound :: Word16) -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
tagInt)
                        | Int32
tagInt Int32 -> Int32 -> Bool
forall a. Ord a => a -> a -> Bool
< Int32
0 -> IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag negative")
                        | Bool
otherwise -> IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag exceeds Word16 range")
                    FieldInt64 Int64
tagInt
                        | Int64
tagInt Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int64
0 Bool -> Bool -> Bool
&& Int64
tagInt Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word16 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16
forall a. Bounded a => a
maxBound :: Word16) -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
tagInt)
                        | Int64
tagInt Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0 -> IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag negative")
                        | Bool
otherwise -> IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: union tag exceeds Word16 range")
                    FieldValue
FieldNull ->
                        IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError String
"duckdb-simple: encountered NULL union tag")
                    FieldValue
other ->
                        IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO
                            ( String -> IOError
userError
                                ( String
"duckdb-simple: unexpected union tag value "
                                    String -> ShowS
forall a. Semigroup a => a -> a -> a
<> FieldValue -> String
forall a. Show a => a -> String
show FieldValue
other
                                )
                            )
            when (memberIdx < 0 || memberIdx >= memberCount) $
                throwIO (userError "duckdb-simple: union tag out of range")
            let selectedMember = [UnionMemberType]
membersList [UnionMemberType] -> Int -> UnionMemberType
forall a. HasCallStack => [a] -> Int -> a
!! Int
memberIdx
                memberLabel = UnionMemberType -> Text
unionMemberName UnionMemberType
selectedMember
            memberVec <- c_duckdb_struct_vector_get_child vector (fromIntegral (memberIdx + 1))
            when (memberVec == nullPtr) $
                throwIO (userError "duckdb-simple: union member vector is null")
            memberType <- vectorElementType memberVec
            memberData <- c_duckdb_vector_get_data memberVec
            memberValidity <- c_duckdb_vector_get_validity memberVec
            payload <- materializeValue memberType memberVec memberData memberValidity rowIdx
            pure
                UnionValue
                    { unionValueIndex = fromIntegral memberIdx
                    , unionValueLabel = memberLabel
                    , unionValuePayload = payload
                    , unionValueMembers = membersArray
                    }

vectorElementType :: DuckDBVector -> IO DuckDBType
vectorElementType :: DuckDBVector -> IO DuckDBType
vectorElementType DuckDBVector
vec = do
    logical <- DuckDBVector -> IO DuckDBLogicalType
c_duckdb_vector_get_column_type DuckDBVector
vec
    dtype <- c_duckdb_get_type_id logical
    destroyLogicalType logical
    pure dtype

listEntryBounds :: Text -> DuckDBListEntry -> IO (Int, Int)
listEntryBounds :: Text -> DuckDBListEntry -> IO (Int, Int)
listEntryBounds Text
context DuckDBListEntry{Word64
duckDBListEntryOffset :: DuckDBListEntry -> Word64
duckDBListEntryOffset :: Word64
duckDBListEntryOffset, Word64
duckDBListEntryLength :: DuckDBListEntry -> Word64
duckDBListEntryLength :: Word64
duckDBListEntryLength} = do
    base <- Text -> Word64 -> IO Int
ensureWithinIntRange (Text
context Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack String
" offset") Word64
duckDBListEntryOffset
    len <- ensureWithinIntRange (context <> Text.pack " length") duckDBListEntryLength
    let maxInt = Int -> Year
forall a. Integral a => a -> Year
toInteger (Int
forall a. Bounded a => a
maxBound :: Int)
        upperBound = Int -> Year
forall a. Integral a => a -> Year
toInteger Int
base Year -> Year -> Year
forall a. Num a => a -> a -> a
+ Int -> Year
forall a. Integral a => a -> Year
toInteger Int
len Year -> Year -> Year
forall a. Num a => a -> a -> a
- Year
1
    when (len > 0 && upperBound > maxInt) $
        throwIO (userError ("duckdb-simple: " <> Text.unpack context <> " bounds exceed Int range"))
    pure (base, len)

ensureWithinIntRange :: Text -> Word64 -> IO Int
ensureWithinIntRange :: Text -> Word64 -> IO Int
ensureWithinIntRange Text
context Word64
value =
    let actual :: Year
actual = Word64 -> Year
forall a. Integral a => a -> Year
toInteger Word64
value
        limit :: Year
limit = Int -> Year
forall a. Integral a => a -> Year
toInteger (Int
forall a. Bounded a => a
maxBound :: Int)
     in if Year
actual Year -> Year -> Bool
forall a. Ord a => a -> a -> Bool
<= Year
limit
            then Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Year -> Int
forall a. Num a => Year -> a
fromInteger Year
actual)
            else IOError -> IO Int
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (String -> IOError
userError (String
"duckdb-simple: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
Text.unpack Text
context String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" exceeds Int range"))

decodeDuckDBDate :: DuckDBDate -> IO Day
decodeDuckDBDate :: DuckDBDate -> IO Day
decodeDuckDBDate DuckDBDate
raw =
    (Ptr DuckDBDateStruct -> IO Day) -> IO Day
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBDateStruct -> IO Day) -> IO Day)
-> (Ptr DuckDBDateStruct -> IO Day) -> IO Day
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBDateStruct
ptr -> do
        DuckDBDate -> Ptr DuckDBDateStruct -> IO ()
c_duckdb_from_date DuckDBDate
raw Ptr DuckDBDateStruct
ptr
        dateStruct <- Ptr DuckDBDateStruct -> IO DuckDBDateStruct
forall a. Storable a => Ptr a -> IO a
peek Ptr DuckDBDateStruct
ptr
        pure (dateStructToDay dateStruct)

decodeDuckDBTime :: DuckDBTime -> IO TimeOfDay
decodeDuckDBTime :: DuckDBTime -> IO TimeOfDay
decodeDuckDBTime DuckDBTime
raw =
    (Ptr DuckDBTimeStruct -> IO TimeOfDay) -> IO TimeOfDay
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBTimeStruct -> IO TimeOfDay) -> IO TimeOfDay)
-> (Ptr DuckDBTimeStruct -> IO TimeOfDay) -> IO TimeOfDay
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBTimeStruct
ptr -> do
        DuckDBTime -> Ptr DuckDBTimeStruct -> IO ()
c_duckdb_from_time DuckDBTime
raw Ptr DuckDBTimeStruct
ptr
        timeStruct <- Ptr DuckDBTimeStruct -> IO DuckDBTimeStruct
forall a. Storable a => Ptr a -> IO a
peek Ptr DuckDBTimeStruct
ptr
        pure (timeStructToTimeOfDay timeStruct)

decodeDuckDBTimestamp :: DuckDBTimestamp -> IO LocalTime
decodeDuckDBTimestamp :: DuckDBTimestamp -> IO LocalTime
decodeDuckDBTimestamp DuckDBTimestamp
raw =
    (Ptr DuckDBTimestampStruct -> IO LocalTime) -> IO LocalTime
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBTimestampStruct -> IO LocalTime) -> IO LocalTime)
-> (Ptr DuckDBTimestampStruct -> IO LocalTime) -> IO LocalTime
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBTimestampStruct
ptr -> do
        DuckDBTimestamp -> Ptr DuckDBTimestampStruct -> IO ()
c_duckdb_from_timestamp DuckDBTimestamp
raw Ptr DuckDBTimestampStruct
ptr
        DuckDBTimestampStruct{duckDBTimestampStructDate = dateStruct, duckDBTimestampStructTime = timeStruct} <- Ptr DuckDBTimestampStruct -> IO DuckDBTimestampStruct
forall a. Storable a => Ptr a -> IO a
peek Ptr DuckDBTimestampStruct
ptr
        pure
            LocalTime
                { localDay = dateStructToDay dateStruct
                , localTimeOfDay = timeStructToTimeOfDay timeStruct
                }

decodeDuckDBTimeNs :: DuckDBTimeNs -> TimeOfDay
decodeDuckDBTimeNs :: DuckDBTimeNs -> TimeOfDay
decodeDuckDBTimeNs (DuckDBTimeNs Int64
nanos) =
    let (Int64
hours, Int64
remainderHours) = Int64
nanos Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`divMod` (Int64
60 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int64
60 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int64
1000000000)
        (Int64
minutes, Int64
remainderMinutes) = Int64
remainderHours Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`divMod` (Int64
60 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int64
1000000000)
        (Int64
seconds, Int64
fractionalNanos) = Int64
remainderMinutes Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int64
1000000000
        fractional :: Pico
fractional = Rational -> Pico
forall a. Fractional a => Rational -> a
fromRational (Int64 -> Year
forall a. Integral a => a -> Year
toInteger Int64
fractionalNanos Year -> Year -> Rational
forall a. Integral a => a -> a -> Ratio a
% Year
1000000000)
        totalSeconds :: Pico
totalSeconds = Int64 -> Pico
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
seconds Pico -> Pico -> Pico
forall a. Num a => a -> a -> a
+ Pico
fractional
     in Int -> Int -> Pico -> TimeOfDay
TimeOfDay
            (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
hours)
            (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
minutes)
            Pico
totalSeconds

decodeDuckDBTimeTz :: DuckDBTimeTz -> IO TimeWithZone
decodeDuckDBTimeTz :: DuckDBTimeTz -> IO TimeWithZone
decodeDuckDBTimeTz DuckDBTimeTz
raw =
    (Ptr DuckDBTimeTzStruct -> IO TimeWithZone) -> IO TimeWithZone
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBTimeTzStruct -> IO TimeWithZone) -> IO TimeWithZone)
-> (Ptr DuckDBTimeTzStruct -> IO TimeWithZone) -> IO TimeWithZone
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBTimeTzStruct
ptr -> do
        DuckDBTimeTz -> Ptr DuckDBTimeTzStruct -> IO ()
c_duckdb_from_time_tz DuckDBTimeTz
raw Ptr DuckDBTimeTzStruct
ptr
        DuckDBTimeTzStruct{duckDBTimeTzStructTime = timeStruct, duckDBTimeTzStructOffset = offset} <- Ptr DuckDBTimeTzStruct -> IO DuckDBTimeTzStruct
forall a. Storable a => Ptr a -> IO a
peek Ptr DuckDBTimeTzStruct
ptr
        let timeOfDay = DuckDBTimeStruct -> TimeOfDay
timeStructToTimeOfDay DuckDBTimeStruct
timeStruct
            minutes = Int32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
offset Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
60
            zone = Int -> TimeZone
minutesToTimeZone Int
minutes
        pure TimeWithZone{timeWithZoneTime = timeOfDay, timeWithZoneZone = zone}

decodeDuckDBTimestampSeconds :: DuckDBTimestampS -> IO LocalTime
decodeDuckDBTimestampSeconds :: DuckDBTimestampS -> IO LocalTime
decodeDuckDBTimestampSeconds (DuckDBTimestampS Int64
seconds) =
    DuckDBTimestamp -> IO LocalTime
decodeDuckDBTimestamp (Int64 -> DuckDBTimestamp
DuckDBTimestamp (Int64
seconds Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int64
1000000))

decodeDuckDBTimestampMilliseconds :: DuckDBTimestampMs -> IO LocalTime
decodeDuckDBTimestampMilliseconds :: DuckDBTimestampMs -> IO LocalTime
decodeDuckDBTimestampMilliseconds (DuckDBTimestampMs Int64
millis) =
    DuckDBTimestamp -> IO LocalTime
decodeDuckDBTimestamp (Int64 -> DuckDBTimestamp
DuckDBTimestamp (Int64
millis Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
* Int64
1000))

decodeDuckDBTimestampNanoseconds :: DuckDBTimestampNs -> IO LocalTime
decodeDuckDBTimestampNanoseconds :: DuckDBTimestampNs -> IO LocalTime
decodeDuckDBTimestampNanoseconds (DuckDBTimestampNs Int64
nanos) = do
    let utcTime :: UTCTime
utcTime = POSIXTime -> UTCTime
posixSecondsToUTCTime (Rational -> POSIXTime
forall a. Fractional a => Rational -> a
fromRational (Int64 -> Year
forall a. Integral a => a -> Year
toInteger Int64
nanos Year -> Year -> Rational
forall a. Integral a => a -> a -> Ratio a
% Year
1000000000))
    LocalTime -> IO LocalTime
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TimeZone -> UTCTime -> LocalTime
utcToLocalTime TimeZone
utc UTCTime
utcTime)

decodeDuckDBTimestampUTCTime :: DuckDBTimestamp -> IO UTCTime
decodeDuckDBTimestampUTCTime :: DuckDBTimestamp -> IO UTCTime
decodeDuckDBTimestampUTCTime (DuckDBTimestamp Int64
micros) =
    UTCTime -> IO UTCTime
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (POSIXTime -> UTCTime
posixSecondsToUTCTime (Rational -> POSIXTime
forall a. Fractional a => Rational -> a
fromRational (Int64 -> Year
forall a. Integral a => a -> Year
toInteger Int64
micros Year -> Year -> Rational
forall a. Integral a => a -> a -> Ratio a
% Year
1000000)))

intervalValueFromDuckDB :: DuckDBInterval -> IntervalValue
intervalValueFromDuckDB :: DuckDBInterval -> IntervalValue
intervalValueFromDuckDB DuckDBInterval{Int32
duckDBIntervalMonths :: Int32
duckDBIntervalMonths :: DuckDBInterval -> Int32
duckDBIntervalMonths, Int32
duckDBIntervalDays :: Int32
duckDBIntervalDays :: DuckDBInterval -> Int32
duckDBIntervalDays, Int64
duckDBIntervalMicros :: Int64
duckDBIntervalMicros :: DuckDBInterval -> Int64
duckDBIntervalMicros} =
    IntervalValue
        { intervalMonths :: Int32
intervalMonths = Int32
duckDBIntervalMonths
        , intervalDays :: Int32
intervalDays = Int32
duckDBIntervalDays
        , intervalMicros :: Int64
intervalMicros = Int64
duckDBIntervalMicros
        }

duckDBHugeIntToInteger :: DuckDBHugeInt -> Integer
duckDBHugeIntToInteger :: DuckDBHugeInt -> Year
duckDBHugeIntToInteger DuckDBHugeInt{Word64
duckDBHugeIntLower :: Word64
duckDBHugeIntLower :: DuckDBHugeInt -> Word64
duckDBHugeIntLower, Int64
duckDBHugeIntUpper :: Int64
duckDBHugeIntUpper :: DuckDBHugeInt -> Int64
duckDBHugeIntUpper} =
    (Int64 -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
duckDBHugeIntUpper Year -> Int -> Year
forall a. Bits a => a -> Int -> a
`shiftL` Int
64) Year -> Year -> Year
forall a. Bits a => a -> a -> a
.|. Word64 -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
duckDBHugeIntLower

duckDBUHugeIntToInteger :: DuckDBUHugeInt -> Integer
duckDBUHugeIntToInteger :: DuckDBUHugeInt -> Year
duckDBUHugeIntToInteger DuckDBUHugeInt{Word64
duckDBUHugeIntLower :: Word64
duckDBUHugeIntLower :: DuckDBUHugeInt -> Word64
duckDBUHugeIntLower, Word64
duckDBUHugeIntUpper :: Word64
duckDBUHugeIntUpper :: DuckDBUHugeInt -> Word64
duckDBUHugeIntUpper} =
    (Word64 -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
duckDBUHugeIntUpper Year -> Int -> Year
forall a. Bits a => a -> Int -> a
`shiftL` Int
64) Year -> Year -> Year
forall a. Bits a => a -> a -> a
.|. Word64 -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
duckDBUHugeIntLower

destroyLogicalType :: DuckDBLogicalType -> IO ()
destroyLogicalType :: DuckDBLogicalType -> IO ()
destroyLogicalType DuckDBLogicalType
logicalType =
    (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr DuckDBLogicalType -> IO ()) -> IO ())
-> (Ptr DuckDBLogicalType -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr DuckDBLogicalType
ptr -> do
        Ptr DuckDBLogicalType -> DuckDBLogicalType -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr DuckDBLogicalType
ptr DuckDBLogicalType
logicalType
        Ptr DuckDBLogicalType -> IO ()
c_duckdb_destroy_logical_type Ptr DuckDBLogicalType
ptr

dateStructToDay :: DuckDBDateStruct -> Day
dateStructToDay :: DuckDBDateStruct -> Day
dateStructToDay DuckDBDateStruct{Int32
duckDBDateStructYear :: Int32
duckDBDateStructYear :: DuckDBDateStruct -> Int32
duckDBDateStructYear, Int8
duckDBDateStructMonth :: Int8
duckDBDateStructMonth :: DuckDBDateStruct -> Int8
duckDBDateStructMonth, Int8
duckDBDateStructDay :: Int8
duckDBDateStructDay :: DuckDBDateStruct -> Int8
duckDBDateStructDay} =
    Year -> Int -> Int -> Day
fromGregorian
        (Int32 -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
duckDBDateStructYear)
        (Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
duckDBDateStructMonth)
        (Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
duckDBDateStructDay)

timeStructToTimeOfDay :: DuckDBTimeStruct -> TimeOfDay
timeStructToTimeOfDay :: DuckDBTimeStruct -> TimeOfDay
timeStructToTimeOfDay DuckDBTimeStruct{Int8
duckDBTimeStructHour :: Int8
duckDBTimeStructHour :: DuckDBTimeStruct -> Int8
duckDBTimeStructHour, Int8
duckDBTimeStructMinute :: Int8
duckDBTimeStructMinute :: DuckDBTimeStruct -> Int8
duckDBTimeStructMinute, Int8
duckDBTimeStructSecond :: Int8
duckDBTimeStructSecond :: DuckDBTimeStruct -> Int8
duckDBTimeStructSecond, Int32
duckDBTimeStructMicros :: Int32
duckDBTimeStructMicros :: DuckDBTimeStruct -> Int32
duckDBTimeStructMicros} =
    let secondsInt :: Year
secondsInt = Int8 -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
duckDBTimeStructSecond :: Integer
        micros :: Year
micros = Int32 -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
duckDBTimeStructMicros :: Integer
        fractional :: Pico
fractional = Rational -> Pico
forall a. Fractional a => Rational -> a
fromRational (Year
micros Year -> Year -> Rational
forall a. Integral a => a -> a -> Ratio a
% Year
1000000)
        totalSeconds :: Pico
totalSeconds = Year -> Pico
forall a. Num a => Year -> a
fromInteger Year
secondsInt Pico -> Pico -> Pico
forall a. Num a => a -> a -> a
+ Pico
fractional
     in Int -> Int -> Pico -> TimeOfDay
TimeOfDay
            (Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
duckDBTimeStructHour)
            (Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
duckDBTimeStructMinute)
            Pico
totalSeconds