Skip to content

Commit

Permalink
Fixed null handling in DataSync 'field IN (null)' queries
Browse files Browse the repository at this point in the history
  • Loading branch information
mpscholten committed Nov 16, 2022
1 parent 5e6851c commit 395c717
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
5 changes: 5 additions & 0 deletions IHP/DataSync/DynamicQueryCompiler.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions Test/DataSync/DynamicQueryCompiler.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 395c717

Please sign in to comment.