diff --git a/src/bin/ProjectM36/Server/RemoteCallTypes/Json.hs b/src/bin/ProjectM36/Server/RemoteCallTypes/Json.hs index df140aa9..b3df3146 100644 --- a/src/bin/ProjectM36/Server/RemoteCallTypes/Json.hs +++ b/src/bin/ProjectM36/Server/RemoteCallTypes/Json.hs @@ -224,4 +224,71 @@ instance FromJSON AtomFunctionError instance ToJSON WithNameExpr instance FromJSON WithNameExpr +instance ToJSON (ScalarExprBase ColumnProjectionName) +instance FromJSON (ScalarExprBase ColumnProjectionName) +instance ToJSON OperatorName +instance FromJSON OperatorName + +instance ToJSON BoolOp +instance FromJSON BoolOp + +instance ToJSON InPredicateValue +instance FromJSON InPredicateValue + +instance ToJSON Select +instance FromJSON Select + +instance ToJSON InFlag +instance FromJSON InFlag + +instance ToJSON QuantifiedComparisonPredicate +instance FromJSON QuantifiedComparisonPredicate + +instance ToJSON ComparisonOperator +instance FromJSON ComparisonOperator + +instance ToJSON (ScalarExprBase ColumnName) +instance FromJSON (ScalarExprBase ColumnName) + +instance ToJSON WithClause +instance FromJSON WithClause + +instance ToJSON Distinctness +instance FromJSON Distinctness + +instance ToJSON TableExpr +instance FromJSON TableExpr + +instance ToJSON WithExpr +instance FromJSON WithExpr + +instance ToJSON SortExpr +instance FromJSON SortExpr + +instance ToJSON HavingExpr +instance FromJSON HavingExpr + +instance ToJSON GroupByExpr +instance FromJSON GroupByExpr + +instance ToJSON RestrictionExpr +instance FromJSON RestrictionExpr + +instance ToJSON TableRef +instance FromJSON TableRef + +instance ToJSON WithExprAlias +instance FromJSON WithExprAlias + +instance ToJSON Direction +instance FromJSON Direction + +instance ToJSON JoinCondition +instance FromJSON JoinCondition + +instance ToJSON NullsOrder +instance FromJSON NullsOrder + +instance ToJSON JoinOnCondition +instance FromJSON JoinOnCondition diff --git a/src/bin/TutorialD/Interpreter/RelationalExpr.hs b/src/bin/TutorialD/Interpreter/RelationalExpr.hs index 09662043..e35c8844 100644 --- a/src/bin/TutorialD/Interpreter/RelationalExpr.hs +++ b/src/bin/TutorialD/Interpreter/RelationalExpr.hs @@ -208,6 +208,7 @@ atomExprP = consumeAtomExprP True consumeAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a) consumeAtomExprP consume = try functionAtomExprP <|> + boolAtomExprP <|> -- we do this before the constructed atom parser to consume True and False try (parens (constructedAtomExprP True)) <|> constructedAtomExprP consume <|> relationalAtomExprP <|> @@ -255,14 +256,18 @@ doubleAtomP = DoubleAtom <$> float integerAtomP :: Parser Atom integerAtomP = IntegerAtom <$> integer +boolP :: Parser Bool +boolP = + (chunk "True" >> spaceConsumer >> pure True) <|> + (chunk "False" >> spaceConsumer >> pure False) + boolAtomP :: Parser Atom -boolAtomP = do - v <- identifier - if v == "True" || v == "False" then - pure $ BoolAtom (v == "t") - else - fail "invalid boolAtom" - +boolAtomP = + BoolAtom <$> boolP + +boolAtomExprP :: Parser (AtomExprBase a) +boolAtomExprP = + NakedAtomExpr <$> boolAtomP relationAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a) relationAtomExprP = RelationAtomExpr <$> makeRelationP diff --git a/src/bin/TutorialD/Interpreter/Types.hs b/src/bin/TutorialD/Interpreter/Types.hs index 7d3370e6..50378d1f 100644 --- a/src/bin/TutorialD/Interpreter/Types.hs +++ b/src/bin/TutorialD/Interpreter/Types.hs @@ -4,6 +4,7 @@ import ProjectM36.Base import ProjectM36.Interpreter import Text.Megaparsec import TutorialD.Interpreter.Base +import Control.Monad class RelationalMarkerExpr a where parseMarkerP :: Parser a @@ -15,7 +16,10 @@ typeConstructorNameP :: Parser TypeConstructorName typeConstructorNameP = capitalizedIdentifier dataConstructorNameP :: Parser DataConstructorName -dataConstructorNameP = capitalizedIdentifier +dataConstructorNameP = try $ do + ident <- capitalizedIdentifier + when (ident `elem` ["True", "False"]) $ failure Nothing mempty --don't parse True or False as ConstructedAtoms (use NakedAtoms instead) + pure ident attributeNameP :: Parser AttributeName attributeNameP = try uncapitalizedIdentifier <|> quotedIdentifier diff --git a/src/lib/ProjectM36/SQL/Convert.hs b/src/lib/ProjectM36/SQL/Convert.hs index b34c9d10..ade78115 100644 --- a/src/lib/ProjectM36/SQL/Convert.hs +++ b/src/lib/ProjectM36/SQL/Convert.hs @@ -835,8 +835,10 @@ convertScalarExpr typeF expr = do IntegerLiteral i -> naked (IntegerAtom i) DoubleLiteral d -> naked (DoubleAtom d) StringLiteral s -> naked (TextAtom s) - BooleanLiteral True -> pure $ ConstructedAtomExpr "True" [] () - BooleanLiteral False -> pure $ ConstructedAtomExpr "False" [] () + BooleanLiteral True -> naked (BoolAtom True) + -- pure $ ConstructedAtomExpr "True" [] () + BooleanLiteral False -> naked (BoolAtom False) + --pure $ ConstructedAtomExpr "False" [] () -- we don't have enough type context with a cast, so we default to text NullLiteral -> pure $ ConstructedAtomExpr "SQLNull" [] () Identifier i -> do @@ -859,8 +861,12 @@ convertProjectionScalarExpr typeF expr = do IntegerLiteral i -> naked (IntegerAtom i) DoubleLiteral d -> naked (DoubleAtom d) StringLiteral s -> naked (TextAtom s) - BooleanLiteral True -> pure $ ConstructedAtomExpr "True" [] () - BooleanLiteral False -> pure $ ConstructedAtomExpr "False" [] () + BooleanLiteral True -> + naked (BoolAtom True) + --pure $ ConstructedAtomExpr "True" [] () + BooleanLiteral False -> + naked (BoolAtom False) + --pure $ ConstructedAtomExpr "False" [] () NullLiteral -> pure $ ConstructedAtomExpr "SQLNull" [] () Identifier i -> AttributeAtomExpr <$> convertColumnProjectionName i @@ -1052,7 +1058,8 @@ joinTableRef typeF rvA (_c,tref) = do new_name joinName = firstAvailableName (1::Int) allAttrs extender = AttributeExtendTupleExpr joinName (FunctionAtomExpr "sql_coalesce_bool" [joinRe] ()) - joinMatchRestriction = Restrict (AttributeEqualityPredicate joinName (ConstructedAtomExpr "True" [] ())) + --joinMatchRestriction = Restrict (AttributeEqualityPredicate joinName (ConstructedAtomExpr "True" [] ())) + joinMatchRestriction = Restrict (AttributeEqualityPredicate joinName (NakedAtomExpr (BoolAtom True))) projectAwayJoinMatch = Project (InvertedAttributeNames (S.fromList [joinName])) pure (projectAwayJoinMatch (joinMatchRestriction (Extend extender (Join exprB exprA)))) other -> throwSQLE $ NotSupportedError ("join: " <> T.pack (show other)) diff --git a/test/SQL/InterpreterTest.hs b/test/SQL/InterpreterTest.hs index ceb2aae0..2fd62854 100644 --- a/test/SQL/InterpreterTest.hs +++ b/test/SQL/InterpreterTest.hs @@ -165,6 +165,9 @@ testSelect = TestCase $ do "(((s group ({all but } as `_sql_aggregate`)):{status:=sql_max( (@`_sql_aggregate`){ status } )}){ status })", "(relation{status SQLNullable Integer}{tuple{status SQLJust 30}})"), -- group by having + ("select city,max(status) as status from s group by city having max(status)=30", + "((((s group ({all but city} as `_sql_aggregate`)):{status:=sql_max( (@`_sql_aggregate`){ status } ), `_sql_having`:=sql_coalesce_bool( sql_equals( sql_max( (@`_sql_aggregate`){ status } ), 30 ) )}){ city, status }) where `_sql_having`=True)", + "(relation{city Text,status SQLNullable Integer}{tuple{city \"Athens\",status SQLJust 30},tuple{city \"Paris\",status SQLJust 30}})"), -- limit -- case when -- union diff --git a/test/TransactionGraph/Automerge.hs b/test/TransactionGraph/Automerge.hs index d2d71031..404f5d24 100644 --- a/test/TransactionGraph/Automerge.hs +++ b/test/TransactionGraph/Automerge.hs @@ -1,7 +1,5 @@ import Test.HUnit import ProjectM36.Client -import ProjectM36.Interpreter -import ProjectM36.DatabaseContext import ProjectM36.Relation import qualified Data.Set as S import TutorialD.Interpreter.TestBase diff --git a/test/TutorialD/Interpreter/TestBase.hs b/test/TutorialD/Interpreter/TestBase.hs index 5a70a4e2..79933b8c 100644 --- a/test/TutorialD/Interpreter/TestBase.hs +++ b/test/TutorialD/Interpreter/TestBase.hs @@ -2,7 +2,6 @@ module TutorialD.Interpreter.TestBase where import ProjectM36.Client import ProjectM36.Interpreter import TutorialD.Interpreter -import TutorialD.Interpreter.Base import ProjectM36.DateExamples import ProjectM36.DatabaseContext import Test.HUnit diff --git a/test/TutorialD/PrinterTest.hs b/test/TutorialD/PrinterTest.hs index becc5c26..4e7fccfe 100644 --- a/test/TutorialD/PrinterTest.hs +++ b/test/TutorialD/PrinterTest.hs @@ -16,7 +16,7 @@ testList = TestList [ testPretty "true:{a:=1, b:=1}" (Extend (AttributeExtendTupleExpr "b" (NakedAtomExpr (IntegerAtom 1))) (Extend (AttributeExtendTupleExpr "a" (NakedAtomExpr (IntegerAtom 1))) (RelationVariable "true" ()))), testPretty "relation{tuple{a fromGregorian(2014, 2, 4)}}" (MakeRelationFromExprs Nothing (TupleExprs () [TupleExpr (fromList [("a",FunctionAtomExpr "fromGregorian" [NakedAtomExpr (IntegerAtom 2014),NakedAtomExpr (IntegerAtom 2),NakedAtomExpr (IntegerAtom 4)] ())])])), testPretty "relation{tuple{a bytestring(\"dGVzdGRhdGE=\")}}" (MakeRelationFromExprs Nothing (TupleExprs () [TupleExpr (fromList [("a",FunctionAtomExpr "bytestring" [NakedAtomExpr (TextAtom "dGVzdGRhdGE=")] ())])])), - testPretty "relation{tuple{a True}}" (MakeRelationFromExprs Nothing (TupleExprs () [TupleExpr (fromList [("a",ConstructedAtomExpr "True" [] ())])])), + testPretty "relation{tuple{a True}}" (MakeRelationFromExprs Nothing (TupleExprs () [TupleExpr (fromList [("a",NakedAtomExpr (BoolAtom True))])])), testPretty "relation{tuple{a Cons 4 (Cons 5 Empty)}}" (MakeRelationFromExprs Nothing (TupleExprs () [TupleExpr (fromList [("a",ConstructedAtomExpr "Cons" [NakedAtomExpr (IntegerAtom 4),ConstructedAtomExpr "Cons" [NakedAtomExpr (IntegerAtom 5),ConstructedAtomExpr "Empty" [] ()] ()] ())])])), testPretty "relation{a Int, b Text, c Bool}{}" (MakeRelationFromExprs (Just [AttributeAndTypeNameExpr "a" (ADTypeConstructor "Int" []) (),AttributeAndTypeNameExpr "b" (ADTypeConstructor "Text" []) (),AttributeAndTypeNameExpr "c" (ADTypeConstructor "Bool" []) ()]) (TupleExprs () [])), testPretty "relation{a relation{b Int}}{}" (MakeRelationFromExprs (Just [AttributeAndTypeNameExpr "a" (RelationAtomTypeConstructor [AttributeAndTypeNameExpr "b" (ADTypeConstructor "Int" []) ()]) ()]) (TupleExprs () []))