From 4a74c34ce51ad223a1ecdb3ba38b0d109f93039d Mon Sep 17 00:00:00 2001 From: belevy Date: Wed, 31 Aug 2022 11:11:25 -0500 Subject: [PATCH 1/3] Revert change to ToAlias that caused issues with subqueries selecting references. Change union behavior to reuse value aliases within the union itself. --- .../Experimental/From/SqlSetOperation.hs | 4 ++-- .../Esqueleto/Experimental/ToAlias.hs | 24 ++++++++++++------- test/PostgreSQL/Test.hs | 13 ++++++---- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/Database/Esqueleto/Experimental/From/SqlSetOperation.hs b/src/Database/Esqueleto/Experimental/From/SqlSetOperation.hs index 1f7b849a0..c4e9145a2 100644 --- a/src/Database/Esqueleto/Experimental/From/SqlSetOperation.hs +++ b/src/Database/Esqueleto/Experimental/From/SqlSetOperation.hs @@ -50,9 +50,7 @@ instance (SqlSelect a r, ToAlias a, ToAliasReference a) => ToSqlSetOperation (Sq toSqlSetOperation subquery = SqlSetOperation $ \p -> do (ret, sideData) <- Q $ W.censor (\_ -> mempty) $ W.listen $ unQ subquery - state <- Q $ lift S.get aliasedValue <- toAlias ret - Q $ lift $ S.put state let aliasedQuery = Q $ W.WriterT $ pure (aliasedValue, sideData) let p' = case p of @@ -70,7 +68,9 @@ instance (SqlSelect a r, ToAlias a, ToAliasReference a) => ToSqlSetOperation (Sq mkSetOperation :: (ToSqlSetOperation a a', ToSqlSetOperation b a') => TLB.Builder -> a -> b -> SqlSetOperation a' mkSetOperation operation lhs rhs = SqlSetOperation $ \p -> do + state <- Q $ lift S.get (leftValue, leftClause) <- unSqlSetOperation (toSqlSetOperation lhs) p + Q $ lift $ S.put state (_, rightClause) <- unSqlSetOperation (toSqlSetOperation rhs) p pure (leftValue, \info -> leftClause info <> (operation, mempty) <> rightClause info) diff --git a/src/Database/Esqueleto/Experimental/ToAlias.hs b/src/Database/Esqueleto/Experimental/ToAlias.hs index d8828344f..b6ab99193 100644 --- a/src/Database/Esqueleto/Experimental/ToAlias.hs +++ b/src/Database/Esqueleto/Experimental/ToAlias.hs @@ -16,20 +16,26 @@ class ToAlias a where toAlias :: a -> SqlQuery a instance ToAlias (SqlExpr (Value a)) where - toAlias (ERaw m f) = do - ident <- newIdentFor (DBName "v") - pure $ ERaw m{sqlExprMetaIsReference = False, sqlExprMetaAlias = Just ident} f + toAlias e@(ERaw m f) + | Just _ <- sqlExprMetaAlias m = pure e + | otherwise = do + ident <- newIdentFor (DBName "v") + pure $ ERaw noMeta{sqlExprMetaAlias = Just ident} f instance ToAlias (SqlExpr (Entity a)) where - toAlias (ERaw m f) = do - ident <- newIdentFor (DBName "v") - pure $ ERaw m{sqlExprMetaIsReference = False, sqlExprMetaAlias = Just ident} f + toAlias e@(ERaw m f) + | Just _ <- sqlExprMetaAlias m = pure e + | otherwise = do + ident <- newIdentFor (DBName "v") + pure $ ERaw m{sqlExprMetaIsReference = False, sqlExprMetaAlias = Just ident} f instance ToAlias (SqlExpr (Maybe (Entity a))) where -- FIXME: Code duplication because the compiler doesnt like half final encoding - toAlias (ERaw m f) = do - ident <- newIdentFor (DBName "v") - pure $ ERaw m{sqlExprMetaIsReference = False, sqlExprMetaAlias = Just ident} f + toAlias e@(ERaw m f) + | Just _ <- sqlExprMetaAlias m = pure e + | otherwise = do + ident <- newIdentFor (DBName "v") + pure $ ERaw m{sqlExprMetaIsReference = False, sqlExprMetaAlias = Just ident} f instance (ToAlias a, ToAlias b) => ToAlias (a,b) where toAlias (a,b) = (,) <$> toAlias a <*> toAlias b diff --git a/test/PostgreSQL/Test.hs b/test/PostgreSQL/Test.hs index 79411cd76..26793aff1 100644 --- a/test/PostgreSQL/Test.hs +++ b/test/PostgreSQL/Test.hs @@ -1318,9 +1318,14 @@ testValuesExpression = do , (Value 2, Value "str2", Value $ Just 2.5) , (Value 3, Value "str3", Value Nothing) ] -testSubselectUnionError :: SpecDb -testSubselectUnionError = do - describe "Subselect union error" $ do +testSubselectAliasingBehavior :: SpecDb +testSubselectAliasingBehavior = focus $ do + describe "Aliasing behavior" $ do + itDb "correctly realiases entities accross multiple subselects" $ do + _ <- select $ do + Experimental.from $ Experimental.from $ Experimental.from $ table @Lord + asserting noExceptions + itDb "doesnt erroneously repeat variable names when using subselect + union" $ do let lordQuery = do l <- Experimental.from $ table @Lord @@ -1428,7 +1433,7 @@ spec = beforeAll mkConnectionPool $ do testJSONOperators testLateralQuery testValuesExpression - testSubselectUnionError + testSubselectAliasingBehavior insertJsonValues :: SqlPersistT IO () insertJsonValues = do From 9294bac739555abae84336042ca55e36a8e7bbb1 Mon Sep 17 00:00:00 2001 From: Matt Parsons Date: Wed, 31 Aug 2022 10:20:35 -0600 Subject: [PATCH 2/3] Update test/PostgreSQL/Test.hs --- test/PostgreSQL/Test.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/PostgreSQL/Test.hs b/test/PostgreSQL/Test.hs index 26793aff1..e239f0ea8 100644 --- a/test/PostgreSQL/Test.hs +++ b/test/PostgreSQL/Test.hs @@ -1319,7 +1319,7 @@ testValuesExpression = do , (Value 3, Value "str3", Value Nothing) ] testSubselectAliasingBehavior :: SpecDb -testSubselectAliasingBehavior = focus $ do +testSubselectAliasingBehavior = do describe "Aliasing behavior" $ do itDb "correctly realiases entities accross multiple subselects" $ do _ <- select $ do From 363bfe102c18f172fcb81c6594787a9a143df805 Mon Sep 17 00:00:00 2001 From: belevy Date: Wed, 31 Aug 2022 11:24:15 -0500 Subject: [PATCH 3/3] Added cabal and changelog. Unfocus tests --- changelog.md | 7 +++++++ esqueleto.cabal | 2 +- test/PostgreSQL/Test.hs | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 46a7f18a5..54b920bdf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,10 @@ +3.5.8.1 +======= +- @belevy + - [#336](https://github.com/bitemyapp/esqueleto/pull/336) + - Fix bug with multiple nested subqueries introduced in 3.5.7.1 + - Set operations will now only reuse variable names within the context of the set operation. + a subquery that references the set operation will correctly pick up where the subquery left off 3.5.8.0 ======= - @ivanbakel diff --git a/esqueleto.cabal b/esqueleto.cabal index 38fc28315..8cae86d18 100644 --- a/esqueleto.cabal +++ b/esqueleto.cabal @@ -2,7 +2,7 @@ cabal-version: 1.12 name: esqueleto -version: 3.5.8.0 +version: 3.5.8.1 synopsis: Type-safe EDSL for SQL queries on persistent backends. description: @esqueleto@ is a bare bones, type-safe EDSL for SQL queries that works with unmodified @persistent@ SQL backends. Its language closely resembles SQL, so you don't have to learn new concepts, just new syntax, and it's fairly easy to predict the generated SQL and optimize it for your backend. Most kinds of errors committed when writing SQL are caught as compile-time errors---although it is possible to write type-checked @esqueleto@ queries that fail at runtime. . diff --git a/test/PostgreSQL/Test.hs b/test/PostgreSQL/Test.hs index 26793aff1..e239f0ea8 100644 --- a/test/PostgreSQL/Test.hs +++ b/test/PostgreSQL/Test.hs @@ -1319,7 +1319,7 @@ testValuesExpression = do , (Value 3, Value "str3", Value Nothing) ] testSubselectAliasingBehavior :: SpecDb -testSubselectAliasingBehavior = focus $ do +testSubselectAliasingBehavior = do describe "Aliasing behavior" $ do itDb "correctly realiases entities accross multiple subselects" $ do _ <- select $ do