Ticket #251: q.diff

File q.diff, 3.6 KB (added by hugo, 14 years ago)

query algebra for complex queries

  • core/meta/__init__.py

     
    12521252            continue
    12531253        if kwarg_value is None:
    12541254            continue
     1255        if kwarg == 'complex':
     1256            tables2, join_where2, where2, params2, table_count = kwarg_value.getSQL(opts, table_count)
     1257            tables.extend(tables2)
     1258            join_where.extend(join_where2)
     1259            where.append(where2)
     1260            params.extend(params2)
     1261            continue
    12551262        if kwarg == '_or':
    12561263            for val in kwarg_value:
    12571264                tables2, join_where2, where2, params2, table_count = _parse_lookup(val, opts, table_count)
     
    13591366                continue
    13601367    return tables, join_where, where, params, table_count
    13611368
     1369class Q_base:
     1370    """
     1371    This is a base class for Q_and and Q_or.
     1372    """
     1373
     1374    def __init__(self, *args):
     1375        self.args = args
     1376
     1377    def __repr__(self):
     1378        return '(%s)' % self.operator.join([repr(el) for el in self.args])
     1379
     1380    def getSQL(self, opts, table_count):
     1381        tables, join_where, where, params = [], [], [], []
     1382        for val in self.args:
     1383            tables2, join_where2, where2, params2, table_count = val.getSQL(opts, table_count)
     1384            tables.extend(tables2)
     1385            join_where.extend(join_where2)
     1386            where.extend(where2)
     1387            params.extend(params2)
     1388        return tables, join_where, '(%s)' % self.operator.join(where), params, table_count
     1389
     1390class Q_and(Q_base):
     1391    """
     1392    This encapsulates a combined query that uses 'and'.
     1393    """
     1394
     1395    operator = ' AND '
     1396
     1397    def __or__(self, other):
     1398        if isinstance(other, (Q_and, Q_or, Q)):
     1399            return Q_or(self, other)
     1400        else:
     1401            raise TypeError, other
     1402
     1403    def __and__(self, other):
     1404        if isinstance(other, Q_and):
     1405            return Q_and(*(self.args+other.args))
     1406        elif isinstance(other, (Q, Q_or)):
     1407            return Q_and(*(self.args+(other,)))
     1408        else:
     1409            raise TypeError, other
     1410
     1411class Q_or(Q_base):
     1412    """
     1413    This encapsulates a combined query that uses 'or'.
     1414    """
     1415
     1416    operator = ' OR '
     1417
     1418    def __and__(self, other):
     1419        if isinstance(other, (Q_and, Q_or, Q)):
     1420            return Q_and(self, other)
     1421        else:
     1422            raise TypeError, other
     1423
     1424    def __or__(self, other):
     1425        if isinstance(other, Q_or):
     1426            return Q_or(*(self.args+other.args))
     1427        elif isinstance(other, (Q, Q_and)):
     1428            return Q_or(*(self.args+(other,)))
     1429        else:
     1430            raise TypeError, other
     1431
     1432class Q:
     1433    """
     1434    This is a class that encapsulates queries for the complex parameter to
     1435    django model functions.
     1436    """
     1437
     1438    def __init__(self, **kwargs):
     1439        self.kwargs = kwargs
     1440
     1441    def __repr__(self):
     1442        return 'Q%r' % self.kwargs
     1443
     1444    def __and__(self, other):
     1445        if isinstance(other, (Q, Q_and, Q_or)):
     1446            return Q_and(self, other)
     1447        else:
     1448            raise TypeError, other
     1449
     1450    def __or__(self, other):
     1451        if isinstance(other, (Q, Q_and, Q_or)):
     1452            return Q_or(self, other)
     1453        else:
     1454            raise TypeError, other
     1455
     1456    def getSQL(self, opts, table_count):
     1457        return _parse_lookup(self.kwargs.items(), opts, table_count)
     1458
    13621459def function_get_sql_clause(opts, **kwargs):
    13631460    select = ["%s.%s" % (db.db.quote_name(opts.db_table), db.db.quote_name(f.column)) for f in opts.fields]
    13641461    tables = [opts.db_table] + (kwargs.get('tables') and kwargs['tables'][:] or [])
Back to Top