Wednesday 28 March 2012

Please turn off hyperlinks in PowerPoint

When giving presentations, you should really turn off PowerPoints AutoCorrect feature of it changing a hyperlink into an underlined link.

Unless you actually are going to click on the link during the presentation, then turn it off. It's much easer to read without it being in a different font and underlined.

To turn it off in PowerPoint, goto Tools -> Options -> Proofing -> AutoCorrect options. Untick the box highlighted below.

Friday 23 March 2012

Recursive CTE (Common Table Expression)

There is sometimes a problem of wanting to remove data (email addresses in this example) from within a string which are delimited.

For example, if you want to remove all non bybox email addresses from "some.name@bybox.com; simon@hicrest.net; fred.bloggs@bybox.com"
and do this for every table, without having to create functions to break apart the string first, how are you going to do it?

Here's how:

Our example table looks like this
CREATE TABLE data_export
(
 data_export_id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
 email_address VARCHAR(255) NOT NULL
 -- ... Other fields left out for brevity
)

Insert some test data
INSERT INTO data_export (email_address)
VALUES  ('some.name@bybox.com; simon@hicrest.net; fred.bloggs@bybox.com'),
        ('neo@matrix.com; me@bybox.com'),
        ('fred@b.com; xxx@bybox.com'),
        ('fred@bbc.com'),
        ('an.other@bybox.com')

Next is the recursive CTE SQL is in several sections:
  • split_by_delimeter - Breaking apart the string by delimeters.
  • just_bybox - Keep the @bybox emaill addresses.
  • distrinct_set - The ID's we want to update.
  • STUFF - The rebuild section is the final select/update statement which containst the STUFF keyword.

;WITH   split_by_delimeter
          AS (
              SELECT    data_export_id,
                        email_address,
                        CHARINDEX(';', email_address + ';') AS n,
                        CAST('' AS VARCHAR(255)) AS result
              FROM      data_export
              UNION ALL
              SELECT    data_export_id,
                        SUBSTRING(email_address,CHARINDEX(';',email_address)+1, 255),
                        CHARINDEX(';', email_address),
                        LTRIM(RTRIM(SUBSTRING(email_address, 0,
                            CASE WHEN CHARINDEX(';', email_address) = 0
                            THEN 255
                            ELSE CHARINDEX(';', email_address)
                            END)))
              FROM      split_by_delimeter
              WHERE     n > 0
             ),
        just_bybox
          AS (
              SELECT    data_export_id,
                        result
              FROM      split_by_delimeter
              WHERE     result <> ''
                        AND result LIKE '%@bybox%'
             ),
        distinct_set
          AS (
              SELECT DISTINCT data_export_id
              FROM just_bybox
             )
    -- For checking
    SELECT  data_export_id,
            STUFF((
                   SELECT ';' + result FROM just_bybox y
                   WHERE y.data_export_id= x.data_export_id
                  FOR XML PATH('')
                  ), 1, 1, '') AS email_address
    FROM    distinct_set x
    /*
    -- For actual update
    UPDATE  data_export
    SET     email_address = STUFF((
                                   SELECT ';' + result FROM just_bybox y
                                   WHERE y.data_export_id= x.data_export_id
                                   FOR XML PATH('')
                                  ), 1, 1, '')
    FROM    distinct_set x
            JOIN data_export
                ON data_export.data_export_id = x.data_export_id
 */

This returns the following results:
data_export_idemail_address
1some.name@bybox.com;fred.bloggs@bybox.com
2me@bybox.com
3xxx@bybox.com
5an.other@bybox.com

Perfect!

Tuesday 20 March 2012

C# 5 attributes on optional parameters

With C# 5, you can put a special attribute on an optional parameter and the compiler will fill in the value not with a constant but with information about the calling method. This means we can implement the Logger.Trace to automagically pick up where it’s being called from:
public static void Trace(string message,
                         [CallerFilePath] string sourceFile = "",
                         [CallerMemberName] string memberName = "")
{
    string msg = String.Format("{0}: {1}.{2}: {3}",
       DateTime.Now.ToString("yyyy-mm-dd HH:MM:ss"),
       Path.GetFileNameWithoutExtension(sourceFile), memberName, message);

    LoggingInfrastructure.Log(msg);
}

Now, if the caller calls Log.Trace("some message") the compiler will fill in the missing arguments not with the empty string, but with the file and member where the call happens:

// In file called Fred.cs
public void SomeFunc()
{
  Log.Trace("Hello");
  // Compiles to Log.Trace("Hello", "Fred.cs", "SomeFunc")
}

Another example of how you can use this is in implementing INotifyPropertyChanged without needing either literal strings, expression magic or mystic weavers:
public class ViewModelBase : INotifyPropertyChanged 
{
  protected void Set(ref T field,
                        T value,
                        [CallerMemberName] string propertyName = "") 
  {
    if (!Object.Equals(field, value)) 
    {
      field = value;
      OnPropertyChanged(propertyName);
    }
  }
  // usual INPC boilerplate
}
 
public class Widget : ViewModelBase 
{
  private int _thingy;
  public int Thingy
  {
    get { return _thingy; }
    set { Set(ref _thingy, value); } // Compiler fills in "Thingy" as propertyName
  }
}
I grabbed this info from http://www.mindscapehq.com/blog/index.php/2012/03/18/what-else-is-new-in-c-5/. More can be found there, but I thought this feature important/cool enough to blog about it on its own right. And mainly so I don't forget about it...

Friday 2 March 2012

www.stilettos-sos.com

I've created yet another WordPress CMS system for a friend of my wifes this time.
Home page is a blog, the others are static pages.
www.stilettos-sos.com

Thursday 1 March 2012

The real doomsday date is Tue Jan 19 2038 at 03:14:07

Some said it was the Y2K bug we had to worry about, but it's actually Tue Jan 19 2038 03:14:07 you've really to worry about.

There are many, many systems built with time saved as a 32bit long integer value.
The max value of a signed long integer is 2147483647. This value is the number of seconds elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC)

Here is an example C program, built with Visual Studio 2010.

__time32_t t;

t = 0;
printf( "The min is %s\n", _ctime32( &t ) ); 

t = 2147483647;
printf( "The max is %s\n", _ctime32( &t) ); 

t = 2147483648;
printf( "The date is %s\n", _ctime32( &t) ); 

Output:
The min is Thu Jan 01 00:00:00 1970
The max is Tue Jan 19 03:14:07 2038
The date is (null)

So after Tue Jan 19 03:14:07 2038, the date goes to null which will cause a crash. Let's just hope all the critical (including embedded) systems get fixed before then.