packages feed

duckdb-ffi-0.1.4.1: test/SelectionVectorTest.hs

{-# LANGUAGE BlockArguments #-}

module SelectionVectorTest (tests) where

import Control.Monad (forM_)
import Data.Int (Int32)
import Data.Word (Word32)
import Database.DuckDB.FFI
import Foreign.Ptr (Ptr, castPtr, nullPtr)
import Foreign.Storable (peekElemOff, pokeElemOff)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertBool, testCase, (@?=))
import Utils (withLogicalType, withSelectionVector, withVector)

tests :: TestTree
tests =
    testGroup
        "Selection Vector Interface"
        [ selectionVectorPointerWritable
        , selectionVectorCopySelection
        ]

selectionVectorPointerWritable :: TestTree
selectionVectorPointerWritable =
    testCase "selection vector exposes writable data pointer" $ do
        withSelectionVector 4 \selVec -> do
            dataPtr <- c_duckdb_selection_vector_get_data_ptr selVec
            assertBool "data pointer should be non-null" (dataPtr /= nullPtr)
            forM_ (zip [0 ..] [0, 2, 4, 6 :: Word32]) (uncurry (pokeElemOff dataPtr))
            fetched <- mapM (peekElemOff dataPtr) [0 .. 3]
            fetched @?= [0, 2, 4, 6]

selectionVectorCopySelection :: TestTree
selectionVectorCopySelection =
    testCase "vector_copy_sel copies selected rows" $ do
        withLogicalType (c_duckdb_create_logical_type DuckDBTypeInteger) \intType -> do
            withVector (c_duckdb_create_vector intType 4) \srcVec -> do
                srcPtr <- vectorDataPtr srcVec
                forM_ (zip [0 ..] [10, 20, 30, 40 :: Int32]) (uncurry (pokeElemOff srcPtr))

                withSelectionVector 2 \selVec -> do
                    selPtr <- c_duckdb_selection_vector_get_data_ptr selVec
                    pokeElemOff selPtr 0 1
                    pokeElemOff selPtr 1 3

                    withVector (c_duckdb_create_vector intType 2) \dstVec -> do
                        c_duckdb_vector_copy_sel srcVec dstVec selVec 2 0 0
                        dstPtr <- vectorDataPtr dstVec
                        val0 <- peekElemOff dstPtr 0
                        val1 <- peekElemOff dstPtr 1
                        val0 @?= 20
                        val1 @?= 40

-- Helpers -------------------------------------------------------------------

vectorDataPtr :: DuckDBVector -> IO (Ptr Int32)
vectorDataPtr vec = do
    raw <- c_duckdb_vector_get_data vec
    pure (castPtr raw)