packages feed

postgresql-simple-bind-0.4.0: tests/Main.hs

{-# 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" } ]
        }