Thursday, January 4, 2007

Apple OS-X Default Applications

You don't necessarily want to use the Apple applications that come with OS-X, nice as they undoubtedly are.

If you want different applications to open as default when you click on a file, try this: select the file in a Finder window, Ctrl-Click to get the pop-up menu, click on the arrow next to 'Open With:' to show the dialogue, select the application to use from the selection box (you can use the 'other' item right at the bottom to hunt for an application that isn't on the menu). To make your new selection the default application for all files of this type, click the 'Change All' button.

To change the default Internet applications (mail client, browser) in 10.2 or earlier, you need to open System Preferences from the Apple menu, select 'Internet' and follow the dialogue there.

For 10.3 onwards, it's a little trickier. To change the default web browser: start Safari, select 'Preferences' under the 'Safari' menu, select the 'General' tab (the leftmost item) and pull down the 'Default Web Browser' selection box. If the browser you want to use is not offered, choose the 'Select...' item and use the file dialogue to find your browser.

The procedure for choosing a mail client is broadly similar but use Mail instead.
:

Friday, November 17, 2006

Proceeding in an orderly fashion with Oracle



PL/SQL has many endearing features for the programmer and one or two which are less so. One of its nicer features is the ability to define procedures which can then be used as if they were a part of the language. Procedures may define and use variables which are local to that procedure. An extension to this is the concept of packages: bundles of procedures which can be used as complete libraries and slotted in as 'black boxes' wherever they're required. Packages may define variables which are local to the package but global to the procedures contained by the package.

Procedures.

A procedure consists of a name (with optional parameters), IS, BEGIN, any number of statements and END. As with C, Perl and similar languages, each statement is terminated with a ';' (semi-colon). Here's a simple example...

PROCEDURE GetSalesList(Customer IN VARCHAR2, Process in VARCHAR2)
IS
BEGIN
IF Process = 'PURGE'
THEN
DELETE FROM SalesFeed
WHERE CustId in (SELECT distinct Id
FROM Customers
WHERE Name = Customer);
ELSE
INSERT INTO Invoice (CustomerId, TranDate, Value)
SELECT CustId,
FeedDate,
Amount
FROM SalesFeed
WHERE CustId in (SELECT distinct Id
FROM Customers
WHERE Name = Customer);
END IF;
END;

Thre's effectively no limit to how large and complex procedures may be. Once installed in a package, procedures may be called by any query which has access to the package, making this a very useful facility.
:

Saturday, July 29, 2006

SQL*Plus: Oracle's Swiss Army Knife

For a very long time, Oracle has shipped with the SQL*Plus application as standard.

There are different versions for different operating systems but users will, most commonly, come across the versions for Microsoft Windows and those for the Unix family. The difference between these is that the Windows version is a fairly basic application whereas that for Unix is a very powerful tool indeed because it allows you to use it as a standard command line application like any other, so permitting its use in complicated shell scripts.

What a lot of people don't realise is: there's a CLI version of SQL*Plus installed along with the not terribly useful Windows version which, within the limitations of Windows, permits all the flexibility of the Unix variant.





Once you know this, your ability to automate Oracle tasks on Windows is increased dramatically. While not quite as flexible as the Unix version, due to the limitations of Windows, there are still many things you can do that are just too much of a pain when using the GUI version.

Wednesday, March 15, 2006

Some Awk Tips and Tricks

Finding the length of a line.

A colleague needed to find the length of a particular line in a file. He discovered that using 'wc' gave the wrong result (as in "head -2 filename | tail -1 | wc -c"). Here's what he came up with instead. Note the parentheses...

cat filename | awk '{ if ( NR == 2 ) {print length($0); exit; } } '

Sizing a directory.

This uses Awk's ability to do arithmetic across multiple input lines to produce a count, total and average file size for a directory or a supplied pattern. It's a usefull tool for quick 'n' dirty system admin...

echo "file counter and sizer"
echo "----------------------"
if [[ -z $1 ]]
then
echo "Sizing entire directory"
else
echo "Sizing files for pattern [$1]"
fi

ls -l >/tmp/fsz.$$_1

# -------------------------------
# Remove any directory entries...
# -------------------------------
grep -v ^total /tmp/fsz.$$_1 | grep -v ^d >/tmp/fsz.$$
rm /tmp/fsz.$$_1
# ------------------------
# Set up the search job...
# ------------------------
if [[ -z $1 ]]
then
cat /tmp/fsz.$$
| awk '{s += $5}; END
{printf "\nThere are %d files matching pattern\nAverage size is %f\nTotal size is %f\n", NR, s/NR, s}'

else
grep $1 /tmp/fsz.$$ | awk '{s += $5}; END {printf "\nThere are %d files matching pattern\nAverage size is %f\nTotal size is %f\n", NR, s/NR, s}'
fi
rm /tmp/fsz.$$


Don't use awk - use nawk!

I couldn't work out why this wouldn't work when I ran it using awk (as it worked fine on another machine). It turned out that it would perform admirably if I ran it using nawk instead. It's worth trying this out on your own machine and seeing what happens...

nawk '{ if(substr($0,405,2)=="LS") print $0 }' sourcefile.dat | head -10000 > targetfile.dat
:

Thursday, July 21, 2005

The when and the wherefor

Dates in Perl are a pretty big subject but the essence can be reduced to two simple rules: use 'localtime' to retrieve Perl's internal date block and then use 'sprintf' to format the retrieved date. The following subroutine returns the current date and time in the format 'dd-MMM-yy hh:mm' (e.g. 23-DEC-05 15:35)...

sub FormatCurrentDateAndTime
{
my $V_CURRENT = localtime;
my $V_SECOND = substr($V_CURRENT, 17, 2);
my $V_MINUTE = substr($V_CURRENT, 14, 2);
my $V_HOUR = substr($V_CURRENT, 11, 2);
my $V_DAY = substr($V_CURRENT, 8, 2);
my $V_MONTH = uc(substr($V_CURRENT, 4, 3));
my $V_YEAR = substr($V_CURRENT, 20, 4);

# -------------------------------
# And Format the output string...
# -------------------------------
$V_ID_STRING = sprintf("%02d-%s-%02d_%02d:%02d",
$V_DAY,
$V_MONTH,
$V_YEAR,
$V_HOUR,
$V_MINUTE);
TraceScript $Debug,
"MakeDateTimeID",
"Generated id is [" . $V_ID_STRING . "]";

return $V_ID_STRING;
}

The above code is very simple. Calling localtime without an argument gets the current date and time which is then sliced up into the named variables. Sprintf is then called to reformat the value the way we want it. The TraceScript call gives the clue that this particular example is being used to generate a unique ID.
:

Monday, July 11, 2005

Getting at the bits

One place that Perl scores very highly is reading complex file formats. A really useful built-in function for this purpose is split(). This takes a divider and a string, whose length is only limited by Perl's string handling limit. The divider is in the form of a regular expression, so it can be as complicated as you wish. Split() returns an array, with each piece of the original string as an element, broken up according to the regex and the divider(s) removed. Say, for example, you wrote ...

@Result = split(/:/, "apples:oranges:pears"

then @Result would contain the elements

apples
oranges
pears

with the dividing ':' discarded. The following, real life, example is for extracting the required item from a comma-delimited list, such as a line in a CSV file...

sub GetCsvElement
{
my @V_ARRAY;
my $P_ELEMENT = $_[0];
my $P_SOURCE_STRING = $_[1];
my $V_RESULT;

# -----------------------------------
# Drop the elements into our array...
# -----------------------------------
@V_ARRAY = split (/,/, $P_SOURCE_STRING);

# ----------------------------------------------------------------
# Arrays are zero based so we pick one less than the passed value!
# ----------------------------------------------------------------
$V_RESULT = trim $V_ARRAY[--$P_ELEMENT];

# ----------------------------
# Return the requested item...
# ----------------------------
return $V_RESULT;
}

Remember, because you're using a regular expression to define the delimiter, you can process multiple types of line or even lines with more than one delimiter.
:

Saturday, July 2, 2005

Perl sans frontiers

I often want to retrieve results from an external process within a Perl script. In theory, this is easy. All you need to do is something like...

$Result = `ls *.sql`

...which works perfectly well on any Unix (or Linux) system. The problem is that it doesn't work at all on Windows so, if you want your programme to be fully portable, you need a workaround. My solution is to use the one common feature on both Windows and Unix, the redirection character (>).

Say I want to run a SQL query (because this is something I do frequently, I have a subroutine for it)...

# =======================================
# Runs an SQL file, returning the result.
# ---------------------------------------
# $_[0] is the connection string.
# $_[1] is the file to run.
# $_[2] is a file to write the result to.
# ---------------------------------------
# (This last is necessary because the ``
# syntax does not work in Windows.)
# =======================================
sub RunSqlQuery
{
my $V_COMMAND = "sqlplus "
. $C_SQLPLUS_FLAGS
. " "
. $_[0]
." \@"
. $_[1]
. " >"
. $_[2];
my $V_RESULT;

# --------------------------------
# Run the command created above...
# --------------------------------
system $V_COMMAND;

# ---------------------------------
# Get the result back from the file
# and send it up the call chain...
# ---------------------------------
$V_RESULT = ReadResultFile $_[2];
return $V_RESULT;
}

Now the above piece of code will work, unaltered, on both Windows and Unix. Then all we need to get at the result is a matching sub-routine to read the file...

# ===============================================
# Reads a file in which a result has been placed.
# -----------------------------------------------
# $_[0] name of the file to read.
# -----------------------------------------------
# This is one of the workarounds made necessary
# because the syntax "VAR=`command`" does not
# work in Windows the same as it does in Unix.
# ===============================================
sub ReadResultFile
{
my $V_BUFFER;
open(H_SQL_FILE, "<$_[0]") or die "FAILURE: Cannot open " . $_[0];
read H_SQL_FILE, $V_BUFFER, 65535;
close H_SQL_FILE;
return $V_BUFFER;
}

The size limit of 65535 bytes is completely arbitrary and can be altered to meet the specific requirements of the application.
:

Followers

Who is this Sejanus character anyway?

I'm a British freelance Analyst Programmer who has spent the last 25 years working on everything from microcontrollers to mainframes. I use a wide variety of languages at work but try to stick to C and Perl for my own projects.