Skip to content
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

It is very non-obvious how to apply limit/offset/order conditionally #491

Open
neongreen opened this issue Jul 7, 2020 · 7 comments · May be fixed by #633
Open

It is very non-obvious how to apply limit/offset/order conditionally #491

neongreen opened this issue Jul 7, 2020 · 7 comments · May be fixed by #633

Comments

@neongreen
Copy link
Contributor

neongreen commented Jul 7, 2020

I want to apply limit_ conditionally, like this:

select_ $
  if limitNeeded then limit_ 10 else id $
  all_ someTable

This fails with cannot construct the infinite type: s ~ QNested s. I get that limit_ changes the type and id doesn't, but I can't figure out what I can use instead of id. I thought subselect_ could work, but I'm getting ugly nested queries when limitNeeded is false:

SELECT `t0`.`res0` AS `res0`, `t0`.`res1` AS `res1` FROM
  (SELECT `t0`.`email` AS `res0`, `t0`.`enabled` AS `res1` FROM `table` AS `t0`)

Any advice?

@neongreen
Copy link
Contributor Author

neongreen commented Jul 7, 2020

I can use unnest instead of id, but this seems risky:

unnest ::
  Q MySQL db (QNested s) (table (QExpr MySQL (QNested s))) ->
  Q MySQL db s (table (QExpr MySQL s))
unnest = unsafeCoerce

@neongreen
Copy link
Contributor Author

neongreen commented Jul 7, 2020

Oh okay, polymorphism saves the day! As long as I'm taking something that is forall s., I'm good.

  let applyLimit ::
        (forall s. Q MySQL db s (table (QExpr MySQL s))) ->
        (forall s. Q MySQL db s (table (QExpr MySQL s)))
      applyLimit x = case mbLimit of
        Nothing -> x
        Just n -> limit_ (toInteger n) x

It's important not to use maybe or fromMaybe here though.

@3noch
Copy link
Contributor

3noch commented Jul 7, 2020

Yuck. We should document this...

@3noch
Copy link
Contributor

3noch commented Jul 7, 2020

Thanks for reporting.

@3noch
Copy link
Contributor

3noch commented Jul 7, 2020

Maybe it really is worth having a noLimit_ function just to make this discoverable.

@neongreen neongreen reopened this Jul 7, 2020
@neongreen
Copy link
Contributor Author

I'll reopen then.

@neongreen neongreen changed the title How to apply limit/offset/order conditionally? It is very unobvious how to apply limit/offset/order conditionally Jul 7, 2020
@neongreen neongreen changed the title It is very unobvious how to apply limit/offset/order conditionally It is very non-obvious how to apply limit/offset/order conditionally Jul 7, 2020
@thomasjm
Copy link
Contributor

thomasjm commented Jan 9, 2021

Is there a way to write the applyLimit workaround above so that it works on an arbitrary return value? (I.e. not just some kind of table.) I'm having trouble writing such a function due to the QNested s stuff in limit_'s signature.

I'd be happy to open a PR for a noLimit_ if someone could give hints on how it would be implemented.

@thomasjm thomasjm linked a pull request Feb 18, 2022 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants