Skip to content

Conversation

@mlell
Copy link

@mlell mlell commented Nov 13, 2025

There were two matching operators:

  • subject ~ pattern (case-insensitive)
  • pattern ?~ subject (case-sensitive)

This is somewhat confusing for newcomers. The reason maybe is that it allows for this:

SELECT * WHERE "Assets:" ?~ ANY(accounts)

which is used for example by the function has_account by AST transformation. The ANY operator so far was only allowed on the RHS, therefore ~ could not be used for the above example. This commit extends it, so it can be used on either side, allowing for

SELECT WHERE ANY(accounts) ~ "Assets:"

Tests pass, also subqueries within any() are still possible!

Moreover, this Pull request solves the issue that some columns are @registered for the type typing.Set[str] but some functions/operators are registered for set, which did not match. They do now, making functions more flexibly applicable

Allow functions/operators registered with unparameterized types (e.g., set)
to match operands with parameterized generic types (e.g., typing.Set[str]).
There were two matching operators:

* subject ~ pattern   (case-insensitive)
* pattern ?~ subject  (case-sensitive)

This is somewhat confusing, but allows for this:

SELECT * WHERE "Assets:" ?~ ANY(accounts)

The ANY operator was only allowed on the RHS. This commit
extends it, so it can be used on either side, allowing for

SELECT WHERE ANY(accounts) ~ "Assets:"
@dnicolodi
Copy link
Collaborator

Thanks for the contribution. However, AFAIK in SQL ANY and ALL can only be on the right hand side of an operator. Do you know of any SQL dialect that allows them on the left hand side?

@mlell
Copy link
Author

mlell commented Nov 14, 2025

Hello, thanks for taking a look on it! No, I am not aware of any SQL dialect which allows this. However, I was not able to find the reasons for it. People instead use subqueries, so they write, e.g. in PostgreSQL

SELECT * FROM book where   EXISTS ( SELECT * from unnest(author) as X where x ~* '^p' )  

instead of the more intutitive (but non-syntactical)

SELECT  ANY(authors) ~* '^p' FROM book;

I for myself are not yet super experienced with SQL, and we certainly agree that beanquery should not be limited to SQL engineers who would notice such a thing. Moreover, BQL does deviate from SQL at times, with the motivation to make it easier to write queries. For example with the semantics of FROM are completely different and the PIVOT BY operator which also exists nowhere else (there is PIVOT BY in some dialects, however with a completely different syntax). Also, no other SQL dialect has an additional matching operator like ?~ to resolve the ANY<->regex matching problem (even if some people define their own), but still in beanquery it exists, presumably to make life easier for the user. So I allowing an inverted form of ANY seems like a minor deviation in comparison.

I have the intuition that x op ANY( .. ) should be equal to ANY(...) inverse_op x, and I suspect many non-SQL-engineers will have this, too, coming from conventions in math notation. Yes, technically this is a 3-argument operator and not a binary operator with a nested function call, but the notation is deliberately chosen to resemble that math notation or maybe spoken language, so I think it should also be consistent in following those conventions. I have implemented this because I feel that writing BQL queries sometimes means wrestling with the language because of some (to me) unintuitive corner cases, instead of getting work done and getting an overview over my transactions.

I have not found any reason for this design decision in SQLs. For me, this change reduces the mental load of writing BQL queries and makes it more pleasant to use, so I thought I would turn the newbies' frustration into something productive and propose this change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants