def get_result(self): # Got to unravel the join stack; the nesting order could be # arbitrary, so we do a depth first search and push the join tokens # and predicates onto a flat list, then format them op = self.expr.op() if isinstance(op, ops.Join): self._walk_join_tree(op) else: self.join_tables.append(self._format_table(self.expr)) # TODO: Now actually format the things buf = StringIO() buf.write(self.join_tables[0]) for jtype, table, preds in zip(self.join_types, self.join_tables[1:], self.join_predicates): buf.write('\n') buf.write(util.indent('{0} {1}'.format(jtype, table), self.indent)) if len(preds): buf.write('\n') fmt_preds = [self._translate(pred) for pred in preds] conj = ' AND\n{0}'.format(' ' * 3) fmt_preds = util.indent('ON ' + conj.join(fmt_preds), self.indent * 2) buf.write(fmt_preds) return buf.getvalue()
def explain(self, expr, params=None): """ Query for and return the query plan associated with the indicated expression or SQL query. Returns ------- plan : string """ if isinstance(expr, ir.Expr): context = self.dialect.make_context(params=params) query_ast = self._build_ast(expr, context) if len(query_ast.queries) > 1: raise Exception('Multi-query expression') query = query_ast.queries[0].compile() else: query = expr statement = 'EXPLAIN {0}'.format(query) with self._execute(statement, results=True) as cur: result = self._get_list(cur) return 'Query:\n{0}\n\n{1}'.format( util.indent(query, 2), '\n'.join(result) )
def _repr(self): buf = StringIO() space = 2 + max(len(x) for x in self.names) for name, tipo in zip(self.names, self.types): buf.write('\n{0}{1}'.format(name.ljust(space), str(tipo))) return "ibis.Schema {{{0}\n}}".format(util.indent(buf.getvalue(), 2))
def format_select_set(self): # TODO: context = self.context formatted = [] for expr in self.select_set: if isinstance(expr, ir.ValueExpr): expr_str = self._translate(expr, named=True) elif isinstance(expr, ir.TableExpr): # A * selection, possibly prefixed if context.need_aliases(): alias = context.get_ref(expr) # materialized join will not have an alias. see #491 expr_str = '{0}.*'.format(alias) if alias else '*' else: expr_str = '*' formatted.append(expr_str) buf = StringIO() line_length = 0 max_length = 70 tokens = 0 for i, val in enumerate(formatted): # always line-break for multi-line expressions if val.count('\n'): if i: buf.write(',') buf.write('\n') indented = util.indent(val, self.indent) buf.write(indented) # set length of last line line_length = len(indented.split('\n')[-1]) tokens = 1 elif (tokens > 0 and line_length and len(val) + line_length > max_length): # There is an expr, and adding this new one will make the line # too long buf.write(',\n ') if i else buf.write('\n') buf.write(val) line_length = len(val) + 7 tokens = 1 else: if i: buf.write(',') buf.write(' ') buf.write(val) tokens += 1 line_length += len(val) + 2 if self.distinct: select_key = 'SELECT DISTINCT' else: select_key = 'SELECT' return '{0}{1}'.format(select_key, buf.getvalue())
def visit(what, extra_indents=0): if isinstance(what, ir.Expr): result = self._format_subexpr(what) else: result = self._indent(str(what)) if extra_indents > 0: result = util.indent(result, self.indent_size) formatted_args.append(result)
def format_subqueries(self): context = self.context subqueries = self.subqueries return ',\n'.join([ '{0} AS (\n{1}\n)'.format( context.get_ref(expr), util.indent(context.get_compiled_expr(expr), 2) ) for expr in subqueries ])
def __repr__(self): space = 2 + max(map(len, self.names)) return "ibis.Schema {{{0}\n}}".format( util.indent( ''.join( '\n{0}{1}'.format(name.ljust(space), str(tipo)) for name, tipo in zip(self.names, self.types) ), 2 ) )
def format_subqueries(self, context): if len(self.subqueries) == 0: return buf = BytesIO() buf.write('WITH ') for i, expr in enumerate(self.subqueries): if i > 0: buf.write(',\n') formatted = util.indent(context.get_formatted_query(expr), 2) alias = context.get_alias(expr) buf.write('{0} AS (\n{1}\n)'.format(alias, formatted)) return buf.getvalue()
def format_subqueries(self): if len(self.subqueries) == 0: return context = self.context buf = StringIO() buf.write('WITH ') for i, expr in enumerate(self.subqueries): if i > 0: buf.write(',\n') formatted = util.indent(context.get_compiled_expr(expr), 2) alias = context.get_ref(expr) buf.write('{0} AS (\n{1}\n)'.format(alias, formatted)) return buf.getvalue()
def _exists_subquery(translator, expr): op = expr.op() ctx = translator.context expr = (op.foreign_table .filter(op.predicates) .projection([ir.literal(1).name(ir.unnamed)])) subquery = ctx.get_compiled_expr(expr) if isinstance(op, transforms.ExistsSubquery): key = 'EXISTS' elif isinstance(op, transforms.NotExistsSubquery): key = 'NOT EXISTS' else: raise NotImplementedError return '{0} (\n{1}\n)'.format(key, util.indent(subquery, ctx.indent))
def _format_table(self, expr): # TODO: This could probably go in a class and be significantly nicer ctx = self.context ref_expr = expr op = ref_op = expr.op() if isinstance(op, ops.SelfReference): ref_expr = op.table ref_op = ref_expr.op() if isinstance(ref_op, ops.PhysicalTable): name = ref_op.name if name is None: raise com.RelationError('Table did not have a name: {0!r}' .format(expr)) result = quote_identifier(name) is_subquery = False else: # A subquery if ctx.is_extracted(ref_expr): # Was put elsewhere, e.g. WITH block, we just need to grab its # alias alias = ctx.get_ref(expr) # HACK: self-references have to be treated more carefully here if isinstance(op, ops.SelfReference): return '{0} {1}'.format(ctx.get_ref(ref_expr), alias) else: return alias subquery = ctx.get_compiled_expr(expr) result = '(\n{0}\n)'.format(util.indent(subquery, self.indent)) is_subquery = True if is_subquery or ctx.need_aliases(): result += ' {0}'.format(ctx.get_ref(expr)) return result
def __repr__(self): lines = map('{}={!r},'.format, *zip(*self.items())) return '{}(\n{}\n)'.format( type(self).__name__, util.indent('\n'.join(lines), 4) )
def __repr__(self): # Temporary rows = ['Sort key:', ' ascending: {0!s}'.format(self.ascending), util.indent(_safe_repr(self.expr), 2)] return '\n'.join(rows)
def _indent(self, text, indents=1): return util.indent(text, self.indent_size * indents)
def _table_array_view(translator, expr): ctx = translator.context table = expr.op().table query = ctx.get_compiled_expr(table) return '(\n{0}\n)'.format(util.indent(query, ctx.indent))
def __repr__(self): # Temporary rows = ["Sort key:", " ascending: {0!s}".format(self.ascending), util.indent(_safe_repr(self.expr), 2)] return "\n".join(rows)