diff --git a/IHP/DataSync/DynamicQueryCompiler.hs b/IHP/DataSync/DynamicQueryCompiler.hs index a26259c0c..d6435be8d 100644 --- a/IHP/DataSync/DynamicQueryCompiler.hs +++ b/IHP/DataSync/DynamicQueryCompiler.hs @@ -85,6 +85,11 @@ compileCondition :: ConditionExpression -> (PG.Query, [PG.Action]) compileCondition (ColumnExpression column) = ("?", [PG.toField $ PG.Identifier (fieldNameToColumnName column)]) compileCondition (InfixOperatorExpression a OpEqual (LiteralExpression Null)) = compileCondition (InfixOperatorExpression a OpIs (LiteralExpression Null)) -- Turn 'a = NULL' into 'a IS NULL' compileCondition (InfixOperatorExpression a OpNotEqual (LiteralExpression Null)) = compileCondition (InfixOperatorExpression a OpIsNot (LiteralExpression Null)) -- Turn 'a <> NULL' into 'a IS NOT NULL' +compileCondition (InfixOperatorExpression a OpIn (ListExpression { values })) | (Null `List.elem` values) = + -- Turn 'a IN (NULL)' into 'a IS NULL' + case partition ((/=) Null) values of + ([], nullValues) -> compileCondition (InfixOperatorExpression a OpIs (LiteralExpression Null)) + (nonNullValues, nullValues) -> compileCondition (InfixOperatorExpression (InfixOperatorExpression a OpIn (ListExpression { values = nonNullValues })) OpOr (InfixOperatorExpression a OpIs (LiteralExpression Null))) compileCondition (InfixOperatorExpression a operator b) = ("(" <> queryA <> ") " <> compileOperator operator <> " " <> rightOperand, paramsA <> paramsB) where (queryA, paramsA) = compileCondition a diff --git a/Test/DataSync/DynamicQueryCompiler.hs b/Test/DataSync/DynamicQueryCompiler.hs index b2a02f5d0..b0669406f 100644 --- a/Test/DataSync/DynamicQueryCompiler.hs +++ b/Test/DataSync/DynamicQueryCompiler.hs @@ -175,6 +175,37 @@ tests = do ( "SELECT ? FROM ? WHERE (?) IS NOT ?" , [PG.Plain "*", PG.EscapeIdentifier "posts", PG.EscapeIdentifier "user_id", PG.Plain "null"] ) + + it "compile 'field IN (NULL)' conditions to 'field IS NULL'" do + let query = DynamicSQLQuery + { table = "posts" + , selectedColumns = SelectAll + , whereCondition = Just $ InfixOperatorExpression (ColumnExpression "a") OpIn (ListExpression { values = [Null] }) + , orderByClause = [] + , distinctOnColumn = Nothing + , limit = Nothing + , offset = Nothing + } + + compileQuery query `shouldBe` + ( "SELECT ? FROM ? WHERE (?) IS ?" + , [PG.Plain "*", PG.EscapeIdentifier "posts", PG.EscapeIdentifier "a", PG.Plain "null"] + ) + it "compile 'field IN (NULL, 'string')' conditions to 'field IS NULL OR field IN ('string')'" do + let query = DynamicSQLQuery + { table = "posts" + , selectedColumns = SelectAll + , whereCondition = Just $ InfixOperatorExpression (ColumnExpression "a") OpIn (ListExpression { values = [Null, TextValue "test" ] }) + , orderByClause = [] + , distinctOnColumn = Nothing + , limit = Nothing + , offset = Nothing + } + + compileQuery query `shouldBe` + ( "SELECT ? FROM ? WHERE ((?) IN ?) OR ((?) IS ?)" + , [PG.Plain "*", PG.EscapeIdentifier "posts", PG.EscapeIdentifier "a", PG.Many [PG.Plain "(", PG.Escape "test", PG.Plain ")"], PG.EscapeIdentifier "a", PG.Plain "null"] + ) it "compile queries with TS expressions" do let query = DynamicSQLQuery