Guest User

ZTOAD - Modifications

a guest
Sep 10th, 2015
274
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. *&---------------------------------------------------------------------*
  2. *& Program : ZTOAD
  3. *& Author  : S. Hermann
  4. *& Date    : 17.08.2015
  5. *& Version : 3.1
  6. *& Required: Table ZTOAD
  7. *&---------------------------------------------------------------------*
  8. *& This program allow you to execute query directly on the server
  9. *& 1/ Write your query in the editor window (ABAP SQL)
  10. *& 2/ View the result in ALV window (in case of SELECT query)
  11. *&
  12. *3 Features :
  13. *& The top center pane allow you to write your query in ABAP SQL format.
  14. *= Query can be complex with JOIN, UNION and subqueries. You can write
  15. *= query on several lines. You could also add spaces.
  16. *= To add comment, start the line by * or prefix your comment by "
  17. *&
  18. *& You could write several queries in the query editor, separated by
  19. *= dot ".". To execute one of them, highlight all the wanted query,
  20. *= or just put the cursor anywhere inside the wanted query.
  21. *= By default, the last query is executed.
  22. *&
  23. *& In case of error, you can display generated code to help you to
  24. *= correct your query (only if you have S_DEVELOP access)
  25. *&
  26. *& The top left pane allow you to store your query :
  27. *& - You could save your query to reuse it later
  28. *& - You could share your query : define users, usergroup, all
  29. *& - You could export query into file to reuse it on another server
  30. *&
  31. *& The top right pane display ddic object that is currently used to help
  32. *= you to write the proper query
  33. *& Synergy with ZSPRO program : display tables defined in ZSPRO in the
  34. *= ddic tree
  35. *& Tips : You can search a table in the tree using header clic
  36. *&
  37. *3 Managed queries
  38. *& SELECT, INSERT, UPDATE, DELETE
  39. *&
  40. *3 Select Clause managed
  41. *& SELECT [DISTINCT / SINGLE] select clause
  42. *& FROM from clause
  43. *& [UP TO x ROWS]
  44. *& [WHERE cond1]
  45. *& [GROUP BY fields1]
  46. *& [HAVING cond2]
  47. *& [ORDER BY fields2]
  48. *& [UNION SELECT...]
  49. *&
  50. *& UP TO (Default max rows) ROWS added at end of query if omitted
  51. *&
  52. *& COUNT, AVG, MAX, MIN, SUM are managed
  53. *& DO NOT FORGET SPACE in ( ) of aggregat
  54. *&
  55. *& F1 Help is managed to help you on ABAP SQL Syntax
  56. *&
  57. *3 Insert special syntax
  58. *& In ABAP, insert query is always used with given structure
  59. *& In this SQL editor, you have 2 ways to do an INSERT :
  60. *& - By passing each value, 1 by 1
  61. *E INSERT SEOCLASSTX VALUES ( 'ZZMACLASS', ' ', 'Test claSS' )
  62. *&
  63. *& - By passing value of used fields only
  64. *E INSERT SEOCLASSTX SET CLSNAME = 'ZZMACLASS' DESCRIPT = 'TeSt class'
  65. *&
  66. *3 Sample of query :
  67. *&
  68. *E SELECT SINGLE * FROM VBAP WHERE VBELN = '00412345678'
  69. *&
  70. *E SELECT COUNT( * ) SUBC MAX( PROG ) FROM TRDIR GROUP BY SUBC
  71. *&
  72. *E SELECT VBAK~* from VBAK UP TO 3 ROWS ORDER BY VKORG.
  73. *&
  74. *E SELECT T1~VBELN T2~POSNR FROM VBAk AS T1
  75. *E        JOIN VBAP AS T2 ON T1~VBELN = T2~VBELN
  76. *&
  77. *E INSERT SEOCLASSTX VALUES ( 'ZZMACLASS', ' ', 'Test claSS' )
  78. *&
  79. *E INSERT SEOCLASSTX SET CLSNAME = 'ZZMACLASS' DESCRIPT = 'TeSt class'
  80. *&
  81. *E UPDATE SEOCLASSTX SET DESCRIPT = 'txt' WHERE CLSNAME = 'ZZMACLASS'
  82. *&
  83. *E DELETE SEOCLASSTX WHERE CLSNAME = 'ZZMACLASS'
  84. *&
  85. *& Please send comment & improvements to http://quelquepart.biz
  86. *&---------------------------------------------------------------------*
  87. *& History :
  88. *& 2015.08.17 v3.1  :Add Manage drag&drop from DDIC tree to SQL Editor
  89. *&                   Mod Double clic on field in DDIC tree paste field
  90. *&                       in editor instead of filling clipboard
  91. *&                       Thanks to Shai Sinai for his suggestions
  92. *&                   Fix Issue with comment removing
  93. *&                   Add Ignore "into table" statement
  94. *&                   Add Ignore alias in field list
  95. *& 2015.06.13 v3.0  :Add INSERT, UPDATE, DELETE command
  96. *&                   Add Authorization management
  97. *&                   Add History tree display first query line if it
  98. *&                       is a comment line
  99. *&                   Mod Code cleaning
  100. *& 2015.03.05 v2.1.1:Mod grid size is no more changed before display
  101. *&                       query result
  102. *& 2015.01.11 v2.1  :Add UNION instruction managed to merge 2 queries
  103. *&                   Mod Do not refresh result grid for count(*)
  104. *&                   Mod Back close the grid instead of leave program if
  105. *&                       result grid is displayed
  106. *&                   Add Display program header as default help
  107. *&                   Add Run highlighted query
  108. *&                   Mod Documentation rewritten
  109. *& 2014.10.23 v2.0.2:Add Display number of entries found
  110. *&                   Add Confirmation before exit for unsaved queries
  111. *& 2014.10.19 v2.0.1:Fix bug on search ddic function
  112. *& 2014.08.03 v2.0 : Completely rewritten version
  113. *&                   - Save and share queries with colaborators
  114. *&                   - Queries are now saved in database
  115. *&                   - Display tables (+ fields) of the where clause
  116. *&                   - Display ZSPRO entries in ddic tree
  117. *&                   - Allow direct change in query after execution
  118. *&                   - Count( * ) allowed
  119. *&                   - Can display generated code
  120. *&                   - Display query execution time
  121. *&                   - Allow write of several queries (but 1 executed)
  122. *& 2013.12.03 v1.3 : Allow case sensitive constant in where clause
  123. *& 2012.08.30 v1.2 : Rewrite data definition to avoid dump on too long
  124. *&                   fieldname
  125. *& 2012.04.01 v1.1 : Updated to work also on BW system
  126. *& 2009.10.26 v1.0 : Initial release
  127. *&---------------------------------------------------------------------*
  128. * Modifications:
  129. * 1. Subroutine paste_to_editor: Add line break.
  130. * 2. Method handle_context_menu_repository: Add 'Delete All History'
  131. *    function.
  132. * 3. Authorization checks impelementation was modified.
  133. * 4. Subroutine init_toolbar, method handle_toolbar_function_sel:
  134. *    Create toolbar on right pane (above DDIC tree).
  135. * 5. Subroutines result_tab_extended_build, display_alv_data:
  136. *    Add Count column.
  137.  
  138. REPORT ztoad2.
  139.  
  140. *######################################################################*
  141. *
  142. *                        CUSTOMIZATION SECTION
  143. *
  144. *######################################################################*
  145.  
  146. CONSTANTS c_actvt_auth_display TYPE tactt-actvt VALUE '03'. "#EC NOTEXT
  147. CONSTANTS c_actvt_auth_create TYPE tactt-actvt VALUE '01'.  "#EC NOTEXT
  148. CONSTANTS c_actvt_auth_change TYPE tactt-actvt VALUE '02'.  "#EC NOTEXT
  149. CONSTANTS c_actvt_auth_delete TYPE tactt-actvt VALUE '06'.  "#EC NOTEXT
  150.  
  151. DATA : BEGIN OF s_auth,                                     "#EC NEEDED
  152. * You could define your authorization object to restrict
  153. * function usage by user
  154. * If you dont define auth object, all users will have same access as
  155. * defined bellow
  156. * The auth object must manage 4 IDs.
  157. * ID must be : SELECT, INSERT, UPDATE, DELETE
  158. * FIELD contain allowed table name pattern
  159. * '*' to allow all table, 'Z*' to allow all specific tables...
  160.          auth_object(20) TYPE c VALUE 'ZCA_TOAD',
  161.  
  162. * Bellow is default AUTH used if no auth_object is defined
  163. * Allow SELECT query on SAP table (restricted by given pattern)
  164.          select TYPE string VALUE '*',
  165. * Allow INSERT query on SAP table (restricted by given pattern)
  166.          insert TYPE string VALUE 'NONE',
  167. * Allow UPDATE query on SAP table (restricted by given pattern)
  168.          update TYPE string VALUE 'NONE',
  169. * Allow DELETE query on SAP table (restricted by given pattern)
  170.          delete TYPE string VALUE 'NONE',
  171.        END OF s_auth.
  172.  
  173. *######################################################################*
  174. *
  175. *                             DATA SECTION
  176. *
  177. *######################################################################*
  178. * Objects
  179. CLASS lcl_application DEFINITION DEFERRED.
  180.  
  181. * Screen objects
  182. DATA : o_handle_event TYPE REF TO lcl_application,
  183.        o_container TYPE REF TO cl_gui_custom_container,
  184.        o_splitter TYPE REF TO cl_gui_splitter_container,
  185.        o_splitter_top TYPE REF TO cl_gui_splitter_container,
  186.        o_splitter_right TYPE REF TO cl_gui_splitter_container,
  187.        o_container_top TYPE REF TO cl_gui_container,
  188.        o_container_right TYPE REF TO cl_gui_container,
  189.        o_container_repository TYPE REF TO cl_gui_container,
  190.        o_container_query TYPE REF TO cl_gui_container,
  191.        o_container_ddic TYPE REF TO cl_gui_container,
  192.        o_container_toolbar TYPE REF TO cl_gui_container,
  193.        o_container_result TYPE REF TO cl_gui_container,
  194.  
  195. * Editor data
  196.        o_textedit TYPE REF TO cl_gui_abapedit,
  197.  
  198. * Repository data
  199.        o_tree_repository TYPE REF TO cl_gui_simple_tree,
  200.        BEGIN OF s_node_repository.
  201.         INCLUDE TYPE treev_node. "mtreesnode.
  202. DATA :  text(100) TYPE c,
  203.         edit(1) TYPE c,
  204.          queryid TYPE ztoad-queryid,
  205.        END OF s_node_repository,
  206.        t_node_repository LIKE TABLE OF s_node_repository,
  207.  
  208.        o_toolbar TYPE REF TO cl_gui_toolbar,
  209.  
  210. * DDIC data
  211.        o_tree_ddic TYPE REF TO cl_gui_column_tree,
  212.        t_node_ddic TYPE treev_ntab,
  213.        t_item_ddic TYPE TABLE OF mtreeitm,
  214.        o_alv_result TYPE REF TO cl_gui_alv_grid,
  215.        o_result TYPE REF TO data,
  216.        w_dragdrop_handle_tree TYPE i,
  217. * ZSPRO data
  218.        t_node_zspro LIKE t_node_ddic,
  219.        t_item_zspro LIKE t_item_ddic,
  220.  
  221. * Save option
  222.        BEGIN OF s_options,
  223.          name TYPE ztoad-text,
  224.          visibility TYPE ztoad-visibility,
  225.          visibilitygrp TYPE usr02-class,
  226.        END OF s_options,
  227.  
  228. * Keep last loaded id
  229.        w_last_loaded_query TYPE ztoad-queryid.
  230.  
  231. DATA: gv_max_rows TYPE i VALUE 200.
  232.  
  233. FIELD-SYMBOLS: <gt_data> TYPE STANDARD TABLE.
  234.  
  235. DATA : w_okcode LIKE sy-ucomm.
  236.  
  237. * Global types
  238. TYPES : BEGIN OF ty_fieldlist,
  239.           field TYPE string,
  240.           ref_table TYPE string,
  241.           ref_field TYPE string,
  242.         END OF ty_fieldlist,
  243.         ty_fieldlist_table TYPE STANDARD TABLE OF ty_fieldlist.
  244.  
  245. * Constants
  246. CONSTANTS : c_ddic_col1 TYPE mtreeitm-item_name
  247.                         VALUE 'col1',                       "#EC NOTEXT
  248.             c_ddic_col2 TYPE mtreeitm-item_name
  249.                         VALUE 'col2',                       "#EC NOTEXT
  250.             c_ddic_header TYPE tv_hdrname
  251.                           VALUE 'HierarchyHeader',          "#EC NOTEXT
  252.             c_visibility_all TYPE ztoad-visibility VALUE '2',
  253.             c_visibility_shared TYPE ztoad-visibility VALUE '1',
  254.             c_visibility_my TYPE ztoad-visibility VALUE '0',
  255.             c_nodekey_repo_my TYPE mtreesnode-node_key VALUE 'MY',
  256.             c_nodekey_repo_shared TYPE mtreesnode-node_key
  257.                                   VALUE 'SHARED',
  258.             c_nodekey_repo_history TYPE mtreesnode-node_key
  259.                                    VALUE 'HISTO',
  260.             c_line_max TYPE i VALUE 255,
  261.             c_msg_success TYPE c VALUE 'S',
  262.             c_msg_error TYPE c VALUE 'E',
  263.             c_vers_active TYPE as4local VALUE 'A',
  264.             c_ddic_dtelm TYPE comptype VALUE 'E'.
  265.  
  266. *######################################################################*
  267. *
  268. *                             CLASS SECTION
  269. *
  270. *######################################################################*
  271.  
  272. *----------------------------------------------------------------------*
  273. *       CLASS lcl_drag_object DEFINITION
  274. *----------------------------------------------------------------------*
  275. *       Class to store object on drag & drop from DDIC to sql editor
  276. *----------------------------------------------------------------------*
  277. CLASS lcl_drag_object DEFINITION FINAL.
  278.   PUBLIC SECTION.
  279.     DATA field TYPE string.
  280. ENDCLASS."lcl_drag_object DEFINITION
  281.  
  282. *----------------------------------------------------------------------*
  283. *       CLASS lcl_application DEFINITION
  284. *----------------------------------------------------------------------*
  285. *       Class to handle application events
  286. *----------------------------------------------------------------------*
  287. CLASS lcl_application DEFINITION FINAL.
  288.   PUBLIC SECTION.
  289.     METHODS :
  290. * Handle F1 call on ABAP editor
  291.                handle_f1_textedit
  292.                    FOR EVENT f1 OF cl_gui_abapedit,
  293. * Handle Header clic on ddic tree
  294.                handle_header_click_ddic
  295.                    FOR EVENT header_click OF cl_gui_column_tree
  296.                    IMPORTING header_name,
  297. * Handle Node double clic on ddic tree
  298.                handle_item_dblclick_ddic
  299.                    FOR EVENT item_double_click OF cl_gui_column_tree
  300.                    IMPORTING node_key,
  301. * Handle context menu display on repository tree
  302.               handle_context_menu_repository
  303.                    FOR EVENT node_context_menu_request
  304.                    OF cl_gui_simple_tree
  305.                      IMPORTING menu,
  306. * Handle context menu clic on repository tree
  307.                handle_context_menu_sel_repo
  308.                    FOR EVENT node_context_menu_select
  309.                    OF cl_gui_simple_tree
  310.                        IMPORTING fcode,
  311. * Handle Node double clic on repository tree
  312.                handle_dblclick_repository
  313.                    FOR EVENT node_double_click OF cl_gui_simple_tree
  314.                    IMPORTING node_key,
  315. * Handle toolbar display on ALV result
  316.                handle_toolbar_result
  317.                    FOR EVENT toolbar OF cl_gui_alv_grid
  318.                    IMPORTING e_object,
  319. * Handle toolbar clic on ALV result
  320.                handle_user_command_result
  321.                    FOR EVENT user_command OF cl_gui_alv_grid
  322.                    IMPORTING e_ucomm,
  323. * Handle DDIC tree drag
  324.                handle_tree_drag
  325.                    FOR EVENT on_drag OF cl_gui_column_tree
  326.                    IMPORTING node_key drag_drop_object,
  327. * Handle editor drop
  328.                handle_edit_drop
  329.                    FOR EVENT on_drop OF cl_gui_abapedit
  330.                    IMPORTING line pos dragdrop_object,
  331.  
  332.                handle_toolbar_function_sel
  333.                  FOR EVENT function_selected OF cl_gui_toolbar
  334.                  IMPORTING fcode.
  335.  
  336. ENDCLASS.                    "lcl_application DEFINITION
  337.  
  338. *----------------------------------------------------------------------*
  339. *       CLASS LCL_APPLICATION IMPLEMENTATION
  340. *----------------------------------------------------------------------*
  341. *       Class to handle application events                             *
  342. *----------------------------------------------------------------------*
  343. CLASS lcl_application IMPLEMENTATION.
  344. *&---------------------------------------------------------------------*
  345. *&      CLASS lcl_application
  346. *&      METHOD handle_context_menu_repository
  347. *&---------------------------------------------------------------------*
  348. *       Handle context menu display on repository tree
  349. *----------------------------------------------------------------------*
  350.   METHOD handle_context_menu_repository.
  351.     DATA l_node_key TYPE tv_nodekey.
  352.  
  353.     CALL METHOD o_tree_repository->get_selected_node
  354.       IMPORTING
  355.         node_key = l_node_key.
  356.     IF l_node_key = 'HISTO'.
  357.       READ TABLE t_node_repository TRANSPORTING NO FIELDS
  358.         WITH KEY relatkey = 'HISTO'.
  359.       IF sy-subrc = 0.
  360.         CALL METHOD menu->add_function
  361.           EXPORTING
  362.             text  = 'Delete All'(m51)
  363.             icon  = '@02@'
  364.             fcode = 'DELETE_HIST'.
  365.       ENDIF.
  366.     ELSE.
  367. *     Add Delete option only for own queries
  368.       READ TABLE t_node_repository INTO s_node_repository
  369.                  WITH KEY node_key = l_node_key.
  370.       IF sy-subrc NE 0 OR s_node_repository-edit = space.
  371.         RETURN.
  372.       ENDIF.
  373.  
  374.       CALL METHOD menu->add_function
  375.         EXPORTING
  376.           text  = 'Delete'(m01)
  377.           icon  = '@02@'
  378.           fcode = 'DELETE_QUERY'.
  379.     ENDIF.
  380.   ENDMETHOD.                    "handle_context_menu_repository
  381.  
  382. *&---------------------------------------------------------------------*
  383. *&      CLASS lcl_application
  384. *&      METHOD handle_context_menu_sel_repo
  385. *&---------------------------------------------------------------------*
  386. *       Handle context menu clic on repository tree
  387. *----------------------------------------------------------------------*
  388.   METHOD handle_context_menu_sel_repo.
  389.  
  390.     CASE fcode.
  391.       WHEN 'DELETE_QUERY'.
  392. *       Delete stored query
  393.         PERFORM query_selected_delete.
  394.       WHEN 'DELETE_HIST'.
  395. *       Delete all histoy queries
  396.         PERFORM queries_hist_delete.
  397.     ENDCASE.
  398.   ENDMETHOD.                    "handle_context_menu_sel_repo
  399.  
  400. *&---------------------------------------------------------------------*
  401. *&      CLASS lcl_application
  402. *&      METHOD handle_f1_textedit
  403. *&---------------------------------------------------------------------*
  404. *       Handle F1 call on ABAP editor
  405. *----------------------------------------------------------------------*
  406.   METHOD handle_f1_textedit.
  407.     DATA : lw_cursor_line_from TYPE i,
  408.            lw_cursor_line_to TYPE i,
  409.            lw_cursor_pos_from TYPE i,
  410.            lw_cursor_pos_to TYPE i,
  411.            lw_offset TYPE i,
  412.            lw_length TYPE i,
  413.            lt_query TYPE soli_tab,
  414.            ls_query LIKE LINE OF lt_query,
  415.            lw_sel TYPE string.
  416.  
  417. * Find active query
  418.     CALL METHOD o_textedit->get_selection_pos
  419.       IMPORTING
  420.         from_line = lw_cursor_line_from
  421.         from_pos  = lw_cursor_pos_from
  422.         to_line   = lw_cursor_line_to
  423.         to_pos    = lw_cursor_pos_to.
  424.  
  425. * If nothing selected, no help to display
  426.     IF lw_cursor_line_from = lw_cursor_line_to
  427.     AND lw_cursor_pos_to = lw_cursor_pos_from.
  428.       RETURN.
  429.     ENDIF.
  430.  
  431. * Get content of abap edit box
  432.     CALL METHOD o_textedit->get_text
  433.       IMPORTING
  434.         table  = lt_query[]
  435.       EXCEPTIONS
  436.         OTHERS = 1.
  437.  
  438.  
  439.     READ TABLE lt_query INTO ls_query INDEX lw_cursor_line_from.
  440.     IF lw_cursor_line_from = lw_cursor_line_to.
  441.       lw_length = lw_cursor_pos_to - lw_cursor_pos_from.
  442.       lw_offset = lw_cursor_pos_from - 1.
  443.       lw_sel = ls_query+lw_offset(lw_length).
  444.     ELSE.
  445.       lw_offset = lw_cursor_pos_from - 1.
  446.       lw_sel = ls_query+lw_offset.
  447.     ENDIF.
  448.     CALL FUNCTION 'ABAP_DOCU_START'
  449.       EXPORTING
  450.         word = lw_sel.
  451.   ENDMETHOD.                    "handle_f1_textedit
  452.  
  453. *&---------------------------------------------------------------------*
  454. *&      CLASS lcl_application
  455. *&      METHOD handle_header_click_ddic
  456. *&---------------------------------------------------------------------*
  457. *       Handle Header clic on ddic tree :
  458. *       - Refresh tree on click on first column header
  459. *       - Search term on click on second column header
  460. *----------------------------------------------------------------------*
  461.   METHOD handle_header_click_ddic.
  462.     DATA : lw_query TYPE string,
  463.            lw_query2 TYPE string,
  464.            lw_select TYPE string,
  465.            lw_from TYPE string,
  466.            lw_from2 TYPE string,
  467.            lw_where TYPE string,
  468.            lw_union TYPE string,
  469.            lw_rows(10) TYPE n,
  470.            ls_sval TYPE sval,
  471.            lt_sval LIKE TABLE OF ls_sval,
  472.            lw_returncode TYPE c,
  473.            lw_search TYPE string,
  474.            lt_search LIKE TABLE OF lw_search,
  475.            ls_item_ddic LIKE LINE OF t_item_ddic,
  476.            lw_search_term TYPE string,
  477.            lw_search_line TYPE i,
  478.            lw_rest TYPE i,
  479.            lw_node_key TYPE tv_nodekey,
  480.            lt_nodekey TYPE TABLE OF tv_nodekey,
  481.            lw_noauth(1) TYPE c.
  482.  
  483. * For column 1 click => Refresh tree
  484.     IF header_name = c_ddic_header OR header_name = c_ddic_col1.
  485. * Get only usefull code for current query
  486.       PERFORM get_query USING space CHANGING lw_query.
  487.  
  488. * Parse Query
  489.       PERFORM parse_query USING lw_query
  490.                           CHANGING lw_select lw_from lw_where
  491.                                    lw_union lw_rows lw_noauth.
  492.       IF lw_noauth NE space.
  493.         RETURN.
  494.       ELSEIF lw_select IS INITIAL.
  495.         PERFORM parse_query_noselect USING lw_query
  496.                                      CHANGING lw_noauth lw_select
  497.                                               lw_from lw_where.
  498.         IF lw_noauth NE space.
  499.           RETURN.
  500.         ENDIF.
  501.       ENDIF.
  502. * Manage unioned queries
  503.       WHILE NOT lw_union IS INITIAL.
  504. * Parse Query
  505.         lw_query2 = lw_union.
  506.         PERFORM parse_query USING lw_query2
  507.                             CHANGING lw_select lw_from2 lw_where
  508.                                      lw_union lw_rows lw_noauth.
  509.         IF NOT lw_from2 IS INITIAL.
  510.           CONCATENATE lw_from 'JOIN' lw_from2
  511.                       INTO lw_from SEPARATED BY space.
  512.         ENDIF.
  513.         IF lw_noauth NE space.
  514.           RETURN.
  515.         ENDIF.
  516.       ENDWHILE.
  517.  
  518. * Refresh ddic tree with list of table/fields of the actual query
  519.       PERFORM set_ddic_tree USING lw_from.
  520. * For column 2 click => Search in description
  521.     ELSE.
  522. * Build search table
  523.       REFRESH lt_search.
  524.       LOOP AT t_item_ddic INTO ls_item_ddic.
  525.         lw_search = ls_item_ddic-text.
  526.         APPEND lw_search TO lt_search.
  527.         APPEND ls_item_ddic-node_key TO lt_nodekey.
  528.       ENDLOOP.
  529.  
  530. * Ask for selection search
  531.       ls_sval-tabname = 'RSDXX'.
  532.       ls_sval-fieldname = 'FINDSTR'.
  533.       ls_sval-value = space.
  534.       APPEND ls_sval TO lt_sval.
  535.       DO.
  536.         CALL FUNCTION 'POPUP_GET_VALUES'
  537.           EXPORTING
  538.             popup_title     = space
  539.           IMPORTING
  540.             returncode      = lw_returncode
  541.           TABLES
  542.             fields          = lt_sval
  543.           EXCEPTIONS
  544.             error_in_fields = 1
  545.             OTHERS          = 2.
  546.         IF sy-subrc NE 0 OR lw_returncode NE space.
  547.           EXIT. "exit do
  548.         ENDIF.
  549.         READ TABLE lt_sval INTO ls_sval INDEX 1.
  550.         IF ls_sval-value = space.
  551.           EXIT. "exit do
  552.         ENDIF.
  553.  
  554. * For new search, start from line 1
  555.         IF lw_search_term NE ls_sval-value.
  556.           lw_search_term = ls_sval-value.
  557.           lw_search_line = 1.
  558. * For next result of same search, start from next line
  559.         ELSE.
  560.           lw_rest = lw_search_line MOD 2.
  561.           lw_search_line = lw_search_line + 1 + lw_rest.
  562.         ENDIF.
  563.  
  564.         FIND FIRST OCCURRENCE OF ls_sval-value IN TABLE lt_search
  565.              FROM lw_search_line
  566.              IN CHARACTER MODE IGNORING CASE
  567.              MATCH LINE lw_search_line
  568.              .
  569.  
  570. * Search string &1 not found
  571.         IF sy-subrc NE 0 AND lw_search_line = 1.
  572.           MESSAGE s065(0k) WITH lw_search_term DISPLAY LIKE c_msg_error.
  573.           CLEAR lw_search_line.
  574.           CLEAR lw_search_term.
  575.  
  576. * Last selected entry reached
  577.         ELSEIF sy-subrc NE 0.
  578.           MESSAGE s066(0k) DISPLAY LIKE c_msg_error.
  579.           CLEAR lw_search_line.
  580.           CLEAR lw_search_term.
  581.  
  582. * Found
  583.         ELSE.
  584.           MESSAGE 'String found'(m04) TYPE c_msg_success.
  585.           READ TABLE lt_nodekey INTO lw_node_key INDEX lw_search_line.
  586.           CALL METHOD o_tree_ddic->set_selected_node
  587.             EXPORTING
  588.               node_key = lw_node_key.
  589.           CALL METHOD o_tree_ddic->ensure_visible
  590.             EXPORTING
  591.               node_key = lw_node_key.
  592.         ENDIF.
  593.  
  594.       ENDDO.
  595.     ENDIF.
  596.   ENDMETHOD.                    "handle_header_click_ddic
  597.  
  598. *&---------------------------------------------------------------------*
  599. *&      CLASS lcl_application
  600. *&      METHOD handle_item_dblclick_ddic
  601. *&---------------------------------------------------------------------*
  602. *       Handle Node double clic on ddic tree
  603. *----------------------------------------------------------------------*
  604.   METHOD handle_item_dblclick_ddic.
  605.     DATA : ls_node LIKE LINE OF t_node_ddic,
  606.            lw_line_start TYPE i,
  607.            lw_pos_start TYPE i,
  608.            lw_line_end TYPE i,
  609.            lw_pos_end TYPE i,
  610.            lw_data TYPE string.
  611.  
  612. * Check clicked node is valid
  613.     READ TABLE t_node_ddic INTO ls_node
  614.                WITH KEY node_key = node_key.
  615.     IF sy-subrc NE 0 OR ls_node-isfolder = abap_true.
  616.       RETURN.
  617.     ENDIF.
  618.  
  619. * Get text for the node selected
  620.     PERFORM get_field_from_node USING node_key ls_node-relatkey
  621.                                 CHANGING lw_data.
  622.  
  623. * Get current cursor position/selection in editor
  624.     CALL METHOD o_textedit->get_selection_pos
  625.       IMPORTING
  626.         from_line = lw_line_start
  627.         from_pos  = lw_pos_start
  628.         to_line   = lw_line_end
  629.         to_pos    = lw_pos_end
  630.       EXCEPTIONS
  631.         OTHERS    = 4.
  632.     IF sy-subrc NE 0.
  633.       MESSAGE 'Cannot get cursor position'(m35) TYPE c_msg_error.
  634.     ENDIF.
  635.  
  636. *   If text is selected/highlighted, delete it
  637.     IF lw_line_start NE lw_line_end
  638.     OR lw_pos_start NE lw_pos_end.
  639.       CALL METHOD o_textedit->delete_text
  640.         EXPORTING
  641.           from_line = lw_line_start
  642.           from_pos  = lw_pos_start
  643.           to_line   = lw_line_end
  644.           to_pos    = lw_pos_end.
  645.     ENDIF.
  646.  
  647.     PERFORM paste_to_editor USING lw_data lw_line_start lw_pos_start.
  648.   ENDMETHOD.                    "handle_item_dblclick_ddic
  649.  
  650. *&---------------------------------------------------------------------*
  651. *&      CLASS lcl_application
  652. *&      METHOD handle_dblclick_repository
  653. *&---------------------------------------------------------------------*
  654. *       Handle Node double clic on repository tree
  655. *----------------------------------------------------------------------*
  656.   METHOD handle_dblclick_repository.
  657.     DATA lt_query TYPE TABLE OF string.
  658.     READ TABLE t_node_repository INTO s_node_repository
  659.                WITH KEY node_key = node_key.
  660.     IF sy-subrc = 0 AND NOT s_node_repository-relatkey IS INITIAL.
  661.       PERFORM load_query USING s_node_repository-queryid
  662.                          CHANGING lt_query.
  663.  
  664.       CALL METHOD o_textedit->set_text
  665.         EXPORTING
  666.           table  = lt_query
  667.         EXCEPTIONS
  668.           OTHERS = 0.
  669.  
  670.       o_handle_event->handle_header_click_ddic( c_ddic_header ).
  671.     ENDIF.
  672.   ENDMETHOD. "handle_dblclick_repository
  673.  
  674. *&---------------------------------------------------------------------*
  675. *&      CLASS lcl_application
  676. *&      METHOD handle_toolbar_result
  677. *&---------------------------------------------------------------------*
  678. *       Handle grid toolbar to add specific button
  679. *----------------------------------------------------------------------*
  680.   METHOD handle_toolbar_result.
  681.     data: ls_toolbar TYPE stb_button.
  682.  
  683. * Add Separator
  684.     CLEAR ls_toolbar.
  685.     ls_toolbar-function = '&&SEP99'.
  686.     ls_toolbar-butn_type = 3.
  687.     APPEND ls_toolbar TO e_object->mt_toolbar.
  688.  
  689. * Add button to close the grid
  690.     CLEAR ls_toolbar.
  691.     ls_toolbar-function = 'CLOSE_GRID'.
  692.     ls_toolbar-icon = '@3X@'.
  693.     ls_toolbar-quickinfo = 'Close Grid'(m05).
  694.     ls_toolbar-text = 'Close'(m06).
  695.     ls_toolbar-butn_type = 0.
  696.     ls_toolbar-disabled = space.
  697.     APPEND ls_toolbar TO e_object->mt_toolbar.
  698.   ENDMETHOD.                    "handle_toolbar_result
  699.  
  700. *&---------------------------------------------------------------------*
  701. *&      CLASS lcl_application
  702. *&      METHOD handle_user_command
  703. *&---------------------------------------------------------------------*
  704. *       Handle grid user command to manage specific fcode
  705. *       (menus & toolbar)
  706. *----------------------------------------------------------------------*
  707.   METHOD handle_user_command_result.
  708.     CASE e_ucomm.
  709.       WHEN 'CLOSE_GRID'.
  710.         CALL METHOD o_splitter->set_row_height
  711.           EXPORTING
  712.             id     = 1
  713.             height = 100.
  714.     ENDCASE.
  715.   ENDMETHOD. "handle_user_command_result
  716.  
  717. *&---------------------------------------------------------------------*
  718. *&      CLASS lcl_application
  719. *&      METHOD handle_tree_drag
  720. *&---------------------------------------------------------------------*
  721. *       Handle drag on DDIC field (store fieldname)
  722. *----------------------------------------------------------------------*
  723.   METHOD handle_tree_drag.
  724.     DATA : lo_drag_object TYPE REF TO lcl_drag_object,
  725.            ls_node LIKE LINE OF t_node_ddic,
  726.            lw_text TYPE string.
  727.  
  728.     READ TABLE t_node_ddic INTO ls_node
  729.                WITH KEY node_key = node_key.
  730.     IF sy-subrc NE 0 OR ls_node-isfolder = abap_true. "may not append
  731.       MESSAGE 'Only fields can be drag&drop to editor'(m34)
  732.                TYPE c_msg_success DISPLAY LIKE c_msg_error.
  733.       RETURN.
  734.     ENDIF.
  735.  
  736. * Get text for the node selected
  737.     PERFORM get_field_from_node USING node_key ls_node-relatkey
  738.                                 CHANGING lw_text.
  739.  
  740. * Store the node text
  741.     CREATE OBJECT lo_drag_object.
  742.     lo_drag_object->field = lw_text.
  743.     drag_drop_object->object = lo_drag_object.
  744.  
  745.   ENDMETHOD."handle_tree_drag
  746.  
  747. *&---------------------------------------------------------------------*
  748. *&      CLASS lcl_application
  749. *&      METHOD handle_edit_drop
  750. *&---------------------------------------------------------------------*
  751. *       Handle drop on SQL Editor : paste fieldname at cursor position
  752. *----------------------------------------------------------------------*
  753.   METHOD handle_edit_drop.
  754.     DATA lo_drag_object TYPE REF TO lcl_drag_object.
  755.  
  756.     lo_drag_object ?= dragdrop_object->object.
  757.     IF lo_drag_object IS INITIAL OR lo_drag_object->field IS INITIAL.
  758.       RETURN.
  759.     ENDIF.
  760.  
  761. * Paste fieldname to editor at drop position
  762.     PERFORM paste_to_editor USING lo_drag_object->field line pos.
  763.  
  764.   ENDMETHOD."HANDLE_EDIT_DROP
  765.  
  766.   METHOD handle_toolbar_function_sel.
  767.     CASE fcode.
  768.       WHEN '9MAX_ROWS'.
  769.         PERFORM max_rows_input_popup CHANGING gv_max_rows.
  770.         PERFORM toolbar_max_rows_text_set.
  771.     ENDCASE.
  772.   ENDMETHOD.                    "handle_toolbar_function_sel
  773.  
  774. ENDCLASS.                    "lcl_application IMPLEMENTATION
  775.  
  776.  
  777. *######################################################################*
  778. *
  779. *                             MAIN SECTION
  780. *
  781. *######################################################################*
  782. START-OF-SELECTION.
  783.   CALL SCREEN 100.
  784.  
  785.  
  786. *######################################################################*
  787. *
  788. *                             PBO SECTION
  789. *
  790. *######################################################################*
  791. *&---------------------------------------------------------------------*
  792. *&      Module  STATUS_0100  OUTPUT
  793. *&---------------------------------------------------------------------*
  794. *       Set status for main screen
  795. *       and initialize custom container at first run
  796. *----------------------------------------------------------------------*
  797. MODULE status_0100 OUTPUT.
  798. * Initialization of object screen
  799.   IF o_container IS INITIAL.
  800.     PERFORM init_screen.
  801.   ENDIF.
  802.  
  803.   AUTHORITY-CHECK OBJECT 'S_DEVELOP' ID 'ACTVT' FIELD '03'
  804.                                      ID 'DEVCLASS' DUMMY
  805.                                      ID 'OBJTYPE' DUMMY
  806.                                      ID 'OBJNAME' DUMMY
  807.                                      ID 'P_GROUP' DUMMY.
  808.   IF sy-subrc = 0.
  809.     SET PF-STATUS 'STATUS100'.
  810.   ELSE.
  811. * If you dont have S_DEVELOP access in display, you probably dont
  812. * understand the code generated => do not display the button
  813.     SET PF-STATUS 'STATUS100' EXCLUDING 'SHOWCODE'.
  814.   ENDIF.
  815.   SET TITLEBAR 'STATUS100'.
  816.  
  817. ENDMODULE.                 " STATUS_0100  OUTPUT
  818.  
  819. *&---------------------------------------------------------------------*
  820. *&      Module  STATUS_0200  OUTPUT
  821. *&---------------------------------------------------------------------*
  822. *       Set status for modal box (save options)
  823. *----------------------------------------------------------------------*
  824. MODULE status_0200 OUTPUT.
  825.  
  826. * Fill dropdown listbox with values
  827.   PERFORM init_listbox_0200.
  828.  
  829.   SET PF-STATUS 'STATUS200'.
  830.   SET TITLEBAR 'STATUS200'.
  831.  
  832. ENDMODULE.                 " STATUS_0200  OUTPUT
  833.  
  834.  
  835. *######################################################################*
  836. *
  837. *                             PAI SECTION
  838. *
  839. *######################################################################*
  840.  
  841. *&---------------------------------------------------------------------*
  842. *&      Module  USER_COMMAND_0200  INPUT
  843. *&---------------------------------------------------------------------*
  844. *       PAI module for modal box (save options)
  845. *----------------------------------------------------------------------*
  846. MODULE user_command_0200 INPUT.
  847.   CASE w_okcode.
  848.     WHEN 'CLOSE'.
  849.       CLEAR s_options.
  850.       LEAVE TO SCREEN 0.
  851.     WHEN 'OK'.
  852.       LEAVE TO SCREEN 0.
  853.   ENDCASE.
  854. ENDMODULE.                 " USER_COMMAND_0200  INPUT
  855.  
  856. *&---------------------------------------------------------------------*
  857. *&      Module  USER_COMMAND_0100  INPUT
  858. *&---------------------------------------------------------------------*
  859. *       User command for main screen
  860. *----------------------------------------------------------------------*
  861. MODULE user_command_0100 INPUT.
  862.  
  863.   CASE w_okcode.
  864.     WHEN 'EXIT'.
  865.       PERFORM exit_program.
  866.     WHEN 'EXECUTE'.
  867.       PERFORM process_query USING space.
  868.     WHEN 'SAVE'.
  869.       PERFORM save_query.
  870.     WHEN 'SHOWCODE'.
  871.       PERFORM process_query USING abap_true.
  872.     WHEN 'HELP'.
  873.       PERFORM display_help.
  874.   ENDCASE.
  875. ENDMODULE.                 " USER_COMMAND_0100  INPUT
  876.  
  877. *######################################################################*
  878. *
  879. *                             FORM SECTION
  880. *
  881. *######################################################################*
  882.  
  883. *&---------------------------------------------------------------------*
  884. *&      Form  INIT_SCREEN
  885. *&---------------------------------------------------------------------*
  886. *       Initialize all objects on the screen
  887. *----------------------------------------------------------------------*
  888. FORM init_screen.
  889. * Create the handle object (required to catch events)
  890.   CREATE OBJECT o_handle_event.
  891.  
  892. * Split the screen into 4 parts
  893.   PERFORM init_splitter.
  894.  
  895. * Init History Tree
  896.   PERFORM init_repository.
  897.  
  898. * Init toolbar
  899.   PERFORM init_toolbar.
  900.  
  901. * Init DDic tree
  902.   PERFORM init_ddic.
  903.  
  904. * Init Query editor
  905.   PERFORM init_editor.
  906.  
  907. * Init ALV result object
  908.   PERFORM init_result.
  909.  
  910. ENDFORM.                    " INIT_SCREEN
  911.  
  912. *&---------------------------------------------------------------------*
  913. *&      Form  INIT_SPLITTER
  914. *&---------------------------------------------------------------------*
  915. *       Split the main screen in 2 lines
  916. * 1 line with 3 columns : Repository tree / Query code / Ddic tree
  917. * 1 line with ALV result
  918. *----------------------------------------------------------------------*
  919. FORM init_splitter.
  920. * Create the custom container
  921.   CREATE OBJECT o_container
  922.     EXPORTING
  923.       container_name = 'CUSTCONT'.
  924.  
  925. * Insert splitter into this container
  926.   CREATE OBJECT o_splitter
  927.     EXPORTING
  928.       parent  = o_container
  929.       rows    = 2
  930.       columns = 1.
  931.  
  932. * Get the first row of the main splitter
  933.   CALL METHOD o_splitter->get_container
  934.     EXPORTING
  935.       row       = 1
  936.       column    = 1
  937.     RECEIVING
  938.       container = o_container_top.
  939.  
  940. *  Spliter for the high part (first row)
  941.   CREATE OBJECT o_splitter_top
  942.     EXPORTING
  943.       parent  = o_container_top
  944.       rows    = 1
  945.       columns = 3.
  946.  
  947. * Affect an object to each "cell" of the high sub splitter
  948.   CALL METHOD o_splitter_top->get_container
  949.     EXPORTING
  950.       row       = 1
  951.       column    = 1
  952.     RECEIVING
  953.       container = o_container_repository.
  954.  
  955.   CALL METHOD o_splitter_top->get_container
  956.     EXPORTING
  957.       row       = 1
  958.       column    = 2
  959.     RECEIVING
  960.       container = o_container_query.
  961.  
  962.   CALL METHOD o_splitter_top->get_container
  963.     EXPORTING
  964.       row       = 1
  965.       column    = 3
  966.     RECEIVING
  967.       container = o_container_right.
  968.  
  969.   CALL METHOD o_splitter->get_container
  970.     EXPORTING
  971.       row       = 2
  972.       column    = 1
  973.     RECEIVING
  974.       container = o_container_result.
  975.  
  976. * Initial repartition :
  977. *   line 1 = 100% (code+repo+ddic)
  978. *   line 2 = 0% (result)
  979. *   line 1 col 1 & 3 = 20% (repo & ddic)
  980. *   line 1 col 2 = 60% (code)
  981.   CALL METHOD o_splitter->set_row_height
  982.     EXPORTING
  983.       id     = 1
  984.       height = 100.
  985.  
  986.   CALL METHOD o_splitter_top->set_column_width
  987.     EXPORTING
  988.       id    = 1
  989.       width = 20.
  990.   CALL METHOD o_splitter_top->set_column_width
  991.     EXPORTING
  992.       id    = 3
  993.       width = 20.
  994.  
  995. * Spliter for the right part (Toolbar/DDIC)
  996.   CREATE OBJECT o_splitter_right
  997.     EXPORTING
  998.       parent  = o_container_right
  999.       rows    = 2
  1000.       columns = 1.
  1001.   o_splitter_right->set_row_mode(
  1002.     EXPORTING
  1003.       mode = cl_gui_splitter_container=>mode_absolute
  1004.  
  1005.   ).
  1006.   CALL METHOD o_splitter_right->set_row_height
  1007.     EXPORTING
  1008.       id     = 1
  1009.       height = 30.
  1010.  
  1011.   CALL METHOD o_splitter_right->get_container
  1012.     EXPORTING
  1013.       row       = 2
  1014.       column    = 1
  1015.     RECEIVING
  1016.       container = o_container_ddic.
  1017.  
  1018.   CALL METHOD o_splitter_right->get_container
  1019.     EXPORTING
  1020.       row       = 1
  1021.       column    = 1
  1022.     RECEIVING
  1023.       container = o_container_toolbar.
  1024.  
  1025. ENDFORM.                    " INIT_SPLITTER
  1026.  
  1027. *&---------------------------------------------------------------------*
  1028. *&      Form  INIT_EDITOR
  1029. *&---------------------------------------------------------------------*
  1030. *       Initialize the sql editor object
  1031. *       Fill it with last query, or template if no previous query
  1032. *----------------------------------------------------------------------*
  1033. FORM init_editor.
  1034.   DATA : lt_events TYPE cntl_simple_events,
  1035.          ls_event TYPE cntl_simple_event,
  1036.          lt_default TYPE TABLE OF string,
  1037.          ls_default LIKE LINE OF lt_default,
  1038.          lw_queryid TYPE ztoad-queryid,
  1039.          lo_dragrop TYPE REF TO cl_dragdrop.
  1040.  
  1041. * Get last query used
  1042.   CONCATENATE sy-uname '#%' INTO lw_queryid.
  1043.   SELECT queryid
  1044.          INTO lw_queryid
  1045.          FROM ztoad
  1046.          UP TO 1 ROWS
  1047.          WHERE queryid LIKE lw_queryid
  1048.          AND owner = sy-uname
  1049.          ORDER BY aedat DESCENDING.
  1050.   ENDSELECT.
  1051.   IF sy-subrc = 0.
  1052.     PERFORM load_query USING lw_queryid
  1053.                        CHANGING lt_default.
  1054.     PERFORM focus_repository USING lw_queryid.
  1055.   ENDIF.
  1056.  
  1057. * If no last query found, use default template
  1058.   IF lt_default IS INITIAL.
  1059.     APPEND 'SELECT *' TO lt_default.                        "#EC NOTEXT
  1060.     APPEND 'FROM xxx' TO lt_default.                        "#EC NOTEXT
  1061.     APPEND 'WHERE xxx' TO lt_default.                       "#EC NOTEXT
  1062.     APPEND '.' TO lt_default.                               "#EC NOTEXT
  1063.   ENDIF.
  1064.  
  1065. * Create the sql editor
  1066.   CREATE OBJECT o_textedit
  1067.     EXPORTING
  1068.       parent = o_container_query.
  1069.  
  1070. * Register events
  1071.   SET HANDLER o_handle_event->handle_f1_textedit FOR o_textedit.
  1072.   SET HANDLER o_handle_event->handle_edit_drop FOR o_textedit.
  1073.  
  1074.   ls_event-eventid = cl_gui_textedit=>event_f1.
  1075.   APPEND ls_event TO lt_events.
  1076.  
  1077.   CALL METHOD o_textedit->set_registered_events
  1078.     EXPORTING
  1079.       events                    = lt_events
  1080.     EXCEPTIONS
  1081.       cntl_error                = 1
  1082.       cntl_system_error         = 2
  1083.       illegal_event_combination = 3.
  1084.  
  1085.   IF sy-subrc <> 0.
  1086.     IF sy-msgno IS NOT INITIAL.
  1087.       MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
  1088.               DISPLAY LIKE c_msg_error
  1089.               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 .
  1090.     ENDIF.
  1091.   ENDIF.
  1092.  
  1093. * Manage Drop on SQL editor
  1094.   CREATE OBJECT lo_dragrop.
  1095.   CALL METHOD lo_dragrop->add
  1096.     EXPORTING
  1097.       flavor     = 'EDIT_INSERT'
  1098.       dragsrc    = space
  1099.       droptarget = abap_true
  1100.       effect     = cl_dragdrop=>copy.
  1101.   CALL METHOD o_textedit->set_dragdrop
  1102.     EXPORTING
  1103.       dragdrop = lo_dragrop.
  1104.  
  1105. * Set Default template
  1106.   CALL METHOD o_textedit->set_text
  1107.     EXPORTING
  1108.       table  = lt_default
  1109.     EXCEPTIONS
  1110.       OTHERS = 0.
  1111.  
  1112. * Set focus
  1113.   CALL METHOD cl_gui_control=>set_focus
  1114.     EXPORTING
  1115.       control = o_textedit
  1116.     EXCEPTIONS
  1117.       OTHERS  = 0.
  1118.  
  1119.   o_handle_event->handle_header_click_ddic( c_ddic_header ).
  1120. ENDFORM.                    " INIT_EDITOR
  1121.  
  1122. *&---------------------------------------------------------------------*
  1123. *&      Form  process_query
  1124. *&---------------------------------------------------------------------*
  1125. *       Process selected query : execute or display code
  1126. *----------------------------------------------------------------------*
  1127. *      -->FP_DISPLAY : Flag abap_true to display code
  1128. *----------------------------------------------------------------------*
  1129. FORM process_query USING fp_display TYPE c.
  1130.   DATA : lw_query TYPE string,
  1131.          lw_select TYPE string,
  1132.          lw_from TYPE string,
  1133.          lw_where TYPE string,
  1134.          lw_union TYPE string,
  1135.          lw_query2 TYPE string,
  1136.          lw_command TYPE string,
  1137.          lw_rows(6) TYPE n,
  1138.          lw_program TYPE sy-repid,
  1139.          lo_result2 TYPE REF TO data,
  1140.          lt_fieldlist TYPE ty_fieldlist_table,
  1141.          lt_fieldlist2 TYPE ty_fieldlist_table,
  1142.          lw_count_only(1) TYPE c,
  1143.          lw_time TYPE p LENGTH 8 DECIMALS 2,
  1144.          lw_time2 LIKE lw_time,
  1145.          lw_count TYPE i,
  1146.          lw_count2 LIKE lw_count,
  1147.          lw_charnumb(12) TYPE c,
  1148.          lw_msg TYPE string,
  1149.          lw_noauth(1) TYPE c,
  1150.          lw_answer(1) TYPE c.
  1151.  
  1152.   FIELD-SYMBOLS : <lft_data> TYPE STANDARD TABLE,
  1153.                   <lft_data2> TYPE STANDARD TABLE.
  1154.  
  1155.   DATA: ld_result TYPE REF TO data.
  1156.  
  1157. * Get only usefull code for current query
  1158.   PERFORM get_query USING space CHANGING lw_query.
  1159.  
  1160. * Parse SELECT Query
  1161.   PERFORM parse_query USING lw_query
  1162.                       CHANGING lw_select lw_from lw_where
  1163.                                lw_union lw_rows lw_noauth.
  1164. * Not a select query
  1165.   IF lw_select IS INITIAL.
  1166.     PERFORM parse_query_noselect USING    lw_query
  1167.                                  CHANGING lw_noauth
  1168.                                           lw_command
  1169.                                           lw_from
  1170.                                           lw_where.
  1171.     IF lw_noauth NE space.
  1172.       RETURN.
  1173.     ENDIF.
  1174.     PERFORM generate_subroutine_noselect USING lw_command lw_from
  1175.                                                lw_where fp_display
  1176.                                          CHANGING lw_program.
  1177.     CONCATENATE 'Are you sure you want to do a'(m31) lw_command
  1178.                 'on table'(m32) lw_from '?'(m33)
  1179.                 INTO lw_msg SEPARATED BY space.
  1180.     CALL FUNCTION 'POPUP_TO_CONFIRM'
  1181.       EXPORTING
  1182.         titlebar              = 'Warning : critical operation'(t04)
  1183.         text_question         = lw_msg
  1184.         default_button        = '2'
  1185.         display_cancel_button = space
  1186.       IMPORTING
  1187.         answer                = lw_answer
  1188.       EXCEPTIONS
  1189.         text_not_found        = 1
  1190.         OTHERS                = 2.
  1191.     IF sy-subrc NE 0 OR lw_answer NE '1'.
  1192.       RETURN.
  1193.     ENDIF.
  1194.     lw_count_only = abap_true. "no result grid to display
  1195.   ELSEIF lw_noauth NE space.
  1196.     RETURN.
  1197.   ELSEIF lw_from IS INITIAL.
  1198.     MESSAGE 'Cannot parse the query'(m07) TYPE c_msg_error.
  1199.   ELSE.
  1200. * Generate SELECT subroutine
  1201.     PERFORM generate_subroutine USING lw_select lw_from
  1202.                                       lw_where fp_display
  1203.                                 CHANGING lw_program lw_rows
  1204.                                          lt_fieldlist lw_count_only.
  1205.   ENDIF.
  1206.  
  1207.  
  1208. * Call the generated subroutine
  1209.   IF NOT lw_program IS INITIAL.
  1210.     PERFORM run_sql IN PROGRAM (lw_program)
  1211.                     CHANGING o_result lw_time lw_count.
  1212.  
  1213. * For union, process second (and further) query
  1214.     WHILE NOT lw_union IS INITIAL.
  1215. * Parse Query
  1216.       lw_query2 = lw_union.
  1217.       PERFORM parse_query USING lw_query2
  1218.                           CHANGING lw_select lw_from lw_where
  1219.                                    lw_union lw_rows lw_noauth.
  1220.       IF lw_noauth NE space.
  1221.         RETURN.
  1222.       ELSEIF lw_select IS INITIAL OR lw_from IS INITIAL.
  1223.         MESSAGE 'Cannot parse the unioned query'(m08) TYPE c_msg_error.
  1224.         EXIT. "exit while
  1225.       ENDIF.
  1226. * Generate subroutine
  1227.       PERFORM generate_subroutine USING lw_select lw_from
  1228.                                         lw_where fp_display
  1229.                                   CHANGING lw_program lw_rows
  1230.                                            lt_fieldlist2 lw_count_only.
  1231. * Call the generated subroutine
  1232.       PERFORM run_sql IN PROGRAM (lw_program)
  1233.                       CHANGING lo_result2 lw_time2 lw_count2.
  1234. * Append lines of the further queries to the first query
  1235.       ASSIGN o_result->* TO <lft_data>.
  1236.       ASSIGN lo_result2->* TO <lft_data2>.
  1237.       APPEND LINES OF <lft_data2> TO <lft_data>.
  1238.       REFRESH <lft_data2>.
  1239.       lw_time = lw_time + lw_time2.
  1240.       lw_count = lw_count + lw_count2.
  1241.     ENDWHILE.
  1242.  
  1243. * Display message
  1244.     lw_charnumb = lw_time.
  1245.     CONCATENATE 'Query executed in'(m09) lw_charnumb INTO lw_msg
  1246.                 SEPARATED BY space.
  1247.     lw_charnumb = lw_count.
  1248.     IF NOT lw_select IS INITIAL.
  1249.       CONCATENATE lw_msg 'seconds.'(m10)
  1250.                   lw_charnumb 'entries found'(m11)
  1251.                   INTO lw_msg SEPARATED BY space.
  1252.     ELSE.
  1253.       CONCATENATE lw_msg 'seconds.'(m10)
  1254.                   lw_charnumb 'entries affected'(m12)
  1255.                   INTO lw_msg SEPARATED BY space.
  1256.     ENDIF.
  1257.     CONDENSE lw_msg.
  1258.     MESSAGE lw_msg TYPE c_msg_success.
  1259.  
  1260. * Display result except for count(*)
  1261.     IF lw_count_only IS INITIAL.
  1262.       ASSIGN o_result->* TO <lft_data>.
  1263.  
  1264. *     Build extended result table (With count column)
  1265.       PERFORM result_tab_extended_build USING <lft_data>
  1266.                                          CHANGING ld_result.
  1267.       ASSIGN ld_result->* TO <gt_data>.
  1268.       FREE <lft_data>[].
  1269.  
  1270.       PERFORM display_alv_data USING <gt_data> lt_fieldlist lw_query.
  1271.     ENDIF.
  1272.  
  1273.     PERFORM save_current_query.
  1274.   ENDIF.
  1275. ENDFORM.                    " PROCESS_QUERY
  1276.  
  1277. *&---------------------------------------------------------------------*
  1278. *&      Form  result_tab_extended_build
  1279. *&---------------------------------------------------------------------*
  1280. *       text
  1281. *----------------------------------------------------------------------*
  1282. *      -->IT_RESULT                  text
  1283. *      -->ED_RESULT_EXTENDED         text
  1284. *      -->DATA                       text
  1285. *      -->:                          text
  1286. *      -->LD_RESULT_EXTENDED_STRUCT  text
  1287. *----------------------------------------------------------------------*
  1288. FORM result_tab_extended_build
  1289.   USING it_result TYPE STANDARD TABLE
  1290.   CHANGING ed_result_extended TYPE REF TO data.
  1291.  
  1292.   DATA: ld_result_extended_struct TYPE REF TO data.
  1293.  
  1294.   FIELD-SYMBOLS: <lt_result_extended> TYPE STANDARD TABLE,
  1295.                  <ls_result> TYPE any,
  1296.                  <ls_result_extended> TYPE any,
  1297.                  <lv_count> TYPE i.
  1298.  
  1299. * Create extended result table (With count column)
  1300.   PERFORM result_tab_extended_create USING it_result
  1301.                                      CHANGING ed_result_extended.
  1302.   ASSIGN ed_result_extended->* TO <lt_result_extended>.
  1303.   CREATE DATA ld_result_extended_struct LIKE LINE OF <lt_result_extended>.
  1304.   ASSIGN ld_result_extended_struct->* TO <ls_result_extended>.
  1305.  
  1306. * Build extended result table data
  1307.   LOOP AT it_result ASSIGNING <ls_result>.
  1308.     MOVE-CORRESPONDING <ls_result> TO <ls_result_extended>.
  1309.  
  1310.     ASSIGN COMPONENT 'COUNT' OF STRUCTURE <ls_result_extended>
  1311.       TO <lv_count>.
  1312.     <lv_count> = 1.
  1313.  
  1314.     APPEND <ls_result_extended> TO <lt_result_extended>.
  1315.   ENDLOOP.
  1316.  
  1317. ENDFORM.                    "result_tab_extended_build
  1318.  
  1319. FORM result_tab_extended_create
  1320.   USING it_result TYPE STANDARD TABLE
  1321.   CHANGING ed_result_extended TYPE REF TO data.
  1322.  
  1323.   DATA: lo_tabledescr TYPE REF TO cl_abap_tabledescr,
  1324.         lo_structdescr TYPE REF TO cl_abap_structdescr,
  1325.         lt_components TYPE abap_component_tab,
  1326.         ls_components LIKE LINE OF lt_components.
  1327.  
  1328. * Get table/structure components
  1329.   lo_tabledescr ?= cl_abap_tabledescr=>describe_by_data( it_result ).
  1330.   lo_structdescr ?= lo_tabledescr->get_table_line_type( ).
  1331.   lt_components = lo_structdescr->get_components( ).
  1332.  
  1333. * Add Count component
  1334.   ls_components-name = 'COUNT'.
  1335.   ls_components-type = cl_abap_elemdescr=>get_i( ).
  1336.   APPEND ls_components TO lt_components.
  1337.  
  1338. * Create extended structure and table descriptors
  1339.   lo_structdescr = cl_abap_structdescr=>create( lt_components ).
  1340.   lo_tabledescr = cl_abap_tabledescr=>create( lo_structdescr ).
  1341.  
  1342. * Create extended data table
  1343.   CREATE DATA ed_result_extended TYPE HANDLE lo_tabledescr.
  1344.  
  1345. ENDFORM.                    "result_tab_extended_create
  1346.  
  1347. *&---------------------------------------------------------------------*
  1348. *&      Form  GET_QUERY
  1349. *&---------------------------------------------------------------------*
  1350. *       Return active query without comment
  1351. *----------------------------------------------------------------------*
  1352. *      -->FP_FORCE_LAST  Keep last request
  1353. *      <--FP_QUERY       Query code
  1354. *----------------------------------------------------------------------*
  1355. FORM get_query USING fp_force_last TYPE c
  1356.                CHANGING fp_query TYPE string.
  1357.   DATA : lt_query TYPE soli_tab,
  1358.          ls_query LIKE LINE OF lt_query,
  1359.          ls_find TYPE match_result,
  1360.          lt_find TYPE match_result_tab,
  1361.          lw_cursor_line TYPE i,
  1362.          lw_cursor_pos TYPE i,
  1363.          lw_delto_line TYPE i,
  1364.          lw_delto_pos TYPE i,
  1365.          lw_cursor_offset TYPE i,
  1366.          lw_last TYPE c.
  1367.  
  1368.   CLEAR fp_query.
  1369.  
  1370. * Get selected content
  1371.   CALL METHOD o_textedit->get_selected_text_as_table
  1372.     IMPORTING
  1373.       table = lt_query[].
  1374.  
  1375. * if no selected content, get complete content of abap edit box
  1376.   IF lt_query[] IS INITIAL.
  1377.     CALL METHOD o_textedit->get_text
  1378.       IMPORTING
  1379.         table  = lt_query[]
  1380.       EXCEPTIONS
  1381.         OTHERS = 1.
  1382.   ENDIF.
  1383.  
  1384. * Remove * comment
  1385.   LOOP AT lt_query INTO ls_query WHERE line(1) = '*'.
  1386.     CLEAR ls_query-line.
  1387.     MODIFY lt_query FROM ls_query.
  1388.   ENDLOOP.
  1389.  
  1390. * Remove " comment
  1391.   LOOP AT lt_query INTO ls_query WHERE line CS '"'.
  1392. *    condense ls_query-line.
  1393.     FIND FIRST OCCURRENCE OF '"' IN ls_query-line RESULTS ls_find.
  1394.     IF sy-subrc NE 0. "may not occurs
  1395.       CONTINUE.
  1396.     ENDIF.
  1397.     IF ls_find-offset GT 0.
  1398.       ls_query-line = ls_query-line(ls_find-offset).
  1399.     ELSE.
  1400.       CLEAR ls_query-line.
  1401.     ENDIF.
  1402.     MODIFY lt_query FROM ls_query.
  1403.   ENDLOOP.
  1404.  
  1405. * Find active query
  1406.   CALL METHOD o_textedit->get_selection_pos
  1407.     IMPORTING
  1408.       from_line = lw_cursor_line
  1409.       from_pos  = lw_cursor_pos.
  1410.   lw_cursor_offset = lw_cursor_pos - 1.
  1411.  
  1412.   FIND ALL OCCURRENCES OF '.' IN TABLE lt_query RESULTS lt_find.
  1413.   CLEAR : lw_delto_line,
  1414.           lw_delto_pos,
  1415.           lw_last.
  1416.   LOOP AT lt_find INTO ls_find.
  1417.     AT LAST.
  1418.       lw_last = abap_true.
  1419.     ENDAT.
  1420. * Active Query
  1421.     IF ls_find-line GT lw_cursor_line
  1422.     OR ( ls_find-line = lw_cursor_line
  1423.          AND ls_find-offset GE lw_cursor_offset )
  1424.     OR ( lw_last = abap_true AND fp_force_last = abap_true ).
  1425. * Delete all query after query active
  1426.       ls_find-line = ls_find-line + 1.
  1427.       DELETE lt_query FROM ls_find-line.
  1428.       ls_find-line = ls_find-line - 1.
  1429. * Do not keep the . for active query
  1430.       IF ls_find-offset = 0.
  1431.         DELETE lt_query FROM ls_find-line.
  1432.       ELSE.
  1433.         READ TABLE lt_query INTO ls_query INDEX ls_find-line.
  1434.         ls_query-line = ls_query-line(ls_find-offset).
  1435.         MODIFY lt_query FROM ls_query INDEX ls_find-line.
  1436.       ENDIF.
  1437.       EXIT.
  1438. * Query before active
  1439.     ELSE.
  1440.       lw_delto_line = ls_find-line.
  1441.       lw_delto_pos = ls_find-offset + 1.
  1442.     ENDIF.
  1443.   ENDLOOP.
  1444.  
  1445. * Delete all query before query active
  1446.   IF NOT lw_delto_line IS INITIAL.
  1447.     IF lw_delto_line GT 1.
  1448.       lw_delto_line = lw_delto_line - 1.
  1449.       DELETE lt_query FROM 1 TO lw_delto_line.
  1450.     ENDIF.
  1451.     READ TABLE lt_query INTO ls_query INDEX 1.
  1452.     ls_query-line(lw_delto_pos) = ''.
  1453.     MODIFY lt_query FROM ls_query INDEX 1.
  1454.   ENDIF.
  1455.  
  1456. * Delete empty lines
  1457.   DELETE lt_query WHERE line CO ' .'.
  1458.  
  1459. * Build query string & Remove unnessential spaces
  1460.   LOOP AT lt_query INTO ls_query.
  1461.     CONDENSE ls_query-line.
  1462.     SHIFT ls_query-line LEFT DELETING LEADING space.
  1463.     CONCATENATE fp_query ls_query-line INTO fp_query SEPARATED BY space.
  1464.   ENDLOOP.
  1465.   IF NOT fp_query IS INITIAL.
  1466.     fp_query = fp_query+1.
  1467.   ENDIF.
  1468.  
  1469.   CLEAR lw_cursor_pos.
  1470. * Remove useless into (corresponding fields of) table
  1471.   IF fp_query CS 'into table'. "ignoring case
  1472.     lw_cursor_pos = sy-fdpos.
  1473.     lw_cursor_offset = sy-fdpos + 11.
  1474.   ELSEIF fp_query CS 'into corresponding fields of table'. "ignoring case
  1475.     lw_cursor_pos = sy-fdpos.
  1476.     lw_cursor_offset = sy-fdpos + 35.
  1477.   ELSEIF fp_query CS 'into corresponding fields of'. "ignoring case
  1478.     lw_cursor_pos = sy-fdpos.
  1479.     lw_cursor_offset = sy-fdpos + 29.
  1480.   ENDIF.
  1481. * Word after into table is the internal table name, remove it with "into table"
  1482.   IF lw_cursor_pos NE 0.
  1483.     DO.
  1484.       lw_last = fp_query+lw_cursor_offset(1).
  1485.       IF lw_last = space.
  1486.         lw_cursor_offset = lw_cursor_offset + 1.
  1487.         CONCATENATE fp_query(lw_cursor_pos) fp_query+lw_cursor_offset INTO fp_query.
  1488.         EXIT. "exit do
  1489.       ENDIF.
  1490.       lw_cursor_offset = lw_cursor_offset + 1.
  1491.     ENDDO.
  1492.   ENDIF.
  1493.  
  1494. * If no query selected, try to get the last one
  1495.   IF lt_query IS INITIAL AND fp_force_last = space.
  1496.     PERFORM get_query USING abap_true
  1497.                       CHANGING fp_query.
  1498.   ENDIF.
  1499. ENDFORM.                    " GET_QUERY
  1500.  
  1501. *&---------------------------------------------------------------------*
  1502. *&      Form  PARSE_QUERY
  1503. *&---------------------------------------------------------------------*
  1504. *       Split the query into 3 parts : Select / From / Where
  1505. *       - Select : List of the fields to extract
  1506. *       - From   : List of the tables - with join condition
  1507. *       - Where  : List of filters + group, order, having clauses
  1508. *----------------------------------------------------------------------*
  1509. *      -->FP_QUERY   Query to parse
  1510. *      <--FP_SELECT  Select part of the query
  1511. *      <--FP_FROM    From part of the query
  1512. *      <--FP_WHERE   Where part of the query
  1513. *      <--FP_ROWS    Number of rows to display
  1514. *      <--FP_UNION   Union part of the query
  1515. *      <--FP_NOAUTH  Unallowed table entered
  1516. *----------------------------------------------------------------------*
  1517. FORM parse_query  USING    fp_query TYPE string
  1518.                   CHANGING fp_select TYPE string
  1519.                            fp_from TYPE string
  1520.                            fp_where TYPE string
  1521.                            fp_union TYPE string
  1522.                            fp_rows TYPE n
  1523.                            fp_noauth TYPE c.
  1524.   DATA : ls_find_select TYPE match_result,
  1525.          ls_find_from TYPE match_result,
  1526.          ls_find_where TYPE match_result,
  1527.          ls_sub LIKE LINE OF ls_find_select-submatches,
  1528.          lw_offset TYPE i,
  1529.          lw_length TYPE i,
  1530.          lw_query TYPE string,
  1531.          lo_regex TYPE REF TO cl_abap_regex,
  1532.          lt_split TYPE TABLE OF string,
  1533.          lw_string TYPE string,
  1534.          lw_tabix TYPE i,
  1535.          lw_table TYPE tabname.
  1536.  
  1537.   CLEAR : fp_select,
  1538.           fp_from,
  1539.           fp_where,
  1540.           fp_rows,
  1541.           fp_union,
  1542.           fp_noauth.
  1543.  
  1544.   lw_query = fp_query.
  1545.  
  1546. * Search union
  1547.   FIND FIRST OCCURRENCE OF ' UNION SELECT ' IN lw_query
  1548.        RESULTS ls_find_select IGNORING CASE.
  1549.   IF sy-subrc = 0.
  1550.     lw_offset = ls_find_select-offset + 7.
  1551.     fp_union = lw_query+lw_offset.
  1552.     lw_query = lw_query(ls_find_select-offset).
  1553.   ENDIF.
  1554.  
  1555. * Create regex
  1556.   CREATE OBJECT lo_regex
  1557.     EXPORTING
  1558.       pattern     = 'UP TO ([0-9]+) ROWS'
  1559.       ignore_case = abap_true.
  1560.  
  1561. * Search UP TO xxx ROWS.
  1562. * Catch the number of rows, delete command in query
  1563.   FIND FIRST OCCURRENCE OF REGEX lo_regex
  1564.        IN fp_query RESULTS ls_find_select.
  1565.   IF sy-subrc = 0.
  1566.     READ TABLE ls_find_select-submatches INTO ls_sub INDEX 1.
  1567.     IF sy-subrc = 0.
  1568.       fp_rows = lw_query+ls_sub-offset(ls_sub-length).
  1569.     ENDIF.
  1570.     REPLACE FIRST OCCURRENCE OF REGEX lo_regex IN lw_query WITH ''.
  1571.   ENDIF.
  1572.  
  1573.   FIND FIRST OCCURRENCE OF 'SELECT ' IN lw_query
  1574.        RESULTS ls_find_select IGNORING CASE.
  1575.   IF sy-subrc NE 0.
  1576.     RETURN.
  1577.   ENDIF.
  1578.  
  1579.   FIND FIRST OCCURRENCE OF ' FROM '
  1580.        IN SECTION OFFSET ls_find_select-offset OF lw_query
  1581.        RESULTS ls_find_from IGNORING CASE.
  1582.   IF sy-subrc NE 0.
  1583.     RETURN.
  1584.   ENDIF.
  1585.  
  1586.   FIND FIRST OCCURRENCE OF ' WHERE '
  1587.        IN SECTION OFFSET ls_find_from-offset OF lw_query
  1588.        RESULTS ls_find_where IGNORING CASE.
  1589.   IF sy-subrc NE 0.
  1590.     FIND FIRST OCCURRENCE OF ' GROUP BY ' IN lw_query
  1591.          RESULTS ls_find_where IGNORING CASE.
  1592.   ENDIF.
  1593.   IF sy-subrc NE 0.
  1594.     FIND FIRST OCCURRENCE OF ' HAVING ' IN lw_query
  1595.          RESULTS ls_find_where IGNORING CASE.
  1596.   ENDIF.
  1597.   IF sy-subrc NE 0.
  1598.     FIND FIRST OCCURRENCE OF ' ORDER BY ' IN lw_query
  1599.          RESULTS ls_find_where IGNORING CASE.
  1600.   ENDIF.
  1601.  
  1602.   lw_offset = ls_find_select-offset + 7.
  1603.   lw_length = ls_find_from-offset - ls_find_select-offset - 7.
  1604.   IF lw_length > 0.
  1605.     fp_select = lw_query+lw_offset(lw_length).
  1606.   ENDIF.
  1607.  
  1608.   lw_offset = ls_find_from-offset + 6.
  1609.   IF ls_find_where IS INITIAL.
  1610.     fp_from = lw_query+lw_offset.
  1611.     fp_where = ''.
  1612.   ELSE.
  1613.     lw_length = ls_find_where-offset - ls_find_from-offset - 6.
  1614.     fp_from = lw_query+lw_offset(lw_length).
  1615.     lw_offset = ls_find_where-offset.
  1616.     fp_where = lw_query+lw_offset.
  1617.   ENDIF.
  1618.  
  1619. * Set default number of rows to default
  1620.   IF fp_rows IS INITIAL.
  1621.     fp_rows = gv_max_rows.
  1622.   ENDIF.
  1623.  
  1624. * Remove , in field list
  1625.   IF fp_select CS ','.
  1626.     REPLACE ALL OCCURRENCES OF ',' IN fp_select WITH ''.
  1627.   ENDIF.
  1628.  
  1629. * Authority-check on used select tables
  1630.   IF s_auth-auth_object NE space OR s_auth-select NE '*'.
  1631.     CONCATENATE 'JOIN' fp_from INTO lw_string SEPARATED BY space.
  1632.     TRANSLATE lw_string TO UPPER CASE.
  1633.     SPLIT lw_string AT space INTO TABLE lt_split.
  1634.     LOOP AT lt_split INTO lw_string.
  1635.       lw_tabix = sy-tabix + 1.
  1636.       CHECK lw_string = 'JOIN'.
  1637. * Read next line (table name)
  1638.       READ TABLE lt_split INTO lw_table INDEX lw_tabix.
  1639.       CHECK sy-subrc = 0.
  1640.  
  1641.       IF s_auth-auth_object NE space.
  1642.         AUTHORITY-CHECK OBJECT s_auth-auth_object
  1643.           ID 'TABLE' FIELD lw_table
  1644.           ID 'ACTVT' FIELD c_actvt_auth_display.
  1645.       ELSEIF s_auth-select NE '*' AND NOT lw_table CP s_auth-select.
  1646.         sy-subrc = 4.
  1647.       ENDIF.
  1648.       IF sy-subrc NE 0.
  1649.         CONCATENATE 'No authorisation for table'(m13) lw_table
  1650.                     INTO lw_string SEPARATED BY space.
  1651.         MESSAGE lw_string TYPE c_msg_success DISPLAY LIKE c_msg_error.
  1652.         CLEAR fp_from.
  1653.         fp_noauth = abap_true.
  1654.         RETURN.
  1655.       ENDIF.
  1656.     ENDLOOP.
  1657.   ENDIF.
  1658.  
  1659. ENDFORM.                    " PARSE_QUERY
  1660.  
  1661. *&---------------------------------------------------------------------*
  1662. *&      Form  add_line_to_table
  1663. *&---------------------------------------------------------------------*
  1664. *       Add a string line in a table
  1665. *       Break line at 255 char, respecting words if possible
  1666. *----------------------------------------------------------------------*
  1667. *      -->FP_LINE    Line to add in table
  1668. *      <--FT_TABLE   Table to append
  1669. *----------------------------------------------------------------------*
  1670. FORM add_line_to_table USING fp_line TYPE string
  1671.                        CHANGING ft_table TYPE table.
  1672.   DATA : lw_length TYPE i,
  1673.          lw_offset TYPE i,
  1674.          ls_find TYPE match_result.
  1675.  
  1676.   lw_length = strlen( fp_line ).
  1677.   lw_offset = 0.
  1678.   DO.
  1679.     IF lw_length LE c_line_max.
  1680.       APPEND fp_line+lw_offset(lw_length) TO ft_table.
  1681.       EXIT. "exit do
  1682.     ELSE.
  1683.       FIND ALL OCCURRENCES OF REGEX '\s' "search space
  1684.            IN SECTION OFFSET lw_offset LENGTH c_line_max
  1685.            OF fp_line RESULTS ls_find.
  1686.       IF sy-subrc NE 0.
  1687.         APPEND fp_line+lw_offset(c_line_max) TO ft_table.
  1688.         lw_length = lw_length - c_line_max.
  1689.         lw_offset = lw_offset + c_line_max.
  1690.       ELSE.
  1691.         ls_find-length = ls_find-offset - lw_offset.
  1692.         APPEND fp_line+lw_offset(ls_find-length) TO ft_table.
  1693.         lw_length = lw_length + lw_offset - ls_find-offset - 1.
  1694.         lw_offset = ls_find-offset + 1.
  1695.       ENDIF.
  1696.     ENDIF.
  1697.   ENDDO.
  1698.  
  1699. ENDFORM.                    "add_line_to_table
  1700.  
  1701. *&---------------------------------------------------------------------*
  1702. *&      Form  GENERATE_SUBROUTINE
  1703. *&---------------------------------------------------------------------*
  1704. *       Create SELECT SQL query in a new generated temp program
  1705. *----------------------------------------------------------------------*
  1706. *      -->FP_SELECT    Select part of the query
  1707. *      -->FP_FROM      From part of the query
  1708. *      -->FP_WHERE     Where part of the query
  1709. *      -->FP_DISPLAY   Display code instead of generated routine
  1710. *      <--FP_PROGRAM   Name of the generated program
  1711. *      <--FP_ROWS      Number of rows to display
  1712. *      <--FT_FIELDLIST List of fields to display
  1713. *----------------------------------------------------------------------*
  1714. FORM generate_subroutine  USING    fp_select TYPE string
  1715.                                    fp_from TYPE string
  1716.                                    fp_where TYPE string
  1717.                                    fp_display TYPE c
  1718.                           CHANGING fp_program TYPE sy-repid
  1719.                                    fp_rows TYPE n
  1720.                                    ft_fieldlist TYPE ty_fieldlist_table
  1721.                                    fp_count TYPE c.
  1722.  
  1723.   DATA : lt_code_string TYPE TABLE OF string,
  1724.          lt_split TYPE TABLE OF string,
  1725.          lw_string TYPE string,
  1726.          lw_string2 TYPE string,
  1727.          BEGIN OF ls_table_alias,
  1728.            table(50) TYPE c,
  1729.            alias(50) TYPE c,
  1730.          END OF ls_table_alias,
  1731.          lt_table_alias LIKE TABLE OF ls_table_alias,
  1732.          lw_select TYPE string,
  1733.          lw_from TYPE string,
  1734.          lw_index TYPE i,
  1735.          lw_select_distinct TYPE c,
  1736.          lw_select_length TYPE i,
  1737.          lw_char_10(10) TYPE c,
  1738.          lw_field_number(6) TYPE n,
  1739.          lw_current_line TYPE i,
  1740.          lw_current_length TYPE i,
  1741.          lw_struct_line TYPE string,
  1742.          lw_struct_line_type TYPE string,
  1743.          lw_select_table TYPE string,
  1744.          lw_select_field TYPE string,
  1745.          lw_dd03l_fieldname TYPE dd03l-fieldname,
  1746.          lw_position_dummy TYPE dd03l-position,
  1747.          lw_mess(255),
  1748.          lw_line TYPE i,
  1749.          lw_word(30),
  1750.          ls_fieldlist TYPE ty_fieldlist,
  1751.          lw_strlen_string TYPE string,
  1752.          lw_explicit TYPE string.
  1753.  
  1754.   DEFINE c.
  1755.     lw_strlen_string = &1.
  1756.     perform add_line_to_table using lw_strlen_string
  1757.                               changing lt_code_string.
  1758.   END-OF-DEFINITION.
  1759.  
  1760.   CLEAR : lw_select_distinct,
  1761.           fp_count.
  1762.  
  1763. * Write Header
  1764.   c 'PROGRAM SUBPOOL.'.
  1765.   c '** GENERATED PROGRAM * DO NOT CHANGE IT **'.
  1766.   c 'TYPE-POOLS: slis.'.                                    "#EC NOTEXT
  1767.   c ''.
  1768.  
  1769.   lw_select = fp_select.
  1770.   TRANSLATE lw_select TO UPPER CASE.
  1771.  
  1772.   lw_from = fp_from.
  1773.   TRANSLATE lw_from TO UPPER CASE.
  1774.  
  1775. * Search special term "single" or "distinct"
  1776.   lw_select_length = strlen( lw_select ).
  1777.   IF lw_select_length GE 7.
  1778.     lw_char_10 = lw_select(7).
  1779.     IF lw_char_10 = 'SINGLE'.
  1780. * Force rows number = 1 for select single
  1781.       fp_rows = 1.
  1782.       lw_select = lw_select+7.
  1783.       lw_select_length = lw_select_length - 7.
  1784.     ENDIF.
  1785.   ENDIF.
  1786.   IF lw_select_length GE 9.
  1787.     lw_char_10 = lw_select(9).
  1788.     IF lw_char_10 = 'DISTINCT'.
  1789.       lw_select_distinct = abap_true.
  1790.       lw_select = lw_select+9.
  1791.       lw_select_length = lw_select_length - 9.
  1792.     ENDIF.
  1793.   ENDIF.
  1794.  
  1795. * Search for special syntax "count( * )"
  1796.   IF lw_select = 'COUNT( * )'.
  1797.     fp_count = abap_true.
  1798.   ENDIF.
  1799.  
  1800. * Create alias table mapping
  1801.   SPLIT lw_from AT space INTO TABLE lt_split.
  1802.   LOOP AT lt_split INTO lw_string.
  1803.     IF lw_string IS INITIAL OR lw_string CO space.
  1804.       DELETE lt_split.
  1805.     ENDIF.
  1806.   ENDLOOP.
  1807.   DO.
  1808.     READ TABLE lt_split TRANSPORTING NO FIELDS WITH KEY = 'AS'.
  1809.     IF sy-subrc NE 0.
  1810.       EXIT. "exit do
  1811.     ENDIF.
  1812.     lw_index = sy-tabix - 1.
  1813.     READ TABLE lt_split INTO lw_string INDEX lw_index.
  1814.     ls_table_alias-table = lw_string.
  1815.     DELETE lt_split INDEX lw_index. "delete table field
  1816.     DELETE lt_split INDEX lw_index. "delete keywork AS
  1817.     READ TABLE lt_split INTO lw_string INDEX lw_index.
  1818.     ls_table_alias-alias = lw_string.
  1819.     DELETE lt_split INDEX lw_index. "delete alias field
  1820.     APPEND ls_table_alias TO lt_table_alias.
  1821.   ENDDO.
  1822. * If no alias table found, create just an entry for "*"
  1823.   IF lt_table_alias[] IS INITIAL.
  1824.     READ TABLE lt_split INTO lw_string INDEX 1.
  1825.     ls_table_alias-table = lw_string.
  1826.     ls_table_alias-alias = '*'.
  1827.     APPEND ls_table_alias TO lt_table_alias.
  1828.   ENDIF.
  1829.   SORT lt_table_alias BY alias.
  1830.  
  1831. * Write Data declaration
  1832.   c '***************************************'.              "#EC NOTEXT
  1833.   c '*      Begin of data declaration      *'.              "#EC NOTEXT
  1834.   c '*   Used to store lines of the query  *'.              "#EC NOTEXT
  1835.   c '***************************************'.              "#EC NOTEXT
  1836.   c 'DATA: BEGIN OF s_result'.                              "#EC NOTEXT
  1837.   lw_field_number = 1.
  1838.   SPLIT lw_select AT space INTO TABLE lt_split.
  1839.  
  1840.   LOOP AT lt_split INTO lw_string.
  1841.     lw_current_line = sy-tabix.
  1842.     IF lw_string = 'AS'.
  1843.       DELETE lt_split INDEX lw_current_line. "delete AS
  1844.       DELETE lt_split INDEX lw_current_line. "delete the alias name
  1845.       CONTINUE.
  1846.     ENDIF.
  1847.     lw_current_length = strlen( lw_string ).
  1848.  
  1849.     CLEAR ls_fieldlist.
  1850.     ls_fieldlist-ref_field = lw_string.
  1851. * Manage "Count"
  1852.     IF lw_current_length GE 6.
  1853.       lw_char_10 = lw_string(6).
  1854.     ELSE.
  1855.       CLEAR lw_char_10.
  1856.     ENDIF.
  1857.     IF lw_char_10 = 'COUNT('.
  1858.       CONCATENATE 'F' lw_field_number INTO ls_fieldlist-field.
  1859.       CONCATENATE ',' ls_fieldlist-field INTO lw_struct_line.
  1860.  
  1861.       lw_index = lw_current_line + 1.
  1862.       DO.
  1863.         SEARCH lw_string FOR ')'.
  1864.         IF sy-subrc = 0.
  1865.           EXIT.
  1866.         ELSE.
  1867. * If there is space in the "count()", delete next lines
  1868.           READ TABLE lt_split INTO lw_string INDEX lw_index.
  1869.           IF sy-subrc NE 0.
  1870.             EXIT.
  1871.           ENDIF.
  1872.           CONCATENATE ls_fieldlist-ref_field lw_string
  1873.                       INTO ls_fieldlist-ref_field SEPARATED BY space.
  1874.           DELETE lt_split INDEX lw_index.
  1875.         ENDIF.
  1876.       ENDDO.
  1877.       CONCATENATE lw_struct_line 'TYPE i'                   "#EC NOTEXT
  1878.                   INTO lw_struct_line SEPARATED BY space.
  1879.       c lw_struct_line.
  1880.       APPEND ls_fieldlist TO ft_fieldlist.
  1881.       lw_field_number = lw_field_number + 1.
  1882.       CONTINUE.
  1883.     ENDIF.
  1884.  
  1885. * Manage Agregate AVG
  1886.     IF lw_current_length GE 4.
  1887.       lw_char_10 = lw_string(4).
  1888.     ELSE.
  1889.       CLEAR lw_char_10.
  1890.     ENDIF.
  1891.     IF lw_char_10 = 'AVG('.
  1892.       CONCATENATE 'F' lw_field_number INTO ls_fieldlist-field.
  1893.       CONCATENATE ',' ls_fieldlist-field INTO lw_struct_line.
  1894.  
  1895.       lw_index = lw_current_line + 1.
  1896.       DO.
  1897.         SEARCH lw_string FOR ')'.
  1898.         IF sy-subrc = 0.
  1899.           EXIT.
  1900.         ELSE.
  1901. * If there is space in the agregate, delete next lines
  1902.           READ TABLE lt_split INTO lw_string INDEX lw_index.
  1903.           IF sy-subrc NE 0.
  1904.             EXIT.
  1905.           ENDIF.
  1906.           CONCATENATE ls_fieldlist-ref_field lw_string
  1907.                       INTO ls_fieldlist-ref_field SEPARATED BY space.
  1908.           DELETE lt_split INDEX lw_index.
  1909.         ENDIF.
  1910.       ENDDO.
  1911.       CONCATENATE lw_struct_line 'TYPE f'                   "#EC NOTEXT
  1912.                   INTO lw_struct_line SEPARATED BY space.
  1913.       c lw_struct_line.
  1914.       APPEND ls_fieldlist TO ft_fieldlist.
  1915.       lw_field_number = lw_field_number + 1.
  1916.       CONTINUE.
  1917.     ENDIF.
  1918.  
  1919. * Manage agregate SUM, MAX, MIN
  1920.     IF lw_current_length GE 4.
  1921.       lw_char_10 = lw_string(4).
  1922.     ELSE.
  1923.       CLEAR lw_char_10.
  1924.     ENDIF.
  1925.     IF lw_char_10 = 'SUM(' OR lw_char_10 = 'MAX('
  1926.     OR lw_char_10 = 'MIN('.
  1927.       lw_index = lw_current_line + 1.
  1928.       DO.
  1929.         SEARCH lw_string FOR ')'.
  1930.         IF sy-subrc = 0.
  1931.           EXIT.
  1932.         ELSE.
  1933. * Search name of the field in next lines.
  1934.           READ TABLE lt_split INTO lw_string INDEX lw_index.
  1935.           IF sy-subrc NE 0.
  1936.             EXIT.
  1937.           ENDIF.
  1938.           CONCATENATE ls_fieldlist-ref_field lw_string
  1939.                       INTO ls_fieldlist-ref_field SEPARATED BY space.
  1940.           IF lw_string2 IS INITIAL.
  1941.             lw_string2 = lw_string.
  1942.           ENDIF.
  1943. * Delete lines of agregage in field table
  1944.           DELETE lt_split INDEX lw_index.
  1945.         ENDIF.
  1946.       ENDDO.
  1947.       lw_string = lw_string2.
  1948.     ENDIF.
  1949.  
  1950. * Now lw_string contain a field name.
  1951. * We have to find the field description
  1952.     SPLIT lw_string AT '~' INTO lw_select_table lw_select_field.
  1953.     IF lw_select_field IS INITIAL.
  1954.       lw_select_field = lw_select_table.
  1955.       lw_select_table = '*'.
  1956.     ENDIF.
  1957. * Search if alias table used
  1958.     CLEAR ls_table_alias.
  1959.     READ TABLE lt_table_alias INTO ls_table_alias
  1960.                WITH KEY alias = lw_select_table             "#EC WARNOK
  1961.                BINARY SEARCH.
  1962.     IF sy-subrc = 0.
  1963.       lw_select_table = ls_table_alias-table.
  1964.     ENDIF.
  1965.     ls_fieldlist-ref_table = lw_select_table.
  1966.     IF lw_string = '*' OR lw_select_field = '*'. " expansion table~*
  1967.       CLEAR lw_explicit.
  1968.       SELECT fieldname position
  1969.       INTO   (lw_dd03l_fieldname,lw_position_dummy)
  1970.       FROM   dd03l
  1971.       WHERE  tabname    = lw_select_table
  1972.       AND    fieldname <> 'MANDT'
  1973.       AND    as4local   = c_vers_active
  1974.       AND    as4vers    = space
  1975.       AND (  comptype   = c_ddic_dtelm
  1976.           OR comptype   = space )
  1977.       ORDER BY position.
  1978.  
  1979.         lw_select_field = lw_dd03l_fieldname.
  1980.  
  1981.         CONCATENATE 'F' lw_field_number INTO ls_fieldlist-field.
  1982.         ls_fieldlist-ref_field = lw_select_field.
  1983.         APPEND ls_fieldlist TO ft_fieldlist.
  1984.         CONCATENATE ',' ls_fieldlist-field INTO lw_struct_line.
  1985.  
  1986.         CONCATENATE lw_select_table '-' lw_select_field
  1987.                     INTO lw_struct_line_type.
  1988.         CONCATENATE lw_struct_line 'TYPE' lw_struct_line_type
  1989.                     INTO lw_struct_line
  1990.                     SEPARATED BY space.
  1991.         c lw_struct_line.
  1992.         lw_field_number = lw_field_number + 1.
  1993. * Explicit list of fields instead of *
  1994. * Generate longer query but mandatory in case of T1~* or MARA~*
  1995. * Required also in some special cases, for example if table use include
  1996.         IF ls_table_alias-alias = space OR ls_table_alias-alias = '*'.
  1997.           CONCATENATE lw_explicit lw_select_table
  1998.                       INTO lw_explicit SEPARATED BY space.
  1999.         ELSE.
  2000.           CONCATENATE lw_explicit ls_table_alias-alias
  2001.                       INTO lw_explicit SEPARATED BY space.
  2002.         ENDIF.
  2003.         CONCATENATE lw_explicit '~' lw_select_field INTO lw_explicit.
  2004.       ENDSELECT.
  2005.       IF sy-subrc NE 0.
  2006.         MESSAGE e701(1r) WITH lw_select_table. "table does not exist
  2007.       ENDIF.
  2008.       IF NOT lw_explicit IS INITIAL.
  2009.         REPLACE FIRST OCCURRENCE OF lw_string
  2010.                 IN lw_select WITH lw_explicit.
  2011.       ENDIF.
  2012.  
  2013.     ELSE. "Simple field
  2014.       CONCATENATE 'F' lw_field_number INTO ls_fieldlist-field.
  2015.       ls_fieldlist-ref_field = lw_select_field.
  2016.       APPEND ls_fieldlist TO ft_fieldlist.
  2017.  
  2018.       CONCATENATE ',' ls_fieldlist-field INTO lw_struct_line.
  2019.  
  2020.       CONCATENATE lw_select_table '-' lw_select_field
  2021.                   INTO lw_struct_line_type.
  2022.       CONCATENATE lw_struct_line 'TYPE' lw_struct_line_type
  2023.                   INTO lw_struct_line
  2024.                   SEPARATED BY space.
  2025.       c lw_struct_line.
  2026.       lw_field_number = lw_field_number + 1.
  2027.     ENDIF.
  2028.   ENDLOOP.
  2029.  
  2030.   c ', END OF s_result'.                                    "#EC NOTEXT
  2031.   c ', t_result like table of s_result'.                    "#EC NOTEXT
  2032.   c ', w_timestart type timestampl'.                        "#EC NOTEXT
  2033.   c ', w_timeend type timestampl.'.                         "#EC NOTEXT
  2034.  
  2035. * Write the dynamic subroutine that run the SELECT
  2036.   c 'FORM run_sql CHANGING fp_result TYPE REF TO data'.     "#EC NOTEXT
  2037.   c '                      fp_time type p'.                 "#EC NOTEXT
  2038.   c '                      fp_count type i.'.               "#EC NOTEXT
  2039.   c '***************************************'.              "#EC NOTEXT
  2040.   c '*            Begin of query           *'.              "#EC NOTEXT
  2041.   c '***************************************'.              "#EC NOTEXT
  2042.   c 'get TIME STAMP FIELD w_timestart.'.                    "#EC NOTEXT
  2043.   IF fp_count = abap_true.
  2044.     CONCATENATE 'SELECT SINGLE' lw_select                   "#EC NOTEXT
  2045.                 INTO lw_select SEPARATED BY space.
  2046.     c lw_select.
  2047.     c 'INTO s_result-f000001'.                              "#EC NOTEXT
  2048.   ELSE.
  2049.     IF lw_select_distinct NE space.
  2050.       CONCATENATE 'SELECT DISTINCT' lw_select               "#EC NOTEXT
  2051.                   INTO lw_select SEPARATED BY space.
  2052.     ELSE.
  2053.       CONCATENATE 'SELECT' lw_select                        "#EC NOTEXT
  2054.                   INTO lw_select SEPARATED BY space.
  2055.     ENDIF.
  2056.     c lw_select.
  2057.     c 'INTO TABLE t_result'.                                "#EC NOTEXT
  2058.  
  2059. * Add UP TO xxx ROWS
  2060.     c 'UP TO'.                                              "#EC NOTEXT
  2061.     c fp_rows.
  2062.     c 'ROWS'.                                               "#EC NOTEXT
  2063.   ENDIF.
  2064.  
  2065.   c 'FROM'.                                                 "#EC NOTEXT
  2066.   c lw_from.
  2067.  
  2068. * Where, group by, having, order by
  2069.   IF NOT fp_where IS INITIAL.
  2070.     c fp_where.
  2071.   ENDIF.
  2072.   c '.'.
  2073.  
  2074. * Display query execution time
  2075.   c 'get TIME STAMP FIELD w_timeend.'.                      "#EC NOTEXT
  2076.   c 'fp_time = w_timeend - w_timestart.'.                   "#EC NOTEXT
  2077.   c 'fp_count = sy-dbcnt.'.                                 "#EC NOTEXT
  2078.  
  2079. * If select count( * ), display number of results
  2080.   IF fp_count NE space.
  2081.     c 'MESSAGE i753(TG) WITH s_result-f000001.'.            "#EC NOTEXT
  2082.   ENDIF.
  2083.  
  2084.   c 'GET REFERENCE OF t_result INTO fp_result.'.            "#EC NOTEXT
  2085.   c 'ENDFORM.'.                                             "#EC NOTEXT
  2086.   CLEAR : lw_line,
  2087.           lw_word,
  2088.           lw_mess.
  2089.   SYNTAX-CHECK FOR lt_code_string PROGRAM sy-repid
  2090.                MESSAGE lw_mess LINE lw_line WORD lw_word.
  2091.   IF sy-subrc NE 0 AND fp_display = space.
  2092.     MESSAGE lw_mess TYPE c_msg_error.
  2093.   ENDIF.
  2094.  
  2095.   IF fp_display = space.
  2096.     GENERATE SUBROUTINE POOL lt_code_string NAME fp_program.
  2097.   ELSE.
  2098.     IF lw_mess IS NOT INITIAL.
  2099.       lw_explicit = lw_line.
  2100.       CONCATENATE lw_mess '(line'(m28) lw_explicit ',word'(m29)
  2101.                   lw_word ')'(m30)
  2102.                   INTO lw_mess SEPARATED BY space.
  2103.       MESSAGE lw_mess TYPE c_msg_success DISPLAY LIKE c_msg_error.
  2104.     ENDIF.
  2105.     EDITOR-CALL FOR lt_code_string DISPLAY-MODE
  2106.                 TITLE 'Generated code for current query'(t01).
  2107.   ENDIF.
  2108.  
  2109. ENDFORM.                    " GENERATE_SUBROUTINE
  2110.  
  2111. *&---------------------------------------------------------------------*
  2112. *&      Form  DISPLAY_ALV_DATA
  2113. *&---------------------------------------------------------------------*
  2114. *       Display data table in the bottom ALV part of the screen
  2115. *----------------------------------------------------------------------*
  2116. *      -->FP_RESULT    Reference to data to display
  2117. *      -->FT_FIELDLIST List of fields to display
  2118. *      -->FP_TITLE     Title of the ALV
  2119. *----------------------------------------------------------------------*
  2120. FORM display_alv_data  USING it_result TYPE STANDARD TABLE
  2121.                              ft_fieldlist TYPE ty_fieldlist_table
  2122.                              fp_title TYPE string.
  2123.   TYPE-POOLS lvc.
  2124.  
  2125.   DATA : ls_layout TYPE lvc_s_layo,
  2126.          lt_fieldcat TYPE lvc_t_fcat.
  2127.   DATA : lw_height TYPE i.
  2128.  
  2129.   FIELD-SYMBOLS: <ls_fieldlist> LIKE LINE OF ft_fieldlist,
  2130.                  <ls_fieldcat> LIKE LINE OF lt_fieldcat.
  2131.  
  2132. * Build field catalog
  2133.   lt_fieldcat = zcl_ca_alv_utils=>fieldcat_build( it_result ).
  2134.  
  2135. * Adjuest column texts for COUNT/AVG fields
  2136.   LOOP AT ft_fieldlist ASSIGNING <ls_fieldlist>
  2137.     WHERE ref_table IS INITIAL.
  2138.     UNASSIGN <ls_fieldcat>.
  2139.     READ TABLE lt_fieldcat ASSIGNING <ls_fieldcat>
  2140.       WITH KEY fieldname = <ls_fieldlist>-field.
  2141.     <ls_fieldcat>-scrtext_s = <ls_fieldlist>-ref_field.
  2142.     <ls_fieldcat>-scrtext_m = <ls_fieldlist>-ref_field.
  2143.     <ls_fieldcat>-scrtext_l = <ls_fieldlist>-ref_field.
  2144.     <ls_fieldcat>-reptext = <ls_fieldlist>-ref_field.
  2145.   ENDLOOP.
  2146.  
  2147.   ls_layout-smalltitle = abap_true.
  2148.   ls_layout-zebra = abap_true.
  2149.   ls_layout-cwidth_opt = abap_true.
  2150.   ls_layout-grid_title = fp_title.
  2151.   ls_layout-countfname = 'COUNT'.
  2152.  
  2153. * Set the grid config and content
  2154.   CALL METHOD o_alv_result->set_table_for_first_display
  2155.     EXPORTING
  2156.       is_layout       = ls_layout
  2157.     CHANGING
  2158.       it_outtab       = it_result
  2159.       it_fieldcatalog = lt_fieldcat.
  2160.  
  2161. * Search if grid is currently displayed
  2162.   CALL METHOD o_splitter->get_row_height
  2163.     EXPORTING
  2164.       id     = 1
  2165.     IMPORTING
  2166.       result = lw_height.
  2167.   CALL METHOD cl_gui_cfw=>flush.
  2168.  
  2169. * If grid is hidden, display it
  2170.   IF lw_height = 100.
  2171.     CALL METHOD o_splitter->set_row_height
  2172.       EXPORTING
  2173.         id     = 1
  2174.         height = 20.
  2175.   ENDIF.
  2176. ENDFORM.                    " DISPLAY_ALV_DATA
  2177.  
  2178. *&---------------------------------------------------------------------*
  2179. *&      Form  INIT_DDIC
  2180. *&---------------------------------------------------------------------*
  2181. *       Init ddic tree
  2182. *----------------------------------------------------------------------*
  2183. FORM init_ddic.
  2184.   DATA : ls_header TYPE treev_hhdr,
  2185.          ls_event TYPE cntl_simple_event,
  2186.          lt_events TYPE cntl_simple_events,
  2187.          lo_dragdrop TYPE REF TO cl_dragdrop.
  2188.  
  2189.   ls_header-heading = 'SAP Table/Fields'(t02).
  2190.   ls_header-t_image = '@42@'. "Refresh icon
  2191.   ls_header-width = 30.
  2192.  
  2193.   CREATE OBJECT o_tree_ddic
  2194.     EXPORTING
  2195.       parent                      = o_container_ddic
  2196.       node_selection_mode         = cl_gui_column_tree=>node_sel_mode_single
  2197.       item_selection              = abap_true
  2198.       hierarchy_column_name       = c_ddic_col1
  2199.       hierarchy_header            = ls_header
  2200.     EXCEPTIONS
  2201.       cntl_system_error           = 1
  2202.       create_error                = 2
  2203.       failed                      = 3
  2204.       illegal_node_selection_mode = 4
  2205.       illegal_column_name         = 5
  2206.       lifetime_error              = 6.
  2207.   IF sy-subrc <> 0.
  2208.     MESSAGE a000(tree_control_msg).
  2209.   ENDIF.
  2210.  
  2211. * Column2
  2212.   CALL METHOD o_tree_ddic->add_column
  2213.     EXPORTING
  2214.       name                         = c_ddic_col2
  2215.       width                        = 21
  2216.       header_text                  = 'Description'(t03)
  2217.       header_image                 = '@13@'
  2218.     EXCEPTIONS
  2219.       column_exists                = 1
  2220.       illegal_column_name          = 2
  2221.       too_many_columns             = 3
  2222.       illegal_alignment            = 4
  2223.       different_column_types       = 5
  2224.       cntl_system_error            = 6
  2225.       failed                       = 7
  2226.       predecessor_column_not_found = 8.
  2227.  
  2228. * Manage Header clic event to refresh screen
  2229.   ls_event-eventid = cl_gui_column_tree=>eventid_header_click.
  2230.   ls_event-appl_event = abap_true.
  2231.   APPEND ls_event TO lt_events.
  2232.  
  2233. * Manage Item clic event to copy value in clipboard
  2234.   ls_event-eventid = cl_gui_column_tree=>eventid_item_double_click.
  2235.   ls_event-appl_event = abap_true.
  2236.   APPEND ls_event TO lt_events.
  2237.  
  2238.   CALL METHOD o_tree_ddic->set_registered_events
  2239.     EXPORTING
  2240.       events                    = lt_events
  2241.     EXCEPTIONS
  2242.       cntl_error                = 1
  2243.       cntl_system_error         = 2
  2244.       illegal_event_combination = 3.
  2245.   IF sy-subrc <> 0.
  2246.     MESSAGE a000(tree_control_msg).
  2247.   ENDIF.
  2248.  
  2249. * Manage Drag from DDIC editor
  2250.   CREATE OBJECT lo_dragdrop.
  2251.   CALL METHOD lo_dragdrop->add
  2252.     EXPORTING
  2253.       flavor     = 'EDIT_INSERT'
  2254.       dragsrc    = abap_true
  2255.       droptarget = space
  2256.       effect     = cl_dragdrop=>copy.
  2257.   CALL METHOD lo_dragdrop->get_handle
  2258.     IMPORTING
  2259.       handle = w_dragdrop_handle_tree.
  2260.  
  2261.   SET HANDLER o_handle_event->handle_header_click_ddic FOR o_tree_ddic.
  2262.   SET HANDLER o_handle_event->handle_item_dblclick_ddic FOR o_tree_ddic.
  2263.   SET HANDLER o_handle_event->handle_tree_drag FOR o_tree_ddic.
  2264.  
  2265. * Calculate ZSPRO nodes to add at the bottom of the ddic tree
  2266.   PERFORM add_tree_zspro IN PROGRAM (sy-repid) IF FOUND.
  2267.  
  2268. ENDFORM.                    " INIT_DDIC
  2269.  
  2270. *&---------------------------------------------------------------------*
  2271. *&      Form  init_toolbar
  2272. *&---------------------------------------------------------------------*
  2273. *       text
  2274. *----------------------------------------------------------------------*
  2275. FORM init_toolbar.
  2276.  
  2277.   DATA: lt_button TYPE ttb_button,
  2278.         ls_button LIKE LINE OF lt_button,
  2279.         lt_events TYPE cntl_simple_events,
  2280.         ls_events LIKE LINE OF lt_events.
  2281.  
  2282.   CREATE OBJECT o_toolbar
  2283.     EXPORTING
  2284.       parent = o_container_toolbar.
  2285.  
  2286. * Add buttons to toolbar
  2287.   ls_button-function = '9MAX_ROWS'.
  2288.   ls_button-icon = icon_change_number.
  2289.   ls_button-quickinfo = 'Set Default Max Rows'(tt2).
  2290.   ls_button-butn_type = cntb_btype_button.
  2291.   APPEND ls_button TO lt_button.
  2292.   CALL METHOD o_toolbar->add_button_group
  2293.     EXPORTING
  2294.       data_table = lt_button.
  2295.   PERFORM toolbar_max_rows_text_set.
  2296.  
  2297. * Register events
  2298.   ls_events-eventid = cl_gui_toolbar=>m_id_function_selected.
  2299.   ls_events-appl_event = ' '.
  2300.   APPEND ls_events TO lt_events.
  2301.   CALL METHOD o_toolbar->set_registered_events
  2302.     EXPORTING
  2303.       events = lt_events.
  2304.  
  2305.   SET HANDLER o_handle_event->handle_toolbar_function_sel FOR o_toolbar.
  2306.  
  2307. ENDFORM.                    "init_toolbar
  2308.  
  2309. *&---------------------------------------------------------------------*
  2310. *&      Form  SET_DDIC_TREE
  2311. *&---------------------------------------------------------------------*
  2312. *       Refresh query with list of table/fields of the given query
  2313. *       Add User defined tree from ZSPRO (if relevant)
  2314. *----------------------------------------------------------------------*
  2315. *      -->FP_FROM  From part of the query
  2316. *----------------------------------------------------------------------*
  2317. FORM set_ddic_tree USING fp_from TYPE string.
  2318.  
  2319.   DATA : lw_from TYPE string,
  2320.          lt_split TYPE TABLE OF string,
  2321.          lw_string TYPE string,
  2322.          lw_tabix TYPE i,
  2323.          BEGIN OF ls_table_list,
  2324.            table(30),
  2325.            alias(30),
  2326.          END OF ls_table_list,
  2327.          lt_table_list LIKE TABLE OF ls_table_list,
  2328.          lw_node_number(6) TYPE n,
  2329.          ls_node LIKE LINE OF t_node_ddic,
  2330.          ls_item LIKE LINE OF t_item_ddic,
  2331.          lw_parent_node LIKE ls_node-node_key,
  2332.          BEGIN OF ls_ddic_fields,
  2333.            tabname TYPE dd03l-tabname,
  2334.            fieldname TYPE dd03l-fieldname,
  2335.            position TYPE dd03l-position,
  2336.            keyflag TYPE dd03l-keyflag,
  2337.            ddtext1 TYPE dd03t-ddtext,
  2338.            ddtext2 TYPE dd04t-ddtext,
  2339.          END OF ls_ddic_fields,
  2340.          lt_ddic_fields LIKE TABLE OF ls_ddic_fields.
  2341.  
  2342.   CONCATENATE 'FROM' fp_from INTO lw_from SEPARATED BY space.
  2343.  
  2344.   TRANSLATE lw_from TO UPPER CASE.
  2345.  
  2346.   SPLIT lw_from AT space INTO TABLE lt_split.
  2347.   LOOP AT lt_split INTO lw_string.
  2348.     lw_tabix = sy-tabix + 1.
  2349.     CHECK sy-tabix = 1 OR lw_string = 'JOIN'.
  2350. * Read next line (table name)
  2351.     READ TABLE lt_split INTO lw_string INDEX lw_tabix.
  2352.     CHECK sy-subrc = 0.
  2353.  
  2354.     CLEAR ls_table_list.
  2355.     ls_table_list-table = lw_string.
  2356.  
  2357.     lw_tabix = lw_tabix + 1.
  2358. * Read next line (search alias)
  2359.     READ TABLE lt_split INTO lw_string INDEX lw_tabix.
  2360.     IF sy-subrc = 0 AND lw_string = 'AS'.
  2361.       lw_tabix = lw_tabix + 1.
  2362.       READ TABLE lt_split INTO lw_string INDEX lw_tabix.
  2363.       IF sy-subrc = 0.
  2364.         ls_table_list-alias = lw_string.
  2365.       ENDIF.
  2366.     ENDIF.
  2367.     APPEND ls_table_list TO lt_table_list.
  2368.   ENDLOOP.
  2369.  
  2370. * Get list of fields for selected tables
  2371.   IF NOT lt_table_list IS INITIAL.
  2372.     SELECT dd03l~tabname dd03l~fieldname dd03l~position
  2373.            dd03l~keyflag dd03t~ddtext dd04t~ddtext
  2374.            INTO TABLE lt_ddic_fields
  2375.            FROM dd03l
  2376.            LEFT OUTER JOIN dd03t
  2377.            ON dd03l~tabname = dd03t~tabname
  2378.            AND dd03l~fieldname = dd03t~fieldname
  2379.            AND dd03l~as4local = dd03t~as4local
  2380.            AND dd03t~ddlanguage = sy-langu
  2381.            LEFT OUTER JOIN dd04t
  2382.            ON dd03l~rollname = dd04t~rollname
  2383.            AND dd03l~as4local = dd04t~as4local
  2384.            AND dd04t~ddlanguage = sy-langu
  2385.            FOR ALL ENTRIES IN lt_table_list
  2386.            WHERE dd03l~tabname = lt_table_list-table
  2387.            AND dd03l~as4local = c_vers_active
  2388.            AND dd03l~as4vers = space
  2389.            AND ( dd03l~comptype = c_ddic_dtelm
  2390.            OR    dd03l~comptype = space ).
  2391.     SORT lt_ddic_fields BY tabname keyflag DESCENDING position.
  2392.     DELETE ADJACENT DUPLICATES FROM lt_ddic_fields
  2393.                                COMPARING tabname fieldname.
  2394.   ENDIF.
  2395.  
  2396. * Build Node & Item tree
  2397.   REFRESH : t_node_ddic,
  2398.             t_item_ddic.
  2399.   lw_node_number = 0.
  2400.   LOOP AT lt_table_list INTO ls_table_list.
  2401. * Check table exists (has at least one field)
  2402.     READ TABLE lt_ddic_fields TRANSPORTING NO FIELDS
  2403.                WITH KEY tabname = ls_table_list-table.
  2404.     IF sy-subrc NE 0.
  2405.       DELETE lt_table_list.
  2406.       CONTINUE.
  2407.     ENDIF.
  2408.  
  2409.     lw_node_number = lw_node_number + 1.
  2410.     CLEAR ls_node.
  2411.     ls_node-node_key = lw_node_number.
  2412.     ls_node-isfolder = abap_true.
  2413.     ls_node-n_image = '@PO@'.
  2414.     ls_node-exp_image = '@PO@'.
  2415.     ls_node-expander = abap_true.
  2416.     APPEND ls_node TO t_node_ddic.
  2417.  
  2418.     CLEAR ls_item.
  2419.     ls_item-node_key = lw_node_number.
  2420.     ls_item-class = cl_gui_column_tree=>item_class_text.
  2421.     ls_item-item_name = c_ddic_col1.
  2422.     IF ls_table_list-alias IS INITIAL.
  2423.       ls_item-text = ls_table_list-table.
  2424.     ELSE.
  2425.       CONCATENATE ls_table_list-table 'AS' ls_table_list-alias
  2426.                    INTO ls_item-text SEPARATED BY space.
  2427.     ENDIF.
  2428.     APPEND ls_item TO t_item_ddic.
  2429.     ls_item-item_name = c_ddic_col2.
  2430.     SELECT SINGLE ddtext INTO ls_item-text
  2431.            FROM dd02t
  2432.            WHERE tabname = ls_table_list-table
  2433.            AND ddlanguage = sy-langu
  2434.            AND as4local = c_vers_active
  2435.            AND as4vers = space.
  2436.     IF sy-subrc NE 0.
  2437.       ls_item-text = ls_table_list-table.
  2438.     ENDIF.
  2439.     APPEND ls_item TO t_item_ddic.
  2440.  
  2441. * Display list of fields
  2442.     lw_parent_node = ls_node-node_key.
  2443.     LOOP AT lt_ddic_fields INTO ls_ddic_fields
  2444.             WHERE tabname = ls_table_list-table.
  2445.       CLEAR ls_node.
  2446.       lw_node_number = lw_node_number + 1.
  2447.       ls_node-node_key = lw_node_number.
  2448.       ls_node-relatkey = lw_parent_node.
  2449.       ls_node-relatship = cl_gui_column_tree=>relat_last_child.
  2450.       IF ls_ddic_fields-keyflag = space.
  2451.         ls_node-n_image = '@3W@'.
  2452.         ls_node-exp_image = '@3W@'.
  2453.       ELSE.
  2454.         ls_node-n_image = '@3V@'.
  2455.         ls_node-exp_image = '@3V@'.
  2456.       ENDIF.
  2457.       ls_node-dragdropid = w_dragdrop_handle_tree.
  2458.       APPEND ls_node TO t_node_ddic.
  2459.  
  2460.       CLEAR ls_item.
  2461.       ls_item-node_key = lw_node_number.
  2462.       ls_item-class = cl_gui_column_tree=>item_class_text.
  2463.       ls_item-item_name = c_ddic_col1.
  2464.       ls_item-text = ls_ddic_fields-fieldname.
  2465.       APPEND ls_item TO t_item_ddic.
  2466.       ls_item-item_name = c_ddic_col2.
  2467.       IF NOT ls_ddic_fields-ddtext1 IS INITIAL.
  2468.         ls_item-text = ls_ddic_fields-ddtext1.
  2469.       ELSE.
  2470.         ls_item-text = ls_ddic_fields-ddtext2.
  2471.       ENDIF.
  2472.       APPEND ls_item TO t_item_ddic.
  2473.     ENDLOOP.
  2474.   ENDLOOP.
  2475.  
  2476. * Add User defined tree from ZSPRO (if relevant)
  2477.   IF NOT t_node_zspro IS INITIAL.
  2478.     APPEND LINES OF t_node_zspro TO t_node_ddic.
  2479.     APPEND LINES OF t_item_zspro TO t_item_ddic.
  2480.   ENDIF.
  2481.  
  2482.   CALL METHOD o_tree_ddic->delete_all_nodes.
  2483.  
  2484.   CALL METHOD o_tree_ddic->add_nodes_and_items
  2485.     EXPORTING
  2486.       node_table                     = t_node_ddic
  2487.       item_table                     = t_item_ddic
  2488.       item_table_structure_name      = 'MTREEITM'
  2489.     EXCEPTIONS
  2490.       failed                         = 1
  2491.       cntl_system_error              = 3
  2492.       error_in_tables                = 4
  2493.       dp_error                       = 5
  2494.       table_structure_name_not_found = 6.
  2495.   IF sy-subrc <> 0.
  2496.     MESSAGE a000(tree_control_msg).
  2497.   ENDIF.
  2498.  
  2499.   DESCRIBE TABLE lt_table_list LINES lw_tabix.
  2500.  
  2501. * If no table found, display message
  2502.   IF lw_tabix = 0.
  2503.     MESSAGE 'No valid table found'(m15) TYPE c_msg_success
  2504.             DISPLAY LIKE c_msg_error.
  2505. * If 1 table found, expand it
  2506.   ELSEIF lw_tabix = 1.
  2507.     o_tree_ddic->expand_root_nodes( ).
  2508.   ENDIF.
  2509. ENDFORM.                    " SET_DDIC_TREE
  2510.  
  2511. *&---------------------------------------------------------------------*
  2512. *&      Form  SAVE_QUERY
  2513. *&---------------------------------------------------------------------*
  2514. *       Save query
  2515. *----------------------------------------------------------------------*
  2516. FORM save_query.
  2517.   DATA : lt_query TYPE soli_tab,
  2518.          ls_query LIKE LINE OF lt_query,
  2519.          lw_query_with_cr TYPE string,
  2520.          lw_guid TYPE guid_32,
  2521.          ls_ztoad TYPE ztoad,
  2522.          lw_timestamp(14) TYPE c.
  2523.  
  2524. * Set default options
  2525.   SELECT SINGLE class INTO s_options-visibilitygrp
  2526.          FROM usr02
  2527.          WHERE bname = sy-uname.
  2528.   s_options-visibility = '0'.
  2529.  
  2530. * Ask for options / query name
  2531.   CALL SCREEN 0200 STARTING AT 10 5
  2532.                   ENDING AT 60 7.
  2533.   IF s_options IS INITIAL.
  2534.     MESSAGE 'Action cancelled'(m14) TYPE c_msg_success
  2535.             DISPLAY LIKE c_msg_error.
  2536.     RETURN.
  2537.   ENDIF.
  2538.  
  2539. * Get content of abap edit box
  2540.   CALL METHOD o_textedit->get_text
  2541.     IMPORTING
  2542.       table  = lt_query[]
  2543.     EXCEPTIONS
  2544.       OTHERS = 1.
  2545.  
  2546. * Serialize query into a string
  2547.   CLEAR lw_query_with_cr.
  2548.   LOOP AT lt_query INTO ls_query.
  2549.     CONCATENATE lw_query_with_cr ls_query cl_abap_char_utilities=>cr_lf
  2550.                 INTO lw_query_with_cr.
  2551.   ENDLOOP.
  2552.  
  2553. * Generate new GUID
  2554.   DO 100 TIMES.
  2555.     TRY.
  2556.         lw_guid = cl_system_uuid=>create_uuid_c32_static( ).
  2557.       CATCH cx_uuid_error.
  2558.         EXIT. "exit do
  2559.     ENDTRY.
  2560.     SELECT SINGLE queryid INTO ls_ztoad-queryid
  2561.            FROM ztoad
  2562.            WHERE queryid = lw_guid.
  2563.  
  2564.     IF sy-subrc NE 0.
  2565.       EXIT. "exit do
  2566.     ENDIF.
  2567.   ENDDO.
  2568.  
  2569.   ls_ztoad-queryid = lw_guid.
  2570.   ls_ztoad-owner = sy-uname.
  2571.   lw_timestamp(8) = sy-datum.
  2572.   lw_timestamp+8 = sy-uzeit.
  2573.   ls_ztoad-aedat = lw_timestamp.
  2574.   ls_ztoad-text = s_options-name.
  2575.   ls_ztoad-visibility = s_options-visibility.
  2576.   ls_ztoad-visibility_group = s_options-visibilitygrp.
  2577.   ls_ztoad-query = lw_query_with_cr.
  2578.   INSERT ztoad FROM ls_ztoad.
  2579.   IF sy-subrc = 0.
  2580.     MESSAGE s031(r9). "Query saved
  2581.   ELSE.
  2582.     MESSAGE e220(iqapi). "Error when saving the query
  2583.   ENDIF.
  2584.  
  2585. * Reset the modified status
  2586.   o_textedit->set_textmodified_status( ).
  2587.  
  2588.   PERFORM fill_repository.
  2589.   PERFORM focus_repository USING lw_guid.
  2590. ENDFORM.                    " SAVE_QUERY
  2591.  
  2592. *&---------------------------------------------------------------------*
  2593. *&      Form  INIT_REPOSITORY
  2594. *&---------------------------------------------------------------------*
  2595. *       Initialize repository tree
  2596. *----------------------------------------------------------------------*
  2597. FORM init_repository.
  2598.   DATA: lt_event TYPE cntl_simple_events,
  2599.         ls_event TYPE cntl_simple_event.
  2600.  
  2601. * Create a tree control
  2602.   CREATE OBJECT o_tree_repository
  2603.     EXPORTING
  2604.       parent              = o_container_repository
  2605.       node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single
  2606.     EXCEPTIONS
  2607.       lifetime_error      = 1
  2608.       cntl_system_error   = 2
  2609.       create_error        = 3
  2610.       failed              = 4
  2611.       OTHERS              = 5.
  2612.   IF sy-subrc <> 0.
  2613.     MESSAGE a000(tree_control_msg).
  2614.   ENDIF.
  2615.  
  2616. * Catch double clic to open query
  2617.   ls_event-eventid = cl_gui_simple_tree=>eventid_node_double_click.
  2618.   ls_event-appl_event = abap_true. " no PAI if event occurs
  2619.   APPEND ls_event TO lt_event.
  2620.  
  2621. * Catch context menu call
  2622.   ls_event-eventid = cl_gui_simple_tree=>eventid_node_context_menu_req.
  2623.   ls_event-appl_event = abap_true. " no PAI if event occurs
  2624.   APPEND ls_event TO lt_event.
  2625.  
  2626.   CALL METHOD o_tree_repository->set_registered_events
  2627.     EXPORTING
  2628.       events                    = lt_event
  2629.     EXCEPTIONS
  2630.       cntl_error                = 1
  2631.       cntl_system_error         = 2
  2632.       illegal_event_combination = 3.
  2633.   IF sy-subrc <> 0.
  2634.     MESSAGE a000(tree_control_msg).
  2635.   ENDIF.
  2636.  
  2637. * Assign event handlers in the application class to each desired event
  2638.   SET HANDLER o_handle_event->handle_dblclick_repository
  2639.       FOR o_tree_repository.
  2640.   SET HANDLER o_handle_event->handle_context_menu_repository
  2641.       FOR o_tree_repository.
  2642.   SET HANDLER o_handle_event->handle_context_menu_sel_repo
  2643.       FOR o_tree_repository.
  2644.  
  2645.   PERFORM fill_repository.
  2646.  
  2647. ENDFORM.                    " INIT_REPOSITORY
  2648.  
  2649. *&---------------------------------------------------------------------*
  2650. *&      Form  FILL_REPOSITORY
  2651. *&---------------------------------------------------------------------*
  2652. *       Fill repository tree with all allowed queries
  2653. *----------------------------------------------------------------------*
  2654. FORM fill_repository.
  2655.   DATA : lw_usergroup TYPE usr02-class,
  2656.          BEGIN OF ls_query,
  2657.            queryid TYPE ztoad-queryid,
  2658.            aedat TYPE ztoad-aedat,
  2659.            visibility TYPE ztoad-visibility,
  2660.            text TYPE ztoad-text,
  2661.            query TYPE ztoad-query,
  2662.          END OF ls_query,
  2663.          lt_query_my LIKE TABLE OF ls_query,
  2664.          lt_query_shared LIKE TABLE OF ls_query,
  2665.          lw_node_key(6) TYPE n,
  2666.          lw_queryid TYPE ztoad-queryid,
  2667.          lw_dummy(1) TYPE c.                                "#EC NEEDED
  2668.  
  2669. * Get usergroup
  2670.   SELECT SINGLE class INTO lw_usergroup
  2671.          FROM usr02
  2672.          WHERE bname = sy-uname.
  2673.  
  2674. * Get all my queries
  2675.   SELECT queryid aedat visibility text query INTO TABLE lt_query_my
  2676.          FROM ztoad
  2677.          WHERE owner = sy-uname.
  2678.  
  2679. * Get all queries that i can use
  2680.   SELECT queryid aedat visibility text INTO TABLE lt_query_shared
  2681.          FROM ztoad
  2682.          WHERE owner NE sy-uname
  2683.          AND ( visibility = c_visibility_all
  2684.                OR ( visibility = c_visibility_shared
  2685.                     AND visibility_group = lw_usergroup )
  2686.              ).
  2687.   REFRESH t_node_repository.
  2688.  
  2689.   CALL METHOD o_tree_repository->delete_all_nodes.
  2690.  
  2691.   CLEAR s_node_repository.
  2692.   s_node_repository-node_key = c_nodekey_repo_my.
  2693.   s_node_repository-isfolder = abap_true.
  2694. *  s_node-n_image = s_node-exp_image = '@MV@'.
  2695.   s_node_repository-text = 'My queries'(m16).
  2696.   APPEND s_node_repository TO t_node_repository.
  2697.  
  2698.   CLEAR lw_node_key.
  2699.   CONCATENATE sy-uname '+++' INTO lw_queryid.
  2700.   LOOP AT lt_query_my INTO ls_query WHERE queryid NP lw_queryid.
  2701.     lw_node_key = lw_node_key + 1.
  2702.     CLEAR s_node_repository.
  2703.     s_node_repository-node_key = lw_node_key.
  2704.     s_node_repository-relatkey = c_nodekey_repo_my.
  2705.     s_node_repository-relatship = cl_gui_simple_tree=>relat_last_child.
  2706.     IF ls_query-visibility = c_visibility_my.
  2707.       s_node_repository-n_image = s_node_repository-exp_image = '@LC@'.
  2708.     ELSE.
  2709.       s_node_repository-n_image = s_node_repository-exp_image = '@L9@'.
  2710.     ENDIF.
  2711.     s_node_repository-text = ls_query-text.
  2712.     s_node_repository-queryid = ls_query-queryid.
  2713.     s_node_repository-edit = abap_true.
  2714.     APPEND s_node_repository TO t_node_repository.
  2715.   ENDLOOP.
  2716.  
  2717.   CLEAR s_node_repository.
  2718.   s_node_repository-node_key = c_nodekey_repo_shared.
  2719.   s_node_repository-isfolder = abap_true.
  2720. *  s_node-n_image = s_node-exp_image = '@MV@'.
  2721.   s_node_repository-text = 'Shared queries'(m17).
  2722.   APPEND s_node_repository TO t_node_repository.
  2723.  
  2724.   LOOP AT lt_query_shared INTO ls_query.
  2725.     lw_node_key = lw_node_key + 1.
  2726.     CLEAR s_node_repository.
  2727.     s_node_repository-node_key = lw_node_key.
  2728.     s_node_repository-relatkey = c_nodekey_repo_shared.
  2729.     s_node_repository-relatship = cl_gui_simple_tree=>relat_last_child.
  2730.     s_node_repository-n_image = s_node_repository-exp_image = '@L9@'.
  2731.     s_node_repository-text = ls_query-text.
  2732.     s_node_repository-queryid = ls_query-queryid.
  2733.     s_node_repository-edit = space.
  2734.     APPEND s_node_repository TO t_node_repository.
  2735.   ENDLOOP.
  2736.  
  2737. * Add history node
  2738.   CLEAR s_node_repository.
  2739.   s_node_repository-node_key = c_nodekey_repo_history.
  2740.   s_node_repository-isfolder = abap_true.
  2741. *  s_node-n_image = s_node-exp_image = '@MV@'.
  2742.   s_node_repository-text = 'History'(m18).
  2743.   APPEND s_node_repository TO t_node_repository.
  2744.  
  2745.   DELETE lt_query_my WHERE queryid NP lw_queryid.
  2746.   SORT lt_query_my BY aedat DESCENDING.
  2747.   LOOP AT lt_query_my INTO ls_query.
  2748.     lw_node_key = lw_node_key + 1.
  2749.     CLEAR s_node_repository.
  2750.     s_node_repository-node_key = lw_node_key.
  2751.     s_node_repository-relatkey = c_nodekey_repo_history.
  2752.     s_node_repository-relatship = cl_gui_simple_tree=>relat_last_child.
  2753.     s_node_repository-n_image = s_node_repository-exp_image = '@LC@'.
  2754.     s_node_repository-text = ls_query-text.
  2755.     s_node_repository-queryid = ls_query-queryid.
  2756.     s_node_repository-edit = abap_true.
  2757.     IF ls_query-query(1) = '*'.
  2758.       SPLIT ls_query-query+1 AT cl_abap_char_utilities=>cr_lf
  2759.             INTO ls_query-query lw_dummy.
  2760.       CONCATENATE s_node_repository-text ':' ls_query-query
  2761.                   INTO s_node_repository-text SEPARATED BY space.
  2762.     ENDIF.
  2763.     APPEND s_node_repository TO t_node_repository.
  2764.   ENDLOOP.
  2765.  
  2766.   CALL METHOD o_tree_repository->add_nodes
  2767.     EXPORTING
  2768.       table_structure_name           = 'MTREESNODE'
  2769.       node_table                     = t_node_repository
  2770.     EXCEPTIONS
  2771.       failed                         = 1
  2772.       error_in_node_table            = 2
  2773.       dp_error                       = 3
  2774.       table_structure_name_not_found = 4
  2775.       OTHERS                         = 5.
  2776.   IF sy-subrc <> 0.
  2777.     MESSAGE a000(tree_control_msg).
  2778.   ENDIF.
  2779.  
  2780. * Exand all root nodes (my, shared, history)
  2781.   CALL METHOD o_tree_repository->expand_root_nodes.
  2782. ENDFORM.                    " FILL_REPOSITORY
  2783.  
  2784. *&---------------------------------------------------------------------*
  2785. *&      Form  SAVE_CURRENT_QUERY
  2786. *&---------------------------------------------------------------------*
  2787. *       Save query in the history area
  2788. *       Keep only 100 last queries
  2789. *----------------------------------------------------------------------*
  2790. FORM save_current_query.
  2791.   DATA : lt_query TYPE soli_tab,
  2792.          ls_query LIKE LINE OF lt_query,
  2793.          lw_query_with_cr TYPE string,
  2794.          ls_ztoad TYPE ztoad,
  2795.          lw_number(2) TYPE n,
  2796.          lw_timestamp(14) TYPE c,
  2797.          lw_dummy(1) TYPE c,                                "#EC NEEDED
  2798.          lw_query_last TYPE string,
  2799.          lw_date(10) TYPE c,
  2800.          lw_time(8) TYPE c.
  2801.  
  2802. * Get content of abap edit box
  2803.   CALL METHOD o_textedit->get_text
  2804.     IMPORTING
  2805.       table  = lt_query[]
  2806.     EXCEPTIONS
  2807.       OTHERS = 1.
  2808.  
  2809. * Serialize query into a string
  2810.   CLEAR lw_query_with_cr.
  2811.   LOOP AT lt_query INTO ls_query.
  2812.     CONCATENATE lw_query_with_cr ls_query cl_abap_char_utilities=>cr_lf
  2813.                 INTO lw_query_with_cr.
  2814.   ENDLOOP.
  2815.  
  2816. * Define timestamp
  2817.   lw_timestamp(8) = sy-datum.
  2818.   lw_timestamp+8 = sy-uzeit.
  2819.   ls_ztoad-aedat = lw_timestamp.
  2820.  
  2821. * Search if query is same as last loaded
  2822.   SELECT SINGLE query INTO lw_query_last
  2823.          FROM ztoad
  2824.          WHERE queryid = w_last_loaded_query.
  2825.   IF sy-subrc = 0 AND lw_query_last = lw_query_with_cr.
  2826.     RETURN.
  2827.   ENDIF.
  2828.  
  2829. * Get usergroup
  2830.   SELECT SINGLE class INTO ls_ztoad-visibility_group
  2831.          FROM usr02
  2832.          WHERE bname = sy-uname.
  2833.  
  2834.   CLEAR lw_number.
  2835.  
  2836. * Get last query from history
  2837.   CONCATENATE sy-uname '#%' INTO ls_ztoad-queryid.
  2838.   SELECT queryid
  2839.          INTO ls_ztoad-queryid
  2840.          FROM ztoad
  2841.          UP TO 1 ROWS
  2842.          WHERE queryid LIKE ls_ztoad-queryid
  2843.          AND owner = sy-uname
  2844.          ORDER BY aedat DESCENDING.
  2845.   ENDSELECT.
  2846.   IF sy-subrc = 0.
  2847.     SPLIT ls_ztoad-queryid AT '#' INTO lw_dummy lw_number.
  2848.   ENDIF.
  2849.  
  2850.   lw_number = lw_number + 1.
  2851.  
  2852. * For history query, guid = <sy-uname>#NN
  2853.   CONCATENATE sy-uname '#' lw_number INTO ls_ztoad-queryid.
  2854.   ls_ztoad-owner = sy-uname.
  2855.   ls_ztoad-visibility = c_visibility_my.
  2856.  
  2857. * Define text for query as timestamp
  2858.   WRITE sy-datlo TO lw_date.
  2859.   WRITE sy-timlo TO lw_time.
  2860.   CONCATENATE lw_date lw_time INTO ls_ztoad-text SEPARATED BY space.
  2861.  
  2862.   ls_ztoad-query = lw_query_with_cr.
  2863.   MODIFY ztoad FROM ls_ztoad.
  2864.  
  2865.   w_last_loaded_query = ls_ztoad-queryid.
  2866.  
  2867. * Reset the modified status
  2868.   o_textedit->set_textmodified_status( ).
  2869.  
  2870. * Refresh repository
  2871.   PERFORM fill_repository.
  2872.  
  2873. * Focus on new query
  2874.   PERFORM focus_repository USING ls_ztoad-queryid.
  2875. ENDFORM.                    " SAVE_CURRENT_QUERY
  2876.  
  2877. *&---------------------------------------------------------------------*
  2878. *&      Form  LOAD_QUERY
  2879. *&---------------------------------------------------------------------*
  2880. *       Load query
  2881. *----------------------------------------------------------------------*
  2882. *      -->FP_QUERYID QueryID to load
  2883. *      <--FT_QUERY   Saved query
  2884. *----------------------------------------------------------------------*
  2885. FORM load_query USING fp_queryid TYPE ztoad-queryid
  2886.                 CHANGING ft_query TYPE table.
  2887.   DATA lw_query_with_cr TYPE string.
  2888.   REFRESH ft_query.
  2889.  
  2890.   SELECT SINGLE query INTO lw_query_with_cr
  2891.          FROM ztoad
  2892.          WHERE queryid = fp_queryid.
  2893.   IF sy-subrc = 0.
  2894.     SPLIT lw_query_with_cr AT cl_abap_char_utilities=>cr_lf
  2895.                            INTO TABLE ft_query.
  2896.   ENDIF.
  2897.   w_last_loaded_query = fp_queryid.
  2898. ENDFORM.                    " LOAD_QUERY
  2899.  
  2900. *&---------------------------------------------------------------------*
  2901. *&      Form  FOCUS_REPOSITORY
  2902. *&---------------------------------------------------------------------*
  2903. *       Focus repository tree on a given queryid
  2904. *----------------------------------------------------------------------*
  2905. *      -->FP_QUERYID  ID of the query to focus
  2906. *----------------------------------------------------------------------*
  2907. FORM focus_repository USING fp_queryid TYPE ztoad-queryid.
  2908.  
  2909.   READ TABLE t_node_repository INTO s_node_repository
  2910.              WITH KEY queryid = fp_queryid.
  2911.   IF sy-subrc NE 0.
  2912.     RETURN.
  2913.   ENDIF.
  2914.  
  2915.   CALL METHOD o_tree_repository->set_selected_node
  2916.     EXPORTING
  2917.       node_key = s_node_repository-node_key.
  2918.  
  2919. ENDFORM.                    " FOCUS_REPOSITORY
  2920.  
  2921. *&---------------------------------------------------------------------*
  2922. *&      Form  INIT_RESULT
  2923. *&---------------------------------------------------------------------*
  2924. *       Init ALV grid
  2925. *----------------------------------------------------------------------*
  2926. FORM init_result.
  2927.  
  2928. * Create ALV
  2929.   CREATE OBJECT o_alv_result
  2930.     EXPORTING
  2931.       i_parent = o_container_result.
  2932.  
  2933. * Register event toolbar to add button
  2934.   SET HANDLER o_handle_event->handle_toolbar_result FOR o_alv_result.
  2935.   SET HANDLER o_handle_event->handle_user_command_result
  2936.       FOR o_alv_result.
  2937.  
  2938. ENDFORM.                    " INIT_RESULT
  2939.  
  2940. *&---------------------------------------------------------------------*
  2941. *&      Form  INIT_LISTBOX_0200
  2942. *&---------------------------------------------------------------------*
  2943. *       Fill dropdown listbox with value on screen 200
  2944. *----------------------------------------------------------------------*
  2945. FORM init_listbox_0200 .
  2946.   DATA : lt_visibility TYPE vrm_values,
  2947.          ls_visibility LIKE LINE OF lt_visibility.
  2948.  
  2949.   REFRESH lt_visibility.
  2950.  
  2951.   ls_visibility-key = c_visibility_my.
  2952.   ls_visibility-text = 'Personal'(m19).
  2953.   APPEND ls_visibility TO lt_visibility.
  2954.  
  2955.   ls_visibility-key = c_visibility_shared.
  2956.   ls_visibility-text = 'User group'(m20).
  2957.   APPEND ls_visibility TO lt_visibility.
  2958.  
  2959.   ls_visibility-key = c_visibility_all.
  2960.   ls_visibility-text = 'All'(m21).
  2961.   APPEND ls_visibility TO lt_visibility.
  2962.  
  2963.   CALL FUNCTION 'VRM_SET_VALUES'
  2964.     EXPORTING
  2965.       id     = 'S_OPTIONS-VISIBILITY'
  2966.       values = lt_visibility.
  2967.  
  2968. ENDFORM.                    " INIT_LISTBOX_0200
  2969.  
  2970. *&---------------------------------------------------------------------*
  2971. *&      Form  EXIT_PROGRAM
  2972. *&---------------------------------------------------------------------*
  2973. *       Close the grid. If grid is closed, leave program
  2974. *       If sql text area is modified, ask confirmation before leave
  2975. *----------------------------------------------------------------------*
  2976. FORM exit_program .
  2977.   DATA : lw_status TYPE i,
  2978.          lw_answer(1) TYPE c,
  2979.          lw_size TYPE i.
  2980.  
  2981. * Check if grid is displayed
  2982.   CALL METHOD o_splitter->get_row_height
  2983.     EXPORTING
  2984.       id     = 1
  2985.     IMPORTING
  2986.       result = lw_size.
  2987.   CALL METHOD cl_gui_cfw=>flush.
  2988.  
  2989. * If grid is displayed, BACK action is only to close the grid
  2990.   IF lw_size < 100.
  2991.     CALL METHOD o_splitter->set_row_height
  2992.       EXPORTING
  2993.         id     = 1
  2994.         height = 100.
  2995.     RETURN.
  2996.   ENDIF.
  2997.  
  2998. * Check if textedit is modified
  2999.   CALL METHOD o_textedit->get_textmodified_status
  3000.     IMPORTING
  3001.       status = lw_status.
  3002.   IF lw_status NE 0.
  3003.     CALL FUNCTION 'POPUP_TO_CONFIRM'
  3004.       EXPORTING
  3005.         text_question         =                                    ".
  3006. 'Current query is not saved. Are you sure you want to exit ?'(m22) ".
  3007.         text_button_1         = 'Exit'(m23)
  3008.         icon_button_1         = '@01@'
  3009.         text_button_2         = 'Cancel'(m24)
  3010.         icon_button_2         = '@02@'
  3011.         default_button        = '2'
  3012.         display_cancel_button = space
  3013.       IMPORTING
  3014.         answer                = lw_answer.
  3015.     IF lw_answer NE '1'.
  3016.       RETURN.
  3017.     ENDIF.
  3018.   ENDIF.
  3019.  
  3020.   LEAVE TO SCREEN 0.
  3021. ENDFORM.                    " EXIT_PROGRAM
  3022.  
  3023. *&---------------------------------------------------------------------*
  3024. *&      Form  DISPLAY_HELP
  3025. *&---------------------------------------------------------------------*
  3026. *       Display help for this program
  3027. *----------------------------------------------------------------------*
  3028. FORM display_help.
  3029.   DATA : l_report TYPE string,
  3030.          l_report_char1(1) TYPE c,
  3031.          l_report_char3(3) TYPE c,
  3032.          l_comment_found TYPE i,
  3033.          lt_report LIKE TABLE OF l_report,
  3034.          lt_lines TYPE rcl_bag_tline,
  3035.          ls_line LIKE LINE OF lt_lines,
  3036.          ls_help TYPE help_info,
  3037.          lt_exclude TYPE STANDARD TABLE OF string.
  3038.  
  3039. * Get program source code
  3040.   READ REPORT sy-repid INTO lt_report.
  3041.  
  3042.   ls_line-tdformat = 'U1'.
  3043.   ls_line-tdline = sy-title.
  3044.   APPEND ls_line TO lt_lines.
  3045.  
  3046.   ls_line-tdformat = 'U3'.
  3047.   ls_line-tdline = '&PURPOSE&'.
  3048.   APPEND ls_line TO lt_lines.
  3049.  
  3050.   LOOP AT lt_report INTO l_report.
  3051.     l_report_char1 = l_report.
  3052.     CHECK l_report_char1 = '*'.
  3053.  
  3054. * Keep only the second block of comment
  3055. * (first block is technical info, third is history)
  3056.     l_report_char3 = l_report.
  3057.     IF l_report_char3 = '*&-'.
  3058.       l_comment_found = l_comment_found + 1.
  3059.       IF l_comment_found LE 2.
  3060.         CONTINUE.
  3061.       ELSE. "l_comment_found > 2
  3062.         EXIT.
  3063.       ENDIF.
  3064.     ENDIF.
  3065.     IF l_comment_found = 2.
  3066.       l_report = l_report+1.
  3067.       l_report_char1 = l_report.
  3068.       CASE l_report_char1.
  3069.         WHEN '='.
  3070.           ls_line-tdformat = '='.
  3071.         WHEN '3'.
  3072.           ls_line-tdformat = 'U3'.
  3073.         WHEN 'E'.
  3074.           ls_line-tdformat = 'PE'.
  3075.         WHEN OTHERS.
  3076.           ls_line-tdformat = '*'.
  3077.       ENDCASE.
  3078.       IF NOT l_report_char1 IS INITIAL.
  3079.         l_report = l_report+1.
  3080.       ENDIF.
  3081.       IF l_report IS INITIAL.
  3082.         ls_line-tdformat = 'LZ'.
  3083.       ENDIF.
  3084.       ls_line-tdline = l_report.
  3085.       APPEND ls_line TO lt_lines.
  3086.     ENDIF.
  3087.   ENDLOOP.
  3088.  
  3089.   CALL FUNCTION 'HELP_DOCULINES_SHOW'
  3090.     EXPORTING
  3091.       help_infos = ls_help
  3092.     TABLES
  3093.       excludefun = lt_exclude
  3094.       helplines  = lt_lines.
  3095.  
  3096. ENDFORM.                    " DISPLAY_HELP
  3097.  
  3098. *&---------------------------------------------------------------------*
  3099. *&      Form  PARSE_QUERY_NOSELECT
  3100. *&---------------------------------------------------------------------*
  3101. *       Check if query is a known SQL command and if user is allowed
  3102. *----------------------------------------------------------------------*
  3103. *      -->FP_QUERY   Query to check
  3104. *      <--FP_NOAUTH  Unallowed table or command entered
  3105. *      <--FP_COMMAND Command to execute (INSERT, DELETE, ...)
  3106. *      <--FP_TABLE   Target table of the query
  3107. *      <--FP_PARAM   Parameters for the command (WHERE, SET, ...)
  3108. *----------------------------------------------------------------------*
  3109. FORM parse_query_noselect  USING    fp_query TYPE string
  3110.                            CHANGING fp_noauth TYPE c
  3111.                                     fp_command TYPE string
  3112.                                     fp_table TYPE string
  3113.                                     fp_param TYPE string.
  3114.   DATA : lw_query TYPE string,
  3115.          lw_table TYPE tabname.
  3116.  
  3117.   CLEAR : fp_noauth,
  3118.           fp_table,
  3119.           fp_command,
  3120.           fp_param.
  3121.  
  3122.   lw_query = fp_query.
  3123.   SPLIT lw_query AT space INTO fp_command lw_query.
  3124.   TRANSLATE fp_command TO UPPER CASE.
  3125.   CASE fp_command.
  3126.     WHEN 'INSERT'.
  3127.       SPLIT lw_query AT space INTO fp_table fp_param.
  3128.       TRANSLATE fp_table TO UPPER CASE.
  3129.       CLEAR sy-subrc.
  3130.       IF s_auth-auth_object NE space.
  3131.         lw_table = fp_table.
  3132.         AUTHORITY-CHECK OBJECT s_auth-auth_object
  3133.           ID 'TABLE' FIELD lw_table
  3134.           ID 'ACTVT' FIELD c_actvt_auth_create.
  3135.       ENDIF.
  3136.       IF sy-subrc NE 0 OR
  3137.          ( s_auth-insert NE '*' AND fp_table NP s_auth-insert ).
  3138.         CONCATENATE 'No authorisation for table'(m13) fp_table
  3139.                     INTO lw_query SEPARATED BY space.
  3140.         MESSAGE lw_query TYPE c_msg_success DISPLAY LIKE c_msg_error.
  3141.         fp_noauth = abap_true.
  3142.         RETURN.
  3143.       ENDIF.
  3144.  
  3145.     WHEN 'UPDATE'.
  3146.       SPLIT lw_query AT space INTO fp_table fp_param.
  3147.       TRANSLATE fp_table TO UPPER CASE.
  3148.       CLEAR sy-subrc.
  3149.       IF s_auth-auth_object NE space.
  3150.         lw_table = fp_table.
  3151.         AUTHORITY-CHECK OBJECT s_auth-auth_object
  3152.           ID 'TABLE' FIELD lw_table
  3153.           ID 'ACTVT' FIELD c_actvt_auth_change.
  3154.       ENDIF.
  3155.       IF sy-subrc NE 0 OR
  3156.          ( s_auth-update NE '*' AND fp_table NP s_auth-update ).
  3157.         CONCATENATE 'No authorisation for table'(m13) fp_table
  3158.                     INTO lw_query SEPARATED BY space.
  3159.         MESSAGE lw_query TYPE c_msg_success DISPLAY LIKE c_msg_error.
  3160.         fp_noauth = abap_true.
  3161.         RETURN.
  3162.       ENDIF.
  3163.  
  3164.     WHEN 'DELETE'.
  3165.       SPLIT lw_query AT space INTO fp_table fp_param.
  3166.       TRANSLATE fp_table TO UPPER CASE.
  3167.       IF fp_table = 'FROM'.
  3168.         SPLIT fp_param AT space INTO fp_table fp_param.
  3169.         TRANSLATE fp_table TO UPPER CASE.
  3170.       ENDIF.
  3171.       CLEAR sy-subrc.
  3172.       IF s_auth-auth_object NE space.
  3173.         lw_table = fp_table.
  3174.         AUTHORITY-CHECK OBJECT s_auth-auth_object
  3175.           ID 'TABLE' FIELD lw_table
  3176.           ID 'ACTVT' FIELD c_actvt_auth_delete.
  3177.       ENDIF.
  3178.       IF sy-subrc NE 0 OR
  3179.         ( s_auth-delete NE '*' AND NOT fp_table CP s_auth-delete ).
  3180.         CONCATENATE 'No authorisation for table'(m13) fp_table
  3181.                     INTO lw_query SEPARATED BY space.
  3182.         MESSAGE lw_query TYPE c_msg_success DISPLAY LIKE c_msg_error.
  3183.         fp_noauth = abap_true.
  3184.         RETURN.
  3185.       ENDIF.
  3186.  
  3187.     WHEN OTHERS.
  3188.       CONCATENATE 'SQL command not allowed :'(m25) fp_command
  3189.                   INTO lw_query.
  3190.       MESSAGE lw_query TYPE c_msg_success DISPLAY LIKE c_msg_error.
  3191.       fp_noauth = abap_true.
  3192.       RETURN.
  3193.   ENDCASE.
  3194. ENDFORM.                    " PARSE_QUERY_NOSELECT
  3195.  
  3196. *&---------------------------------------------------------------------*
  3197. *&      Form  GENERATE_SUBROUTINE_NOSELECT
  3198. *&---------------------------------------------------------------------*
  3199. *       Create all other than SELECT SQL query in a new generated
  3200. *       temp program
  3201. *----------------------------------------------------------------------*
  3202. *      -->FP_COMMAND Query type
  3203. *      -->FP_TABLE   Target table of the query
  3204. *      -->FP_PARAM   Parameters of the query
  3205. *      -->FP_DISPLAY   Display code instead of generated routine
  3206. *      <--FP_PROGRAM Name of the generated program
  3207. *----------------------------------------------------------------------*
  3208. FORM generate_subroutine_noselect  USING    fp_command TYPE string
  3209.                                             fp_table TYPE string
  3210.                                             fp_param TYPE string
  3211.                                             fp_display TYPE c
  3212.                                    CHANGING fp_program TYPE sy-repid.
  3213.  
  3214.   DATA : lt_code_string TYPE TABLE OF string,
  3215.          lw_mess(255),
  3216.          lw_line TYPE i,
  3217.          lw_word(30),
  3218.          lw_strlen_string TYPE string,
  3219.          lw_explicit TYPE string,
  3220.          lw_length TYPE i,
  3221.          lw_pos TYPE i,
  3222.          lw_fieldnum TYPE i,
  3223.          lw_fieldval TYPE string,
  3224.          lw_fieldname TYPE string,
  3225.          lw_wait_name(1) TYPE c,
  3226.          lw_char(1) TYPE c,
  3227.          lw_started(1) TYPE c,
  3228.          lw_started_field(1) TYPE c.
  3229.  
  3230.   DEFINE c.
  3231.     lw_strlen_string = &1.
  3232.     perform add_line_to_table using lw_strlen_string
  3233.                               changing lt_code_string.
  3234.   END-OF-DEFINITION.
  3235.  
  3236. * Write Header
  3237.   c 'PROGRAM SUBPOOL.'.                                     "#EC NOTEXT
  3238.   c '** GENERATED PROGRAM * DO NOT CHANGE IT **'.           "#EC NOTEXT
  3239.   c 'type-pools: slis.'.                                    "#EC NOTEXT
  3240.   c 'DATA : w_timestart type timestampl,'.                  "#EC NOTEXT
  3241.   c '       w_timeend type timestampl.'.                    "#EC NOTEXT
  3242.   c ''.
  3243.   IF fp_command = 'INSERT'.
  3244.     c 'DATA s_insert type'.                                 "#EC NOTEXT
  3245.     c fp_table.
  3246.     c '.'.                                                  "#EC NOTEXT
  3247.     c 'FIELD-SYMBOLS <fs> TYPE ANY.'.                       "#EC NOTEXT
  3248.     c '.'.                                                  "#EC NOTEXT
  3249.   ENDIF.
  3250.  
  3251. * Write the dynamic subroutine that run the SELECT
  3252.   c 'FORM run_sql CHANGING fp_result TYPE REF TO data'.     "#EC NOTEXT
  3253.   c '                      fp_time TYPE p'.                 "#EC NOTEXT
  3254.   c '                      fp_count TYPE i.'.               "#EC NOTEXT
  3255.   c '***************************************'.              "#EC NOTEXT
  3256.   c '*            Begin of query           *'.              "#EC NOTEXT
  3257.   c '***************************************'.              "#EC NOTEXT
  3258.   c 'CLEAR fp_count.'.                                      "#EC NOTEXT
  3259.   c 'GET TIME STAMP FIELD w_timestart.'.                    "#EC NOTEXT
  3260.  
  3261.   CASE fp_command.
  3262.     WHEN 'UPDATE'.
  3263.       c fp_command.
  3264.       c fp_table.
  3265.       c fp_param.
  3266.       c '.'.
  3267.     WHEN 'DELETE'.
  3268.       c fp_command.
  3269.       c 'FROM'.                                             "#EC NOTEXT
  3270.       c fp_table.
  3271.       c fp_param.
  3272.       c '.'.
  3273.     WHEN 'INSERT'.
  3274.  
  3275.       IF fp_param(6) = 'VALUES'.
  3276.         lw_length = strlen( fp_param ).
  3277.         lw_pos = 6.
  3278.         lw_fieldnum = 0.
  3279.         WHILE lw_pos < lw_length.
  3280.           lw_char = fp_param+lw_pos(1).
  3281.           lw_pos = lw_pos + 1.
  3282.           IF lw_started = space.
  3283.             IF lw_char NE '('. "begin of the list
  3284.               CONTINUE.
  3285.             ENDIF.
  3286.             lw_started = abap_true.
  3287.             CONTINUE.
  3288.           ENDIF.
  3289.           IF lw_started_field = space.
  3290.             IF lw_char = ')'. "end of the list
  3291.               EXIT. "exit while
  3292.             ENDIF.
  3293.  
  3294.             IF lw_char NE ''''. "field value must start by '
  3295.               CONTINUE.
  3296.             ENDIF.
  3297.             lw_started_field = abap_true.
  3298.             lw_fieldval = lw_char.
  3299.             lw_fieldnum = lw_fieldnum + 1.
  3300.             CONTINUE.
  3301.           ENDIF.
  3302.           IF lw_char = space.
  3303.             CONCATENATE lw_fieldval lw_char INTO lw_fieldval
  3304.                         SEPARATED BY space.
  3305.           ELSE.
  3306.             CONCATENATE lw_fieldval lw_char INTO lw_fieldval.
  3307.           ENDIF.
  3308.           IF lw_char = ''''. "end of a field ?
  3309.             IF lw_pos < lw_length.
  3310.               lw_char = fp_param+lw_pos(1).
  3311.             ELSE.
  3312.               CLEAR lw_char.
  3313.             ENDIF.
  3314.             IF lw_char = ''''. "not end !
  3315.               CONCATENATE lw_fieldval lw_char INTO lw_fieldval.
  3316.               lw_pos = lw_pos + 1.
  3317.               CONTINUE.
  3318.             ELSE. "end of a field!
  3319.               c 'ASSIGN COMPONENT'.                         "#EC NOTEXT
  3320.               c lw_fieldnum.
  3321.               c 'OF STRUCTURE s_insert TO <fs>.'.           "#EC NOTEXT
  3322.               c '<fs> = '.                                  "#EC NOTEXT
  3323.               c lw_fieldval.
  3324.               c '.'.                                        "#EC NOTEXT
  3325.               lw_started_field = space.
  3326.             ENDIF.
  3327.           ENDIF.
  3328.         ENDWHILE.
  3329.       ELSEIF fp_param(3) = 'SET'.
  3330.  
  3331.  
  3332.         lw_length = strlen( fp_param ).
  3333.         lw_pos = 3.
  3334.         lw_fieldnum = 0.
  3335.         lw_wait_name = abap_true.
  3336.         WHILE lw_pos < lw_length.
  3337.           lw_char = fp_param+lw_pos(1).
  3338.           lw_pos = lw_pos + 1.
  3339.           IF lw_wait_name = abap_true.
  3340.             TRANSLATE lw_char TO UPPER CASE.
  3341.             IF lw_char = space OR NOT sy-abcde CS lw_char.
  3342.               CONTINUE. "not a begin of fieldname
  3343.             ENDIF.
  3344.             lw_wait_name = space.
  3345.             lw_started = abap_true.
  3346.             CONCATENATE 's_insert-' lw_char
  3347.                         INTO lw_fieldname.                  "#EC NOTEXT
  3348.             CONTINUE.
  3349.           ENDIF.
  3350.  
  3351.           IF lw_started = abap_true.
  3352.             IF lw_char = space.
  3353.               CONCATENATE lw_fieldname lw_char INTO lw_fieldname
  3354.                           SEPARATED BY space.
  3355.             ELSE.
  3356.               CONCATENATE lw_fieldname lw_char INTO lw_fieldname.
  3357.             ENDIF.
  3358.             IF lw_char = '='. "end of the field name
  3359.               lw_started = space.
  3360.             ENDIF.
  3361.  
  3362.             CONTINUE.
  3363.           ENDIF.
  3364.  
  3365.           IF lw_started_field NE abap_true.
  3366.             IF lw_char NE ''''. "field value must start by '
  3367.               CONTINUE.
  3368.             ENDIF.
  3369.             lw_started_field = abap_true.
  3370.             lw_fieldval = lw_char.
  3371.             CONTINUE.
  3372.           ENDIF.
  3373.  
  3374.           IF lw_char = space.
  3375.             CONCATENATE lw_fieldval lw_char INTO lw_fieldval
  3376.                         SEPARATED BY space.
  3377.           ELSE.
  3378.             CONCATENATE lw_fieldval lw_char INTO lw_fieldval.
  3379.           ENDIF.
  3380.           IF lw_char = ''''. "end of a field ?
  3381.             IF lw_pos < lw_length.
  3382.               lw_char = fp_param+lw_pos(1).
  3383.             ELSE.
  3384.               CLEAR lw_char.
  3385.             ENDIF.
  3386.             IF lw_char = ''''. "not end !
  3387.               CONCATENATE lw_fieldval lw_char INTO lw_fieldval.
  3388.               lw_pos = lw_pos + 1.
  3389.               CONTINUE.
  3390.             ELSE. "end of a field!
  3391.               c lw_fieldname.
  3392.               c lw_fieldval.
  3393.               c '.'.
  3394.               lw_started_field = space.
  3395.               lw_wait_name = abap_true.
  3396.             ENDIF.
  3397.           ENDIF.
  3398.         ENDWHILE.
  3399.       ELSE.
  3400.         MESSAGE 'Error in INSERT syntax : VALUES / SET required'(m26)
  3401.                 TYPE c_msg_error.
  3402.       ENDIF. "if fp_param(6) = 'VALUES'.
  3403.       c fp_command.
  3404.       c 'INTO'.                                             "#EC NOTEXT
  3405.       c fp_table.
  3406.       c 'VALUES s_insert.'.                                 "#EC NOTEXT
  3407.   ENDCASE.
  3408.  
  3409. * Get query execution time & affected lines
  3410.   c 'IF sy-subrc = 0.'.                                     "#EC NOTEXT
  3411.   c '  fp_count = sy-dbcnt.'.                               "#EC NOTEXT
  3412.   c 'ENDIF.'.                                               "#EC NOTEXT
  3413.   c 'GET TIME STAMP FIELD w_timeend.'.                      "#EC NOTEXT
  3414.   c 'fp_time = w_timeend - w_timestart.'.                   "#EC NOTEXT
  3415.   c 'ENDFORM.'.                                             "#EC NOTEXT
  3416.  
  3417.   CLEAR : lw_line,
  3418.           lw_word,
  3419.           lw_mess.
  3420.   SYNTAX-CHECK FOR lt_code_string PROGRAM sy-repid
  3421.                MESSAGE lw_mess LINE lw_line WORD lw_word.
  3422.   IF sy-subrc NE 0 AND fp_display = space.
  3423.     MESSAGE lw_mess TYPE c_msg_error.
  3424.   ENDIF.
  3425.  
  3426.   IF fp_display = space.
  3427.     GENERATE SUBROUTINE POOL lt_code_string NAME fp_program.
  3428.   ELSE.
  3429.     IF lw_mess IS NOT INITIAL.
  3430.       lw_explicit = lw_line.
  3431.       CONCATENATE lw_mess '(line'(m28) lw_explicit ',word'(m29)
  3432.                   lw_word ')'(m30)
  3433.                   INTO lw_mess SEPARATED BY space.
  3434.       MESSAGE lw_mess TYPE c_msg_success DISPLAY LIKE c_msg_error.
  3435.     ENDIF.
  3436.     EDITOR-CALL FOR lt_code_string DISPLAY-MODE
  3437.                 TITLE 'Generated code for current query'(t01).
  3438.   ENDIF.
  3439. ENDFORM.                    " GENERATE_SUBROUTINE_NOSELECT
  3440.  
  3441. *&---------------------------------------------------------------------*
  3442. *&      Form  GET_FIELD_FROM_NODE
  3443. *&---------------------------------------------------------------------*
  3444. *       Get text for a DDIC node
  3445. *       Format of the text : tablename~fieldname
  3446. *----------------------------------------------------------------------*
  3447. *      -->FW_NODE_KEY   DDIC node key
  3448. *      -->FW_RELAT_KEY  DDIC parent node key
  3449. *      -->FW_DATA       Text
  3450. *----------------------------------------------------------------------*
  3451. FORM get_field_from_node  USING    fw_node_key TYPE tv_nodekey
  3452.                                    fw_relat_key TYPE tv_nodekey
  3453.                           CHANGING fw_text TYPE string.
  3454.   DATA : ls_item LIKE LINE OF t_item_ddic,
  3455.          ls_item_parent LIKE LINE OF t_item_ddic,
  3456.          lw_table TYPE string,
  3457.          lw_alias TYPE string.
  3458.  
  3459. * Get field name
  3460.   READ TABLE t_item_ddic INTO ls_item
  3461.              WITH KEY node_key = fw_node_key
  3462.                       item_name = c_ddic_col1.
  3463.  
  3464. * Get table name
  3465.   READ TABLE t_item_ddic INTO ls_item_parent
  3466.              WITH KEY node_key = fw_relat_key
  3467.                       item_name = c_ddic_col1.
  3468.  
  3469. * Search for alias
  3470.   SPLIT ls_item_parent-text AT ' AS ' INTO lw_table lw_alias.
  3471.   IF NOT lw_alias IS INITIAL.
  3472.     lw_table = lw_alias.
  3473.   ENDIF.
  3474.  
  3475. * Build tablename~fieldname
  3476.   CONCATENATE lw_table '~' ls_item-text INTO fw_text.
  3477.   CONCATENATE space fw_text space INTO fw_text RESPECTING BLANKS.
  3478.  
  3479. ENDFORM.                    " GET_FIELD_FROM_NODE
  3480.  
  3481. *&---------------------------------------------------------------------*
  3482. *&      Form  PASTE_TO_EDITOR
  3483. *&---------------------------------------------------------------------*
  3484. *       Paste given text to SQL editor at given position
  3485. *----------------------------------------------------------------------*
  3486. *      -->FW_TEXT Text to paste in editor
  3487. *      -->FW_LINE Line in editor to paste
  3488. *      -->FW_POS  Position in the line in editor
  3489. *----------------------------------------------------------------------*
  3490. FORM paste_to_editor  USING fw_text TYPE string
  3491.                             fw_line TYPE i
  3492.                             fw_pos TYPE i.
  3493.  
  3494.   STATICS: sv_set_new_line TYPE xfeld VALUE abap_true.
  3495.  
  3496.   DATA : lt_text TYPE TABLE OF string,
  3497.          lv_text LIKE LINE OF lt_text,
  3498.          lw_line TYPE i,
  3499.          lw_pos TYPE i,
  3500.          lw_message TYPE string.
  3501.  
  3502. * Set text with/without new line
  3503.   APPEND fw_text TO lt_text.
  3504.   IF sv_set_new_line = abap_true.
  3505.     PERFORM string_blanks_get USING fw_pos
  3506.                               CHANGING lv_text.
  3507.     APPEND lv_text TO lt_text.
  3508.   ENDIF.
  3509.  
  3510.   CALL METHOD o_textedit->insert_block_at_position
  3511.     EXPORTING
  3512.       line     = fw_line
  3513.       pos      = fw_pos
  3514.       text_tab = lt_text
  3515.     EXCEPTIONS
  3516.       OTHERS   = 0.
  3517.  
  3518. * Set cursor at end of line / new (empty) line
  3519.   IF sv_set_new_line = abap_true.
  3520.     lw_line = fw_line + 1.
  3521.     lw_pos = fw_pos.
  3522.   ELSE.
  3523.     lw_line = fw_line.
  3524.     lw_pos = fw_pos + strlen( fw_text ).
  3525.   ENDIF.
  3526.   CALL METHOD o_textedit->set_selection_pos_in_line
  3527.     EXPORTING
  3528.       line   = lw_line
  3529.       pos    = lw_pos
  3530.     EXCEPTIONS
  3531.       OTHERS = 0.
  3532.  
  3533. * Focus on editor
  3534.   CALL METHOD cl_gui_control=>set_focus
  3535.     EXPORTING
  3536.       control = o_textedit
  3537.     EXCEPTIONS
  3538.       OTHERS  = 0.
  3539.  
  3540.   CONCATENATE fw_text 'pasted to SQL Editor'(m27)
  3541.               INTO lw_message SEPARATED BY space.
  3542.   MESSAGE lw_message TYPE c_msg_success.
  3543. ENDFORM.                    " PASTE_TO_EDITOR
  3544.  
  3545. *&---------------------------------------------------------------------*
  3546. *&      Form  string_blanks_get
  3547. *&---------------------------------------------------------------------*
  3548. *       text
  3549. *----------------------------------------------------------------------*
  3550. *      -->IV_POSITION  text
  3551. *      -->EV_TEXT      text
  3552. *----------------------------------------------------------------------*
  3553. FORM string_blanks_get USING iv_position TYPE numeric
  3554.                        CHANGING ev_text TYPE string.
  3555.   DATA: lv_blanks TYPE i.
  3556.  
  3557.   CLEAR ev_text.
  3558.  
  3559.   lv_blanks = iv_position - 1.
  3560.   DO lv_blanks TIMES.
  3561.     CONCATENATE ev_text space INTO ev_text RESPECTING BLANKS.
  3562.   ENDDO.
  3563.  
  3564. ENDFORM.                    "string_blanks_get
  3565.  
  3566. *&---------------------------------------------------------------------*
  3567. *&      Form  query_delete
  3568. *&---------------------------------------------------------------------*
  3569. *       text
  3570. *----------------------------------------------------------------------*
  3571. *      -->IV_NODE_KEY  text
  3572. *----------------------------------------------------------------------*
  3573. FORM query_delete USING iv_node_key TYPE tv_nodekey
  3574.                   CHANGING ev_error TYPE xfeld.
  3575.  
  3576.   CLEAR ev_error.
  3577.  
  3578.   READ TABLE t_node_repository INTO s_node_repository
  3579.              WITH KEY node_key = iv_node_key.
  3580.   IF sy-subrc = 0 AND s_node_repository-edit NE space.
  3581.     DELETE FROM ztoad WHERE queryid = s_node_repository-queryid.
  3582.     IF sy-subrc = 0.
  3583.       CALL METHOD o_tree_repository->delete_node
  3584.         EXPORTING
  3585.           node_key = iv_node_key.
  3586.     ELSE.
  3587.       ev_error = abap_true.
  3588.     ENDIF.
  3589.   ENDIF.
  3590.  
  3591. ENDFORM.                    "query_delete
  3592.  
  3593. *&---------------------------------------------------------------------*
  3594. *&      Form  query_selected_Delete
  3595. *&---------------------------------------------------------------------*
  3596. *       text
  3597. *----------------------------------------------------------------------*
  3598. FORM query_selected_delete.
  3599.   DATA l_node_key TYPE tv_nodekey.
  3600.  
  3601.   DATA: lv_error TYPE xfeld.
  3602.  
  3603.   CALL METHOD o_tree_repository->get_selected_node
  3604.     IMPORTING
  3605.       node_key = l_node_key.
  3606.   PERFORM query_delete USING l_node_key
  3607.                        CHANGING lv_error.
  3608.  
  3609.   IF lv_error = abap_false.
  3610.     MESSAGE 'Query deleted'(m02) TYPE c_msg_success.
  3611.   ELSE.
  3612.     MESSAGE 'Error when deleting the query'(m03)
  3613.       TYPE c_msg_success.
  3614.   ENDIF.
  3615.  
  3616. ENDFORM.                    "query_selected_Delete
  3617.  
  3618. *&---------------------------------------------------------------------*
  3619. *&      Form  queries_hist_delete
  3620. *&---------------------------------------------------------------------*
  3621. *       text
  3622. *----------------------------------------------------------------------*
  3623. FORM queries_hist_delete.
  3624.  
  3625.   FIELD-SYMBOLS: <ls_node_repostiory> LIKE LINE OF t_node_repository.
  3626.  
  3627.   DATA: lv_error TYPE xfeld,
  3628.         lv_count TYPE i.
  3629.  
  3630.   LOOP AT t_node_repository ASSIGNING <ls_node_repostiory>
  3631.     WHERE relatkey = 'HISTO'.
  3632.     PERFORM query_delete USING <ls_node_repostiory>-node_key
  3633.                          CHANGING lv_error.
  3634.     IF lv_error = abap_false.
  3635.       lv_count = lv_count + 1.
  3636.     ENDIF.
  3637.   ENDLOOP.
  3638.  
  3639.   MESSAGE s003(zca_toad) WITH lv_count.
  3640.   " '&Number of queries' Queries deleted
  3641.  
  3642. ENDFORM.                    "query_selected_delete
  3643.  
  3644. *&---------------------------------------------------------------------*
  3645. *&      Form  max_rows_input_popup
  3646. *&---------------------------------------------------------------------*
  3647. *       text
  3648. *----------------------------------------------------------------------*
  3649. *      -->CV_MAX_ROWS  text
  3650. *----------------------------------------------------------------------*
  3651. FORM max_rows_input_popup CHANGING cv_max_rows TYPE rseumod-tbmaxsel.
  3652.  
  3653.   DATA: lt_fields TYPE STANDARD TABLE OF sval,
  3654.         ls_fields LIKE LINE OF lt_fields,
  3655.         lv_returncode TYPE c.
  3656.  
  3657. * Build table of fields: Max rows
  3658.   ls_fields-tabname = 'RSEUMOD'.
  3659.   ls_fields-fieldname = 'TBMAXSEL'.
  3660.   ls_fields-value = cv_max_rows.
  3661.   APPEND ls_fields TO lt_fields.
  3662.  
  3663. * Display value request popup
  3664.   CALL FUNCTION 'POPUP_GET_VALUES'
  3665.     EXPORTING
  3666. *     NO_VALUE_CHECK        = ' '
  3667.       popup_title           = 'Please enter default:'(p01)
  3668. *     START_COLUMN          = '5'
  3669. *     START_ROW             = '5'
  3670.     IMPORTING
  3671.       returncode            = lv_returncode
  3672.      TABLES
  3673.        fields                = lt_fields
  3674. *   EXCEPTIONS
  3675. *     ERROR_IN_FIELDS       = 1
  3676. *     OTHERS                = 2
  3677.             .
  3678. * If user has confirmed input - Update pricing date
  3679.   IF lv_returncode IS INITIAL.
  3680.     READ TABLE lt_fields INTO ls_fields
  3681.       WITH KEY fieldname = 'TBMAXSEL'.
  3682.     cv_max_rows = ls_fields-value.
  3683.   ENDIF.
  3684.  
  3685. ENDFORM.                    "max_rows_input_popup
  3686.  
  3687. *&---------------------------------------------------------------------*
  3688. *&      Form  toolbar_max_rows_text_set
  3689. *&---------------------------------------------------------------------*
  3690. *       text
  3691. *----------------------------------------------------------------------*
  3692. FORM toolbar_max_rows_text_set.
  3693.  
  3694.   DATA: lv_text TYPE text40,
  3695.         lv_rows TYPE char20.
  3696.  
  3697.   lv_text = 'Max rows: &1'(tt1).
  3698.   IF gv_max_rows > 0.
  3699.     lv_rows = |{ gv_max_rows }|.
  3700.   ELSE.
  3701.     lv_rows = 'Unlimited'(tt3).
  3702.   ENDIF.
  3703.   REPLACE FIRST OCCURRENCE OF '&1' IN lv_text
  3704.     WITH lv_rows.
  3705.  
  3706.   o_toolbar->set_button_info(
  3707.     EXPORTING
  3708.       fcode            = '9MAX_ROWS'
  3709. *      icon             = icon    " Icon Name Defined Like "@0a@"
  3710.        text             = lv_text
  3711. *      quickinfo        = quickinfo    " Purpose of Button Text
  3712. *    EXCEPTIONS
  3713. *      cntl_error       = 1
  3714. *      cntb_error_fcode = 2
  3715. *      others           = 3
  3716.   ).
  3717.  
  3718. ENDFORM.                    "toolbar_max_rows_text_set
RAW Paste Data