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
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)))
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))
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)
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]