diff --git a/base/src/org/compiere/model/AccessSqlParser.java b/base/src/org/compiere/model/AccessSqlParser.java
index bdaf3e86e2..2ab50054fa 100644
--- a/base/src/org/compiere/model/AccessSqlParser.java
+++ b/base/src/org/compiere/model/AccessSqlParser.java
@@ -32,6 +32,8 @@ import org.compiere.util.CLogger;
* @author Teo Sarca, SC ARHIPAC SERVICE SRL
*
BF [ 1652623 ] AccessSqlParser.getTableInfo(String) - tablename parsing bug
* BF [ 1964496 ] AccessSqlParser is not parsing well JOIN CLAUSE
+ * BF [ 2840157 ] AccessSqlParser is not parsing well ON keyword
+ * https://sourceforge.net/tracker/?func=detail&aid=2840157&group_id=176962&atid=879332
*/
public class AccessSqlParser
{
@@ -233,6 +235,7 @@ public class AccessSqlParser
from = from.replaceAll("[\r\n\t ]+LEFT[\r\n\t ]+OUTER[\r\n\t ]+JOIN[\r\n\t ]+", ", ");
from = from.replaceAll("[\r\n\t ]+RIGHT[\r\n\t ]+OUTER[\r\n\t ]+JOIN[\r\n\t ]+", ", ");
from = from.replaceAll("[\r\n\t ]+FULL[\r\n\t ]+JOIN[\r\n\t ]+", ", ");
+ from = from.replaceAll("[\r\n\t ]+[Oo][Nn][\r\n\t ]+", ON); // teo_sarca, BF [ 2840157 ]
// Remove ON clause - assumes that there is no IN () in the clause
index = from.indexOf(ON);
while (index != -1)
@@ -242,7 +245,13 @@ public class AccessSqlParser
if (indexNextOn != -1)
indexClose = from.lastIndexOf(')', indexNextOn);
if (indexClose != -1)
+ {
+ if (index > indexClose)
+ {
+ throw new IllegalStateException("Could not remove (index="+index+" > indexClose="+indexClose+") - "+from);
+ }
from = from.substring(0, index) + from.substring(indexClose+1);
+ }
else
{
log.log(Level.SEVERE, "Could not remove ON " + from);
diff --git a/base/src/org/compiere/model/AccessSqlParserTest.java b/base/src/org/compiere/model/AccessSqlParserTest.java
index fbfb4ad328..ce2a35c79e 100644
--- a/base/src/org/compiere/model/AccessSqlParserTest.java
+++ b/base/src/org/compiere/model/AccessSqlParserTest.java
@@ -233,6 +233,35 @@ public class AccessSqlParserTest extends TestCase
fixture = new AccessSqlParser(sql);
assertEquals("AccessSqlParser[C_Invoice,C_BPartner=bp|0]", fixture.toString());
}
+
+ /**
+ * BF [ 2840157 ] AccessSqlParser is not parsing well ON keyword
+ *
+ * Following query is generating OutOfMemoryException:
+ * SELECT 1
+ * FROM M_Product p
+ * INNER JOIN M_Product_Category pc on
+ * (pc.M_Product_Category_ID=p.M_Product_Category_ID)
+ * LEFT OUTER JOIN M_Product_PO mpo ON (mpo.M_Product_ID=p.M_Product_ID)
+ *
+ * (please note the lower case "on")
+ *
+ *
+ * @see https://sourceforge.net/tracker/?func=detail&aid=2840157&group_id=176962&atid=879332
+ */
+ public void test_BF2840157()
+ {
+ final String sql =
+ "SELECT 1 FROM M_Product p"
+ +"\n"+"INNER JOIN M_Product_Category pc on (pc.M_Product_Category_ID=p.M_Product_Category_ID)"
+ +"\n"+"LEFT OUTER JOIN M_Product_PO mpo ON (mpo.M_Product_ID=p.M_Product_ID)"
+ +"\n"+" WHERE p.IsActive='Y' AND p.IsPurchased='Y'"
+ +"\n"+"AND COALESCE(mpo.DeliveryTime_Promised,0) <= 0"
+ ;
+ final String expected = "AccessSqlParser[M_Product=p,M_Product_Category=pc,M_Product_PO=mpo|0]";
+ AccessSqlParser fixture = new AccessSqlParser(sql);
+ assertEquals(expected, fixture.toString());
+ }
}