server/mssql: fix aggregations

Aggregate fields - both the table and the relationship fields haven't been enabled till now. This PR fixes enables the aggregate fields and fixes an issue with root aggregate fields.

Co-authored-by: Chris Done <11019+chrisdone@users.noreply.github.com>
GitOrigin-RevId: a6d7ed9b45cda6af659a57576a8623c725a7372f
This commit is contained in:
Vamshi Surabhi 2021-04-28 16:35:33 +05:30 committed by hasura-bot
parent bc1e131717
commit 1c668dac0e
6 changed files with 62 additions and 28 deletions

View File

@ -6,7 +6,7 @@
### Bug fixes and improvements
(Add entries below in the order of: server, console, cli, docs, others)
- server: aggregation fields are now supported on mssql
- server: accept a new server config flag `--events-fetch-batch-size` to configure the number of rows being fetched from the events log table in a single batch
- server: fix regression: `on_conflict` was missing in the schema for inserts in tables where the current user has no columns listed in their update permissions (fix #6804)
- server: fix one-to-one relationship bug (introduced in #459) which prevented adding one-to-one relationships which didn't have the same column name for target and source

View File

@ -46,6 +46,7 @@ import Hasura.SQL.Backend
data Error
= UnsupportedOpExpG (IR.OpExpG 'MSSQL Expression)
| FunctionNotSupported
| NodesUnsupportedForNow
deriving (Show, Eq)
-- | The base monad used throughout this module for all conversion
@ -188,7 +189,7 @@ fromSelectAggregate annSelectG = do
, selectJoins = argsJoins <> mapMaybe fieldSourceJoin fieldSources
, selectWhere = argsWhere <> Where [filterExpression]
, selectFor =
JsonFor ForJson {jsonCardinality = JsonSingleton, jsonRoot = NoRoot}
JsonFor ForJson {jsonCardinality = JsonSingleton, jsonRoot = Root "aggregate"}
, selectOrderBy = argsOrderBy
, selectOffset = argsOffset
}
@ -502,7 +503,8 @@ fromTableAggregateFieldG (IR.FieldName name, field) =
{ aliasedThing = TSQL.ValueExpression (ODBC.TextValue text)
, aliasedAlias = name
})
IR.TAFNodes x _ -> case x of {}
IR.TAFNodes {} ->
refute (pure NodesUnsupportedForNow)
fromAggregateField :: IR.AggregateField 'MSSQL -> ReaderT EntityAlias FromIr Aggregate
fromAggregateField aggregateField =

View File

@ -44,7 +44,7 @@ instance BackendSchema 'MSSQL where
buildFunctionMutationFields = msBuildFunctionMutationFields
-- backend extensions
relayExtension = const Nothing
nodesAggExtension = const Nothing
nodesAggExtension = const $ Just ()
-- indivdual components
columnParser = msColumnParser
jsonPathArg = msJsonPathArg

View File

@ -41,7 +41,7 @@ instance Backend 'MSSQL where
type XComputedField 'MSSQL = XDisable
type XRemoteField 'MSSQL = XDisable
type XRelay 'MSSQL = XDisable
type XNodesAgg 'MSSQL = XDisable
type XNodesAgg 'MSSQL = XEnable
type XDistinct 'MSSQL = XDisable
functionArgScalarType :: FunctionArgType 'MSSQL -> ScalarType 'MSSQL

View File

@ -55,7 +55,17 @@ planNoPlan userInfo queryDB = do
{ selectFor =
case selectFor select of
NoFor -> NoFor
JsonFor forJson -> JsonFor forJson {jsonRoot = Root "root"}
JsonFor forJson ->
JsonFor forJson {jsonRoot =
case jsonRoot forJson of
NoRoot -> Root "root"
-- Keep whatever's there if already
-- specified. In the case of an
-- aggregate query, the root will
-- be specified "aggregate", for
-- example.
keep -> keep
}
}
planMultiplex

View File

@ -138,9 +138,7 @@ fromDelete Delete {deleteTable, deleteWhere} =
]
fromSelect :: Select -> Printer
fromSelect Select {..} = case selectFor of
NoFor -> result
JsonFor _ -> SeqPrinter ["SELECT ISNULL((", result, "), '[]')"]
fromSelect Select {..} = wrapFor selectFor result
where
result =
SepByPrinter
@ -186,18 +184,20 @@ fromJoinSource =
JoinReselect reselect -> fromReselect reselect
fromReselect :: Reselect -> Printer
fromReselect Reselect {..} =
SepByPrinter
NewlinePrinter
[ "SELECT " <+>
IndentPrinter
7
(SepByPrinter
("," <+> NewlinePrinter)
(map fromProjection (toList reselectProjections)))
, fromFor reselectFor
, fromWhere reselectWhere
]
fromReselect Reselect {..} = wrapFor reselectFor result
where
result =
SepByPrinter
NewlinePrinter
[ "SELECT " <+>
IndentPrinter
7
(SepByPrinter
("," <+> NewlinePrinter)
(map fromProjection (toList reselectProjections)))
, fromFor reselectFor
, fromWhere reselectWhere
]
fromOrderBys ::
Top -> Maybe Expression -> Maybe (NonEmpty OrderBy) -> Printer
@ -258,15 +258,11 @@ fromFor :: For -> Printer
fromFor =
\case
NoFor -> ""
JsonFor ForJson {jsonCardinality, jsonRoot = root} ->
JsonFor ForJson {jsonCardinality} ->
"FOR JSON PATH" <+>
case jsonCardinality of
JsonArray -> ""
JsonSingleton ->
", WITHOUT_ARRAY_WRAPPER" <+>
case root of
NoRoot -> ""
Root text -> "ROOT(" <+> QueryPrinter (toSql text) <+> ")"
JsonArray -> ""
JsonSingleton -> ", WITHOUT_ARRAY_WRAPPER"
fromProjection :: Projection -> Printer
fromProjection =
@ -362,6 +358,32 @@ trueExpression = ValueExpression (BoolValue True)
falseExpression :: Expression
falseExpression = ValueExpression (BoolValue False)
-- | Wrap a select with things needed when using FOR JSON.
wrapFor :: For -> Printer -> Printer
wrapFor for' inner = nullToArray
where
nullToArray =
case for' of
NoFor -> rooted
JsonFor _ -> SeqPrinter ["SELECT ISNULL((", rooted, "), '[]')"]
rooted =
case for' of
JsonFor ForJson {jsonRoot, jsonCardinality = JsonSingleton} ->
case jsonRoot of
NoRoot -> inner
-- This is gross, but unfortunately ROOT and
-- WITHOUT_ARRAY_WRAPPER are not allowed to be used at the
-- same time (reason not specified). Therefore we just
-- concatenate the necessary JSON string literals around
-- the JSON.
Root text ->
SeqPrinter
[ fromString ("SELECT CONCAT('{" <> show text <> ":', (")
, inner
, "), '}')"
]
_ -> inner
--------------------------------------------------------------------------------
-- Basic printing API