'Convert this S3ResourceQuery into a DAL query, ignoring virtual
fields (the necessary joins for this query can be constructed
with the joins() method)
@param resource: the resource to resolve the query against'

def query(self, resource):

    op = self.op
    l = self.left
    r = self.right
    if (op == self.AND):
        l = (l.query(resource) if isinstance(l, S3ResourceQuery) else l)
        r = (r.query(resource) if isinstance(r, S3ResourceQuery) else r)
        if ((l is None) or (r is None)):
            return None
        elif ((l is False) or (r is False)):
            return (l if (r is False) else (r if (l is False) else False))
        else:
            return (l & r)
    elif (op == self.OR):
        l = (l.query(resource) if isinstance(l, S3ResourceQuery) else l)
        r = (r.query(resource) if isinstance(r, S3ResourceQuery) else r)
        if ((l is None) or (r is None)):
            return None
        elif ((l is False) or (r is False)):
            return (l if (r is False) else (r if (l is False) else False))
        else:
            return (l | r)
    elif (op == self.NOT):
        l = (l.query(resource) if isinstance(l, S3ResourceQuery) else l)
        if (l is None):
            return None
        elif (l is False):
            return False
        else:
            return (~ l)
    if isinstance(l, S3FieldSelector):
        try:
            rfield = S3ResourceField(resource, l.name)
        except:
            return None
        if rfield.virtual:
            return None
        elif (not rfield.field):
            return False
        lfield = l.expr(rfield.field)
    elif isinstance(l, Field):
        lfield = l
    else:
        return None
    if isinstance(r, S3FieldSelector):
        try:
            rfield = S3ResourceField(resource, r.name)
        except:
            return None
        rfield = rfield.field
        if rfield.virtual:
            return None
        elif (not rfield.field):
            return False
        rfield = r.expr(rfield.field)
    else:
        rfield = r
    invert = False
    query_bare = self._query_bare
    ftype = str(lfield.type)
    if (isinstance(rfield, (list, tuple)) and (ftype[:4] != 'list')):
        if (op == self.EQ):
            op = self.BELONGS
        elif (op == self.NE):
            op = self.BELONGS
            invert = True
        elif (op not in (self.BELONGS, self.TYPEOF)):
            query = None
            for v in rfield:
                q = query_bare(op, lfield, v)
                if (q is not None):
                    if (query is None):
                        query = q
                    else:
                        query |= q
            return query
    if ((ftype in ('date', 'datetime')) and isinstance(rfield, basestring)):
        to_type = (datetime.date if (ftype == 'date') else datetime.datetime)
        rfield = S3TypeConverter.convert(to_type, rfield)
    if ((op == self.EQ) and (rfield is not None) and ((ftype == 'id') or (ftype[:9] == 'reference'))):
        try:
            rfield = long(rfield)
        except (ValueError, TypeError):
            rfield = 0
    query = query_bare(op, lfield, rfield)
    if invert:
        query = (~ query)
    return query
