The FeedDetail Table and the PairRange View
Most instances of Feed refer to a hardware sensor, and stores the periodically collected sensor values in related instances of Poll. Some instances of Feed, however, are used to store information resulting from a calculation of some sort. Initially, this is limited to the aggregation of values from several instances of Feed once the sensor values have been transformed to actual values with a Correlation-based lookup. The relationship of which instance of Feed is the aggregator, and which instances of Feed are being aggregated, is maintained through the use of the newly-created FeedDetail table.
In a given instance of FeedDetail, the id_Feed attribute identifies the aggregator Feed, whereas the id_Feed_related attribute identifies the feed being aggregated. id_Feed must be populated, because all FeedDetail instances must be related to a Feed. On the other hand, id_Feed_related is only populated when one Feed has a relationship to another. In the future, other types of FeedDetail instances will be introduced which won’t have related instances of Feed, but rather, will have some other sort of calculation logic that needs to be applied.
Speaking of Correlation-based lookup, the first step for the logic was to create the PairRange view. This takes subsequent instances of Pair, and creates lower and upper boundaries with them. For instance, if xAmt and yAmt for two successive instances of Pair were populated with 0, 0 and 10, 15 respectively, then PairRange would have a single row with lowerXAmt, upperXAmt set to 0 & 10, and lowerYAmt and upperYAmt set to 0 & 15 respectively. This enables the easy comparison of values with Poll.amt to see where a particular value falls. The instance of PairRange also contains enough information to enable straight line interpolation between the lowerYAmt and upperYAmt. For example, if Poll.amt is 4, the yAmt can be interpolated by taking 4 / (upperXAmt - lowerXAmt) * (upperYAmt - lowerYAmt) + lowerYAmt. To complete the example, 4 / (10 - 0) * (15 - 0) + 0 => 0.4 * 15 + 0 which results in 6 for yAmt.
PairRange basically uses H2’s ROWNUM function to assign row numbers to two subqueries of Pair, and then joins them based on SubQuery1.seq - 1 = SubQuery0.seq AND SubQuery1.id_Correlation = SubQuery0.id_Correlation. It works perfectly well, but does result in odd behaviour though; unless you query this view with a WHERE clause which specifies id_Correlation, it will only ever return rows for the first Correlation. When H2 processes the view, the first time id_Correlation changes, the clause which is the basis for the join is no longer true, and because it’s not true, it’s also not true for any subsequent row of the view. In other words, the breakage cascades its way though the balance of the view. It’s just a little jarring to have things show up when you consciously specify something with a WHERE clause, and for things to disappear when you don’t, which is the reverse of what’s usually the case.
Code Shavings Many thanks to Sergi Vladykin for his reply to my post on the H2 forum. For a while there, I figured I was going to have to write some Java code to get around a limitation of H2’s ROWNUM function, but his suggestion worked like a charm and prevented all that. ♦ One thing which got omitted from the previous post was the necessity for having the H2 Console open in order to have the JDBC code work. This is because H2 Console starts the instance of H2 to which the JDBC code then connects. The JDBC code, on its own, is not smart enough to start an instance of H2.
Posted on 31st July 2009
Under: Arago, Developers' Journal | 2 Comments »

