def exec_if_not_yet_execed(self):
        """Query execution is delayed until the first result or total row count is requested."""
        if self.gqi is not None:
            return
        if self.options & Option.UPPER_CASE_WHERE:
            # Uppercase the entire condition string. Should cause no problems,
            # since query keywords are case insensitive as well.
            self.conditions_for_exec = self.conditions.upper()
        import irods_types
        self.gqi = self.callback.msiMakeGenQuery(', '.join(self.columns),
                                                 self.conditions_for_exec,
                                                 irods_types.GenQueryInp())['arguments'][2]
        if self.offset > 0:
            self.gqi.rowOffset = self.offset
        else:
            # If offset is 0, we can (relatively) cheaply let iRODS count rows.
            # - with non-zero offset, the query must be executed twice if the
            #   row count is needed (see total_rows()).
            self.options |= Option.RETURN_TOTAL_ROW_COUNT

        if self.limit is not None and self.limit < MAX_SQL_ROWS - 1:
            # We try to limit the amount of rows we pull in, however in order
            # to close the query, 256 more rows will (if available) be fetched
            # regardless.
            self.gqi.maxRows = self.limit

        self.gqi.options |= self.options

        self.gqo    = self.callback.msiExecGenQuery(self.gqi, irods_types.GenQueryOut())['arguments'][1]
        self.cti    = self.gqo.continueInx
        self._total = None
예제 #2
0
    def get_more_rows(self, query):
        """
        Wrapper for msiGetMoreRows.  Reruns the given query at the continuation index to retrieve additional rows.

        :param query:
        :returns: a tuple of the query result, and the new continuation index.
        :rtype: (irods_types.GenQueryOut, int)
        """
        debug.trace_begin(self, locals())
        res = self._irods.msiGetMoreRows(query, irods_types.GenQueryOut(), 0)
        return debug.trace_end(
            self, (self.validate_result(res, 1), self.validate_result(res, 2)))
예제 #3
0
    def exec_gen_query(self, query):
        """
        Wrapper for msiExecGenQuery.  Executes a given GenQueryInp query (constructed with make_gen_query).

        :param irods_types.GenQueryInp query: preprocessed iRODS gen query to execute
        :return: the result of the query execution
        :rtype: irods_types.GenQueryOut
        """
        debug.trace_begin(self, locals())
        return debug.trace_end(
            self,
            self.validate_result(
                self._irods.msiExecGenQuery(query, irods_types.GenQueryOut()),
                1))
예제 #4
0
def get_resource_name_by_replica_number(callback, logical_path,
                                        replica_number):
    coll_name = os.path.dirname(logical_path)
    data_name = logical_path.split('/')[-1]
    conditions = "COLL_NAME = '{0}' AND DATA_NAME = '{1}' AND DATA_REPL_NUM = '{2}'".format(
        coll_name, data_name, replica_number)

    ret_val = callback.msiMakeGenQuery("RESC_NAME", conditions,
                                       irods_types.GenQueryInp())
    genQueryInp = ret_val['arguments'][2]

    ret_val = callback.msiExecGenQuery(genQueryInp, irods_types.GenQueryOut())
    genQueryOut = ret_val['arguments'][1]
    result_count = genQueryOut.rowCnt

    resource_name = str(
        genQueryOut.sqlResult[0].row(0)) if result_count > 0 else None
    return (result_count, resource_name)
예제 #5
0
def get_existing_replica_size_from_destination(callback, logical_path):
    coll_name = os.path.dirname(logical_path)
    data_name = logical_path.split('/')[-1]
    resc_names = ','.join(
        ["'" + i + "'" for i in LIST_OF_DESTINATION_RESOURCE_LEAVES])
    conditions = "COLL_NAME = '{0}' AND DATA_NAME = '{1}' AND RESC_NAME in ({2})".format(
        coll_name, data_name, resc_names)

    ret_val = callback.msiMakeGenQuery("DATA_SIZE", conditions,
                                       irods_types.GenQueryInp())
    genQueryInp = ret_val['arguments'][2]

    ret_val = callback.msiExecGenQuery(genQueryInp, irods_types.GenQueryOut())
    genQueryOut = ret_val['arguments'][1]
    previously_registered_replicas = genQueryOut.rowCnt

    logical_size = int(genQueryOut.sqlResult[0].row(
        0)) if previously_registered_replicas > 0 else None
    return (previously_registered_replicas, logical_size)
def row_iterator(  columns,     # comma-separated string, or list, of columns
                   conditions,  # genquery condition eg. "COLL_NAME not like '%/trash/%'"
                   row_return,  # AS_DICT or AS_LIST to specify rows as Python 'list's or 'dict's
                   callback     # fed in directly from rule call argument
                ):

    import irods_types

    if not issubclass(row_return, row_return_type):
        raise bad_returntype_spec( "row_return parameter should be AS_DICT or AS_LIST" )

    if not isinstance(columns, (list, tuple)):
        if isinstance(columns, str):
            columns = list(map(lambda obj: obj.strip(), columns.split(",")))
        else:
            raise bad_column_spec ( "Column argument '{!r}' should be column names " \
                                    "as list or comma separated string".format(columns))

    if len(columns) < 1:
        raise bad_column_spec( "Must select at least one column for the query" )

    column_indices = list(map(reversed,enumerate(columns)))
    column_lookup = dict(column_indices)

    ret_val = callback.msiMakeGenQuery(",".join(columns) , conditions , irods_types.GenQueryInp())
    genQueryInp = ret_val['arguments'][2]

    ret_val = callback.msiExecGenQuery(genQueryInp , irods_types.GenQueryOut())
    genQueryOut = ret_val['arguments'][1]
    continue_index_old = 1

    ret_val = callback.msiGetContInxFromGenQueryOut( genQueryOut, 0 )
    continue_index = ret_val['arguments'][1]

    exit_type = ''

    try:

        while continue_index_old > 0:

            for j in range(genQueryOut.rowCnt):

                row_as_list = [ genQueryOut.sqlResult[i].row(j) for i in range(len(column_indices)) ]

                if row_return is AS_DICT:
                    yield { k : row_as_list[v] for k,v in column_lookup.items() }
                elif row_return is AS_LIST:
                    yield row_as_list

            continue_index_old = continue_index

            ret_val = None  #-- in case of exception from msiGetMoreRows call
            ret_val = callback.msiGetMoreRows(genQueryInp , genQueryOut, 0)

            genQueryOut = ret_val['arguments'][1]
            continue_index = ret_val['arguments'][2]

    except GeneratorExit:
        exit_type = 'ITERATION_STOPPED_BY_CALLER'
    except Exception as e:
        if ret_val is None:
            exit_type = 'GET_ROWS_ERROR'
        else:
            exit_type = 'UNKNOWN_ERROR'
        continue_index = 0 # Unanticipated source of error, preserve exception as-is
        raise              # ('finally' clause runs, but no forced closing of query)
    else:
        exit_type = '(Normal)'
    finally:
        if Report_Exit_To_Log:
            callback.writeLine("serverLog","Python GenQuery exit type - {}".format(exit_type))
        if AUTO_CLOSE_QUERIES:
            while continue_index > 0:
                continue_index_old = continue_index
                ret_val = callback.msiGetMoreRows(genQueryInp , genQueryOut, 0) 
                genQueryOut = ret_val['arguments'][1]
                continue_index = ret_val['arguments'][2]