
Code for the sql server type conversion rules (and implicit/explicit
casting)

The plan is to follow the same functions as postgresql support for now:

findCallMatch
resolveResultSetType
checkAssignmentValid

The rules in sql server for implicit casting and function resolution
are quite different to postgresql. The biggest one is that e.g. select
cast(1 as int) + cast('2' as varchar(20)) works in sql server but not
in postgresql.


just hack for operators for now: if one argument is a number type, and
the other is a text type, then cast the text to number.

> {-# LANGUAGE PatternGuards,OverloadedStrings #-}
> module Database.HsSqlPpp.Internals.TypeChecking.SqlTypeConversion (
>                        findCallMatch
>                       ) where
>
> --import Data.Maybe
> --import Data.List
> --import Data.Either
> --import Debug.Trace
> --import Data.Char
> --import Control.Monad
>
> import Database.HsSqlPpp.Internals.TypesInternal
> import Database.HsSqlPpp.Internals.Catalog.CatalogInternal
> --import Database.HsSqlPpp.Utils.Utils
> --import Database.HsSqlPpp.Internals.TypeChecking.OldTediousTypeUtils
> import qualified Database.HsSqlPpp.Internals.TypeChecking.OldTypeConversion as T
> import Data.Text (Text)

> findCallMatch :: Catalog -> Text -> [Type] ->  Either [TypeError] OperatorPrototype
> findCallMatch cat fnName argsType =
>   case argsType of
>      [_a,_b] | Just x <- checkOperator cat fnName argsType -> Right x
>      _ -> T.findCallMatch cat fnName argsType

hack to allow implicit casting one of the args to a numeric operator
from a text type to the correct numeric type:

check is an operator
check on arg is numeric, the other text
match an exact operator itself with two args the same numeric type
- in this case, cast the text arg to the numeric type and return a match


> checkOperator :: Catalog -> Text -> [Type] -> Maybe OperatorPrototype
> checkOperator cat fnName [a,b] | Just t <- ty a b =
>   -- have the argument type in t
>   -- find all the matching fns by name
>   let nm = catLookupFns cat fnName
>   -- keep the ones which have exactly two args with the
>   -- type t, only proceed if there is onne match
>       cands = filter (\(_,as,_,_) -> as == [t,t]) nm
>   in case cands of
>        [c] -> return c
>        _ -> Nothing
>   where
>     ty a' b' | isNumber a' && isText b' = Just a'
>     ty a' b' | isText a' && isNumber b' = Just b'
>     ty _ _ = Nothing
>     isNumber x =
>       x `elem` [typeSmallInt,typeBigInt,typeInt
>                ,typeNumeric,typeFloat4,typeFloat8]
>     --isNumber _ = False
>     isText x =
>       x `elem` [typeVarChar,typeNVarChar,typeChar, ScalarType "text"]
>     --isText _ = False
> checkOperator _ _ _ = Nothing
