def get_keyword_hierarchy(self, pattern="*"):
        """Returns all keywords that match a glob-style pattern

        The result is a list of dictionaries, sorted by collection
        name.

        The pattern matching is insensitive to case. The function
        returns a list of (library_name, keyword_name,
        keyword_synopsis tuples) sorted by keyword name

        """

        sql = """SELECT collection.collection_id, collection.name, collection.path,
                 keyword.name, keyword.doc
                 FROM collection_table as collection
                 JOIN keyword_table as keyword
                 WHERE collection.collection_id == keyword.collection_id
                 AND keyword.name like ?
                 ORDER by collection.name, collection.collection_id, keyword.name
             """
        cursor = self._execute(sql, (self._glob_to_sql(pattern),))
        libraries = []
        current_library = None
        for row in cursor.fetchall():
            (c_id, c_name, c_path, k_name, k_doc) = row
            if c_id != current_library:
                current_library = c_id
                libraries.append({"name": c_name, "collection_id": c_id, "keywords": [], "path": c_path})
            libraries[-1]["keywords"].append({"name": k_name, "doc": k_doc})
        return libraries
Returns all keywords that match a glob-style pattern

        The result is a list of dictionaries, sorted by collection
        name.

        The pattern matching is insensitive to case. The function
        returns a list of (library_name, keyword_name,
        keyword_synopsis tuples) sorted by keyword name