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