Skip to content

lead1_ has the wrong type #745

Open
@emilaxelsson

Description

@emilaxelsson

See the code at the bottom. It uses coerce to change the result of lead1_ to be nullable.

Uncommenting the line

    fmap fixType <$>

Makes the code fail with

BeamRowReadError {brreColumn = Just 1, brreError = ColumnErrorInternal "Column parse failed with unknown exception"}

Code:

#!/usr/bin/env stack
{- stack script
    --snapshot lts-23.0
    --system-ghc
    --package beam-core
    --package beam-postgres
    --package postgresql-simple
    --package text
s-}

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}

import Data.Coerce (coerce)
import Data.Text (Text)
import Database.Beam
import Database.Beam.Postgres
import Database.PostgreSQL.Simple (Query, execute_)

data PersonT f = Person
    { name :: C f Text
    }
    deriving (Generic)

type Person = PersonT Identity

type PersonExpr s = PersonT (QExpr Postgres s)

deriving instance Show Person
deriving instance Eq Person

instance Beamable PersonT

instance Table PersonT where
    data PrimaryKey PersonT f = PersonKey (C f Text)
        deriving stock (Generic)
        deriving anyclass (Beamable)

    primaryKey Person{name} = PersonKey name

data Db f = Db
    { persons :: f (TableEntity PersonT)
    }
    deriving (Generic)

instance Database Postgres Db

db :: DatabaseSettings Postgres Db
db = defaultDbSettings

-- The type of `lead1_` is incorrect
fixType :: QExpr Postgres s a -> QExpr Postgres s (Maybe a)
fixType = coerce

query =
    fmap fixType <$>
        withWindow_
            ( \Person{name} ->
                frame_
                    noPartition_
                    (orderPartitionBy_ (asc_ name))
                    noBounds_
            )
            ( \Person{name} w ->
                (name, lead1_ name `over_` w)
            )
            (all_ $ persons db)

main = do
    conn <- connect defaultConnectInfo {connectDatabase = "test"}

    execute_ conn "create table if not exists persons (name varchar)"
    execute_ conn "delete from persons"
    execute_ conn "insert into persons (name) values ('Janne'), ('Jenny')"

    results <- runBeamPostgres conn $
        runSelectReturningList $ select query

    mapM_ print results

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions