Ejemplo n.º 1
0
 def _translate_term(self, node):
     """Pushes an element onto the operand stack."""
     v = node.value
     if isinstance(v, ast.Scalar):
         self._operands[-1].append(sql.Constant(v.value))
     elif isinstance(v, ast.Ref) and len(v.terms) == 3:
         table = v.terms[1].value.value
         self._tables.add(table)
         col = sql.Column(v.terms[2].value.value, table)
         self._operands[-1].append(col)
     elif isinstance(v, ast.Call):
         try:
             op = v.op()
             sql_op = self._sql_call_operators[op]
         except KeyError:
             raise TranslationError(
                 'invalid call: operator not supported: %s' % op)
         self._operands.append([])
         for term in v.operands:
             walk.walk(term, self)
         sql_operands = self._operands.pop()
         self._operands[-1].append(sql.Call(sql_op, sql_operands))
     else:
         raise TranslationError('invalid term: type not supported: %s' %
                                v.__class__.__name__)
Ejemplo n.º 2
0
 def _translate_expr(self, node):
     """Pushes an element onto the relation stack."""
     builtinFunctionType = False
     if not node.is_call():
         return
     if len(node.operands) != 2:
         raise TranslationError('invalid expression: too many arguments')
     try:
         op = node.op()
         sql_op = sql.RelationOp(self._sql_relation_operators[op])
     except KeyError:
         try:
             sql_op = sql.RelationOp(
                 self._sql_built_in_binary_operators[op])
             builtinFunctionType = True
         except KeyError:
             raise TranslationError(
                 'invalid expression: operator not supported: %s' % op)
     self._operands.append([])
     for term in node.operands:
         walk.walk(term, self)
     sql_operands = self._operands.pop()
     if builtinFunctionType:
         self._relations.append(
             sql.BuiltInBinaryFunction(sql_op, *sql_operands))
     else:
         self._relations.append(sql.Relation(sql_op, *sql_operands))
Ejemplo n.º 3
0
    def __call__(self, node):
        if isinstance(node, ast.Query):
            self._table_names.append({})
            self._table_vars = {}
        elif isinstance(node, ast.Expr):
            if node.is_call():
                # Skip the built-in call operator.
                for o in node.operands:
                    walk.walk(o, self)
                return
        elif isinstance(node, ast.Call):
            # Skip the call operator.
            for o in node.operands:
                walk.walk(o, self)
            return
        elif isinstance(node, ast.Ref):
            head = node.terms[0].value.value

            if head in self._table_vars:
                # Expand ref in case head was an intermediate var. E.g.,
                # "data.foo[x]; x.bar" => "data.foo[x]; data.foo.bar".
                node.terms = self._table_vars[head] + node.terms[1:]
                return

            row_id = node.terms[2].value

            # Refs must be of the form data.<table>[<iterator>].<column>.
            if not isinstance(row_id, ast.Var):
                raise TranslationError(
                    'invalid reference: row identifier type not supported: %s'
                    % row_id.__class__.__name__)

            prefix = node.terms[:2]

            # Add mapping so that we can expand refs above.
            self._table_vars[row_id.value] = prefix
            table_name = node.terms[1].value.value

            # Keep track of iterators used for each table. We do not support
            # self-joins currently. Self-joins require namespacing in the SQL
            # query.
            exist = self._table_names[-1].get(table_name, row_id.value)
            if exist != row_id.value:
                raise TranslationError(
                    'invalid reference: self-joins not supported')
            else:
                self._table_names[-1][table_name] = row_id.value

            # Rewrite ref to remove iterator var. E.g., "data.foo[x].bar" =>
            # "data.foo.bar".
            node.terms = prefix + node.terms[3:]
            return

        return self
Ejemplo n.º 4
0
 def translate(self, query_set):
     """Returns a :class:`sql.Union` containing :class:`sql.Where` and
     :class:`sql.InnerJoin` clauses to be applied to the query."""
     walk.walk(query_set, self)
     clauses = []
     if len(self._conjunctions) > 0:
         clauses = [sql.Where(sql.Disjunction([conj for conj in self._conjunctions]))]
     for (tables, conj) in self._joins:
         pred = sql.InnerJoin(tables, conj)
         clauses.append(pred)
     return sql.Union(clauses)
Ejemplo n.º 5
0
 def _translate_query(self, node):
     """Pushes an expression onto the conjunction or join stack if multiple
     tables are referred to."""
     for expr in node.exprs:
         walk.walk(expr, self)
     conj = sql.Conjunction(self._relations)
     if len(self._tables) > 1:
         self._tables.remove(self._from_table)
         self._joins.append((self._tables, conj))
     else:
         self._conjunctions.append(conj)
     self._tables = set([])
     self._relations = []
Ejemplo n.º 6
0
 def _translate_expr(self, node):
     """Pushes an element onto the relation stack."""
     if not node.is_call():
         return
     if len(node.operands) != 2:
         raise TranslationError('invalid expression: too many arguments')
     try:
         op = node.op()
         sql_op = sql.RelationOp(self._sql_relation_operators[op])
     except KeyError:
         raise TranslationError('invalid expression: operator not supported: %s' % op)
     self._operands.append([])
     for term in node.operands:
         walk.walk(term, self)
     sql_operands = self._operands.pop()
     self._relations.append(sql.Relation(sql_op, *sql_operands))
Ejemplo n.º 7
0
 def process(self, query_set):
     walk.walk(query_set, self)