MainBlogContactRSS




Login    
Login
 
Recent Entries    
Next Projects
INITCAP this!
APEX 3.1 released ...
Exploiting the strange behavio ...
Where's my SQL?
Undocumented Packages for Back ...
Debugging an APEX application
Splitting strings
Where's the space gone?
The size of a (XE) database
1 2 3 4 5 6 
Search    
Search
 
Recent Articles    
Introduction to Regular Expres ...
Extracting SQL statements from ...
BBCode Parser
MODEL clause vs. old school SQ ...
IF NULL or how to match two va ...
Views    
Firefox1241
IExplorer1597
Linux108
Windows2888
Total Views49328
System    
BCHR 
CMS_TS (100MB) 
DB (XE) (5GB) 
PGA (256MB) 
Daily insights of a database application developer    
Debugging an APEX application [2008.01.09] Bookmark (1.0.0.0)

While developing my CMS lite app I sometimes need to have a look at the state of certain regions or package function/procedures results. Thanks to the chapter Debugging an Application in the Application Express User's Guide I started with the #timing# tag, which does provide some information on the execution time (per region) which you can see at the bottom of my page. But I wanted also some output on packages, so I searched OTN and found a nice introduction at Injecting custom debug output into debug mode. The rest is easy, using a debug procedure (which is part of a package) that will work both inside SQL*PLUS (or any other tool) and APEX:

  PROCEDURE Debug(
    p_Message IN VARCHAR2
  )
  IS
   BEGIN
     IF v_Debug_Mode
     THEN
        DBMS_OUTPUT.PUT_LINE(p_Message);
     ELSIF wwv_flow.g_debug
     THEN
        htp.p(p_Message || '<br>');
     END IF;
  END Debug;


and placing debug statements in my packages. While going through the OTN Application Express forum I found an even better solution in Debug comments cannot be seen: wwv_flow.debug
(in my opinion this information should be mentioned in the APEX debug chapter)

Changing my Debug procedure to

  PROCEDURE Debug(
    p_Message IN VARCHAR2
  )
  IS
   BEGIN
     IF v_Debug_Mode
     THEN
        DBMS_OUTPUT.PUT_LINE(p_Message);
     ELSIF wwv_flow.g_debug
     THEN
        wwv_flow.debug(p_Message);
     END IF;
  END Debug;


now also shows timings of each debug line, such as this:

Daily insights of a database application developer
0.14: show report
0.14: determine column headings
0.14: parse query as: L2IS
0.14: binding: ":P3_ID"="P3_ID" value=""
0.14: binding: ":P3_NAME"="P3_NAME" value=""
0.14: binding: ":P3_SEARCH_TEXT"="P3_SEARCH_TEXT" value=""
0.14: print column headings
0.14: rows loop: 2 row(s)
0.15: --- cm_parse.bbcode_to_html ---
0.15: --- cm_parse.bbcode_to_html ---
0.16: --- cm_parse.bbcode_to_html ---
0.18: --- cm_parse.bbcode_to_html ---
0.19: --- cm_parse.bbcode_to_html ---
0.20: --- cm_parse.bbcode_to_html ---
0.20: --- cm_parse.bbcode_to_html ---
0.21: --- cm_parse.bbcode_to_html ---
0.21: --- cm_parse.bbcode_to_html ---
0.22: --- cm_parse.bbcode_to_html ---
0.22: --- cm_parse.bbcode_to_html ---
0.23: --- cm_parse.bbcode_to_html ---
0.23: --- cm_parse.bbcode_to_html ---
0.23: --- cm_parse.bbcode_to_html ---
0.24: --- cm_parse.bbcode_to_html ---
0.25: --- cm_parse.bbcode_to_html ---
0.25: --- cm_parse.bbcode_to_html ---

which gave me some hints on how to improve the rendering on the main page.

Splitting strings [2008.01.08] Bookmark (1.0.0.0)

Somehow this question slipped my last years Odd things (on OTN) series, so I decided to collect several methods for this problem. Sort of a reverse String Aggregation Techniques. ;-)

Version 1: CONNECT BY (taken from MODEL clause vs. old school SQL)

WITH t AS (SELECT '10,12,20,30,30,3,12,12,56' col1
             FROM dual
          )
SELECT SUBSTR(col1
             ,DECODE(level, 1, 1, INSTR(col1,',',1,level-1)+1)
             ,DECODE(INSTR(col1,',',1,level), 0, LENGTH(col1), instr(col1,',',1,level)
             -DECODE(level, 1, 0, INSTR(col1,',',1,level-1))-1)
             ) col_new
  FROM t
  CONNECT BY level < LENGTH(REPLACE(TRANSLATE(col1,'01234567890','00000000000'),'0')) + 2
; 
COL_NEW
----------
10
12
20
30
30
3
12
12
56


Version 2: regular expressions

WITH t AS (SELECT '10,12,20,30,30,3,12,12,56' col1
             FROM dual
          )
SELECT REGEXP_SUBSTR(col1, '[^,]+', 1, ROWNUM) col_new
  FROM t
  CONNECT BY level <= LENGTH(REGEXP_REPLACE(col1, '([^,])+|.', '\1'))
; 

COL_NEW
----------
10
12
20
30
30
3
12
12
56


Version 3: pipelined function

CREATE OR REPLACE PACKAGE utl_strings
AS
  TYPE t_outtab IS TABLE OF VARCHAR2(255);
  
  FUNCTION str_to_rows(
    p_string IN VARCHAR2             -- source string
  , p_delim  IN VARCHAR2 DEFAULT ',' -- delimiteter 
  ) RETURN t_outtab PIPELINED
  ;
END utl_strings;
/ 
 
CREATE OR REPLACE PACKAGE BODY utl_strings
AS
  FUNCTION str_to_rows(
    p_string IN VARCHAR2             -- source string
  , p_delim  IN VARCHAR2 DEFAULT ',' -- delimiteter 
  ) RETURN t_outtab PIPELINED
  IS
    v_start   NUMBER := 1;
    v_len     NUMBER := NVL(LENGTH(p_string), 0);
    v_pos     NUMBER;
  BEGIN  
    WHILE v_start <= v_len 
    LOOP
      v_pos := INSTR(p_string, p_delim, v_start);  
    
      IF v_pos = 0 THEN 
         v_pos := v_len + 1;
      END IF;
         
      PIPE ROW(SUBSTR(p_string, v_start, v_pos - v_start));
      
      v_start := v_pos + 1;   
    END LOOP;  
  END str_to_rows;  
END utl_strings;
/ 

SELECT column_value col_new
  FROM TABLE(utl_strings.str_to_rows('10,12,20,30,30,3,12,12,56'))
;

COL_NEW
----------
10
12
20
30
30
3
12
12
56


Version 4: MODEL clause (taken from MODEL clause vs. old school SQL)

WITH t AS (SELECT '10,12,20,30,30,3,12,12,56' col1
             FROM dual
          )
SELECT col_new
  FROM t
 MODEL
   PARTITION BY (ROWNUM rn)
   DIMENSION BY (0 dim)
   MEASURES(col1, col1 col_new)
   RULES ITERATE(99) UNTIL (ITERATION_NUMBER = LENGTH(REGEXP_REPLACE(col1[0], '[^,]')))
                (col_new[ITERATION_NUMBER] = REPLACE(REGEXP_SUBSTR(col1[0], '(^|,)[^,]*', 1, ITERATION_NUMBER+1), ','))
;

COL_NEW
----------
10
12
20
30
30
3
12
12
56


There are probably more variations, but that should cover it for now.

1 2 3 
Entries rendered in: 0.30 s




nobody