On Thu, Apr 19, 2018 at 5:21 AM, Антонио Антуан <a.ch....@gmail.com> wrote:
> Hi guys.
>
> Is there any mechanism in SQLAlchemy which allows to redefine operator
> compilation? I want to the same thing as already exists for functions.
> An example for functions:
>
>
> class IntDiv(GenericFunction):
>  type = Integer
>  package = 'adc_custom'
>  name = 'div'
>  identifier = 'div'
>
>
> @compiles(IntDiv)
> def visit_div_default(element, compiler, **kwargs):
>  params = [compiler.process(c.self_group()) for c in
> element.clause_expr.element.get_children()]
>  return '%s / %s' % (params[0], params[1])
>
>
> @compiles(IntDiv, 'clickhouse')
> def visit_div_ch(element, compiler, **kwargs):
>  return 'intDiv(%s)' % compiler.process(element.clause_expr.element)
>
> What I want to do:
>
> class BitAdd(CustomOp):
>  pass
>
> @compiles(BitAdd)
> def visit_bit_add_default(element, compiler, **kwargs):
>  return '%s & %s' % (element.left, element.right)
>
>
> @compiles(IntDiv, 'clickhouse')
> def visit_bit_add_ch(element, compiler, **kwargs):
>  return 'bitAnd(%s, %s)' % (element.left, element.right)
>
> Statement looks like that:
> some_col.op('&')(some_int_flag)
>
>
> I understand that I can define generic function and use it instead of
> `.op('&')`, but at first I want to find another way.

So in this case you are looking to override the compilation for
BinaryElement in any case since you want to run a function around them
in one case, that is the whole left/operator/right object.

from sqlalchemy.sql.expression import BinaryExpression
@compiles(BinaryExpression, "clickhouse")
def visit_binary(element, compiler, **kw):
    if isinstance(element.operator, BitAdd):
        return "bitAnd(%s, %s)" % (compiler.process(element.left,
**kw), compiler.process(element.right, **kw))
    else:
        return compiler.visit_binary(element, **kw)

For the part where you want op('&') to be magic, it can't work that
way, though you can get at the '&' operator directly but you normally
need to use a subclass of Integer:

http://docs.sqlalchemy.org/en/latest/core/custom_types.html#redefining-and-creating-new-operators

so here you'd be saying:

from sqlalchemy import Integer

class MyInt(Integer):
    class comparator_factory(Integer.Comparator):
        def __and__(self, other):
            return BitAnd()(self.expr, other)

then you'd use the MyInt datatype in your mappings where you want your
special operator to take place.

If you want the base Integer to do this, you'd need to monkeypatch the
comparator, this is less recommended as it can cause surprises:


class comparator_factory_mixin(object):
    def __and__(self, other):
        return BitAnd()(self.expr, other)

Integer.Comparator.__bases__ = (comparator_factory_mixin, ) +
Integer.Comparator.__bases__





> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to