The SQL knowledge came in handy when I started working on the Dodeca feature which will allow users to copy comments from one set of key combinations to another. We have had a number of requests for this functionality over the years and I have read many requests from frustrated Hyperion Planning users who desperately needed that functionality.
In our case, we store commentary in a relational table on the Dodeca server. The comments table has the COMMENT_TENANT and the COMMENT_ID fields as the primary key. The tenant code is a unique identifier for a Dodeca application. The comment ID is a GUID (Guaranteed Unique ID) obtained from the operating system. Here is a screenshot of the COMMENTS table.
The key/value pairs that identify the datapoint, or partial datapoint, that identify the comment are stored in a separate table that has a one-to-many relationship. Here is a screenshot of the COMMENT_KEY_ITEMS table.
The SQL problem I needed to solve was ‘How do I get a list of comment ID’s that have, for example, both the Scenario equal to Budget and the Year equal to Apr? My initial thoughts focused on the fact that no matter how I wrote the where clause, I would still get two rows back if my query returned the rows that I wanted. Myopia nearly got the best of me until I remembered the SQL GROUP BY clause. Using the GROUP BY clause, I could flatten the two rows into one. I still needed to make sure the original query, however, returned two rows, so the SQL HAVING clause did exactly what I wanted.
The next complication is that we use Hibernate Object-to-Relational Mapping technology in our server in order to support many relational data sources. This technology handles the translation of Plain Old Java Objects (POJOs) to, and from, relational sources. So, I had to write my Hibernate Query Language, or HQL, using GROUP BY and HAVING clauses:
select c.CommentId from Comment c join c.keyItems i where c.Tenant = 'SAMPLE' and (i.Key = 'Scenario' and i.Value = 'Budget') or (i.Key = 'Year' and i.Value = 'Apr') group by c.CommentId having count(c.CommentId) = 2
Of course, in my code this HQL is created on the fly based on tenant code and the variable number of key/value pairs passed into the routine. Hibernate, in turn, writes the SQL. Here is an example of the SQL in SQL Server syntax:
Select comment0_.COMMENT_ID as col_0_0_ from COMMENTS comment0_ inner join COMMENT_KEY_ITEMS keyitems1_ on comment0_.COMMENT_TENANT=keyitems1_.COMMENT_TENANT and comment0_.COMMENT_ID=keyitems1_.COMMENT_ID where comment0_.COMMENT_TENANT='SAMPLE' and keyitems1_.KEY_ITEM_KEY='Scenario' and keyitems1_.KEY_ITEM_VALUE='Budget' or keyitems1_.KEY_ITEM_KEY='Year' and keyitems1_.KEY_ITEM_VALUE='Apr' group by comment0_.COMMENT_ID having count(comment0_.COMMENT_ID)=2
This SQL gave me the comment ID’s I needed to copy which was just the start. To complete the project, I also had to update the comment ID with a new Java UUID, update the related KeyItem records with the new UUID, recompute the COMMENT_KEY_HASH that is used to reduce the network traffic and required server resources by allowing for a query filter based on a single column value instead of a one-to-many join, and track/update the comment ID’s in the PARENT_ID field which is used to track threaded comments.
The code is now complete and will be checked into our source code control system today. QA can then get started with their testing so this feature can be released in the next Dodeca release.
No comments:
Post a Comment