{-# LANGUAGE OverloadedStrings #-}
import Test.Hspec
import Database.PostgreSQL.Simple.Bind.Representation
import Data.Text ()
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
let test = \declaration result -> parsePGFunction declaration >>= shouldBe result
describe "parsePGFunction" $ do
it "works with simple signatures" $ do
let r = PGFunction {
pgfSchema = ""
, pgfName = ""
, pgfArguments = []
, pgfResult = PGSingle ""
}
test "function f(x bigint) returns bigint" r {
pgfName = "f"
, pgfResult = PGSingle "bigint"
, pgfArguments = [
PGArgument { pgaName = "x", pgaType = "bigint", pgaOptional = False }
]
}
test "function g(x bigint, y varchar) returns void" r {
pgfName = "g"
, pgfArguments = [
PGArgument { pgaName = "x", pgaType = "bigint", pgaOptional = False }
, PGArgument { pgaName = "y", pgaType = "varchar", pgaOptional = False }
]
, pgfResult = PGSingle "void"
}
test "function h() returns varchar" r {
pgfName = "h"
, pgfArguments = []
, pgfResult = PGSingle "varchar"
}
test "FUNCTION H(Z VARCHAR) RETURNS BIGINT" r {
pgfName = "h"
, pgfArguments = [
PGArgument { pgaName = "z", pgaType = "varchar", pgaOptional = False }
]
, pgfResult = PGSingle "bigint"
}
it "works with default values" $ do
let r = PGFunction {
pgfSchema = ""
, pgfName = "f"
, pgfArguments = []
, pgfResult = PGSingle "void"
}
test "function f(x bigint default 0::bigint) returns void" r {
pgfArguments = [
PGArgument { pgaName = "x", pgaType = "bigint", pgaOptional = True }
]
}
test "function f(x bigint, y bigint default 0::bigint) returns void" r {
pgfArguments = [
PGArgument { pgaName = "x", pgaType = "bigint", pgaOptional = False }
, PGArgument { pgaName = "y", pgaType = "bigint", pgaOptional = True }
]
}
test "function f(x bigint, y bigint = 0::bigint, z bigint = 0::bigint) returns void" r {
pgfArguments = [
PGArgument { pgaName = "x", pgaType = "bigint", pgaOptional = False }
, PGArgument { pgaName = "y", pgaType = "bigint", pgaOptional = True }
, PGArgument { pgaName = "z", pgaType = "bigint", pgaOptional = True }
]
}
it "works with return value types" $ do
let r = PGFunction {
pgfSchema = ""
, pgfName = "f"
, pgfArguments = []
, pgfResult = PGSetOf ""
}
test "function f() returns setof bigint" r { pgfResult = PGSetOf "bigint" }
test "function f() returns SETOF bigint" r { pgfResult = PGSetOf "bigint" }
test "function f() returns table (x bigint, y varchar)" r {
pgfResult = PGTable [
PGColumn { pgcName = "x", pgcType = "bigint" }
, PGColumn { pgcName = "y", pgcType = "varchar" }
]
}
it "works with schema names" $ do
let r = PGFunction {
pgfSchema = ""
, pgfName = "f"
, pgfArguments = []
, pgfResult = PGSingle "bigint"
}
test "function public.f() returns bigint" r { pgfSchema = "public" }
test "function Test.f() returns bigint" r { pgfSchema = "test" }
describe "parsing a function with specific type" $ do
let r = PGFunction {
pgfSchema = ""
, pgfName = "f"
, pgfArguments = []
, pgfResult = PGSingle "void"
}
let x = PGArgument { pgaName = "x", pgaType = "", pgaOptional = False }
it "works for multiple word types" $ do
test "function f(x double precision) returns void" r {
pgfArguments = [ x { pgaType = "double precision" } ]
}
it "works for types with precisions" $ do
test "function f(x bit) returns void" r {
pgfArguments = [ x { pgaType = "bit" } ]
}
test "function f(x bit (32)) returns void" r {
pgfArguments = [ x { pgaType = "bit" } ]
}
it "works for types with precisions and multiple words" $ do
test "function f(x character varying) returns void" r {
pgfArguments = [ x { pgaType = "character varying" } ]
}
test "function f(x character varying (256)) returns void" r {
pgfArguments = [ x { pgaType = "character varying" } ]
}
it "works for types with multiple precisions" $ do
test "function f(x numeric) returns void" r {
pgfArguments = [ x { pgaType = "numeric" } ]
}
test "function f(x numeric(10)) returns void" r {
pgfArguments = [ x { pgaType = "numeric" } ]
}
test "function f(x numeric(10,3)) returns void" r {
pgfArguments = [ x { pgaType = "numeric" } ]
}
test "function f(x user_defined_type(1,2,3,4)) returns void" r {
pgfArguments = [ x { pgaType = "user_defined_type" } ]
}
it "works for time types" $ do
test "function f(x time) returns void" r {
pgfArguments = [ x { pgaType = "time" } ]
}
test "function f(x time (6)) returns void" r {
pgfArguments = [ x { pgaType = "time" } ]
}
test "function f(x time (6) with time zone) returns void" r {
pgfArguments = [ x { pgaType = "time with time zone" } ]
}
test "function f(x time with time zone) returns void" r {
pgfArguments = [ x { pgaType = "time with time zone" } ]
}
test "function f(x time without time zone) returns void" r {
pgfArguments = [ x { pgaType = "time without time zone" } ]
}
test "function f(x timestamp with time zone) returns void" r {
pgfArguments = [ x { pgaType = "timestamp with time zone" } ]
}
test "function f(x timestamptz) returns void" r {
pgfArguments = [ x { pgaType = "timestamptz" } ]
}
it "works for intervals" $ do
test "function f(x interval) returns void" r {
pgfArguments = [ x { pgaType = "interval" } ]
}
test "function f(x interval month) returns void" r {
pgfArguments = [ x { pgaType = "interval month" } ]
}
test "function f(x interval minute to second (4)) returns void" r {
pgfArguments = [ x { pgaType = "interval minute to second" } ]
}