'Probe whether the row matches the query
@param resource: the resource to resolve the query against
@param row: the DB row
@param virtual: execute only virtual queries'

def __call__(self, resource, row, virtual=True):

    if (self.op == self.AND):
        l = self.left(resource, row, virtual=False)
        r = self.right(resource, row, virtual=False)
        if (l is None):
            return r
        if (r is None):
            return l
        return (l and r)
    elif (self.op == self.OR):
        l = self.left(resource, row, virtual=False)
        r = self.right(resource, row, virtual=False)
        if (l is None):
            return r
        if (r is None):
            return l
        return (l or r)
    elif (self.op == self.NOT):
        l = self.left(resource, row)
        if (l is None):
            return None
        else:
            return (not l)
    real = False
    left = self.left
    if isinstance(left, S3FieldSelector):
        try:
            lfield = left.resolve(resource)
        except (AttributeError, KeyError, SyntaxError):
            return None
        if (lfield.field is not None):
            real = True
        elif (not lfield.virtual):
            return None
    else:
        lfield = left
        if isinstance(left, Field):
            real = True
    right = self.right
    if isinstance(right, S3FieldSelector):
        try:
            rfield = right.resolve(resource)
        except (AttributeError, KeyError, SyntaxError):
            return None
        if rfield.virtual:
            real = False
        elif (rfield.field is None):
            return None
    else:
        rfield = right
    if (virtual and real):
        return None
    extract = (lambda f: S3FieldSelector.extract(resource, row, f))
    try:
        l = extract(lfield)
        r = extract(rfield)
    except (KeyError, SyntaxError):
        current.log.error(sys.exc_info()[1])
        return None
    if isinstance(left, S3FieldSelector):
        l = left.expr(l)
    if isinstance(right, S3FieldSelector):
        r = right.expr(r)
    op = self.op
    invert = False
    probe = self._probe
    if (isinstance(rfield, (list, tuple)) and (not isinstance(lfield, (list, tuple)))):
        if (op == self.EQ):
            op = self.BELONGS
        elif (op == self.NE):
            op = self.BELONGS
            invert = True
        elif (op != self.BELONGS):
            for v in r:
                try:
                    r = probe(op, l, v)
                except (TypeError, ValueError):
                    r = False
                if r:
                    return True
            return False
    try:
        r = probe(op, l, r)
    except (TypeError, ValueError):
        return False
    if (invert and (r is not None)):
        return (not r)
    else:
        return r
