Tuesday, April 29, 2008

Validating a Process

I mentioned sometime back that I would be posting the code. I can't post the entire set of code but I can post the relevant parts.

Problem


Inbound Remittance Advice files are loaded into our Operational Data Store (ODS). We have absolutely no control over this, it lies with another group. On occasion, those files are double, or even triple, loaded.

Goal


To provide the business (and ourselves) with a way to track when files came in and if the entire processed worked as expected (no lost dollars, no lost record counts).

What do we do?


1. Read the files when they first come in (on disk).
2. Query the appropriate tables at certain intervals to verify it matches the file amounts.
3. Load those results into a table and then fail the normal load process if we detect any incongruities.

Solution (proposed)


1. Create a directory object on the Oracle server.
2. Copy inbound files to that directory.
3. Read files from that directory (Java anyone?)
4. Load files into CLOBs (so that I don't have to spend half my day finding the damn things, simple APEX app and I'm good to go).
5. Parse files to find relevant information (Java)
6. Query tables at various stages, blah blah blah.

Solution


Since the UTL_FILE doesn't have a function to read the contents of a directory, Java comes into play. I've done it before and I found the code originally on asktom (where else?).

For those of you too lazy (like me) to click the link, here's the important stuff:
snip...
File file = new File( path );

list = file.list();

for ( int i = 0; i < list.length; i++ )
{
File indvidualFile = new File( path + list[i] );

if ( indvidualFile.isFile() )
{
element = list[i];
statement.setString( 1, element );
}
}
snip...
Since I'm using Java, I might as well use the StringTokenizer, makes like so much easier. But wait, since I'm reading it as a CLOB (and not a String), what do I do? I tried clob.toString(). Nope, it's just a pointer to the actual CLOB.

I have to use Reader and CharacterStream, getting well beyond my knowledge of Java.

With the help of a fellow Java developer, I was pointed towards StreamTokenizer which works in a similar fashion to StringTokenizer, or so I thought. Apparently StreamTokenizer is one of the lower level classes...so I had to figure out the ASCII values of the character I wanted to split on (a tilde: ~). I think my Java friend was surprised I figured this out...

Reader characterStream = clob.getCharacterStream();
StreamTokenizer stream = new StreamTokenizer( characterStream );
stream.resetSyntax();
stream.wordChars( 32, 125 );
stream.parseNumbers();
Fun.

After I got that as a String, I could then use the StringTokenizer, which I knew.

Could I have split the CLOB using PL/SQL? Yes. Did I want to? Not really. I was already using Java so why not just use the Tokenizer?

The five classes were jarred and loaded into Oracle via the loadjava command. Wrap it all up in PL/SQL and life is easy!

PROCEDURE get_directory_contents( i_directory IN VARCHAR2 )
AS
LANGUAGE JAVA NAME 'com.hmocompany.dw.LoadFileNames.getFileNames( java.lang.String )';

Thursday, April 24, 2008

ApEx Presenting = FUN!

Wow...that's all I can say.

At lunch today, I put together my power point presentation. I meant to do it sooner of course, but it's been another busy week. In fact, I hadn't done a thing to prepare other than walking through it in my head.

I did not want this to be a presentation so much as a demo. Six slides is all they got.

I suddenly got very nervous around 4 today. I just want to get over there and start. I ended up leaving work just before 5.

The meeting was at the PriceWaterhouseCoopers building in Tampa, just across the street from the Tampa Bay Buccaneers headquarters. Very nice building.

The Presentation


I was introduced by the SOUG president promptly at 6:30. Roughly 40 people showed up (filled the room).

I had an hour and a half to complete my presentation...ummm...WHAT? I've got like 10 minutes worth of material! How the hell am I going to manage this??

Anyway, I walked through some of the features of APEX: Load/Unload data, SQL Commands, that kind of stuff, just trying to get to the application builder.

A couple of nights ago I began walking through and building a basic little reporting application tailored to the DBAs. Reports on roles and privileges basically. I never even got to that.

I created a 2 line csv (yes, I should have done it before hand), uploaded it to demonstrate how easy it was and then off the creating a report on that table.

"Can you create a form to update that record?"

Sure, here's how you do it. One minute later the form was done and I had updated the record. True to form...it's just so damn easy.

I answered a few other questions and then I got stuck. A member of the audience started answering the questions that I couldn't. We (the member in the audience) had spoken before the meeting and I believe he's just as passionate about APEX as I am). It worked rather well, so well in fact, that we're going to try and work out a dual presentation at the upcoming Technology Day SOUG puts on.

Someone would ask a question, I would answer them by showing them how to do it. Have I mentioned how much I like APEX? Rocks.

Next thing I know, it's a little past 8 and I can see the President trying to end the meeting. No way dude, too many questions to answer!

I got out of there around 9:30. I answered questions to the best of my ability...if I didn't know, pointed them to resources that could.

Exhilarating!

Can't wait to do it again...but next time I'll practice!

update
BTW, great crowd tonight. I couldn't have asked for a better group. Thanks to everyone for their support, and thanks to Tom and LewisC for asking me to do it.

Did I mention how cool it was? ;)

Monday, April 21, 2008

ApEx Presentation

I'll be doing my first professional IT presentation this Thursday for the Suncoast Oracle Users Group.

I'm a bit nervous, but excited at the same time. My goal is to make it as interactive as possible and just let it take me where it takes me.

I will have a canned demo, but I would rather it be more fluid. Can't always plan for those things...I could be a total bust!

So, if you're in the neighborhood and you want to check it out (or just laugh and heckle me), come on by. Details can be found here.

It's a Matter of Time

I've been thinking a lot lately about my recent failed deployments.

How did I get so sloppy?

I'm not one to make excuses, but I would say there are some mitigating circumstances at least. Time being one of them.

So I got out my trusty calculator (SQL*Plus), and ran the numbers.

From August 26, 2007 through March 30, 2008, I've worked 1802 hours. Of that, 118 were PTO or holiday, which brings the total down to 1784. For perspective, a work year of 8 hours per day comes out to 2080 hours a year.


VAR HOURS NUMBER;
EXEC :hours := 1784

1 SELECT
2 ROUND( ( :HOURS / 2080 ) * 100, 1 ) per_of_tot_year_hours
3* FROM DUAL
ETL_WRK@ORA10GR2>/

PER_OF_TOT_YEAR_HOURS
---------------------
85.8

Cool! Only 86% of my hours in a little over 6 months!

Obviously, this is not a good thing.

Further breaking the numbers down:


VAR C VARCHAR2(10);
EXEC :C := '26-AUG-07';

SELECT
start_day,
end_day,
days_between db,
SUM( business_days ) bd,
ROUND( ( :hours / days_between ), 1 ) hpd,
ROUND( ( :hours / ( days_between / 7 ) ), 1 ) hpdw,
ROUND( ( :hours / SUM( business_days ) ), 1 ) hpwd,
ROUND( ( :hours / SUM( business_days / 5 ) ), 1 ) hpww
FROM
(
SELECT
start_day,
end_day,
TRUNC( end_day - start_day ) days_between,
start_day + rownum dayof,
( CASE
WHEN TO_CHAR( start_day + rownum, 'D' ) IN ( 2, 3, 4, 5, 6 ) THEN
1
END ) business_days
FROM
dual a,
(
SELECT
TO_DATE( :c, 'DD-MON-YY' ) start_day,
TO_DATE( '30-MAR-08', 'DD-MON-YY' ) end_day
FROM dual
) b
CONNECT BY LEVEL <= TRUNC( end_day - start_day )
)
GROUP BY
start_day,
end_day,
days_between
/

START_DAY END_DAY DB BD HPD HPDW HPWD HPWW
---------- ---------- ------ ------ ------ ------ ------ ------
08/26/2007 03/30/2008 217 155 8.2 57.5 11.5 57.5

DB = Days Between
BD = Business Days
HPD = Hours Per Day
HPDW = Hours Per Day/Week
HPWD = Hours Per Work Day
HPWW = Hours Per Work Week

The scary part is that I am not very diligent about entering my time. It's probably short anywhere between 5 and 10%.

I'm not the only one working these kinds of hours either. I know for a fact there are others.

Do you think this plays a role in my failed deployments?