-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with aliasing expression for "a depth-first" query using Esqueleto's "withRecursive" #388
Comments
Is |
I tried this too with the same RUNTIME error (compiles without problems):
I'm trying to do something like what is described in 3.4. Controlling Depth-First Versus Breadth-First Search Of a Tree Using ORDER BY:
Maybe there is a way to order by column position? I didn't find anything about this. |
Right so it looks like in order to use an expression like v+1 in an order by you need to wrap that in parentheses. That seems to be not specific to how recursive CTEs work. That said sorting by a value |
If I may, how to wrap the expression in parentheses? This clearly doesn't work:)
|
Please read my entire reply. The error you are experiencing is more general than just recursive CTEs and would require a more general fix. However, you don't actually need to sort on your |
It does not work for:
Error:
Generated SQL:
|
You could probably just Ultimately the bug that needs fixing is to properly parenthesize expressions in order by clauses. As an aside, the whole order of the rows popping off the work queue thing is super low level and not all that intuitive to me(but I don't really use recursive CTEs all that much). I would personally prefer to keep IDs to reference who my parent is rather than relying on the order of the results to build a tree like that. |
Unfortunately this doesn't work either:
Error:
Generated query:
|
I think the work-around for this is to use sqliteOrderByColumnIndex
:: Int
-> (forall a. SqlExpr (Value a) -> SqlExpr OrderBy)
-> SqlExpr OrderBy
sqliteOrderByColumnIndex i ascOrDesc =
ascOrDesc
( unsafeSqlValue
$ Data.Text.Lazy.Builder.Int.decimal i
:: SqlExpr (Value Int)
) Then you'd write I tried to write a minimal test reproduction, assuming the issue was itDb "works with an expression" $ do
let p1 = Point 1 2 "Hello"
p2 = Point 2 1 "Goodbye"
p1k <- insert p1
p2k <- insert p2
entityPoints <-
select $ do
p <- Experimental.from table
orderBy [asc (p ^. PointX +. val 1)]
pure p
asserting $ do
fmap entityKey entityPoints
`shouldBe`
[p1k, p2k] If I implement a test for the behavior above, I get failures on all three backends:
If I look at the generated query more carefully, I see this: WITH RECURSIVE cte AS (
SELECT ? as v, SignTag.id AS v2_id, SignTag.group AS v2_group
FROM SignTag
WHERE SignTag.group IS NOTHING
UNION ALL
SELECT (cte.v + ?), SignTag2.id, SignTag2.group
FROM cte INNER JOIN SignTag as SignTag2 ON cte.v2_id = SignTag2.group
ORDER BY cte.v + ? DESC)
SELECT cte.v, cte.v2_id, cte.v2_group The second If we use a literal describe "withRecursive" $ do
describe "depth first search" $ do
itDb "works" $ do
tags <- select $ do
cte <- withRecursive
(do
x <- from $ table @SignTag
where_ $ isNothing_ $ x ^. SignTagGroup
let level = val (0 :: Int)
return (level,x)
)
unionAll_
(\parent -> do
(l,_) :& x <- from $ parent
`innerJoin` table @SignTag `on` (\((_, p) :& x) -> just (p ^. SignTagId) ==. x ^. SignTagGroup)
let level = l +. literalInt 1
orderBy [desc level] -- ^ Here is the issue, I think
return (level,x)
)
from cte
asserting $ do
tags `shouldBe` []
literalInt :: Int -> SqlExpr (Value Int)
literalInt = unsafeSqlValue . TLBI.decimal This passes on SQLite tests, but still fails on MySQL and Postgres. Likewise, using describe "withRecursive" $ do
describe "depth first search" $ do
itDb "works" $ do
tags <- select $ do
cte <- withRecursive
(do
x <- from $ table @SignTag
where_ $ isNothing_ $ x ^. SignTagGroup
let level = val (0 :: Int)
return (level,x)
)
unionAll_
(\parent -> do
(l,_) :& x <- from $ parent
`innerJoin` table @SignTag `on` (\((_, p) :& x) -> just (p ^. SignTagId) ==. x ^. SignTagGroup)
let level = l +. val 1
orderBy [desc (literalInt 1)] -- ^ Here is the issue, I think
return (level,x)
)
from cte
asserting $ do
tags `shouldBe` []
literalInt :: Int -> SqlExpr (Value Int)
literalInt = unsafeSqlValue . TLBI.decimal I think the fix is to add a function to the |
I'm trying to run the following query with a recursive common table expressions using Esqueleto's
withRecursive
but received an unexpected error at runtime.Is there a way to fix this?
Runtime error:
The generated query is:
with 0 and 1 as arguments.
The text was updated successfully, but these errors were encountered: