Converting Java Properties Config to a Database Schema – Part II

Today I spent time taking the database schema I made yesterday and making it look like a Java Properties file so that I could easily create Properties objects and then feed them to the alerts I had and not have to worry about changing the rest of the code. The problem is, the database schema was logical, but it wasn't anything like what the previous Properties file layout looked like.

The ChatTo and MailTo properties were at the same level as the rest of the parameters, but in the new database schema, it's an entirely new (and separate) table, with links to an existing table for the email address. It's different, all right. After a little messing around in SQSH, I came up with the following stored procedure that takes a set name and returns two columns - keys and values, and from this, I can easily feed a newly created Properties object and we're good to go.

  CREATE PROCEDURE sp_getProperties
      @setName VARCHAR(80)
  AS
  BEGIN
      -- get an answer table to hold the whole lot of it
      CREATE TABLE #answer (
          name    VARCHAR(256),
          VALUE   VARCHAR(4096)
      )
 
      -- get the list of the alertIDs that are in this set
      CREATE TABLE #interesting (
          alertID     INT
      )
      INSERT INTO #interesting
          SELECT DISTINCT a.alertID
            FROM Alerts a, ALertParams p
           WHERE p.setName=@setName
             AND a.alertID=p.alertID
             AND a.active=1
 
      -- get the list of all active, interesting alerts
      DECLARE @id INT,
              @val VARCHAR(4096)
      SELECT @val=''
      SELECT @val=@val+CASE WHEN @val='' THEN '' ELSE ';' END+a.name
        FROM Alerts a
       WHERE a.active=1
      -- ...and now that it's built, put it into the answer
      INSERT INTO #answer
          VALUES('Alerts', @val)
 
      -- run through them all, processing each in turn
      DECLARE actives cursor FOR
          SELECT alertID FROM #interesting
      OPEN actives
      fetch NEXT FROM actives INTO @id
      while @@fetch_status = 0
      BEGIN
          -- get the ClassName for this active guy
          INSERT INTO #answer
              SELECT 'Alert.'+a.name+'.ClassName' AS name, a.classname AS VALUE
                FROM Alerts a
               WHERE a.alertID=@id
 
          -- get the VersionID for this active guy
          INSERT INTO #answer
              SELECT 'Alert.'+a.name+'.VersionID' AS name, a.versionID AS VALUE
                FROM Alerts a
               WHERE a.alertID=@id
 
          -- get the bulk of the parameters for the alert...
          INSERT INTO #answer
              SELECT 'Alert.'+name+'.'+p.name AS name, p.value AS VALUE
                FROM Alerts a, AlertParams p
               WHERE a.alertID=@id
                 AND a.alertID=p.alertID
                 AND p.setName=@setName
 
          -- get the ChatTo list for this active guy
          SELECT @val=''
          SELECT @val=@val+CASE WHEN @val='' THEN '' ELSE ';' END+u.username
            FROM AlertRecv r, Users u
           WHERE r.alertID=@id
             AND r.username=u.username
             AND r.chat=1
             AND r.setName=@setName
          -- ...now that it's built, insert it into the answer
          IF @val<>''
              INSERT INTO #answer
                  SELECT 'Alert.'+a.name+'.ChatTo' AS name, @val AS VALUE
                    FROM Alerts a
                   WHERE a.alertID=@id
 
          -- get the MailTo list for this active guy
          SELECT @val=''
          SELECT @val=@val+CASE WHEN @val='' THEN '' ELSE ';' END+u.username
            FROM AlertRecv r, Users u
           WHERE r.alertID=@id
             AND r.username=u.username
             AND r.email=1
             AND r.setName=@setName
          -- ...now that it's built, insert it into the answer
          IF @val<>''
              INSERT INTO #answer
                  SELECT 'Alert.'+a.name+'.MailTo' AS name, @val AS VALUE
                    FROM Alerts a
                   WHERE a.alertID=@id
 
          fetch NEXT FROM actives INTO @id
      END
      close actives
      deallocate actives
 
      -- now return this to the caller
      SELECT name, VALUE FROM #answer
  END

Now while I'll be the first to admit that this is not the most efficient way of getting the data into a format that I can easily parse, it's pretty fool-proof. I wanted to make the Java parsing as simple as possible, and this does the job - a simple table with two columns - names and values to put in the map. Can't get any simpler than that.

I will say that some of the parts that I think are clever are the building of the strings that are really individual rows in the database - like the list of active alerts, or the list of ChatTo or MailTo recipients:

      SELECT @val=''
      SELECT @val=@val+CASE WHEN @val='' THEN '' ELSE ';' END+a.name
        FROM Alerts a
       WHERE a.active=1
      -- ...and now that it's built, put it into the answer
      INSERT INTO #answer
          VALUES('Alerts', @val)

We know that the select statement contains an implicit loop, and by using the case statement in the select, we get the delimiters in the right place - as opposed to an unnecessary trailing, or leading, one. I have to give credit for the use of the case to a co-worker. Pretty nice and concise.

With this, I'm able to finish the replacement of the Properties file with a database schema, and that's what I needed. In the coming days I need to make an editor in my web app, and then put a user-serviceable subscription page together so that the users can update what they get on their own. That will be a nice win for the web app.