Advertisement
Guest User

apex_ir_query

a guest
Nov 25th, 2010
2,946
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Oracle 8 17.46 KB | None | 0 0
  1. CREATE OR REPLACE PACKAGE apex_ir_query IS
  2.  
  3.   -- Author  : STEWART_L_STRYKER
  4.   -- Created : 2/13/2009 4:00:45 PM
  5.   -- Purpose : Method of collecting user query from Interactive Report
  6.  
  7.   -- GRANT EXECUTE ON apex_ir_query to <apex_schema>;
  8.  
  9.   /* ----------- PUBLIC FUNCTION AND PROCEDURE DECLARATIONS ----------- */
  10.  
  11.     /* Setup:
  12.  
  13.        Add your own version of the following Javascript function to the application page
  14.        that contains the button to run your custom report.
  15.        In this example, I'm popping up a new page (#7) to display a PDF report.  The important
  16.        thing is to pass the apexir_report_id value to a page item via a parameter.
  17.  
  18.         <script language="JavaScript" type="text/javascript">
  19.         function SaveAndRunReport() {
  20.              popUp2('f?p=&APP_ID.:7:&SESSION.:new_request:NO::'+
  21.                     'P7_IR_REPORT_ID:'+$v('apexir_report_id'), 1024, 768);
  22.         }
  23. </script>
  24.  
  25.         I calculate this WHERE clause, then add it to a fixed query string that our interactive
  26.         reports run against.
  27.  
  28.         It supports Filters, Searches and Saved reports.
  29.         It DOES NOT support saving the Sort order.
  30.  
  31.     */
  32.     -- Generate IR query string
  33.     FUNCTION ir_query_where(app_id_in IN NUMBER,
  34.                             page_id_in IN NUMBER,
  35.                             session_id_in IN NUMBER,
  36.                             base_report_id_in IN VARCHAR2) RETURN VARCHAR2;
  37.  
  38. END apex_ir_query;
  39. /
  40. CREATE OR REPLACE PACKAGE BODY apex_ir_query IS
  41.  
  42.   /* ----------- PRIVATE FUNCTION AND PROCEDURE DECLARATIONS ----------- */
  43.     FUNCTION string_is_valid_date(string_in IN VARCHAR2, format_in IN VARCHAR2 DEFAULT 'MM/DD/YYYY')
  44.         RETURN BOOLEAN IS
  45.         v_date DATE;
  46.     -- From Kai-Joachim Kamrath @ columbia.edu
  47.     BEGIN
  48.         IF string_in IS NULL
  49.         THEN
  50.             RETURN FALSE;
  51.         ELSE
  52.             v_date := TO_DATE(string_in, format_in);
  53.             RETURN TRUE;
  54.         END IF;
  55.     EXCEPTION
  56.         WHEN OTHERS THEN
  57.             RETURN FALSE;
  58.     END string_is_valid_date;
  59.  
  60.    FUNCTION string_is_valid_number (string_in IN VARCHAR2)
  61.       RETURN BOOLEAN
  62.    IS
  63.       l_dummy       NUMBER;
  64.       l_is_number   BOOLEAN DEFAULT FALSE;
  65.    BEGIN
  66.       IF string_in IS NOT NULL
  67.       THEN
  68.          l_dummy := TO_NUMBER (string_in);
  69.          l_is_number := TRUE;
  70.       END IF;
  71.  
  72.       RETURN l_is_number;
  73.    EXCEPTION
  74.       WHEN OTHERS
  75.       THEN
  76.          RETURN FALSE;
  77.    END string_is_valid_number;
  78.  
  79.     -- Generic routine to log usage to your favorite log table
  80.     -- You'll need to write your own version, as this is simply a place-holder for the
  81.     -- installation-specific version I call in production
  82.     PROCEDURE log_apex_access(app_name_in IN VARCHAR2,
  83.                               app_user_in IN VARCHAR2,
  84.                               msg_in IN VARCHAR2) IS
  85.     BEGIN
  86.         NULL;
  87.     END log_apex_access;
  88.  
  89.     -- Convert Apex Interactive Report filter values to query clause
  90.     FUNCTION ir_query_parse_filter(col_name IN VARCHAR2,
  91.                             col_operator IN VARCHAR2,
  92.                             exp1 IN VARCHAR2,
  93.                             exp2 IN VARCHAR2) RETURN VARCHAR2 IS
  94.         result_clause VARCHAR2(512);
  95.         l_col_name VARCHAR2(32) := TRIM(col_name);
  96.         l_col_operator VARCHAR2(32) := LOWER(TRIM(col_operator));
  97.         l_expr1 VARCHAR2(512) := REPLACE(TRIM(exp1), '''', '''''');
  98.         l_expr2 VARCHAR2(512) := REPLACE(TRIM(exp2), '''', '''''');
  99.         in_list VARCHAR2(512);
  100.         in_table wwv_flow_global.vc_arr2;
  101.    
  102.         FUNCTION wrap_expr(expr_in IN VARCHAR2) RETURN VARCHAR2 IS
  103.             c_date_fmt CONSTANT VARCHAR2(32) := 'YYYYMMDD';
  104.             l_expr VARCHAR2(512) := TRIM(expr_in);
  105.             l_short_date VARCHAR2(8) := SUBSTR(l_expr, 1, 8);
  106.         BEGIN
  107.             IF string_is_valid_date(l_short_date, c_date_fmt)
  108.             THEN
  109.                 RETURN 'TO_DATE(''' || l_short_date || ''', ''' || c_date_fmt || ''')';
  110.             ELSIF string_is_valid_number(l_expr)
  111.             THEN
  112.                 RETURN l_expr;
  113.             ELSE
  114.                 RETURN '''' || l_expr || '''';
  115.             END IF;
  116.         END wrap_expr;
  117.    
  118.         -- For "in the last/next" date comparisons
  119.         FUNCTION calc_time_diff(operator_in IN VARCHAR2,
  120.                                 value_in IN VARCHAR2,
  121.                                 diff_expr IN VARCHAR2) RETURN VARCHAR2 IS
  122.             ret_value VARCHAR2(60);
  123.             factor VARCHAR2(32);
  124.         BEGIN
  125.             factor := CASE LOWER(diff_expr)
  126.                           WHEN 'minutes' THEN value_in || ' / 1440'
  127.                           WHEN 'hours' THEN value_in || ' / 24'
  128.                           WHEN 'days' THEN value_in
  129.                           WHEN 'weeks' THEN value_in || ' * 7'
  130.                           WHEN 'months' THEN value_in || ' * 30'
  131.                           WHEN 'years' THEN value_in || ' * 365'
  132.                           END;
  133.             ret_value := CASE operator_in
  134.                          WHEN 'is in the last' THEN '>= SYSDATE - (' || factor || ')'
  135.                          WHEN 'is in the next' THEN '>= SYSDATE + (' || factor || ')'
  136.                          WHEN 'is not in the last'
  137.                               THEN 'NOT BETWEEN (SYSDATE - ' || factor || ') AND SYSDATE'
  138.                          WHEN 'is not in the next'
  139.                               THEN 'NOT BETWEEN SYSDATE AND (SYSDATE + ' || factor || ')'
  140.                          END;
  141.             RETURN ret_value;
  142.         END calc_time_diff;
  143.    
  144.     BEGIN
  145.         CASE
  146.             WHEN l_col_operator IN ('not in', 'in') THEN
  147.                 in_table := apex_util.string_to_table(l_expr1, ',');
  148.            
  149.                 IF in_table.COUNT > 0
  150.                 THEN
  151.                     FOR i IN 1 .. in_table.COUNT
  152.                     LOOP
  153.                         in_table(i) := TRIM(in_table(i));
  154.                    
  155.                         in_table(i) := wrap_expr(in_table(i));
  156.                     END LOOP;
  157.                 END IF;
  158.                 in_list := apex_util.table_to_string(in_table, ',');
  159.                 result_clause := l_col_name || ' ' || l_col_operator || ' (' || in_list || ')';
  160.             WHEN l_col_operator IN ('is null', 'is not null') THEN
  161.                 result_clause := l_col_name || ' ' || l_col_operator;
  162.             WHEN l_col_operator IN ('not like',
  163.                                            'like',
  164.                                            '=',
  165.                                            '>=',
  166.                                            '<=',
  167.                                            '<',
  168.                                            '>',
  169.                                            '!=') THEN
  170.                 result_clause := l_col_name || ' ' || l_col_operator || ' ' || wrap_expr(l_expr1);
  171.             WHEN l_col_operator IN ('regexp_like') THEN
  172.                 result_clause := l_col_operator || '(' || l_col_name || ', ' || wrap_expr(l_expr1) || ')';
  173.             WHEN l_col_operator = 'contains' THEN
  174.                 result_clause := 'INSTR(UPPER(' || l_col_name || '), UPPER(''' || l_expr1 || ''')) > 0';
  175.             WHEN l_col_operator = 'does not contain' THEN
  176.                 result_clause := 'INSTR(UPPER(' || l_col_name || '), UPPER(''' || l_expr1 || ''')) = 0';
  177.             WHEN l_col_operator = 'between' THEN
  178.                 result_clause := l_col_name || ' ' || l_col_operator || ' ' || wrap_expr(l_expr1) ||
  179.                                  ' AND ' || wrap_expr(l_expr2);
  180.             WHEN l_col_operator LIKE 'is %in the %' THEN
  181.                 result_clause := l_col_name || ' ' ||
  182.                                  calc_time_diff(l_col_operator, l_expr1, l_expr2);
  183.             ELSE
  184.                 DBMS_OUTPUT.PUT_LINE('Unknown operator: ' || l_col_operator || ']');
  185.         END CASE;
  186.    
  187.         RETURN result_clause;
  188.     END ir_query_parse_filter;
  189.  
  190.     -- Convert Apex Interactive Report filter values to query clause
  191.     FUNCTION ir_query_parse_search(col_name_list IN VARCHAR2,
  192.                              expr_in IN VARCHAR2,
  193.                              app_id_in IN NUMBER,
  194.                              ir_id_in IN VARCHAR2 DEFAULT NULL) RETURN VARCHAR2 IS
  195.         crlf CONSTANT VARCHAR2(2) := CHR(10);
  196.    
  197.         result_clause VARCHAR2(2000);
  198.         l_expr VARCHAR2(512);
  199.         col_name_table wwv_flow_global.vc_arr2;
  200.         col_count PLS_INTEGER := 0;
  201.         match_count PLS_INTEGER := 0;
  202.    
  203.         FUNCTION wrap_expr(exp_in IN VARCHAR2) RETURN VARCHAR2 IS
  204.             l_expr VARCHAR2(512) := TRIM(exp_in);
  205.         BEGIN
  206.             RETURN '''' || l_expr || '''';
  207.         END wrap_expr;
  208.        
  209.         -- limit searches to String and numbers and exclude bogus columns
  210.         -- which can be generated by Apex
  211.         FUNCTION right_col_type(col_name_in IN VARCHAR2) RETURN BOOLEAN IS
  212.             found_col VARCHAR2(32);
  213.         BEGIN
  214.             SELECT col.column_type
  215.               INTO found_col
  216.               FROM apex_application_page_ir_col col
  217.              WHERE col.application_id = app_id_in
  218.            --    AND col.page_id = page_id_in
  219.                AND col.interactive_report_id = ir_id_in
  220.                AND col.allow_filtering = 'Yes'
  221.                AND col.column_type IN ('STRING', 'NUMBER')
  222.                AND col.column_alias = col_name_in
  223.                AND ROWNUM <= 1;
  224.                
  225.            RETURN found_col IS NOT NULL;
  226.        
  227.         EXCEPTION WHEN OTHERS THEN
  228.             RETURN FALSE;
  229.         END;
  230.                              
  231.     BEGIN
  232.         -- Simplistic protection against user entering huge match value
  233.         IF LENGTH(REPLACE(TRIM(expr_in), '''', '''''')) > 512
  234.         THEN
  235.             RETURN NULL;
  236.         END IF;
  237.        
  238.         l_expr := REPLACE(TRIM(expr_in), '''', '''''');
  239.         col_name_table := apex_util.string_to_table(col_name_list);
  240.         col_count := col_name_table.COUNT;
  241.  
  242.         IF col_count > 0
  243.            AND l_expr IS NOT NULL
  244.         THEN
  245.             result_clause := '(';
  246.            
  247.             FOR i IN 1 .. col_count
  248.             LOOP
  249.                 IF result_clause > '(' AND right_col_type(col_name_table(i))
  250.                 THEN
  251.                     result_clause := result_clause || ' or ';
  252.                 END IF;
  253.  
  254.                 IF right_col_type(col_name_table(i))
  255.                 THEN            
  256.                     match_count := match_count + 1;
  257.                     result_clause := result_clause || 'instr(upper(' || col_name_table(i) ||
  258.                                      '), upper(' || wrap_expr(l_expr) || ')) > 0' || crlf;
  259.                 END IF;
  260.             END LOOP;
  261.         END IF;
  262.    
  263.         result_clause := result_clause || ')';
  264.         RETURN result_clause;
  265.     EXCEPTION
  266.     WHEN OTHERS THEN
  267.             log_apex_access(app_name_in => 'ir_query_parse_search',
  268.                                               app_user_in => v('APP_USER'),
  269.                                               msg_in      => 'EXCEPTION: ' || SQLERRM ||
  270.                                                              '.  column count: ' || col_count ||
  271.                                                              '.  IR Report id: ' || ir_id_in ||
  272.                                                              '.  l_expr length: ' || LENGTH(l_expr));
  273.     END ir_query_parse_search;
  274.  
  275.     -- Generate IR query string for a user from their filters and searches
  276.     FUNCTION ir_query_where(app_id_in IN NUMBER,
  277.                             page_id_in IN NUMBER,
  278.                             session_id_in IN NUMBER,
  279.                             base_report_id_in IN VARCHAR2) RETURN VARCHAR2 IS
  280.         /*
  281.             Parameters:     base_report_id_in - User's currently-displayed report (including saved)
  282.        
  283.             Returns:        ANDed WHERE clause to be run against base view
  284.        
  285.             Author:         STEWART_L_STRYKER
  286.             Created:        2/12/2009 5:16:51 PM
  287.        
  288.             Usage:          RETURN apex_ir_query.ir_query_where(app_id_in => :APP_ID,
  289.                                         page_id_in => 2,
  290.                                         session_id_in => :APP_SESSION);
  291.        
  292.             CS-RCS Modification History: (Do NOT edit manually)
  293.        
  294.             $Log: $
  295.         */
  296.         query_string VARCHAR2(32500);
  297.         test_val VARCHAR2(80);
  298.         search_count PLS_INTEGER := 0;
  299.         clause VARCHAR2(32000);
  300.        
  301.         query_too_long EXCEPTION;
  302.         PRAGMA EXCEPTION_INIT(query_too_long, -24381);
  303.     BEGIN
  304.         FOR filters IN (SELECT condition_column_name,
  305.                                condition_operator,
  306.                                condition_expression,
  307.                                condition_expression2
  308.                           FROM apex_application_page_ir_cond cond
  309.                           JOIN apex_application_page_ir_rpt r ON r.application_id =
  310.                                                                  cond.application_id
  311.                                                              AND r.page_id = cond.page_id
  312.                                                              AND r.report_id = cond.report_id
  313.                          WHERE cond.application_id = app_id_in
  314.                            AND cond.page_id = page_id_in
  315.                            AND cond.condition_type = 'Filter'
  316.                            AND cond.condition_enabled = 'Yes'
  317.                            AND r.base_report_id = base_report_id_in
  318.                            AND r.session_id = session_id_in)
  319.         LOOP
  320.             clause := ir_query_parse_filter(filters.condition_column_name,
  321.                                             filters.condition_operator,
  322.                                             filters.condition_expression,
  323.                                             filters.condition_expression2);
  324.             IF LENGTH(clause) + LENGTH(query_string) > 32500
  325.             THEN
  326.                 RAISE query_too_long;
  327.             END IF;
  328.            
  329.             query_string := query_string || ' AND ' || clause;                            
  330.         END LOOP;
  331.    
  332.  
  333.         FOR searches IN (SELECT r.report_columns,
  334.                                 cond.condition_expression,
  335.                                 TO_CHAR(r.interactive_report_id) AS interactive_report_id
  336.                           FROM apex_application_page_ir_cond cond
  337.                           JOIN apex_application_page_ir_rpt r ON r.application_id =
  338.                                                                  cond.application_id
  339.                                                              AND r.page_id = cond.page_id
  340.                                                              AND r.report_id = cond.report_id
  341.                          WHERE cond.application_id = app_id_in
  342.                            AND cond.page_id = page_id_in
  343.                            AND cond.condition_type = 'Search'
  344.                            AND cond.condition_enabled = 'Yes'
  345.                            AND r.base_report_id = base_report_id_in
  346.                            AND r.session_id = session_id_in)
  347.         LOOP
  348.             search_count := search_count + 1;
  349.             test_val := NVL(searches.interactive_report_id, 'null');
  350.             clause := ir_query_parse_search(searches.report_columns,
  351.                                             searches.condition_expression,
  352.                                             app_id_in,
  353.                                             searches.interactive_report_id);
  354.  
  355.             IF LENGTH(clause) + LENGTH(query_string) > 32500
  356.             THEN
  357.                 RAISE query_too_long;
  358.             END IF;
  359.            
  360.             query_string := query_string || ' AND ' || clause;
  361.                            
  362.         END LOOP;
  363.  
  364.         log_apex_access(app_name_in => app_id_in,
  365.                                           app_user_in => v('APP_USER'),
  366.                                           msg_in      => 'Searches: ' || search_count ||
  367.                                                          '.  base_report_id_in: ' || NVL(base_report_id_in, 'null')
  368.                                                          || '.  Session: ' || session_id_in);
  369.         RETURN query_string;
  370.     EXCEPTION
  371.         WHEN query_too_long THEN
  372.             log_apex_access(app_name_in => app_id_in,
  373.                                               app_user_in => v('APP_USER'),
  374.                                               msg_in      => 'Generated query string would have been > 32k');
  375.        
  376.             RETURN query_string;
  377.         WHEN no_data_found THEN
  378.             log_apex_access(app_name_in => app_id_in,
  379.                                               app_user_in => v('APP_USER'),
  380.                                               msg_in      => 'NDF. Searches: ' || search_count ||
  381.                                                              '.  IR Report id: ' || NVL(test_val, 'null'));
  382.        
  383.             RETURN query_string;
  384.         WHEN OTHERS THEN
  385.             log_apex_access(app_name_in => app_id_in,
  386.                                               app_user_in => v('APP_USER'),
  387.                                               msg_in      => 'EXCEPTION: ' || SQLERRM ||
  388.                                                              '.  Searches: ' || search_count ||
  389.                                                              '.  IR Report id: ' || NVL(test_val, 'null'));
  390.        
  391.             RETURN query_string;
  392.     END ir_query_where;
  393.  
  394. END apex_ir_query;
  395. /
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement