#!/usr/bin/env python # Copyright (c) 2012 Cloudera, Inc. All rights reserved. # # Impala's shell import cmd import time import sys from optparse import OptionParser from ImpalaService import ImpalaService from JavaConstants.constants import DEFAULT_QUERY_OPTIONS from ImpalaService.ImpalaService import TImpalaQueryOptions from beeswaxd import BeeswaxService from beeswaxd.BeeswaxService import QueryState from thrift.transport.TSocket import TSocket from thrift.transport.TTransport import TBufferedTransport, TTransportException from thrift.protocol import TBinaryProtocol from thrift.Thrift import TApplicationException VERSION_STRING = "Impala v0.1 " # Tarball / packaging build makes impala_build_version available try: from impala_build_version import get_version_string from impala_build_version import get_build_date VERSION_STRING += "(" + get_version_string()[:7] + ") built on " + get_build_date() except Exception: VERSION_STRING += "(build version not available)" # Simple Impala shell. Can issue queries (with configurable options) # Basic usage: type connect to connect to an impalad # Then issue queries or other commands. Tab-completion should show the set of # available commands. # TODO: (amongst others) # - Column headers / metadata support # - Report profiles # - A lot of rpcs return a verbose TStatus from thrift/Status.thrift # This will be useful for better error handling. The next iteration # of the shell should handle this return paramter. # - Make commands case agnostic. class ImpalaShell(cmd.Cmd): def __init__(self, options): cmd.Cmd.__init__(self) self.is_alive = True self.disconnected_prompt = "[Not connected] > " self.prompt = self.disconnected_prompt self.connected = False self.handle = None self.impalad = None self.imp_service = None self.transport = None self.query_options = {} self.query_state = QueryState._NAMES_TO_VALUES if options.impalad != None: if self.do_connect(options.impalad) == False: sys.exit(1) def __make_default_options(self): def get_name(option): return TImpalaQueryOptions._VALUES_TO_NAMES[option] for option, default in DEFAULT_QUERY_OPTIONS.iteritems(): self.query_options[get_name(option)] = default def __print_options(self): print '\n'.join(["\t%s: %s" % (k,v) for (k,v) in self.query_options.iteritems()]) def __options_to_string_list(self): return ["%s:%s" % (k,v) for (k,v) in self.query_options.iteritems()] def do_options(self, args): self.__print_options() def do_set(self, args): tokens = args.split(" ") if len(tokens) != 2: print "Error: SET