docs: def check_all_columns(state, allow_extra=True, too_many_cols_msg=None, expand_msg=None):
      """Zoom in on the columns that are specified by the solution
      
      Behind the scenes, this is using ``check_column()`` for every column that is in the solution query result.
      Afterwards, it's selecting only these columns from the student query result and stores them in a child
      state that is returned, so you can use ``has_equal_value()`` on it.
  
      This function does not allow you to customize the messages for ``check_column()``. If you want to manually
      set those, simply use ``check_column()`` explicitly.
  
      Args:
          allow_extra: True by default, this determines whether students are allowed to have included
                       other columns in their query result.
          too_many_cols_msg: If specified, this overrides the automatically generated feedback message in
                             case ``allow_extra`` is False and the student's query returned extra columns when
                             comparing the so the solution query result.
          expand_msg: if specified, this overrides the automatically generated feedback 
                      message that is prepended to feedback messages that are thrown
                      further in the SCT chain.
  
      :Example:
  
          Consider the following solution and SCT: ::
  
              # solution
              SELECT artist_id as id, name FROM artists
  
              # sct
              Ex().check_all_columns()
  
              # passing submission
              SELECT artist_id as id, name FROM artists
  
              # failing submission (wrong names)
              SELECT artist_id, name FROM artists
  
              # passing submission (allow_extra is True by default)
              SELECT artist_id as id, name, label FROM artists
      """
  
      if too_many_cols_msg is None:
          too_many_cols_msg = (
              "Your query result contains the column {{col}} but shouldn't."
          )
      if expand_msg is None:
          expand_msg = "Have another look at your query result. "
  
      child_stu_result = {}
      child_sol_result = {}
  
      for col in state.solution_result:
          child = check_column(state, col)
          child_stu_result.update(**child.student_result)
          child_sol_result.update(**child.solution_result)
  
      cols_not_in_sol = list(
          set(state.student_result.keys()) - set(child_stu_result.keys())
      )
      if not allow_extra and len(cols_not_in_sol) > 0:
          _msg = state.build_message(
              "Your query result contains the column `{{col}}` but shouldn't.",
              fmt_kwargs={"col": cols_not_in_sol[0]},
          )
          state.do_test(_msg)
  
      return state.to_child(
          append_message={"msg": expand_msg, "kwargs": {}},
          student_result=child_stu_result,
          solution_result=child_sol_result,
      )