0

stackingers!

I'm trying to deepen my python knowledge and found the code below:

from sqlalchemy import or_
filter(or_(User.name == 'ed', User.name == 'wendy'))

While trying to figure out what happens inside the or_(...), I found this case case that looks related.

My question is how the operator is passed without the compiler solving the equation. In the example above, the operator sends it as a string. However, sqlalchemy uses it in a 'raw' form.

brunoto
  • 91
  • 9
  • 2
    `x == y` returns whatever `type(x).__eq__` is defined to return, which isn't necessarily a `bool`. In this case, it's an object that represents a query. – chepner Oct 18 '19 at 20:58
  • 1
    SQLalchemy overwrites many operator like `==` to return special objects instead of just a boolen value. These objects are then used to construct a query. – Klaus D. Oct 18 '19 at 21:02

1 Answers1

1

Basically under the hood it is overriding the default implementation of __eq__ and mapping the table/row names into a SQL friendly string format that can be a part of a bigger query.

You can refer to How is __eq__ handled in Python and in what order? which has some other great answers to help understand more what’s going on here.

Without delving into the source code (and possibly making it more confusing, if not the links are below) I made a mock-up class to demonstrate the basic premise behind what it’s doing and that it can easily done with other classes as well. (Please take this as only an example and nothing close to what it exactly does just a simple example)

class CustomProperty:
    """Serves as a mock property for a User object"""

    def __init__(self, table, name, value):
        self.table = table
        self.name = name
        self.value = value

    #below is essentially the magic here
    def __eq__(self, other):
        return f"{self.table.__class__.__name__}.{self.name} == {other}"

class User:
    """Just a simple User class for example sake"""
    def __init__(self, *args, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, CustomProperty(self, k, v))


#Here’s a basic example of what the `or_` method does.
def or_(*conditions):
    return ' OR '.join(conditions)

user = User(name=str)

print(or_(user.name == 'bob', user.name == 'sally'))

This prints:

'User.name == bob OR User.name == sally'

Hopefully this helps break it down to what you were asking.

Edit

If you want to know where in the source code these methods can be found to trace out how it’s actually done by sqlalchemy refer to these links:

or_() - sqlalchemy.sql.expression.or_

__eq__ - sqlalchemy.sql.operators.ColumnOperators.eq

Jab
  • 26,853
  • 21
  • 75
  • 114