Sunday, April 22, 2007

God Bless the Congress of the United States of America!

This is a great country. I am very lucky to have been born where I was, when I was.

This fact was driven home to me very forcefully tonite by a visit to My Yahoo, where I found some exciting news, news that made me proud to be an American.

As I am sure you are aware, a young man killed 33 people at Virginia Tech several days ago. A horrible, horrible event. He was clearly deranged, a madman. And look what he did with all those guns. A massacre.

Well, Congress is not wasting any time in showing that it means business when it comes to protecting the citizens of this great nation, the citizens who, in fact, put those men and women where they are today.

No, sir, Congresspeople are contemplating swift and strong action, as explained by this article from Reuters:

U.S. Congress may act to keep guns from mentally ill By Thomas Ferraro Sun Apr 22, 4:09 PM ET

WASHINGTON (Reuters) - Prompted by the Virginia Tech massacre, a U.S. Congress reluctant to tackle gun control may pass limited legislation to help keep firearms out of the hands of the mentally ill, lawmakers and aides said on Sunday.

"Given the horror that happened at Virginia Tech, I think there's a real chance of passing this," said Sen. Charles Schumer (news, bio, voting record), a New York Democrat, told "Fox News Sunday."

A Republican leadership aide agreed, telling Reuters, "If there is a consensus, and it is in lieu of knee-jerk draconian measures, (the chances are) probably really good." ... more

==========================

Can there be any doubt about the great wisdom of our leaders?

I certainly agree with them: people who are mentally ill should not be allowed to own weapons.

This is a great time to be an American.

I pity all the other people around the world who have to be some other kind of person, like a European or even a Chinapean.

But maybe, just maybe, if you help the National Rifle Association establish a lobbying office in your country, then your nation, too, can rise to greatness.

In the meantime, it is entirely possible that God will only bless America.

Tough break, world.

Saturday, April 21, 2007

Quseful #1: Trace argument passing

About Qusefuls

A Quseful is a Quick and Useful (as opposed to Quick and Dirty) tip on now to write programs in the Oracle PL/SQL language more effectively. I will publish Qusefuls on my blog (feuerthoughts.blogspot.com) on a regular (hopefully at least weekly) basis. Each Quseful contains a description of the tip ("What's the point?"), some PL/SQL code you can install in your environment to implement the tip ("Show me the code!"), an example of how to use the code to help you get your job done ("How do I use it?").

What's the point?

A very good habit to develop is to add application-level tracing to your code. This tracing capability should be something you can turn on and off from outside your application code. Use it to keep track of application-specific information that is being used or processed by your code.

Options for tracing include:

Whichever tracing option you choose, information that very often needs to be traced/verified are the values that were passed into a program through the parameter list (IN and IN OUT arguments). Programmers usually write such tracing code themselves, which can be a major pain in the neck when you have lots of arguments.

Below you will find a program that extracts the arguments of a program from the ALL_ARGUMENTS data dictionary view and generates a starting point for your argument tracing. It assumes that your tracing function takes two string inputs:

  1. the context: defaulted to the name of the program you provided
  2. the trace message: a single string that contains concatenations of all the arguments in the form ARGUMENT_NAME = ARGUMENT_VALUE.

You may well need to change either this program or the output from the program to match your actual tracing interface or to remove any arguments whose type does not allow implicit conversions to strings. At least it will have generated a nice starting point for you, saving a bunch of time.

Note: many thanks to Jornica for his help in enhancing and testing this utility!

Show me the code!

Sorry, rather than show you all the code here (very clumsy), I offer the source code and any supporting files in this zip file.

You can also download my entire "demo zip", containing all the scripts and reusable code that are part of my regular trainings. The zip for this Quseful is inside that zip as well.

How do I use it?

Call gen_trace_call and pass it the name of the program for which you need argument tracing. It then queries the correct argument information from ALL_ARGUMENTS and generates code by displaying it on the screen with DBMS_OUTPUT.

This program has four arguments:

pkg_or_prog_in

The name of the package that contains the subprogram you want to trace, or the name of the schema-level function or procedure you want to trace.

pkg_subprog_in

If tracing a program in a package, provide the name of that function or procedure here. If tracing a schema-level program, pass NULL.

nest_tracing_in

Pass TRUE (the default) if you want to nest your tracing call within a conditional statement that is used to first see whether or not tracing is enabled. This is useful for reducing the runtime overhead of tracing when disabled.

tracing_enabled_func_in

The name of the function (or chunk of code) that you want to run to see if tracing is enabled. The default is 'qd_runtime.trace_enabled', which is the function used by the Quest CodeGen Utility to check to see if tracing is enabled.

trace_func_in

The name of the function that you want to call to do the tracing. The default is 'qd_runtime.trace', which is the trace function offered by the Quest CodeGen Utility.

Examples

Here are some examples, generating code for programs that are available in my "demo zip" file. Please note that I have formatted all code using Toad's auto-formatter. It will not be quite as pretty "out of the box". I have also turned on serveroutput before running these scripts.

1. A schema-level function (betwnstr.sf):

DECLARE
/* AFTER ENTERING - IN and IN OUT argument tracing */
PROCEDURE trace_in_arguments
IS
FUNCTION bool_to_char (bool_in IN BOOLEAN)
RETURN VARCHAR2
IS
BEGIN
IF bool_in
THEN
RETURN 'TRUE';
ELSIF NOT bool_in
THEN
RETURN 'FALSE';
ELSE
RETURN 'NULL';
END IF;
END bool_to_char;
BEGIN
IF qd_runtime.trace_enabled
THEN
qd_runtime.TRACE ('BETWNSTR'
, 'STRING_IN='
|| string_in
|| ' - START_IN='
|| start_in
|| ' - END_IN='
|| end_in
|| ' - INCLUSIVE_IN='
|| bool_to_char (inclusive_in)
);
END IF;
END trace_in_arguments;

/* BEFORE LEAVING - OUT and IN OUT argument tracing */
PROCEDURE trace_out_arguments
IS
BEGIN
IF qd_runtime.trace_enabled
THEN
qd_runtime.TRACE ('BETWNSTR', 'RETURN_VALUE=' || return_value);
END IF;
END trace_out_arguments;
BEGIN
NULL;
END;

You will find an example of betwnstr that includes this tracing logic in it in the betwnstr_with_tracing.sf file.

2. A function inside a package (dyn_placeholder.pks/pkb):

DECLARE
/* AFTER ENTERING - IN and IN OUT argument tracing */
PROCEDURE trace_in_arguments
IS
FUNCTION bool_to_char (bool_in IN BOOLEAN)
RETURN VARCHAR2
IS
BEGIN
IF bool_in
THEN
RETURN 'TRUE';
ELSIF NOT bool_in
THEN
RETURN 'FALSE';
ELSE
RETURN 'NULL';
END IF;
END bool_to_char;
BEGIN
IF qd_runtime.trace_enabled
THEN
qd_runtime.TRACE ('DYN_PLACEHOLDER.ALL_IN_STRING'
, 'STRING_IN='
|| string_in
|| ' - DYN_PLSQL_IN='
|| bool_to_char (dyn_plsql_in)
);
END IF;
END trace_in_arguments;

/* BEFORE LEAVING - OUT and IN OUT argument tracing */
PROCEDURE trace_out_arguments
IS
BEGIN
IF qd_runtime.trace_enabled
THEN
qd_runtime.TRACE ('DYN_PLACEHOLDER.ALL_IN_STRING'
, 'RETURN_VALUE=' || return_value
);
END IF;
END trace_out_arguments;
BEGIN
NULL;
END;

3. Same function, but using overrides for the tracing programs:

DECLARE
/* AFTER ENTERING - IN and IN OUT argument tracing */
PROCEDURE trace_in_arguments
IS
FUNCTION bool_to_char (bool_in IN BOOLEAN)
RETURN VARCHAR2
IS
BEGIN
IF bool_in
THEN
RETURN 'TRUE';
ELSIF NOT bool_in
THEN
RETURN 'FALSE';
ELSE
RETURN 'NULL';
END IF;
END bool_to_char;
BEGIN
IF mypkg.tracing_on ()
THEN
mupkg.show_action ('DYN_PLACEHOLDER.ALL_IN_STRING'
, 'STRING_IN='
|| string_in
|| ' - DYN_PLSQL_IN='
|| bool_to_char (dyn_plsql_in)
);
END IF;
END trace_in_arguments;

/* BEFORE LEAVING - OUT and IN OUT argument tracing */
PROCEDURE trace_out_arguments
IS
BEGIN
IF mypkg.tracing_on ()
THEN
mupkg.show_action ('DYN_PLACEHOLDER.ALL_IN_STRING'
, 'RETURN_VALUE=' || return_value
);
END IF;
END trace_out_arguments;
BEGIN
NULL;
END;

Gotchas

Keep the following in mind:

  • You have serveroutput turned on to see the output from this program.
  • If your parameter list contains complex datatypes, like records and collections, you will definitely need to modify the output before it will work.
  • It will only generate trace information for programs defrined in the current schema. You can add a schema argument to the program and change the user_arguments reference to all_arguments to generate code for programs in other schemas.
  • On Oracle9i, you will still be facing a limit of 255 characters in a call to DBMS_OUTPUT.PUT_LINE (rises to 32K in 10g and above). You can avoid this issue by substituting the call to DBMS_OUTPUT.PUT_LINE with a program that works around this issue, a number of which are available in my "demo zip", including the pl.sp procedure and the p.pks/pkb package.

Do you like it? Do you use it?

I'd love to hear what you think of this utility and, in particular, if you found it useful. So please don't hesitate to post a comment on this blog or send me a note at steven@stevenfeuerstein.com.

About Qusefuls

A Quseful is a Quick and Useful (as opposed to Quick and Dirty) tip on now to write programs in the Oracle PL/SQL language more effectively. I will publish Qusefuls on my blog (feuerthoughts.blogspot.com) on a regular (hopefully at least weekly) basis. Each Quseful contains a description of the tip ("What's the point?"), some PL/SQL code you can install in your environment to implement the tip ("Show me the code!"), an example of how to use the code to help you get your job done ("How do I use it?").

Saturday, April 07, 2007

Green and ethical hotel-ing

As I write this post, I am flying at 33000 feet in a Boeing 777, heading back home after two weeks in Europe (Copenhagen, Zurich, Vilnius, Amsterdam). I stayed in four different hotels.

I have been doing lots of (too much) traveling for many (too many) years. Yet it was only on this trip that I felt like I was finally hitting my stride, with everything I needed in place to make my trip really, really smooth.

In the bad old days of travel, I had a single backpack that I used (a) to carry all of my computer gear and extras for traveling, (b) to take to the fitness center for workouts, and (c) for just about anything I needed a pack for. So I was constantly moving stuff in and out of the pack. This meant that every time I was leaving for a trip, I had to make sure the pack contained everything I needed.

About two months ago, I had a brainstorm: why not buy another backpack and use it only for business travel? Then I can keep all the gear I need in that pack all the time. When I need to travel, I drop my laptop in and off I go! So I got a very nice Targus backpack for about $20 (CompUSA was going out of business and the pack was about 66% off.), and I put inside it:

* A mouse (regular size and functionality). I can't stand the Thinkpad touchpad. I need a mouse to do any serious work.

* A very cool in-your-hand "one finger mouse". This comes in really handy when I stuck in a coach seat, with no room for a regular mouse. Iwould have to scrunch up my shoulders to use the touchpad, and that really hurts my upper back. With the trackball, I can fully extend my arm and move the mouse from any position.

* A super-thin, but stiff Wowpad mousepad that I can put right over indentations sometimes found on a fold out airplane tray, and which normally louse up a mouse. I talked about this in a previous blog entry.

* An Imak computer glove that has a built-in beanie-bag that provides support for my palm and wrist. It goes wherever I go.

* The IGo universal adaptor so I can plug into the on-board electricity and not be bound to just battery power. Note: I found mine on eBay for half the cost of retail.

* An extra battery for the laptop. Oh wow, that can sure come in handy. On a recent trip, I waited till the last minute to pack and run for the airport. Now, when I put my laptop in the dock, I have to take out the battery, because it is (both are) an extended life battery and it sticks out the back. So this time around, I grabbed the laptop and dropped into my pack - without putting in the battery! Without the spare already in the pack, I would have been in BIG TROUBLE.

* An inflatable Eagle Creek lumbar pillow. Very nicely designed and a big help for avoiding lower back stiffness and aches on long flights.

* A headset with microphone that I can use with Skype. I am very much enjoying Skype when I travel internationally. It makes staying in touch back home so much easier. And I barely ever use Skype for computer-to-computer conversations. I can call "real" telephone numbers and pay something like $.021 per minute.

Well, that's about it for the gear I use on most every flight or most every trip.

And with my pre-prepped backpack, it all comes with me, all the time. How wonderful! So that's a big improvement over past travel experiences.

But it gets even better. I went to Denmark and Switzerland on this trip, and one thing I have noticed over the years about hotels in these northern European countries is that they often have a thick quilt for a top sheet on the beds (it is actually like a blanket that is slipped inside a sheet). That's very nice when it is very cold, or when a person easily gets cold. But that's not me. I tend to "run hot." I prefer fewer blankets and have trouble sleeping when I get too warm. This has caused problems in the past.

So I bought another travel accessory for this trip: the Cocoon TravelSheet. This very lightweight silk sheet is actually a superthin sleeping bag, of sorts. You spread it on your bed and lie inside it. It even has a section near the head into which you can slide a pillow, so it stays nicely in place. The whole thing compresses to the size of a large orange. How cool is that? So I figured I could use it when I would otherwise have to sleep under a heavy quilt-sheet.

But what I realized upon arriving at my first hotel, is that I could make much better use of this sheet than I had thought: I could simply lay it down on top of the nicely-made bed and never actually use the hotel linens!

What's so great about that? Well, two things that I can think of:

* I reduce the amount of linen that must be washed, saving water, cutting back on the phosphate and bleach pollution that washing produces. I simply come home from my trip and wash my nice silk travel sheet.

* Cleaning staff do not have to tear down and remake the bed. They can clean the room faster and they are less likely to strain themselves. "Strain themselves?" you ask. "What is Steven talking about?"

Many hotel chains are "upgrading" their rooms and implementing "sleep systems" that usually involve lots of pillows, heavy blankets, higher thread count sheets, and so on. Sounds really comfy, right? Well, there usually is a downside for someone in such situations. Cleaning staff now have to deal with more and heavier linens, and work harder to clean the same number of rooms in the same amount of time as before. Injuries are on the increase.

So by using my travel sheet, I am not only more comfortable, but I reduce pollution and improve the quality of life of at least one other human being. I like that.

Finally, I make sure that whenever I travel, I have $5 or the equivalent in foreign currency to leave as a thank-you for the cleaning staff. Two perspectives motivate my giving:

1. The way I see it, the more personal a service that a person provides to you, the more important it is that you leave a tip for that person. Someone cleaning up in my hotel room is essentially cleaning up my temporary home, including my bathroom. That's very personal.

2. As far as I can tell, the less visible the worker, the less they are likely to be paid. I don't think cleaning staff are paid very well, but they work very hard. So I feel it is important to complement their meager hourly wages.

So, in conclusion, I suggest that if you too travel an awful lot, that you:

* Prepack as much as you can to avoid unpleasant surprises ("Oh no! I forgot my power cable!").

* Find ways to minimize the ecological impact of your hotel stays. The level of convenience and luxury provided in business hotels tracks closely with the amount of resources consumed and waste produced.

* Leave tips for your room cleaners. Those few dollars will mean little to you and I, but an awful lot to people who are probably earning minimum wage.

Sunday, April 01, 2007

You call this wisdom?

I don't know what you call it. Steven's Fortune Cookie text? Pompously presumptuous meanderings?

Well, nobody's going to force you to read these. Here goes (writing from Vilnius, Lithuania):
  • There are two kinds of people in the world: people who think there are two kinds of people in the world and people who don't. Which do you think is the more dangerous type?
  • It's not hard to solve many of the biggest problems faced by humanity. You just have to get the rich and powerful to give up a bunch of their wealth and power.
  • Our so-called leaders have utterly failed us (consider: we are causing massive climate change; 50,000,000 Americans are without medical insurance; the disaster in Iraq; people still dying of malaria and TB, etc.). I am not sure I could have done any better, but at least we should be honest enough with ourselves to admit this much.
Oh, and you know that saying by Santana that "Those who cannot learn from history are doomed to repeat it."? I think that it is total rubbish and needs to be completely rejected for several reasons, which I will come back to in a future blog entry.

But allow me to close with my favorite painting from the Contemporary Art Centre in Vilnius, by Aija Zarina titled My Mates: