You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2022/08/18 13:06:30 UTC

[empire-db] branch master updated: EMPIREDB-394 replaced DBExpr::getObjectValue(...) by DBExpr::addSQLValue(...)

This is an automated email from the ASF dual-hosted git repository.

doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/master by this push:
     new 5ae2fe65 EMPIREDB-394 replaced DBExpr::getObjectValue(...) by DBExpr::addSQLValue(...)
5ae2fe65 is described below

commit 5ae2fe6527edf2b19424870dfbc697f0ba5bea50
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Thu Aug 18 15:06:27 2022 +0200

    EMPIREDB-394 replaced DBExpr::getObjectValue(...) by DBExpr::addSQLValue(...)
---
 .../src/main/java/org/apache/empire/db/DBExpr.java | 74 ++++++++++++++++-----
 .../empire/db/expr/column/DBAbstractFuncExpr.java  | 75 +++++++++++++++++++++-
 .../apache/empire/db/expr/column/DBCalcExpr.java   |  2 +-
 .../apache/empire/db/expr/column/DBConcatExpr.java | 16 +++--
 .../apache/empire/db/expr/column/DBDecodeExpr.java | 75 +++++++++++++++++-----
 .../apache/empire/db/expr/column/DBScalarExpr.java | 20 ++----
 .../empire/db/expr/compare/DBCompareColExpr.java   | 43 ++++++-------
 .../org/apache/empire/db/expr/set/DBSetExpr.java   | 10 +--
 8 files changed, 236 insertions(+), 79 deletions(-)

diff --git a/empire-db/src/main/java/org/apache/empire/db/DBExpr.java b/empire-db/src/main/java/org/apache/empire/db/DBExpr.java
index 89d7a579..c90193d3 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBExpr.java
@@ -26,6 +26,7 @@ import org.apache.empire.commons.OptionEntry;
 // java
 import org.apache.empire.data.DataType;
 import org.apache.empire.dbms.DBMSHandler;
+import org.apache.empire.exceptions.InvalidArgumentException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,22 +68,22 @@ public abstract class DBExpr extends DBObject
     public abstract void addReferencedColumns(Set<DBColumn> list);
 
     /**
-     * Returns the sql representation of a value.
+     * Appends the SQL representation of a value
      * 
+     * @param StringBuilder but the SQL builder
      * @param dataType the DataType
      * @param value an DBExpr object, array or a basis data type(e.g. int, String)
      * @param context the context of the DBColumnExpr object
      * @param arraySep the separator value
      * @return the new SQL-Command
      */
-    protected String getObjectValue(DataType dataType, Object value, long context, String arraySep)
+    protected void addSQLValue(StringBuilder buf, DataType dataType, Object value, long context, String arraySep)
     {
         // it's an Object
         if (value instanceof DBExpr)
-        { // it's an expression
-            StringBuilder buf = new StringBuilder();
+        {   // it's an expression
             ((DBExpr) value).addSQL(buf, context);
-            return buf.toString();
+            return;
         } 
         // check option entry
         if (value instanceof OptionEntry)
@@ -100,29 +101,72 @@ public abstract class DBExpr extends DBObject
         }
         // Check whether it is an array
         if (value!=null && value.getClass().isArray())
-        {
-            StringBuilder buf = new StringBuilder();
-            // An Array of Objects
+        {   // An Array of Objects
             Object[] array = (Object[]) value;
             for (int i = 0; i < array.length; i++)
-            { // Array Separator
+            {   // Array Separator
                 if (i > 0 && arraySep != null)
                     buf.append(arraySep);
                 // Append Value
-                buf.append(getObjectValue(dataType, array[i], context, arraySep));
+                addSQLValue(buf, dataType, array[i], context, arraySep);
             }
-            return buf.toString();
+            return;
         } 
         else
         {   // Scalar Value from DB
             DBMSHandler dbms = getDatabase().getDbms();
             if (dbms==null)
             {   // Convert to String
-                log.warn("No dbms set for getting object value. Using default!");
-                return String.valueOf(value);
+                log.warn("No DBMS set for getting object value. Using default!");
+                buf.append(String.valueOf(value));
             }
             // Get Value Expression from dmbs
-            return dbms.getValueString(value, dataType);
+            buf.append(dbms.getValueString(value, dataType));
+        }
+    }
+    
+    /**
+     * Expands an SQL template and adds it to the SQL command
+     * 
+     * @param StringBuilder but the SQL builder
+     * @param template the SQL template
+     * @param values an array of values to be inserted into the template
+     * @param dataType the DataType
+     * @param context the context of the DBColumnExpr object
+     * @param arraySep the separator value
+     * @return the new SQL-Command
+     */
+   protected void addSQLTemplate(StringBuilder sql, String template, Object[] values, DataType[] dataTypes, long context, String arraySep)
+    {
+        int pos = 0;
+        while (true)
+        {
+            // find begin
+            int beg = template.indexOf('{', pos);
+            if (beg < 0)
+                break;
+            // append
+            sql.append(template.substring(pos, beg));
+            // find end
+            int end = template.indexOf('}', ++beg);
+            if (end < 0)
+                throw new InvalidArgumentException("template", template);
+            // part
+            int iParam = Integer.parseInt(template.substring(beg, end));
+            if (iParam<0 || iParam>=values.length)
+                throw new InvalidArgumentException("params", values);
+            // add value
+            DataType dataType = (dataTypes.length>=iParam ? dataTypes[iParam] : dataTypes[0]);
+            addSQLValue(sql, dataType, values[iParam], context, arraySep);
+            // next
+            pos = end + 1;
+        }
+        if (pos < template.length())
+        {   // add the rest
+            sql.append(template.substring(pos));
+            // special case: Nothing added yet
+            if (pos==0 && values!=null && values.length>0)
+                log.warn("No Placeholder for found in template {}!", template);
         }
-    }    
+    }
 }
\ No newline at end of file
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java
index 3976c17d..f44ce381 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java
@@ -206,6 +206,7 @@ public abstract class DBAbstractFuncExpr extends DBColumnExpr
      * @param params an array of function parameters 
      * @param context the current SQL-Command context
      */
+    /*
     public final void addSQL(StringBuilder sql, String template, Object[] params, long context)
     {
         // Get Template
@@ -229,7 +230,7 @@ public abstract class DBAbstractFuncExpr extends DBColumnExpr
                         if (StringUtils.isNotEmpty(typeName) && !typeName.equals("*"))
                             paramDataType = DataType.valueOf(typeName);
                         else if (typeName.equals("*") || params[i]==null || (params[i] instanceof DBExpr))
-                            paramDataType = DataType.UNKNOWN;   /* use as literal */
+                            paramDataType = DataType.UNKNOWN;
                         else
                             paramDataType = DataType.fromJavaType(params[i].getClass());
                     }
@@ -266,7 +267,79 @@ public abstract class DBAbstractFuncExpr extends DBColumnExpr
                 log.warn("No Placeholder for Column found in function template.");
         }
     }
+    */
 
+    public final void addSQL(StringBuilder sql, String template, Object[] params, long context)
+    {
+        // parse template
+        int pos=0, prev=0, len=template.length();
+        while (pos<len)
+        {
+            char c = template.charAt(pos);
+            // Expression
+            if (c=='?') {
+                if (prev<pos)
+                    sql.append(template.substring(prev, pos));
+                // expression
+                expr.addSQL(sql, (context & ~CTX_ALIAS));
+                // next
+                prev = ++pos;
+            }
+            // Placeholder
+            else if (c=='{') {
+                if (prev<pos)
+                    sql.append(template.substring(prev, pos));
+                // find index
+                int end = ++pos;
+                for (;end<len;end++)
+                {   // check digit
+                    char digit = template.charAt(end);
+                    if (digit<'0' || digit>'9')
+                        break;
+                }
+                if (end>=len)
+                    throw new InvalidArgumentException("template", template);
+                // parse index
+                int iParam = Integer.parseInt(template.substring(pos, end));
+                if (iParam<0 || iParam>=params.length)
+                    throw new InvalidArgumentException("params", params);
+                // find end
+                for (end=++pos;end<len;end++)
+                {   // check terminator
+                    if (template.charAt(end)=='}')
+                        break;
+                }
+                if (end>=len)
+                    throw new InvalidArgumentException("template", template);
+                // DataType
+                DataType paramDataType = expr.getDataType();
+                if (template.charAt(pos)==':')
+                {   // Yes, get the DataType name and look it up
+                    String typeName = template.substring(pos+1, end);
+                    if (StringUtils.isNotEmpty(typeName) && !typeName.equals("*"))
+                        paramDataType = DataType.valueOf(typeName);
+                    else if (typeName.equals("*") || params[iParam]==null || (params[iParam] instanceof DBExpr))
+                        paramDataType = DataType.UNKNOWN;   /* use as literal */
+                    else
+                        paramDataType = DataType.fromJavaType(params[iParam].getClass());
+                }
+                // append value
+                addSQLValue(sql, paramDataType, params[iParam], CTX_DEFAULT, ",");
+                // next
+                prev = pos = end+1;
+            }
+            else 
+                pos++; // next
+        }
+        if (prev < len)
+        {   // add the rest
+            sql.append(template.substring(prev));
+            // special case: Nothing added yet
+            if (prev==0)
+                log.warn("No Placeholder found in template {}", template);
+        }
+    }
+    
     @Override
     public Element addXml(Element parent, long flags)
     {
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBCalcExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBCalcExpr.java
index 73a84e45..e211fc68 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBCalcExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBCalcExpr.java
@@ -221,7 +221,7 @@ public class DBCalcExpr extends DBColumnExpr
         if (type.isNumeric()==false && (value instanceof Number))
             type = DataType.DECIMAL;
         // append
-        buf.append(getObjectValue(type, value, context, op));
+        addSQLValue(buf, type, value, context, op);
     }
 
     @Override
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatExpr.java
index ff376b49..1f4ef1fd 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatExpr.java
@@ -18,7 +18,6 @@
  */
 package org.apache.empire.db.expr.column;
 
-import java.text.MessageFormat;
 import java.util.Set;
 
 // Java
@@ -164,14 +163,23 @@ public class DBConcatExpr extends DBColumnExpr
         {   // Complex Pattern with placeholder ? for this expression and {0} for the value
             buf.append(template.substring(0, sep));
             left.addSQL(buf, context);
-            String value = getObjectValue(getDataType(), right, context, ", ");
-            buf.append(MessageFormat.format(template.substring(sep + 1), value));
+            // template = template.substring(sep + 1)
+            int iph = template.indexOf("{0}", ++sep);
+            if (iph>0)
+                buf.append(template.substring(sep, iph));
+            else 
+                buf.append(template.substring(sep));
+            // value
+            addSQLValue(buf, getDataType(), right, context, template);
+            // rest
+            if (iph>0)
+                buf.append(template.substring(iph+3));
         } 
         else
         {   // Simple Pattern without placeholders
             left.addSQL(buf, context);
             buf.append(template);
-            buf.append(getObjectValue(getDataType(), right, context, template));
+            addSQLValue(buf, getDataType(), right, context, template);
         }        
     }
 
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBDecodeExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBDecodeExpr.java
index 9be80c80..15741cc4 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBDecodeExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBDecodeExpr.java
@@ -22,13 +22,13 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.DataType;
 import org.apache.empire.db.DBColumn;
 import org.apache.empire.db.DBColumnExpr;
 import org.apache.empire.db.DBExpr;
 import org.apache.empire.dbms.DBMSHandler;
 import org.apache.empire.dbms.DBSqlPhrase;
+import org.apache.empire.exceptions.InvalidArgumentException;
 
 /**
  * This class is used to decode a set of keys to the corresponding target values.
@@ -101,33 +101,76 @@ public class DBDecodeExpr extends DBAbstractFuncExpr
     public void addSQL(StringBuilder sql, long context)
     {
         DBMSHandler dbms = getDatabase().getDbms();
-        StringBuilder inner = new StringBuilder();
-        // Generate parts
+        // decode
+        String template = dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE);
+        // parse template
+        int pos=0, prev=0, len=template.length();
+        while (pos<len)
+        {
+            char c = template.charAt(pos);
+            // Expression
+            if (c=='?') {
+                if (prev<pos)
+                    sql.append(template.substring(prev, pos));
+                // expression
+                expr.addSQL(sql, (context & ~CTX_ALIAS));
+                // next
+                prev = ++pos;
+            }
+            // Placeholder
+            else if (c=='{') {
+                if (prev<pos)
+                    sql.append(template.substring(prev, pos));
+                // find end
+                int end = ++pos;
+                for (end=++pos;end<len;end++)
+                {   // find terminator
+                    if (template.charAt(end)=='}')
+                        break;
+                }
+                if (end>=len)
+                    throw new InvalidArgumentException("template", template);
+                // Add parts
+                addDecodeParts(dbms, sql);
+                // next
+                prev = pos = end+1;
+            }
+            else 
+                pos++; // next
+        }
+        if (prev < len)
+        {   // add the rest
+            sql.append(template.substring(prev));
+            // special case: Nothing added yet
+            if (prev==0)
+                log.warn("No Placeholder found in template {}", template);
+        }
+    }
+    
+    public void addDecodeParts(DBMSHandler dbms, StringBuilder sql)
+    {
+        // Append parts
         for (Iterator<?> i = valueMap.keySet().iterator(); i.hasNext();)
         {
             Object key = i.next();
             Object val = valueMap.get(key);
 
+            sql.append(dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE_SEP));
+            
+            Object[] keyVal = new Object[] { key, val };
+            DataType[] dataTypes = new DataType[] { expr.getDataType(), this.getDataType() };
+            
             String part = dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE_PART);
-            part = StringUtils.replaceAll(part, "{0}", getObjectValue(expr.getDataType(), key, DBExpr.CTX_DEFAULT, ""));
-            part = StringUtils.replaceAll(part, "{1}", getObjectValue(this.getDataType(), val, DBExpr.CTX_DEFAULT, ""));
-
-            inner.append(dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE_SEP));
-            inner.append(part);
+            addSQLTemplate(sql, part, keyVal, dataTypes, CTX_DEFAULT, "");
         }
         // Generate other
         if (elseExpr != null)
         { // Else
+            sql.append(dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE_SEP));
+            // else
             String other = dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE_ELSE);
-            other = StringUtils.replaceAll(other, "{0}", getObjectValue(getDataType(), elseExpr, DBExpr.CTX_DEFAULT, ""));
-
-            inner.append(dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE_SEP));
-            inner.append(other);
+            addSQLTemplate(sql, other, new Object[] { elseExpr }, new DataType[] { getDataType() }, CTX_DEFAULT, "");
         }
-        DBValueExpr param = new DBValueExpr(getDatabase(), inner, DataType.UNKNOWN); 
-        // Set Params
-        String template = dbms.getSQLPhrase(DBSqlPhrase.SQL_FUNC_DECODE);
-        super.addSQL(sql, template, new Object[] { param }, context);
     }
     
     private DBColumnExpr getFirstColumnExpr()
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBScalarExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBScalarExpr.java
index 32c6c018..3f03b781 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBScalarExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBScalarExpr.java
@@ -27,6 +27,8 @@ import org.apache.empire.db.DBColumn;
 import org.apache.empire.db.DBColumnExpr;
 import org.apache.empire.db.DBDatabase;
 import org.apache.empire.xml.XMLUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.w3c.dom.Element;
 
 
@@ -38,7 +40,8 @@ import org.w3c.dom.Element;
 public class DBScalarExpr extends DBColumnExpr
 {
     // *Deprecated* private static final long serialVersionUID = 1L;
-  
+    protected static final Logger log = LoggerFactory.getLogger(DBScalarExpr.class);
+
     public final DBDatabase   db;
     public final DataType     dataType;
     public final String       template;
@@ -220,19 +223,8 @@ public class DBScalarExpr extends DBColumnExpr
      * @param context the current SQL-Command context
      */
     @Override
-    public void addSQL(StringBuilder buf, long context)
+    public void addSQL(StringBuilder sql, long context)
     {
-        // Get Text from Template
-        String text = this.template;
-        if (params != null)
-        {   // Replace Params
-            for (int i = 0; i < params.length; i++)
-            {   // String test  =(params[i] != null) ? params[i].toString() : "";
-                String value = getObjectValue(dataType, params[i], CTX_DEFAULT, ",");
-                text = StringUtils.replaceAll(template, "{"+ String.valueOf(i) + "}", value);
-            }
-        }
-        buf.append(text);
+        addSQLTemplate(sql, template, params, new DataType[] { dataType }, CTX_DEFAULT, ",");
     }
-
 }
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java
index 3936dc99..39f8fcc4 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java
@@ -182,8 +182,13 @@ public class DBCompareColExpr extends DBCompareExpr
      */
     public void addCompareExpr(StringBuilder buf, long context)
     {   // Assemble expression
-        String arraySep = "+";
         DBCmpType op = cmpop;
+        if (ObjectUtils.isEmpty(value))
+        { // Null oder Not Null!
+            op = DBCmpType.getNullType(op);
+        }
+        // Array Separator
+        String arraySep;
         switch (op)
         { // other than default:
             case BETWEEN:
@@ -195,16 +200,11 @@ public class DBCompareColExpr extends DBCompareExpr
                 arraySep = ", ";
                 break;
             default:
-                // Nothing to do
+                arraySep = "+";
                 break;
         }
-        // Value
-        String valsql = getObjectValue(expr.getDataType(), value, context, arraySep);
-        if (valsql == null || valsql.equalsIgnoreCase("null"))
-        { // Null oder Not Null!
-            op = DBCmpType.getNullType(op);
-        }
         // Add comparison operator and value
+        String suffix = null;
         switch (op)
         {
             case EQUAL:
@@ -233,12 +233,10 @@ public class DBCompareColExpr extends DBCompareExpr
                 break;
             case NULL:
                 buf.append(" IS NULL");
-                valsql = null;
-                break;
+                return;
             case NOTNULL:
                 buf.append(" IS NOT NULL");
-                valsql = null;
-                break;
+                return;
             case BETWEEN:
                 buf.append(" BETWEEN ");
                 break;
@@ -247,22 +245,21 @@ public class DBCompareColExpr extends DBCompareExpr
                 break;
             case IN:
                 buf.append(" IN (");
-                buf.append(valsql);
-                buf.append(")");
-                valsql = null;
+                suffix = ")";
                 break;
             case NOTIN:
                 buf.append(" NOT IN (");
-                buf.append(valsql);
-                buf.append(")");
-                valsql = null;
+                suffix = ")";
                 break;
             default:
                 // NONE
                 buf.append(" ");
         }
-        if (valsql != null)
-            buf.append(valsql);
+        // append value
+        addSQLValue(buf, expr.getDataType(), value, context, arraySep);
+        // append suffix
+        if (suffix != null)
+            buf.append(suffix);
     }
 
     /**
@@ -282,13 +279,13 @@ public class DBCompareColExpr extends DBCompareExpr
         }
         // Value Only ?
         if ((context & CTX_NAME) == 0)
-        {
-            String valsql = getObjectValue(expr.getDataType(), value, context, "+");
-            buf.append((valsql != null) ? valsql : "null");
+        {   // add SQL
+            addSQLValue(buf, expr.getDataType(), value, context, null);
             return;
         }
         // Add Compare Expression
         expr.addSQL(buf, context);
+        // Add Comparison Value
         addCompareExpr(buf, context);
     }
 
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/set/DBSetExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/set/DBSetExpr.java
index 317ef0dc..7cdc1835 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/set/DBSetExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/set/DBSetExpr.java
@@ -128,17 +128,17 @@ public class DBSetExpr extends DBExpr
     /**
      * Creates the SQL-Command.
      * 
-     * @param buf the SQL-Command
+     * @param sql the SQL-Command
      * @param context the current SQL-Command context
      */
     @Override
-    public void addSQL(StringBuilder buf, long context)
+    public void addSQL(StringBuilder sql, long context)
     {
         if ((context & CTX_NAME) != 0)
-            column.addSQL(buf, CTX_NAME);
+            column.addSQL(sql, CTX_NAME);
         if ((context & CTX_NAME) != 0 && (context & CTX_VALUE) != 0)
-            buf.append("=");
+            sql.append("=");
         if ((context & CTX_VALUE) != 0)
-            buf.append(getObjectValue(column.getDataType(), value, context, "+"));
+            addSQLValue(sql, column.getDataType(), value, context, "+");
     }
 }