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

Support for ANY in condition DSL #413

Open
wuarmin opened this issue Oct 12, 2022 · 5 comments
Open

Support for ANY in condition DSL #413

wuarmin opened this issue Oct 12, 2022 · 5 comments

Comments

@wuarmin
Copy link

wuarmin commented Oct 12, 2022

Describe the bug

Following code

filter_type_id = "test"
states
  .where { filter_type_ids.any(filter_type_id) | filter_type_ids.is(nil) }
  .order(:order)

produces following sql:

SELECT "states"."id", "states"."name", "states"."order", "states"."filter_type_ids"
FROM "states"
WHERE ("states"."filter_type_ids" IS NULL)
ORDER BY "order"

but the resulting sql should be following:

SELECT "states"."id", "states"."name", "states"."order", "states"."filter_type_ids"
FROM "states"
WHERE (('test' = ANY("states"."filter_type_ids")) OR ("states"."filter_type_ids" IS NULL))
ORDER BY "order"

If I change the order of the OR-condition

states
  .where { filter_type_ids.is(nil) | filter_type_ids.any(filter_type_id) }
  .order(:order)

it works.

My environment

  • Ruby version: 3.1.2
  • OS: ruby:3.1.2-slim-buster
@flash-gordon
Copy link
Member

I wouldn't say it's a bug because filter_type_ids is a fallback identifier from Sequel rather than a ROM attribute. You should use where { self[:filter_type_ids].is(...) | ... }

@wuarmin
Copy link
Author

wuarmin commented Oct 27, 2022

hello @flash-gordon ,
thanks, that explains the problem, but if I change the code to:

filter_type_id = "test"
states
  .where { self[:filter_type_ids].any(filter_type_id) | self[:filter_type_ids].is(nil) }
  .order(:order)

I get following error:

     Failure/Error:
       states
         .where { self[:filter_type_ids].any(filter_type_id) | self[:filter_type_ids].is(nil) }
         .order(:order).to_a
     
     NameError:
       wrong constant name []
     
               types.const_get(type_name) if types.const_defined?(type_name)

@flash-gordon
Copy link
Member

flash-gordon commented Oct 27, 2022

@wuarmin sorry for the confusion, I think the truth is in the middle: there's in, there's no any in rom-sql API, that's why it falls back to Sequel. You should use

.where { filter_type_ids.is(nil) | filter_type_ids.in(*filter_type_id) }

There's no difference between col in (1, 2, 3) and col = any(array[1, 2, 3]) as far as I know.

@wuarmin
Copy link
Author

wuarmin commented Oct 27, 2022

Yes, there's no difference, but I cannot write it that way:

.where { filter_type_ids.is(nil) | filter_type_ids.in(*filter_type_id) }

produces

OR ("states"."filter_type_ids" IN ARRAY['test']::text[])

which is invalid and not what I need, I need

('test' = ANY("states"."filter_type_ids"))

What about adding any to rom-sql API?

@flash-gordon
Copy link
Member

which is invalid and not what I need, I need

I'm just saying it should have no difference at the database level. You can use inline SQL with backticks:

where { `filter_type_ids is null or filter_type_ids = any(array([#{filter_type_id.map { "'#{_1}'" }.join(',') }]))`  }

A PR with adding ANY is welcome.

@flash-gordon flash-gordon changed the title OR-DSL is failing in a specific context Support for ANY in condition DSL Oct 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants