FR [ 2546052 ] Introduce Query aggregate methods
https://sourceforge.net/tracker/index.php?func=detail&aid=2546052&group_id=176962&atid=879335
This commit is contained in:
parent
fafda130ee
commit
132b79aa02
|
@ -19,6 +19,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.compiere.model;
|
package org.compiere.model;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
@ -39,19 +40,26 @@ import org.compiere.util.Util;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Low Heng Sin
|
* @author Low Heng Sin
|
||||||
* @author Teo Sarca, SC ARHIPAC SERVICE SRL
|
* @author Teo Sarca, www.arhipac.ro
|
||||||
* <li>FR [ 1981760 ] Improve Query class
|
* <li>FR [ 1981760 ] Improve Query class
|
||||||
* <li>BF [ 2030280 ] org.compiere.model.Query apply access filter issue
|
* <li>BF [ 2030280 ] org.compiere.model.Query apply access filter issue
|
||||||
* <li>FR [ 2041894 ] Add Query.match() method
|
* <li>FR [ 2041894 ] Add Query.match() method
|
||||||
* <li>FR [ 2107068 ] Query.setOrderBy should be more error tolerant
|
* <li>FR [ 2107068 ] Query.setOrderBy should be more error tolerant
|
||||||
* <li>FR [ 2107109 ] Add method Query.setOnlyActiveRecords
|
* <li>FR [ 2107109 ] Add method Query.setOnlyActiveRecords
|
||||||
* <li>FR [ 2421313 ] Introduce Query.firstOnly convenient method
|
* <li>FR [ 2421313 ] Introduce Query.firstOnly convenient method
|
||||||
|
* <li>FR [ 2546052 ] Introduce Query aggregate methods
|
||||||
* @author Redhuan D. Oon
|
* @author Redhuan D. Oon
|
||||||
* <li>FR: [ 2214883 ] Remove SQL code and Replace for Query // introducing SQL String prompt in log.info
|
* <li>FR: [ 2214883 ] Remove SQL code and Replace for Query // introducing SQL String prompt in log.info
|
||||||
* >li>FR: [ 2214883 ] - to introduce .setClient_ID
|
* <li>FR: [ 2214883 ] - to introduce .setClient_ID
|
||||||
*/
|
*/
|
||||||
public class Query
|
public class Query
|
||||||
{
|
{
|
||||||
|
public static final String AGGREGATE_COUNT = "COUNT";
|
||||||
|
public static final String AGGREGATE_SUM = "SUM";
|
||||||
|
public static final String AGGREGATE_AVG = "AVG";
|
||||||
|
public static final String AGGREGATE_MIN = "MIN";
|
||||||
|
public static final String AGGREGATE_MAX = "MAX";
|
||||||
|
|
||||||
private static CLogger log = CLogger.getCLogger (Query.class);
|
private static CLogger log = CLogger.getCLogger (Query.class);
|
||||||
|
|
||||||
private Properties ctx = null;
|
private Properties ctx = null;
|
||||||
|
@ -294,6 +302,68 @@ public class Query
|
||||||
{
|
{
|
||||||
return buildSQL(null, true);
|
return buildSQL(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregate given expression on this criteria
|
||||||
|
* @param sqlExpression
|
||||||
|
* @param sqlFunction
|
||||||
|
* @return aggregated value
|
||||||
|
*/
|
||||||
|
public BigDecimal aggregate(String sqlExpression, String sqlFunction) throws DBException
|
||||||
|
{
|
||||||
|
if (Util.isEmpty(sqlFunction, true))
|
||||||
|
{
|
||||||
|
throw new DBException("No Aggregate Function defined");
|
||||||
|
}
|
||||||
|
if (Util.isEmpty(sqlExpression, true))
|
||||||
|
{
|
||||||
|
if (AGGREGATE_COUNT == sqlFunction)
|
||||||
|
{
|
||||||
|
sqlExpression = "*";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new DBException("No Expression defined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuffer sqlSelect = new StringBuffer("SELECT ").append(sqlFunction).append("(")
|
||||||
|
.append(sqlExpression).append(")")
|
||||||
|
.append(" FROM ").append(table.getTableName());
|
||||||
|
|
||||||
|
BigDecimal value = null;
|
||||||
|
String sql = buildSQL(sqlSelect, false);
|
||||||
|
PreparedStatement pstmt = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pstmt = DB.prepareStatement(sql, this.trxName);
|
||||||
|
rs = createResultSet(pstmt);
|
||||||
|
if (rs.next())
|
||||||
|
{
|
||||||
|
value = rs.getBigDecimal(1);
|
||||||
|
}
|
||||||
|
if (rs.next())
|
||||||
|
{
|
||||||
|
throw new DBException("QueryMoreThanOneRecordsFound"); // TODO : translate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
throw new DBException(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
DB.close(rs, pstmt);
|
||||||
|
rs = null; pstmt = null;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
value = Env.ZERO;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count items that match query criteria
|
* Count items that match query criteria
|
||||||
|
@ -302,25 +372,18 @@ public class Query
|
||||||
*/
|
*/
|
||||||
public int count() throws DBException
|
public int count() throws DBException
|
||||||
{
|
{
|
||||||
int count = -1;
|
return aggregate("*", AGGREGATE_COUNT).intValue();
|
||||||
String sql = buildSQL(new StringBuffer("SELECT COUNT(*) FROM ").append(table.getTableName()), false);
|
|
||||||
PreparedStatement pstmt = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
pstmt = DB.prepareStatement(sql, this.trxName);
|
|
||||||
rs = createResultSet(pstmt);
|
|
||||||
rs.next();
|
|
||||||
count = rs.getInt(1);
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw new DBException(e);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
DB.close(rs, pstmt);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SUM sqlExpression for items that match query criteria
|
||||||
|
* @param sqlExpression
|
||||||
|
* @return sum
|
||||||
|
*/
|
||||||
|
public BigDecimal sum(String sqlExpression)
|
||||||
|
{
|
||||||
|
return aggregate(sqlExpression, AGGREGATE_SUM);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Check if there items for query criteria
|
* Check if there items for query criteria
|
||||||
* @return true if exists, false otherwise
|
* @return true if exists, false otherwise
|
||||||
|
@ -548,5 +611,4 @@ public class Query
|
||||||
}
|
}
|
||||||
return retValue;
|
return retValue;
|
||||||
} // get_IDs
|
} // get_IDs
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,5 +183,47 @@ public class QueryTest extends AdempiereTestCase
|
||||||
assertEquals(101, ids[0]);
|
assertEquals(101, ids[0]);
|
||||||
assertEquals(102, ids[1]);
|
assertEquals(102, ids[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAggregate() throws Exception
|
||||||
|
{
|
||||||
|
final int AD_Client_ID = Env.getAD_Client_ID(getCtx());
|
||||||
|
final String sqlFrom = "FROM C_InvoiceLine WHERE IsActive='Y' AND AD_Client_ID="+AD_Client_ID;
|
||||||
|
final Query query = new Query(getCtx(), "C_InvoiceLine", null, getTrxName())
|
||||||
|
.setOnlyActiveRecords(true)
|
||||||
|
.setClient_ID();
|
||||||
|
//
|
||||||
|
// Test COUNT:
|
||||||
|
assertEquals("COUNT not match",
|
||||||
|
DB.getSQLValueBDEx(getTrxName(), "SELECT COUNT(*) "+sqlFrom),
|
||||||
|
query.aggregate(null, Query.AGGREGATE_COUNT));
|
||||||
|
//
|
||||||
|
// Test SUM:
|
||||||
|
assertEquals("SUM not match",
|
||||||
|
DB.getSQLValueBDEx(getTrxName(), "SELECT SUM(LineNetAmt+TaxAmt) "+sqlFrom),
|
||||||
|
query.aggregate("LineNetAmt+TaxAmt", Query.AGGREGATE_SUM));
|
||||||
|
//
|
||||||
|
// Test MIN:
|
||||||
|
assertEquals("MIN not match",
|
||||||
|
DB.getSQLValueBDEx(getTrxName(), "SELECT MIN(LineNetAmt) "+sqlFrom),
|
||||||
|
query.aggregate("LineNetAmt", Query.AGGREGATE_MIN));
|
||||||
|
//
|
||||||
|
// Test MAX:
|
||||||
|
assertEquals("MAX not match",
|
||||||
|
DB.getSQLValueBDEx(getTrxName(), "SELECT MAX(LineNetAmt) "+sqlFrom),
|
||||||
|
query.aggregate("LineNetAmt", Query.AGGREGATE_MAX));
|
||||||
|
//
|
||||||
|
// Test Exception : No Aggregate Function defined
|
||||||
|
assertExceptionThrowed("No Aggregate Function defined", DBException.class, new Runnable(){
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
query.aggregate("*", null);
|
||||||
|
}});
|
||||||
|
//
|
||||||
|
// Test Exception : No Expression defined
|
||||||
|
assertExceptionThrowed("No Expression defined", DBException.class, new Runnable(){
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
query.aggregate(null, Query.AGGREGATE_SUM);
|
||||||
|
}});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue