diff --git a/CHANGELOG.md b/CHANGELOG.md index f00184566d5..8575f732dee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Hasura GraphQL Engine Changelog ## Next release + +### Bug fixes and improvements + +- server/mssql: fix runtime errors when selecting geography/geometry columns + +## v1.4.0-alpha.2 ### MSSQL support It's now possible to add a MSSQL server as a source. For now, only read-only queries and subscriptions are supported. diff --git a/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs b/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs index 79676e65a6d..e714cea38fe 100644 --- a/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs +++ b/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs @@ -587,14 +587,20 @@ fromAnnColumnField :: -> ReaderT EntityAlias FromIr Expression fromAnnColumnField _stringifyNumbers annColumnField = do fieldName <- fromPGCol pgCol - if asText || True -- TODO: FIXME: - -- TODO: Does MSSQL support bignums? Probably, but needs researching. - {-(IR.isScalarColumnWhere PG.isBigNum typ && stringifyNumbers == StringifyNumbers)-} - then pure (ToStringExpression (ColumnExpression fieldName)) + -- TODO: Handle stringifying large numbers + {-(IR.isScalarColumnWhere PG.isBigNum typ && stringifyNumbers == StringifyNumbers)-} + + -- for geometry and geography values, the automatic json encoding on sql + -- server would fail. So we need to convert it to a format the json encoding + -- handles. Ideally we want this representation to be GeoJSON but sql server + -- doesn't have any functions to convert to GeoJSON format. So we return it in + -- WKT format + if typ == (IR.ColumnScalar GeometryType) || typ == (IR.ColumnScalar GeographyType) + then pure $ MethodExpression (ColumnExpression fieldName) "STAsText" [] else pure (ColumnExpression fieldName) where - IR.AnnColumnField { _acfInfo = IR.ColumnInfo{pgiColumn=pgCol,pgiType=_typ} - , _acfAsText = asText :: Bool + IR.AnnColumnField { _acfInfo = IR.ColumnInfo{pgiColumn=pgCol,pgiType=typ} + , _acfAsText = _asText :: Bool , _acfOp = _ :: Maybe (IR.ColumnOp 'MSSQL) -- TODO: What's this? } = annColumnField diff --git a/server/src-lib/Hasura/Backends/MSSQL/Meta.hs b/server/src-lib/Hasura/Backends/MSSQL/Meta.hs index dbf8637cea8..692f8415c91 100644 --- a/server/src-lib/Hasura/Backends/MSSQL/Meta.hs +++ b/server/src-lib/Hasura/Backends/MSSQL/Meta.hs @@ -3,8 +3,7 @@ -- | module Hasura.Backends.MSSQL.Meta - ( MetadataError(..) - , loadDBMetadata + ( loadDBMetadata ) where import Hasura.Prelude @@ -31,10 +30,6 @@ import Hasura.SQL.Backend -------------------------------------------------------------------------------- -- Loader -data MetadataError - = UnknownScalarType Text - deriving (Show) - loadDBMetadata :: Connection -> IO (DBTablesMetadata 'MSSQL) loadDBMetadata conn = do let sql = $(Q.sqlFromFile "src-rsr/mssql_table_metadata.sql") @@ -179,6 +174,8 @@ parseScalarType = \case "varbinary" -> VarbinaryType "bit" -> BitType "uniqueidentifier" -> GuidType + "geography" -> GeographyType + "geometry" -> GeometryType t -> UnknownType t diff --git a/server/src-lib/Hasura/Backends/MSSQL/ToQuery.hs b/server/src-lib/Hasura/Backends/MSSQL/ToQuery.hs index f505a58f73b..6a348ec3b05 100644 --- a/server/src-lib/Hasura/Backends/MSSQL/ToQuery.hs +++ b/server/src-lib/Hasura/Backends/MSSQL/ToQuery.hs @@ -93,6 +93,10 @@ fromExpression = "(" <+> fromExpression x <+> ") != (" <+> fromExpression y <+> ")" ToStringExpression e -> "CONCAT(" <+> fromExpression e <+> ", '')" SelectExpression s -> "(" <+> IndentPrinter 1 (fromSelect s) <+> ")" + MethodExpression field method args -> + fromExpression field <+> "." <+> + fromString (T.unpack method) <+> + "(" <+> (SeqPrinter $ map fromExpression args) <+> ")" OpExpression op x y -> "(" <+> fromExpression x <+> diff --git a/server/src-lib/Hasura/Backends/MSSQL/Types/Internal.hs b/server/src-lib/Hasura/Backends/MSSQL/Types/Internal.hs index 0e2f2996b0d..879adee3158 100644 --- a/server/src-lib/Hasura/Backends/MSSQL/Types/Internal.hs +++ b/server/src-lib/Hasura/Backends/MSSQL/Types/Internal.hs @@ -157,6 +157,8 @@ data Expression -- behave like it knows your field is JSON and not double-encode -- it. | ToStringExpression Expression + -- expression.text(e1, e2, ..) + | MethodExpression !Expression !Text ![Expression] | JsonValueExpression Expression JsonPath -- ^ This is for getting actual atomic values out of a JSON -- string. @@ -266,6 +268,8 @@ data ScalarType | TinyintType | BitType | GuidType + | GeographyType + | GeometryType | UnknownType !Text scalarTypeDBName :: ScalarType -> Text @@ -291,6 +295,8 @@ scalarTypeDBName = \case TinyintType -> "tinyint" BitType -> "bit" GuidType -> "uniqueidentifier" + GeographyType -> "geography" + GeometryType -> "geometry" -- the input form for types that aren't explicitly supported is a string UnknownType t -> t @@ -317,6 +323,11 @@ parseScalarValue scalarType jValue = case scalarType of TinyintType -> ODBC.IntValue <$> parseJValue jValue BitType -> ODBC.ByteValue <$> parseJValue jValue GuidType -> ODBC.TextValue <$> parseJValue jValue + + -- TODO: We'll need to wrap this with geography::STGeomFromText + GeographyType -> ODBC.TextValue <$> parseJValue jValue + GeometryType -> ODBC.TextValue <$> parseJValue jValue + -- the input format for types that aren't explicitly supported is a string UnknownType _ -> ODBC.TextValue <$> parseJValue jValue where