Axaptapedia is now maintained by AgileCadence For more information please click here.
SYS ExpressionQueryBuilder
From Axaptapedia
What is it?[edit]
SYS_ExpressionQueryBuilder is a way to easily code queries with dynamic structure. It is based on Expression Builder pattern by Martin Fowler
The problem[edit]
For example, you have the following code (select number of negative inventory transactions in year 2006 grouped by ItemID, in some specific inventory location):
<xpp> InventDim inventDim;
InventLocationID inventLocationID;
while select count(recID) from inventTrans group by ItemID where inventTrans.DatePhysical >= 01\01\2006 && inventTrans.DatePhysical <= 31\12\2006 && inventTrans.Qty < 0 exists join inventDim where inventDim.inventDimId == inventTrans.inventDimId && inventDim.InventLocationId == inventLocationID { info(strFmt('%1: %2', inventTrans.ItemId, InventTrans.RecId)); }
</xpp>
Now somebody wants to use the same query, but invent location should be specified by standard filter. There is no way except using QueryBuildDataSources:
<xpp>
Query q=new Query(); QueryBuildDataSource dsInventTrans = q.addDataSource(tableNum(InventTrans)); QueryBuildDataSource dsInventDim = dsInventTrans.addDataSource(tableNum(InventDim));
dsInventDim.joinMode(JoinMode::ExistsJoin); dsInventDim.fetchMode(QueryFetchMode::One2One); dsInventDim.addLink(fieldNum(InventTrans, InventDimID), fieldNum(InventDim, InventDimID));
dsInventTrans.addSelectionField(fieldNum(InventTrans, RecID), SelectionField::Count); dsInventTrans.orderMode(OrderMode::GroupBy); dsInventTrans.addSortField(fieldNum(InventTrans, ItemID)); dsInventTrans.addRange(fieldNum(InventTrans, DatePhysical)).value(queryRange(01\01\2006, 31\12\2006)); dsInventTrans.addRange(fieldNum(InventTrans, Qty)).value('<0');
dsInventDim.addRange(fieldNum(InventDim, InventLocationID)).value(condition);
while(qr.next()) { inventTrans = qr.get(tableNum(InventTrans)); info(strFmt('%1: %2', inventTrans.ItemId, InventTrans.RecId)); }
</xpp>
The code is very fat and contains lots of duplications
The Solution[edit]
SYS_ExpressionQueryBuilder provides sligntly more elegant way:
<xpp>
InventTrans inventTrans; QueryRun qr = SYS_ExpressionQueryBuilder::construct() .dataSource(tableNum(InventTrans)) .count(fieldNum(InventTrans, RecID)) .groupBy(fieldNum(InventTrans, ItemID)) .between(fieldNum(InventTrans, DatePhysical), 01\01\2006, 31\12\2006) .matches(fieldNum(InventTrans, Qty), '<0')
.exists(tableNum(InventDim)) .link(fieldNum(InventTrans, InventDimID), fieldNum(InventDim, InventDimID)) .matches(fieldNum(InventDim, InventLocationID), condition) .run();
while(qr.next()) { inventTrans = qr.get(tableNum(InventTrans)); info(strFmt('%1: %2', inventTrans.ItemId, InventTrans.RecId)); }
</xpp>
...to be continued...