示例#1
0
def gpudb_cmd( argv ):
    """An interface to GPUDB.  Run the specified query on GPUDB on the local
       machine or at the specified address.  Also provide usage information.
    """

    # Default values
    file_name = ""

    # Add arguments to the parser
    parser = argparse.ArgumentParser()
    parser.add_argument( '-g', nargs = '?', default = "127.0.0.1:9191",
                         help = "IP address and port of GPUdb in the format: xxx.xx.xx.xx:xxxx (defaults to 127.0.0.1:9191)" )
    # User must provide one or the other
    query_group = parser.add_mutually_exclusive_group( required = True )
    query_group.add_argument( "--list-queries", action = 'store_true',
                         help = "Lists all available GPUDB queries." )
    query_group.add_argument( '--query', nargs = argparse.REMAINDER,
                         help = "Name of the query to be executed and any parameters associated with the query. For example, '--query max_min --attribute x --set_id set1'. Not providing any parameter after the query name will print query specific help information." )

    # Print the help message and quit if no arguments are given
    if ( len(sys.argv) == 1 ): # None provided
        parser.print_help()
        sys.exit( 2 )

    # Parse the command line arguments
    args = parser.parse_args()


    # --------------------------------------
    # Set up GPUdb
    GPUdb_IP, GPUdb_Port = args.g.split( ":" )
    gpudb = GPUdb( encoding = 'BINARY', host = GPUdb_IP, port = GPUdb_Port )

    # Get a list of all endpoint names
    query_names = sorted( gpudb.gpudb_schemas.keys() )

    # --------------------------------------
    # List all endpoint/query names, if desired by user
    if (args.list_queries == True) or (len(args.query) == 0):
        for q in sorted( query_names ):
            print q
        sys.exit( 0 ) # Succesful termination after printing the desired help message
    # --------------------------------------


    # Get the query JSON string from GPUdb
    query_name = args.query[ 0 ]
    if query_name not in query_names:
        print "Query not found: ", query_name
        sys.exit( 2 )
    request_json = gpudb.gpudb_schemas[ query_name ][ "REQ_SCHEMA_STR" ]

    # Parse the request JSON to get the parameters
    request_schema = gpudb.gpudb_schemas[ query_name ][ "REQ_SCHEMA" ]
    request_json =  request_schema.to_json()["fields"]

    # Create a dictionary of (param name, param type) pairs based on the JSON
    param_name_type = {}
    param_vals = {}
    for param in request_json:
        param_name_type[ param['name'] ] = param['type']
        # Binary/bytes parameters will be skipped
        if param['type'] == "string" or param['type'] == "bytes":
            param_vals[ param['name'] ] = "" # Default is empty string
        if param['type'] == "map":
            param_vals[ param['name'] ] = {} # Default is empty map
        if param['type'] == "list":
            param_vals[ param['name'] ] = [] # Default is empty list
        # Note that numeric attributes are not getting a default
        # User MUST provide such values, or we output an error

    # Create a parser for query-specific parameters
    query_parser = argparse.ArgumentParser()

    # Add parameters to be parsed
    query_parser.add_argument( "--format-response", action = 'store_true', dest = "format_response",
                             help = "Boolean parameter, include to print formatted GPUDB response. Omitting it prints the raw GPUDB response." )
    for pname, ptype in param_name_type.iteritems():
        if ptype == "string": # Make string arguments optional
            query_parser.add_argument( "--" + pname, nargs='?', default="", help = "Defaults to empty string" )
        elif ptype == "double" or ptype == "float":
            query_parser.add_argument( "--" + pname, type = float, required = True, help = "Required parameter, type %s" % ptype )
        elif ptype == "long":
            query_parser.add_argument( "--" + pname, type = long, required = True, help = "Required parameter, type %s" % ptype )
        elif ptype == "int":
            query_parser.add_argument( "--" + pname, type = int, required = True, help = "Required parameter, type %s" % ptype )
        elif ptype == "bytes":
            continue # ignore bytes
        elif ptype == "boolean": # Boolean flag
            # User must provide one or the other
            bool_group = query_parser.add_mutually_exclusive_group( required = True )
            bool_group.add_argument( "--" + pname, action = 'store_true', dest = pname,
                                       help = "Boolean parameter, include to set %s to TRUE" %pname )
            bool_group.add_argument( "--no-" + pname, action = 'store_false', dest = pname,
                                       help = "Boolean parameter, include to set %s to FALSE" % pname )
        else: # Maps and lists get empty ones by default; handling is delicate; ignore 'bytes'
            if ptype[ 'type' ] == "map":
                query_parser.add_argument( "--" + pname, nargs = '?', type = json.loads, default = {},
                                           help = "Expected map value of type: %s; surround the whole map with single quotes (') and any string (key or value) within with double quotes (\"). E.g. for random, --param_map '{\"x\":{\"min\":2}}'. When omitted, defaults to empty map" % ptype['values'] )
            else: # Arrays
                query_parser.add_argument( "--" + pname, type = json.loads, default=[],
                                           help = "Comma separated list (escape spaces with \) enclosed in []. For example, for filter_by_nai, --x_vector [1,2,3,4] or --x_vector [1,\ 2,\ 3,\ 4]. If contains strings, then enclose the whole thing within single quotes and the individual string in double quotes.  E.g., for filter_by_string, --attributes '[\"x\",\"y\"]'. When omitted, defaults to an empty list." )

    # Print the help message and quit if no arguments are given (and none is expected)
    if ( len( args.query[1:] ) == 0 and len( param_name_type ) > 0 ):
        print "No parameters provided for query: ", query_name
        query_parser.print_help()
        sys.exit( 2 )

    # Parse the parameters and store in a dictionary
    query_args = vars( query_parser.parse_args( args.query[1:] ) )

    # Copy the parsed values to the ordered dictionar to pass to GPUdb
    for key, val in query_args.iteritems():
        param_vals[ key ] = val
    # --------------------------------------


    # --------------------------------------
    # Call the GPUDB query:

    # Obtain the request and response schemas for the given query
    (req_schema, resp_schema) = gpudb.get_schemas( query_name )
    endpoint = gpudb.get_endpoint( query_name )

    # Perform the GPUDB query
    response = gpudb.post_then_get( req_schema, resp_schema, param_vals, endpoint )

    print
    print "GPUDB Response:"
    if query_args[ "format_response" ] == True:
        print format_response( response )
    else:
        print response