abap   REPORT zsql_query_alv.

CLASS lcl_sql_query DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      execute_query IMPORTING
                      p_sqlquery TYPE string
                    EXPORTING
                      et_result_data TYPE STANDARD TABLE OF REF TO DATA,
      create_alv_container IMPORTING
                            p_container_name TYPE scrfname
                          RETURNING
                            VALUE(ro_grid) TYPE REF TO cl_gui_alv_grid,
      display_result IMPORTING
                      it_outtab TYPE STANDARD TABLE OF REF TO DATA
                    CHANGING
                      ct_fieldcatalog TYPE lvc_t_fcat.
ENDCLASS.

CLASS lcl_sql_query IMPLEMENTATION.
  METHOD execute_query.
    DATA: lv_sql_query TYPE string,
          lt_result_data TYPE STANDARD TABLE OF REF TO DATA,
          ls_result_data LIKE LINE OF lt_result_data,
          lo_statement TYPE REF TO if_sql_statement,
          lx_sy_dynamic_osql_error TYPE cx_sy_dynamic_osql_error.

    lv_sql_query = p_sqlquery.

    IF lv_sql_query IS INITIAL.
      RAISE EXCEPTION TYPE cx_static_check MESSAGE 'Please enter a valid SQL query.'.
    ENDIF.

    CONCATENATE lv_sql_query 'LIMIT 100' INTO lv_sql_query.

    TRY.
        lo_statement = cl_sql_statement=>create( ).
        lo_statement->execute( lv_sql_query ).
        
        LOOP AT lo_statement->get_result() INTO DATA(ls_row).
          CREATE DATA ls_result_data LIKE LINE OF lt_result_data.
          ls_result_data->* = ls_row.
          APPEND ls_result_data TO lt_result_data.
        ENDLOOP.
      CATCH cx_sy_dynamic_osql_error INTO lx_sy_dynamic_osql_error.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH lx_sy_dynamic_osql_error->if_message~get_text( ) INTO DATA(lv_error_msg).
        RAISE EXCEPTION TYPE cx_static_check MESSAGE lv_error_msg.
    ENDTRY.

    et_result_data = lt_result_data.
  ENDMETHOD.

  METHOD create_alv_container.
    IF alv_grid IS BOUND.
      RETURN.
    ENDIF.

    CREATE OBJECT alv_grid
      EXPORTING
        i_parent = p_container_name.

    RETURN.
  ENDMETHOD.

  METHOD display_result.
    CALL METHOD alv_grid->set_table_for_first_display
      EXPORTING
        is_layout       = lt_layout
      CHANGING
        it_outtab       = it_outtab
        it_fieldcatalog = ct_fieldcatalog.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  DATA: lo_query TYPE REF TO lcl_sql_query,
        ls_layout TYPE lvc_s_layo,
        lt_fields TYPE lvc_t_fcat,
        lt_result_data TYPE STANDARD TABLE OF REF TO DATA,
        ls_result_data LIKE LINE OF lt_result_data.

  CREATE OBJECT lo_query.

  ls_layout = cl_alv_table_create=>get_default_layout( ).
  CALL METHOD lo_query->execute_query
    EXPORTING
      p_sqlquery = p_sqlquery
    IMPORTING
      et_result_data = lt_result_data.

  CALL METHOD lo_query->display_result
    CHANGING
      it_outtab = lt_result_data
      ct_fieldcatalog = lt_fields.

  CALL METHOD lo_query->create_alv_container
    EXPORTING
      p_container_name = alv_container_name
    RETURNING
      VALUE(ro_grid) = alv_grid.

  CALL METHOD alv_grid->set_table_for_first_display
    EXPORTING
      is_layout       = ls_layout
    CHANGING
      it_outtab       = lt_result_data
      it_fieldcatalog = lt_fields.