def _get_categorization_parameters_for_extract_study(extract_study_id, dict_cur):
    """
        returns a dictionary keyed by (vocabulary_id, concept_code) of lists of rows. 
        The rows are dictionaries as those returned by a dict_cur. 

        param extract_study_id
        Returns dictionary keyed by (vocabulary_id, concept_code) ->  list of row-dicts
           the keys for the attributes are: 
        (from_vocabulary_id, from_concept_code, short_name, function_name, value_limit, rank, vocabulary_id, concept_name)
    """

    calc_map = {}
    stmt = """  SELECT m.from_vocabulary_id, m.from_concept_code, m.short_name, 
                m.function_name, p.value_limit, p.rank, c.vocabulary_id, c.concept_code, c.concept_name
                FROM categorization_function_metadata m 
                LEFT JOIN categorization_function_parameters p 
                  ON  m.extract_study_id = p.extract_study_id
                  AND m.function_name = p.function_name
                  AND m.long_name = p.long_name
                  AND m.rule_id = p.rule_id
                LEFT JOIN concept c
                  ON p.from_concept_id = c.concept_id
                WHERE m.extract_study_id =  %s
                 ORDER BY sequence, rank ;
            """
            ## --  AND m.rank = p.rank

    dict_cur.execute(stmt, [extract_study_id])
    rows = dict_cur.fetchall()
    
    for row in rows:
        if (row['from_vocabulary_id'], row['from_concept_code']) not in calc_map:
            calc_map[(row['from_vocabulary_id'], row['from_concept_code'])] = []
        calc_map[(row['from_vocabulary_id'], row['from_concept_code'])].append(row)

    return calc_map