All posts by Alistair Lattimore

About Alistair Lattimore

My name is Alistair Lattimore, I'm in my very early 30's and live on the sunny Gold Coast in Australia. I married my high school sweet heart & we've been together for longer than I can remember. Claire and I started our family in September 2008 when Hugo was born and added a gorgeous little girl named Evie in May 2010. You can find me online in the typical hangouts, Google+, Twitter & facebook. .

Raising The Bar

I’ve now played played two seasons of squash at the Gold Coast and it has been a really great experience. Since joining the Robina Squash Club and having different opponents with varying hitting styles, my game has improved drastically.

The most recent squash season is coming to an end and unfortunately, my team didn’t make the finals. It isn’t all bad though, as this season I know my game has improved further than the first season I played.

This season I’ve had a new opponent who has been a real challenge for me to compete against; so much so, I haven’t beaten him yet. I’ve played Steve about five times in the last couple of months, more than I should have due to substituting for other players and I have struggled against his game each time. I expect that Steve could be playing the grade above without a lot of problem, their loss and my gain.

After paying attention to what is happening to me on the court, I’ve been making mental notes about Steve’s game:

  • A consistent serve, not a whole lot of variety in it but its placed well enough that it doesn’t really matter
  • Comfortable hitting from the back of the court
  • Strong forehand, capable of changing the pace and direction well
  • Very good backhand, can change the pace of the ball very well
  • Good court sense, uses it to his advantage by boasting off the walls
  • Magnificent backhand drop shot, can play it from pretty much anywhere in the court.

I use the word magnificent, which is probably overstating it by higher standards – however it is the best that I have played against to date. Through good court sense, Steve changes the pace of the ball, with or without the drop shot to his advantage to move his opponent around a lot. He favours the short ball, as it’s an easy way to make his opponent run with a low chance of being able to hit an attacking shot off it.

After playing Steve and losing each of the matches, it really accentuates the faults in my game. As such, I’ve got a short list of items I’m going to be changing about my game to improve and really give Steve and cohorts a series shake on the court:

  • Vary the pace of the ball more. Hitting it consistently at whatever pace the game is being played at, just feeds into my opponents advantage; by giving them a ball they can judge easily
  • Change the length of my shots. When I first started playing, I wasn’t hitting the ball deep enough, regularly enough and one of the higher graded players pointed out that I needed to hit the ball deeper. Taking that advice on board, I strive to hit the ball at about 3/4 court plus a bit. As per the previous point, this consistency is a great thing to have on my side – however if I’m not changing the length of the ball up, it reduces the effectiveness of the deep ball as they are prepared for it in nearly all circumstances.
  • Boast the ball more. Currently, I only boast the ball when it is the obvious shot to play. That strategy needs to change, so that boasting is part of my normal game play to move my opponent around. This shouldn’t be limited to just off the side walls, the high ball should be included in this as well – to push the opponent into the back of the court.
  • Develop a slice backhand. To some extent, this is a follow on from point one. I currently hit the standard backhand drive off most balls. This needs to change to allow me to more consistently move my opponent around by dropping the ball short or boasting it off the wall after washing the speed off through a slice backhand.

The next Gold Coast squash season starts at the Bond University, via the Robina Squash Club in about another month I believe. I’m really looking forward to putting some of the above points into action onto the squash court to see where it takes me, fun times ahead.

If you’re interested in joining the club for some fun and fitness, you can contact:

Robina Squash Club
University Drive
Robina QLD, 4226
0427 627 229

Getting Your CSS Off

Toward the end of March 2006, Dustin Diaz thought that stripping all of the presentation from his web site was an excellent way of promoting web standards and CSS based design. The idea caught on and a whole swag of people participated in the first CSS Naked Day on April 5th 2006.

A year has passed and once more, web standards advocates alike around the world are stripping all of the presentation from their sites by running around butt naked without any cascading style sheets to hide their wobbly bits!

I thought about participating in the naked day this year, however I pretty much participate in it all year around so I didn’t think it would have had that much effort. If I had a graphic design bone in my body, I could have created the anti-naked day by getting my CSS on and releasing an amazing visual feast for everyone.

Unfortunately, I don’t have a visual feast for you this year – in the mean time, you should check out some cute cat photos!

EMI Removes Digital Rights Management (DRM)

Music industry heavy weight EMI has announced that it will allow the download of their music catalog online without Digital Rights Management attached to the files.

DRM was released with the intention it would curb digital media piracy. Unfortunately, implementing DRM in a manner that worked well for the consumer seemed to be a constant thorn in the side of the media publishers as the consumers pushed back against the use of digital rights management.

Users would download music encrypted using DRM technology and would then not be able to transfer the song from one media device to another, such as from a computer to an MP3 player. If you could move or transfer the file, there was a limited number of transfers available. This problem was circumvented if you were downloading from the Apple iTunes store, as it would allow syncing of the downloaded songs onto associated Apple devices.

As expected, Apple will be the first retailer to sell the newly released DRM free media through the iTunes store at a slightly higher price than a DRM encrypted media file. EMI have stated that they will continue to use DRM technology where appropriate for time or subscription based services. The use of DRM in that area is well within the bounds of its reach in my opinion and is an excellent use of the technology.

From my point of view, this is excellent news. I have refused to download music from iTunes store because the files have DRM attached. Sometime in the near future, I might just swing by the iTunes store and see what they have on offer.

Oracle Dynamic SQL Using The DECODE Function

When developing most applications, you end up having to interact with a database. If you’re application is large enough and warrants the design and effort, it will no doubt be tiered as well. If your application is tiered, one of your layers will probably include a database API. A database API is used to restrict access to the database, a funnel which all requests from your application must pass through. Implementing this additional layer of abstraction normally yields in higher performance, increased security and easier maintenance.

In most cases, you’re application code will require a fairly standard interface into your database to retrieve information. A simple way to achieve that consistent interface is using the DECODE function in your PL/SQL procedures and functions. There are always cases where you need to do something special, and in those cases it is probably a perfect scenario for this methods counter-part – the string building technique.

For a simple but practical example, consider the following table definition:

  1. CREATE TABLE MyTable (
  2. PrimaryKeyID NUMBER NOT NULL,
  3. ForeignKeyID NUMBER NOT NULL,
  4. Name VARCHAR2 (255) NOT NULL
  5. )

As I have mentioned before, the Oracle DECODE function provides similar functionality to an IF-THEN-ELSE code block. Lets examine an example which relates to MyTable above.

  1. PROCEDURE Get
  2. (pDetails OUT grcDetails,
  3. pPrimaryKeyID IN MyTable.PrimaryKeyID%TYPE DEFAULT NULL,
  4. pForeignKeyID IN MyTable.ForeignKeyID%TYPE DEFAULT NULL,
  5. pName IN MyTable.Name%TYPE DEFAULT NULL)
  6. IS
  7. BEGIN
  8. OPEN pDetails FOR
  9. SELECT *
  10. FROM MyTable
  11. WHERE PrimaryKeyID = DECODE(pPrimaryKeyID, NULL, PrimaryKeyID, 0, PrimaryKeyID, pPrimaryKeyID)
  12. AND ForeignKeyID = DECODE(pForeignKeyID, NULL, ForeignKeyID, 0, ForeignKeyID, pForeignKeyID)
  13. AND LOWER(Name) LIKE DECODE(pName, NULL, LOWER(Name), '%'||LOWER(pName)||'%');
  14. END;

Working top down, the second line declares pDetails (the parameter name) as being an OUT parameter. As the name suggests, an OUT parameter is a way for you to pass information out of your procedure. In some aspects it would be similar to returning a value out of a typical programming function. The difference to an OUT parameter is that you can have many OUT parameters in a single procedure, where as a typical programming function can only return a single value at a time.

The next thing you’ve probably noticed is this weird thing in there, grcDetails. Just as the IN parameters below it, grcDetails is the type of the parameter. It would be akin to defining a paramter in a traditional function as accepting an integer or string type. In this case, grcDetails is declared in the package header:

  1. TYPE grcDetails IS REF CURSOR RETURN MyTable%ROWTYPE;

The important thing to notice about grcDetails is that it is a REF CURSOR and its type is the ROWTYPE of MyTable. The benefit of defining it as a ROWTYPE is that if tomorrow the definition of the table changed in some way, you don’t have to worry about changing any code to match the new table definition – it simply continues to work. This is the same reason why the INPUT parameters above have their type defined against the field that they represent. Of course, if you are passing in or out a value which isn’t based on a field – you would simply define it as a standard PL/SQL type.

Next, you have probably noticed that each IN parameter has a DEFAULT value. As with most programming languages, providing a DEFAULT value allows the programmer to optionally supply that parameter. For our example, this is a pivotal point as it simplifies the use of this method; more on that later.

Moving on to the actual SQL statement, the flexibility of the DECODE function starts to show. Since the DECODE function acts like an IF-THEN-ELSE block, you’re actually seeing an inline IF-THEN-ELSE IF-ELSE block per field. Lets take a practical example of that statement and assume we passed in pPrimaryKeyID with a value of 1, while the other two input parameter’s are not passed in (thus taking their default value of NULL). The SQL statement would be parsed and executed as follows:

  1. SELECT *
  2. FROM MyTable
  3. WHERE PrimaryKeyID = 1
  4. AND ForeignKeyID = ForeignKeyID
  5. AND LOWER(Name) LIKE LOWER(Name);

Of course, the net effect of that SQL statement is that the first WHERE condition is used, while the second and third conditions are nullified as the left and right half of each expression are equivalent. So by passing in a NULL value for the pForeignKeyID and pName parameters, they are effectively removed from the SQL statement by evaluating to themselves. Of course, you could also pass in two, three or none of the parameters to the procedure as well. In which case you would get either a restricted set from the statement or all records in the table.

As mentioned above, the DEFAULT value of each IN parameter is critical to this methods success. By providing a default value, the programmer no longer needs to call the procedure with all parameters; all, some or none are also perfectly valid combinations. Since the input parameter’s default value is NULL, the following DECODE function call is all that is required to negate the parameter in the WHERE clause:

  1. PrimaryKeyID = DECODE(pPrimaryKeyID, NULL, PrimaryKeyID, pPrimaryKeyID)

By now, you have probably noticed some extra parameters in the example GET procedure listed above. The additional values are used to exclude any other ‘not important’ values from the statement. In the example procedure, NULL and the value 0 are considered unimportant; whilst all other values are considered useful.

If you’re wondering why you’d want to exclude other values, it might be to make another section of your application simpler. Some programming languages don’t support nullable primitive types. If you use such a language and you intend to pass in all parameters to your procedure in all circumstances (this is the ‘simpler’ above); then all values will have a value of some sort. In the case of a primitive such as an integer, you might find that its default uninitialised value is zero. If that is the case and you don’t require the ability to filter on a zero value, then excluding it within the DECODE function makes things simpler.

Don’t think you’re limited to using this method on SELECT statements, it will work a treat on DELETE too. Consider the following DEL procedure:

  1. PROCEDURE Del
  2. (pRowCount OUT NUMBER,
  3. pRoomTypeID IN RoomTypes.ROOMTYPEID%TYPE DEFAULT NULL,
  4. pBuildingID IN RoomTypes.BUILDINGID%TYPE DEFAULT NULL)
  5. IS
  6. BEGIN
  7. IF (pRoomTypeID IS NOT NULL OR pBuildingID IS NOT NULL) THEN
  8. DELETE
  9. FROM RoomTypes
  10. WHERE RoomTypeID = DECODE(pRoomTypeID, NULL, RoomTypeID, 0, RoomTypeID, pRoomTypeID)
  11. AND BuildingID = DECODE(pBuildingID, NULL, BuildingID, 0, BuildingID, pBuildingID);
  12. ELSE
  13. RAISE_APPLICATION_ERROR(-20001, 'At least one parameter must be supplied');
  14. END IF;
  15. pRowCount := SQL%ROWCOUNT;
  16. END;

There is a caveat to using this method for building dynamic SQL within Oracle, it cannot handle columns which are nullable. If you consider the use of the DEFAULT value on all of the input parameters, it will become clear. Within Orcale PL/SQL, it is not possible to use an equality (=) operator to compare a NULL value. As a simple example, take the two simple SQL statements:

  1. SELECT * FROM DUAL
  2. SELECT * FROM DUAL WHERE NULL = NULL

The first SQL statement above will return the expected row from the DUAL table, while the second statement will return no results as you cannot compare the NULL value in that manner. If a comparison against a NULL is required, it must be handled using the IS NULL clause.

Other than not being able to use this method against columns which are nullable, its a really convenient way to write dynamic SQL in Oracle. Next time you need a little flexibility and you don’t want to go down the string building path, try using the Oracle DECODE function to produce your dynamic SQL.

The Naked Sausage

This afternoon, Claire and I dropped by the supermarket to pick up some odds and sods for dinner and among our findings were naked sausages. You’re probably wondering what the hell a naked sausage is, well its a standard sausage without the skin on it.

The particular ones we found were by a Western Australian company named Chevups. Other than the fact that the sausages were skinless, which in itself is pretty cool – they were also:

  • made of Australian lean beef
  • gluten free
  • 92% fat free

They look a little different to normal but man were they tasty – I highly recommend trying some out if you come across them.