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/01/25 17:42:05 UTC

[empire-db] branch version3 updated: EMPIREDB-362 DBCommand cleanup

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

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


The following commit(s) were added to refs/heads/version3 by this push:
     new d518b57  EMPIREDB-362 DBCommand cleanup
     new fcb3d39  Merge branch 'version3' of https://gitbox.apache.org/repos/asf/empire-db into version3
d518b57 is described below

commit d518b5737f7f2b5191cc60fd0348718cdcc0bc01
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Tue Jan 25 18:38:06 2022 +0100

    EMPIREDB-362 DBCommand cleanup
---
 .../org/apache/empire/samples/db/SampleApp.java    |   2 +-
 .../empire/rest/service/EmployeeService.java       |   8 +-
 .../java/org/apache/empire/db/DBCombinedCmd.java   | 270 +++++++++++----------
 .../main/java/org/apache/empire/db/DBCommand.java  | 138 ++++++-----
 .../java/org/apache/empire/db/DBCommandExpr.java   | 213 ++++++++--------
 .../main/java/org/apache/empire/db/DBDatabase.java |   6 +-
 .../main/java/org/apache/empire/db/DBReader.java   |  58 ++---
 7 files changed, 363 insertions(+), 332 deletions(-)

diff --git a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
index 0c4ce41..9449c6f 100644
--- a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
+++ b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
@@ -596,7 +596,7 @@ public class SampleApp
         cmd.select(DEP.NAME.as("DEPARTMENT"));
         cmd.select(DEP.BUSINESS_UNIT);
         // add payment of current year
-        cmd.groupBy(cmd.getSelectExprList());
+        cmd.groupBy(cmd.getSelectExpressions());
         cmd.select(PAYMENTS_LAST_YEAR);
         // join
         cmd.join(EMP.DEPARTMENT_ID, DEP.ID);
diff --git a/empire-db-examples/empire-db-example-vue/src/main/java/org/apache/empire/rest/service/EmployeeService.java b/empire-db-examples/empire-db-example-vue/src/main/java/org/apache/empire/rest/service/EmployeeService.java
index a62e7f8..c784050 100644
--- a/empire-db-examples/empire-db-example-vue/src/main/java/org/apache/empire/rest/service/EmployeeService.java
+++ b/empire-db-examples/empire-db-example-vue/src/main/java/org/apache/empire/rest/service/EmployeeService.java
@@ -69,7 +69,7 @@ public class EmployeeService extends Service {
         DBCommand cmd = db.createCommand();
         cmd.select(db.T_DEPARTMENTS.DEPARTMENT_ID, db.T_DEPARTMENTS.NAME);
         cmd.join  (db.T_DEPARTMENTS.DEPARTMENT_ID, db.T_EMPLOYEES.DEPARTMENT_ID);
-        cmd.groupBy(cmd.getSelectExprList());
+        cmd.groupBy(cmd.getSelectExpressions());
         cmd.orderBy(db.T_DEPARTMENTS.NAME);
         Options departmentOptions = ctx.getUtils().queryOptionList(cmd);
         
@@ -118,12 +118,12 @@ public class EmployeeService extends Service {
             cmd.where(TE.DEPARTMENT_ID.is(filter.getValue(TE.DEPARTMENT_ID)));
         
 
-        DBColumnExpr[] cols = cmd.getSelectExprList();
-        JsoColumnMeta[] meta = new JsoColumnMeta[cols.length]; 
+        List<DBColumnExpr> cols = cmd.getSelectExpressions();
+        JsoColumnMeta[] meta = new JsoColumnMeta[cols.size()]; 
         TextResolver txtres = SampleServiceApp.instance().getTextResolver(Locale.ENGLISH);
         for (int i=0; i<meta.length; i++)
         {
-            meta[i] = new JsoColumnMeta(cols[i], txtres);
+            meta[i] = new JsoColumnMeta(cols.get(i), txtres);
         }
         
         DBReader reader = new DBReader(getRecordContext());
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCombinedCmd.java b/empire-db/src/main/java/org/apache/empire/db/DBCombinedCmd.java
index 464a2b0..0eed3e7 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCombinedCmd.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCombinedCmd.java
@@ -18,11 +18,12 @@
  */
 package org.apache.empire.db;
 
-import org.apache.empire.db.expr.order.DBOrderByExpr;
-
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 
+import org.apache.empire.db.expr.order.DBOrderByExpr;
+
 /**
  * This class is used for building up a partition of a SQL-Command.
  * It handles the insert from a specified key word between two DBCommandExpr objects.
@@ -32,142 +33,155 @@ import java.util.Set;
  */
 public class DBCombinedCmd extends DBCommandExpr
 {
-   // *Deprecated* private static final long serialVersionUID = 1L;
-  
-   // Members
-   protected DBCommandExpr left;
-   protected DBCommandExpr right;
-   protected String        keyWord;
+    // *Deprecated* private static final long serialVersionUID = 1L;
+
+    // Members
+    protected DBCommandExpr left;
+    protected DBCommandExpr right;
+    protected String        keyWord;
 
-  /**
-   * Constructs a new DBFuncExpr object and
-   * sets the specified parameters to this object.
-   * 
-   * @param left the first DBCommandExpr object
-   * @param keyWord the key word between the two DBCommandExpr objects
-   * @param right the second DBCommandExpr object
-   */
-   public DBCombinedCmd(DBCommandExpr left, String keyWord, DBCommandExpr right)
-   {
-      this.left    = left;
-      this.right   = right;
-      this.keyWord = keyWord;
-   }
+    /**
+     * Constructs a new DBFuncExpr object and
+     * sets the specified parameters to this object.
+     * 
+     * @param left the first DBCommandExpr object
+     * @param keyWord the key word between the two DBCommandExpr objects
+     * @param right the second DBCommandExpr object
+     */
+    public DBCombinedCmd(DBCommandExpr left, String keyWord, DBCommandExpr right)
+    {
+        this.left = left;
+        this.right = right;
+        this.keyWord = keyWord;
+    }
 
-   @Override
-   public boolean isValid()
-   {
-       return (left.isValid() && right.isValid()); 
-   }
+    @Override
+    public boolean isValid()
+    {
+        return (left.isValid() && right.isValid());
+    }
 
-  /**
-   * Returns the current DBDatabase object.
-   * 
-   * @return the current DBDatabase object
-   */
-   @Override
-   public final <T extends DBDatabase> T getDatabase()
-   {
-      return left.getDatabase();
-   }
+    /**
+     * Returns the current DBDatabase object.
+     * 
+     * @return the current DBDatabase object
+     */
+    @Override
+    public final <T extends DBDatabase> T getDatabase()
+    {
+        return left.getDatabase();
+    }
 
-   /**
+    /**
     * @see org.apache.empire.db.DBExpr#addReferencedColumns(Set)
     */
-   @Override
-   public void addReferencedColumns(Set<DBColumn> list)
-   {
-      left .addReferencedColumns(list);
-      right.addReferencedColumns(list);
-   }
-  /**
-   * Calls the method dbDBCommandExpr.getSelectExprList from the private variable 'left'.
-   * Returns a array of all DBColumnExpr object of the Vector: 'select'.
-   * 
-   * @see org.apache.empire.db.DBCommandExpr#getSelectExprList()
-   * @return returns an array of all DBColumnExpr object of the Vector: 'select'
-   */
-   @Override
-   public DBColumnExpr[] getSelectExprList()
-   {
-      // DebugMsg(2, "Check: getSelectExprList() for DBCombinedCmd");
-      return left.getSelectExprList();
-   }
-   
-   /**
+    @Override
+    public void addReferencedColumns(Set<DBColumn> list)
+    {
+        left.addReferencedColumns(list);
+        right.addReferencedColumns(list);
+    }
+
+    /**
+     * Returns all select expressions as unmodifiable list
+     * @return the list of DBColumnExpr used for select
+     */
+    @Override
+    public List<DBColumnExpr> getSelectExpressions()
+    {
+        return left.getSelectExpressions();
+    }
+
+    /**
+     * Calls the method dbDBCommandExpr.getSelectExprList from the private variable 'left'.
+     * Returns a array of all DBColumnExpr object of the Vector: 'select'.
+     * 
+     * @see org.apache.empire.db.DBCommandExpr#getSelectExprList()
+     * @return returns an array of all DBColumnExpr object of the Vector: 'select'
+     */
+    @Override
+    public DBColumnExpr[] getSelectExprList()
+    {
+        // DebugMsg(2, "Check: getSelectExprList() for DBCombinedCmd");
+        return left.getSelectExprList();
+    }
+
+    /**
     * Returns the list of parameter values for a prepared statement.
     * @return the list of parameter values for a prepared statement 
     */
-   @Override
-   public Object[] getParamValues()
-   {
-       Object[] leftParams  = left.getParamValues();
-       Object[] rightParams = right.getParamValues();
-       // Check
-       if (leftParams==null)
-           return rightParams;
-       if (rightParams==null)
-           return leftParams;
-       // Put them all together
-       Object[] allParams = new Object[leftParams.length+rightParams.length];
-       for (int i=0; i<leftParams.length; i++)
-           allParams[i]=leftParams[i];
-       for (int i=0; i<rightParams.length; i++)
-           allParams[leftParams.length+i]=rightParams[i];
-       // return Params
-       return allParams;
-   }
+    @Override
+    public Object[] getParamValues()
+    {
+        Object[] leftParams = left.getParamValues();
+        Object[] rightParams = right.getParamValues();
+        // Check
+        if (leftParams == null)
+            return rightParams;
+        if (rightParams == null)
+            return leftParams;
+        // Put them all together
+        Object[] allParams = new Object[leftParams.length + rightParams.length];
+        for (int i = 0; i < leftParams.length; i++)
+            allParams[i] = leftParams[i];
+        for (int i = 0; i < rightParams.length; i++)
+            allParams[leftParams.length + i] = rightParams[i];
+        // return Params
+        return allParams;
+    }
 
-  /**
-   * Creates the SQL-Command.
-   * 
-   * @param buf the SQL-Command
-   */
-   @Override
-   public void getSelect(StringBuilder buf)
-   {
-      // the left part
-      left.clearOrderBy();
-      if (!(left instanceof DBCombinedCmd)) {
-	      buf.append( "(" );
-	      left.getSelect(buf);
-	      buf.append( ")" );
-      } else
-	      left.getSelect(buf);
-      // concat keyword     
-      buf.append( "\r\n" );
-      buf.append( keyWord );
-      buf.append( "\r\n" );
-      // the right part
-      right.clearOrderBy();
-      if (!(right instanceof DBCombinedCmd)) {
-	      buf.append( "(" );
-	      right.getSelect(buf);
-	      buf.append( ")" );
-      } else
-	      right.getSelect(buf);
-      // done
-      // Add optional Order by statement
-      if ( orderBy!=null )
-      {    // Having
-           buf.append("\r\nORDER BY ");
-           addListExpr(buf, orderBy, CTX_DEFAULT, ", ");
-      }
-   }
+    /**
+     * Creates the SQL-Command.
+     * 
+     * @param buf the SQL-Command
+     */
+    @Override
+    public void getSelect(StringBuilder buf)
+    {
+        // the left part
+        left.clearOrderBy();
+        if (!(left instanceof DBCombinedCmd))
+        {
+            buf.append("(");
+            left.getSelect(buf);
+            buf.append(")");
+        }
+        else
+            left.getSelect(buf);
+        // concat keyword
+        buf.append("\r\n");
+        buf.append(keyWord);
+        buf.append("\r\n");
+        // the right part
+        right.clearOrderBy();
+        if (!(right instanceof DBCombinedCmd))
+        {
+            buf.append("(");
+            right.getSelect(buf);
+            buf.append(")");
+        }
+        else
+            right.getSelect(buf);
+        // done
+        // Add optional Order by statement
+        if (orderBy != null)
+        { // Having
+            buf.append("\r\nORDER BY ");
+            addListExpr(buf, orderBy, CTX_DEFAULT, ", ");
+        }
+    }
 
-   @Override
-   public void orderBy(DBOrderByExpr... exprs)
-   {
-      if (orderBy == null)
-          orderBy = new ArrayList<DBOrderByExpr>();
-      // Add order by expression
-      for (DBOrderByExpr obe : exprs)
-      {
-          DBColumnExpr c = getCmdColumn(obe.getColumnExpr());
-          orderBy.add(new DBOrderByExpr(c, obe.isDescending()));
-      }
-   }
+    @Override
+    public void orderBy(DBOrderByExpr... exprs)
+    {
+        if (orderBy == null)
+            orderBy = new ArrayList<DBOrderByExpr>();
+        // Add order by expression
+        for (DBOrderByExpr obe : exprs)
+        {
+            DBColumnExpr c = getCmdColumn(obe.getColumnExpr());
+            orderBy.add(new DBOrderByExpr(c, obe.isDescending()));
+        }
+    }
 
 }
-
-
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
index af24778..39862e5 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
@@ -25,7 +25,6 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
-import java.util.Vector;
 
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.DataType;
@@ -71,7 +70,7 @@ public abstract class DBCommand extends DBCommandExpr
     protected List<DBCompareExpr>    having         = null;
     protected List<DBColumnExpr>     groupBy        = null;
     // Parameters for prepared Statements
-    protected Vector<DBCmdParam>     cmdParams      = null;
+    protected List<DBCmdParam>       cmdParams      = null;
     private int                      paramUsageCount= 0;
 
     /**
@@ -120,7 +119,7 @@ public abstract class DBCommand extends DBCommandExpr
     /**
      * internally used to reorder the command params to match their order of occurance
      */
-    protected synchronized void notifyParamUsage(DBCmdParam param)
+    protected void notifyParamUsage(DBCmdParam param)
     {
         int index = cmdParams.indexOf(param);
         if (index < paramUsageCount)
@@ -130,7 +129,7 @@ public abstract class DBCommand extends DBCommandExpr
         if (index > paramUsageCount)
         {   // Correct parameter order
             cmdParams.remove(index);
-            cmdParams.insertElementAt(param, paramUsageCount);
+            cmdParams.add(paramUsageCount, param);
         }
         paramUsageCount++;
     }
@@ -186,7 +185,7 @@ public abstract class DBCommand extends DBCommandExpr
             if (cmdParams!=null)
             {   // clone params
                 clone.paramUsageCount = 0;
-                clone.cmdParams = new Vector<DBCmdParam>();
+                clone.cmdParams = new ArrayList<DBCmdParam>();
                 for (DBCmdParam p : cmdParams)
                 {
                     DBCmdParam param = new DBCmdParam(this, p.getDataType(), p.getValue());
@@ -492,12 +491,11 @@ public abstract class DBCommand extends DBCommandExpr
     public DBCmdParam addParam(DataType type, Object value)
     {
         if (cmdParams==null)
-            cmdParams= new Vector<DBCmdParam>();
-        // Adds the parameter 
+            cmdParams= new ArrayList<DBCmdParam>();
+        // Create and add the parameter to the parameter list 
         DBCmdParam param = new DBCmdParam(this, type, value);
-        if (cmdParams.add(param)==false)
-            return null; // unknown error
-        // Creates a Parameter expression
+        cmdParams.add(param);
+        // done
         return param;
     }
 
@@ -981,31 +979,13 @@ public abstract class DBCommand extends DBCommandExpr
         return (select!=null ? (select.indexOf(expr)>=0) : false);
     }
     
-    @Override
-    public synchronized void getSelect(StringBuilder buf)
-    {
-        resetParamUsage();
-        if (select == null)
-            throw new ObjectNotValidException(this); // invalid!
-        // Prepares statement
-        addSelect(buf);
-        // From clause
-        addFrom(buf);
-        // Add Where
-        addWhere(buf);
-        // Add Grouping
-        addGrouping(buf);
-        // Add Order
-        addOrder(buf);
-    }
-    
     /**
      * Returns an array of all select expressions
      * 
      * @return an array of all DBColumnExpr objects or <code>null</code> if there is nothing to select
      */
     @Override
-    public DBColumnExpr[] getSelectExprList()
+    protected DBColumnExpr[] getSelectExprList()
     {
         int count = (select != null) ? select.size() : 0;
         if (count < 1)
@@ -1022,6 +1002,7 @@ public abstract class DBCommand extends DBCommandExpr
      * Returns all select expressions as unmodifiable list
      * @return the list of DBColumnExpr used for select
      */
+    @Override
     public List<DBColumnExpr> getSelectExpressions()
     {
         return (this.select!=null ? Collections.unmodifiableList(this.select) : null);
@@ -1226,52 +1207,37 @@ public abstract class DBCommand extends DBCommandExpr
         // values
         return values;
     }
-
+    
     /**
-     * Creates the update SQL-Command.
+     * Creates a select SQL-Statement
      * 
-     * @return the update SQL-Command
+     * @return a select SQL-Statement
      */
-    public synchronized String getUpdate()
+    @Override
+    public void getSelect(StringBuilder buf)
     {
         resetParamUsage();
-        if (set == null)
-            return null;
-        StringBuilder buf = new StringBuilder("UPDATE ");
-        DBRowSet table =  set.get(0).getTable();
-        if (joins!=null && !joins.isEmpty())
-        {   // Join Update
-            buf.append( table.getAlias() );
-            long context = CTX_DEFAULT;
-            // Set Expressions
-            buf.append("\r\nSET ");
-            addListExpr(buf, set, context, ", ");
-            // From clause
-            addFrom(buf);
-            // Add Where
-            addWhere(buf, context);
-        }
-        else
-        {   // Simple Statement
-            table.addSQL(buf, CTX_FULLNAME);
-            long context = CTX_NAME | CTX_VALUE;
-            // Set Expressions
-            buf.append("\r\nSET ");
-            addListExpr(buf, set, context, ", ");
-            // Add Where
-            addWhere(buf, context);
-        }
-        // done
-        return buf.toString();
+        if (select == null)
+            throw new ObjectNotValidException(this); // invalid!
+        // Prepares statement
+        addSelect(buf);
+        // From clause
+        addFrom(buf);
+        // Add Where
+        addWhere(buf);
+        // Add Grouping
+        addGrouping(buf);
+        // Add Order
+        addOrder(buf);
     }
 
     /**
-     * Creates the insert SQL-Command.
+     * Creates an insert SQL-Statement
      * 
-     * @return the insert SQL-Command
+     * @return an insert SQL-Statement
      */
     // get Insert
-    public synchronized String getInsert()
+    public String getInsert()
     {
         resetParamUsage();
         if (set==null || set.get(0)==null)
@@ -1322,15 +1288,53 @@ public abstract class DBCommand extends DBCommandExpr
         buf.append(")");
         return buf.toString();
     }
+
+    /**
+     * Creates an update SQL-Statement
+     * 
+     * @return an update SQL-Statement
+     */
+    public String getUpdate()
+    {
+        resetParamUsage();
+        if (set == null)
+            return null;
+        StringBuilder buf = new StringBuilder("UPDATE ");
+        DBRowSet table =  set.get(0).getTable();
+        if (joins!=null && !joins.isEmpty())
+        {   // Join Update
+            buf.append( table.getAlias() );
+            long context = CTX_DEFAULT;
+            // Set Expressions
+            buf.append("\r\nSET ");
+            addListExpr(buf, set, context, ", ");
+            // From clause
+            addFrom(buf);
+            // Add Where
+            addWhere(buf, context);
+        }
+        else
+        {   // Simple Statement
+            table.addSQL(buf, CTX_FULLNAME);
+            long context = CTX_NAME | CTX_VALUE;
+            // Set Expressions
+            buf.append("\r\nSET ");
+            addListExpr(buf, set, context, ", ");
+            // Add Where
+            addWhere(buf, context);
+        }
+        // done
+        return buf.toString();
+    }
     
     /**
-     * Creates the delete SQL-Command.
+     * Creates a delete SQL-Statement
      * 
      * @param table the table object 
      * 
-     * @return the delete SQL-Command
+     * @return a delete SQL-Statement
      */
-    public synchronized String getDelete(DBTable table)
+    public String getDelete(DBTable table)
     {
         resetParamUsage();
         StringBuilder buf = new StringBuilder("DELETE ");
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java b/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java
index b6d3d34..6665618 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCommandExpr.java
@@ -52,15 +52,15 @@ public abstract class DBCommandExpr extends DBExpr
         /**
          * Creates a new DBCmdQueryObject
          * @param cmd the command expression
-         * @param colList 
+         * @param exprList 
          */
-        public DBCmdQuery(DBCommandExpr cmd, DBColumnExpr[] colList)
+        public DBCmdQuery(DBCommandExpr cmd, DBColumnExpr[] exprList)
         { // Set the column expressions
             super(cmd.getDatabase());
             this.cmd = cmd;
-            // Add Expressions to vector
-            for (int i = 0; i < colList.length; i++)
-                columns.add(colList[i].getUpdateColumn());
+            // Add Expressions to list
+            for (int i = 0; i < exprList.length; i++)
+                columns.add(exprList[i].getUpdateColumn());
         }
 
         /** Not applicable - returns null */
@@ -300,40 +300,24 @@ public abstract class DBCommandExpr extends DBExpr
         // Default Constructor
     }
 
-    // get Select SQL
     public abstract boolean isValid();
 
-    public abstract void getSelect(StringBuilder buf);
-
-    public abstract DBColumnExpr[] getSelectExprList();
+    /**
+     * Returns the list of all select expressions as an array
+     * Used internally only
+     */
+    protected abstract DBColumnExpr[] getSelectExprList();
     
     /**
-     * returns an array holding all parameter values in the order of their occurrence.
-     * To ensure the correct order, getSelect() should be called first.
-     * @return an array of command parameter values 
+     * returns a list of expressions for the SELECT part of the sql statement
      */
-    public abstract Object[] getParamValues();
+    public abstract List<DBColumnExpr> getSelectExpressions();
 
     /**
-     * returns column expression that is specific for to this command and detached from its source.
+     * returns an SQL select command
+     * @param buf the string builder to add the command to
      */
-    protected DBColumnExpr getCmdColumn(DBColumnExpr col)
-    {
-        // Check the Instance of col
-        if ((col instanceof DBCmdColumn))
-        { // Check Owner
-            DBCmdColumn c = (DBCmdColumn) col;
-            if (c.getRowSet() == cmdQuery)
-                return col; // it's already a command column
-            // extract the expression
-            col = c.expr;
-        }
-        // Check if we already have a Command Query
-        if (cmdQuery == null)
-            cmdQuery = new DBCmdQuery(this, getSelectExprList());
-        // create a command column
-        return new DBCmdColumn(cmdQuery, col);
-    }
+    public abstract void getSelect(StringBuilder buf);
 
     /**
      * returns an SQL select command for querying records.
@@ -345,23 +329,13 @@ public abstract class DBCommandExpr extends DBExpr
         getSelect(sql);
         return sql.toString();
     }
-
+    
     /**
-     * Internally used to build a string from a list of database expressions
-     * @param buf the sql target buffer
-     * @param list list of database objects
-     * @param context the sql command context
-     * @param separator string to use as separator between list items
+     * returns an array holding all parameter values in the order of their occurrence.
+     * To ensure the correct order, getSelect() should be called first.
+     * @return an array of command parameter values 
      */
-    protected void addListExpr(StringBuilder buf, List<? extends DBExpr> list, long context, String separator)
-    {
-        for (int i = 0; i < list.size(); i++)
-        {   // assemble select columns
-            if (i > 0)
-                buf.append(separator);
-            list.get(i).addSQL(buf, context);
-        }
-    }
+    public abstract Object[] getParamValues();
 
     /**
      * Creates the SQL-Command.
@@ -476,33 +450,6 @@ public abstract class DBCommandExpr extends DBExpr
     }
 
     /**
-     * set the maximum number of rows to return when executing a query command
-     * A negative value will remove the limit.
-     *
-     */
-    public void limitRows(int numRows)
-    {
-        throw new NotSupportedException(this, "limitRows");
-    }
-
-    /**
-     * sets the offset of the first row to return when executing a query command.
-     * A negative value will remove the offset.
-     */
-    public void skipRows(int numRows)
-    {
-        throw new NotSupportedException(this, "skipRows");
-    }
-    
-    /**
-     * Clears a limit or offset set by calling limit() or offset()
-     */
-    public void clearLimit()
-    {
-        // Nothing to do!
-    }
-
-    /**
      * Adds a list of columns to the orderBy clause in ascending order
      * 
      * @param exprs vararg of column expressions
@@ -527,35 +474,30 @@ public abstract class DBCommandExpr extends DBExpr
     }
 
     /**
-     * Create the insert into SQL-Command which copies data
-     * from a select statement to a destination table.
-     * 
-     * @return the insert into SQL-Command
+     * set the maximum number of rows to return when executing a query command
+     * A negative value will remove the limit.
+     *
      */
-    protected String getInsertInto(DBTable table, DBColumnExpr[] select, List<DBColumnExpr> columns)
+    public void limitRows(int numRows)
     {
-        if (select == null)
-            throw new ObjectNotValidException(this);
-        // prepare buffer
-        StringBuilder buf = new StringBuilder("INSERT INTO ");
-        table.addSQL(buf, CTX_FULLNAME);
-        // destination columns
-        if (columns != null && columns.size() > 0)
-        { // Check Count
-            if (columns.size() != select.length)
-            {
-                throw new InvalidArgumentException("columns", "size()!=select.length");
-            }
-            // Append Names
-            buf.append(" (");
-            addListExpr(buf, columns, CTX_NAME, ", ");
-            buf.append(")");
-        }
-        // append select statement
-        buf.append("\r\n");
-        getSelect(buf);
-        // done
-        return buf.toString();
+        throw new NotSupportedException(this, "limitRows");
+    }
+
+    /**
+     * sets the offset of the first row to return when executing a query command.
+     * A negative value will remove the offset.
+     */
+    public void skipRows(int numRows)
+    {
+        throw new NotSupportedException(this, "skipRows");
+    }
+    
+    /**
+     * Clears a limit or offset set by calling limit() or offset()
+     */
+    public void clearLimit()
+    {
+        // Nothing to do!
     }
 
     /**
@@ -600,4 +542,75 @@ public abstract class DBCommandExpr extends DBExpr
         }
         return getInsertInto(table, select, inscols);
     }
+
+    /**
+     * returns column expression that is specific for to this command and detached from its source.
+     */
+    protected DBColumnExpr getCmdColumn(DBColumnExpr col)
+    {
+        // Check the Instance of col
+        if ((col instanceof DBCmdColumn))
+        { // Check Owner
+            DBCmdColumn c = (DBCmdColumn) col;
+            if (c.getRowSet() == cmdQuery)
+                return col; // it's already a command column
+            // extract the expression
+            col = c.expr;
+        }
+        // Check if we already have a Command Query
+        if (cmdQuery == null)
+            cmdQuery = new DBCmdQuery(this, getSelectExprList());
+        // create a command column
+        return new DBCmdColumn(cmdQuery, col);
+    }
+
+    /**
+     * Internally used to build a string from a list of database expressions
+     * @param buf the sql target buffer
+     * @param list list of database objects
+     * @param context the sql command context
+     * @param separator string to use as separator between list items
+     */
+    protected void addListExpr(StringBuilder buf, List<? extends DBExpr> list, long context, String separator)
+    {
+        for (int i = 0; i < list.size(); i++)
+        {   // assemble select columns
+            if (i > 0)
+                buf.append(separator);
+            list.get(i).addSQL(buf, context);
+        }
+    }
+
+    /**
+     * Create the insert into SQL-Command which copies data
+     * from a select statement to a destination table.
+     * 
+     * @return the insert into SQL-Command
+     */
+    protected String getInsertInto(DBTable table, DBColumnExpr[] select, List<DBColumnExpr> columns)
+    {
+        if (select == null)
+            throw new ObjectNotValidException(this);
+        // prepare buffer
+        StringBuilder buf = new StringBuilder("INSERT INTO ");
+        table.addSQL(buf, CTX_FULLNAME);
+        // destination columns
+        if (columns != null && columns.size() > 0)
+        { // Check Count
+            if (columns.size() != select.length)
+            {
+                throw new InvalidArgumentException("columns", "size()!=select.length");
+            }
+            // Append Names
+            buf.append(" (");
+            addListExpr(buf, columns, CTX_NAME, ", ");
+            buf.append(")");
+        }
+        // append select statement
+        buf.append("\r\n");
+        getSelect(buf);
+        // done
+        return buf.toString();
+    }
+    
 }
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java b/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
index f53217e..89f14ad 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
@@ -905,14 +905,14 @@ public abstract class DBDatabase extends DBObject
         }
         // Check for Command expression
         if (value instanceof DBCommandExpr)
-        {   DBColumnExpr[] exprList = ((DBCommandExpr)value).getSelectExprList();
-            if (exprList.length!=1)
+        {   List<DBColumnExpr> exprList = ((DBCommandExpr)value).getSelectExpressions();
+            if (exprList.size()!=1)
             {   // Incompatible data types
                 log.info("Invalid command expression for column {} using command {}!", column.getName(), ((DBCommandExpr)value).getSelect());
                 throw new FieldIllegalValueException(column, ((DBCommandExpr)value).getSelect());
             }
             // Compare types
-            if (!type.isCompatible(exprList[0].getDataType()))
+            if (!type.isCompatible(exprList.get(0).getDataType()))
             {   // Incompatible data types
                 log.info("Incompatible data types in expression for column {} using function {}!", column.getName(), value.toString());
                 throw new FieldIllegalValueException(column, String.valueOf(value));
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBReader.java b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
index 5f15cb4..206151e 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBReader.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
@@ -250,7 +250,7 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     
     // Object references
     private DBDatabase     db      = null;
-    private DBColumnExpr[] colList = null;
+    private DBColumnExpr[] columns = null;
     private ResultSet      rset    = null;
     // the field index map
     private Map<ColumnExpr, Integer> fieldIndexMap = null;
@@ -336,10 +336,10 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     @Override
     public DBColumnExpr getColumnExpr(int iColumn)
     {
-        if (colList == null || iColumn < 0 || iColumn >= colList.length)
+        if (columns == null || iColumn < 0 || iColumn >= columns.length)
             return null; // Index out of range
         // return column Expression
-        return colList[iColumn];
+        return columns[iColumn];
     }
 
     /**
@@ -351,10 +351,10 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     @Override
     public int getFieldIndex(String column)
     {
-        if (colList != null)
+        if (columns != null)
         {
-            for (int i = 0; i < colList.length; i++)
-                if (colList[i].getName().equalsIgnoreCase(column))
+            for (int i = 0; i < columns.length; i++)
+                if (columns[i].getName().equalsIgnoreCase(column))
                     return i;
         }
         // not found
@@ -372,7 +372,7 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     @Override
     public boolean isNull(int index)
     {
-        if (index < 0 || index >= colList.length)
+        if (index < 0 || index >= columns.length)
         { // Index out of range
             log.error("Index out of range: " + index);
             return true;
@@ -398,11 +398,11 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     public Object getValue(int index)
     {
         // Check params
-        if (index < 0 || index >= colList.length)
+        if (index < 0 || index >= columns.length)
             throw new InvalidArgumentException("index", index);
         try
         {   // Get Value from Resultset
-            DataType dataType = colList[index].getDataType();
+            DataType dataType = columns[index].getDataType();
             return context.getDbms().getResultValue(rset, index + 1, dataType);
 
         } catch (SQLException e)
@@ -521,7 +521,7 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
                 endTrackingThisResultSet();
             }
             // Detach columns
-            colList = null;
+            columns = null;
             rset = null;
             // clear FieldIndexMap
             if (fieldIndexMap!=null)
@@ -747,13 +747,13 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     @Override
     public int getXmlMeta(Element parent)
     {
-        if (colList == null)
+        if (columns == null)
             throw new ObjectNotValidException(this);
         // Add Field Description
-        for (int i = 0; i < colList.length; i++)
-            colList[i].addXml(parent, 0);
+        for (int i = 0; i < columns.length; i++)
+            columns[i].addXml(parent, 0);
         // return count
-        return colList.length; 
+        return columns.length; 
     }
 
     /**
@@ -768,9 +768,9 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
         if (rset == null)
             throw new ObjectNotValidException(this);
         // Add all children
-        for (int i = 0; i < colList.length; i++)
+        for (int i = 0; i < columns.length; i++)
         { // Read all
-            String name = colList[i].getName();
+            String name = columns[i].getName();
             String idColumnAttr = getXmlDictionary().getRowIdColumnAttribute();
             if (name.equalsIgnoreCase("id"))
             { // Add Attribute
@@ -785,7 +785,7 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
             }
         }
         // return count
-        return colList.length; 
+        return columns.length; 
     }
 
     /**
@@ -843,19 +843,19 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     @Override
     public int getFieldCount()
     {
-        return (colList != null) ? colList.length : 0;
+        return (columns != null) ? columns.length : 0;
     }
 
     /**
      * Initialize the reader from an open JDBC-ResultSet 
      * @param db the database
-     * @param colList the query column expressions
+     * @param columns the query column expressions
      * @param rset the JDBC-ResultSet
      */
-    protected void init(DBDatabase db, DBColumnExpr[] colList, ResultSet rset)
+    protected void init(DBDatabase db, DBColumnExpr[] columns, ResultSet rset)
     {
         this.db = db;
-        this.colList = colList;
+        this.columns = columns;
         this.rset = rset;
         // clear fieldIndexMap         
         if (fieldIndexMap!=null)
@@ -870,7 +870,7 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
      */
     protected final DBColumnExpr[] getColumnExprList()
     {
-        return colList;
+        return columns;
     }
 
     /**
@@ -889,20 +889,20 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
      */
     protected int findFieldIndex(ColumnExpr column)
     {
-        if (colList == null)
+        if (columns == null)
             return -1;
         // First chance: Try to find an exact match
-        for (int i = 0; i < colList.length; i++)
+        for (int i = 0; i < columns.length; i++)
         {
-            if (colList[i].equals(column))
+            if (columns[i].equals(column))
                 return i;
         }
         // Second chance: Try Update Column
         if (column instanceof DBColumn)
         {
-            for (int i = 0; i < colList.length; i++)
+            for (int i = 0; i < columns.length; i++)
             {
-                DBColumn updColumn = colList[i].getUpdateColumn();                    
+                DBColumn updColumn = columns[i].getUpdateColumn();                    
                 if (updColumn!=null && updColumn.equals(column))
                     return i;
                  // Query Expression?
@@ -987,8 +987,8 @@ public class DBReader extends DBRecordData implements DBContextAware, Closeable
     {
         // Check whether we can use a constructor
         Class<?>[] paramTypes = new Class[getFieldCount()];
-        for (int i = 0; i < colList.length; i++)
-            paramTypes[i] = DBExpr.getValueClass(colList[i].getDataType()); 
+        for (int i = 0; i < columns.length; i++)
+            paramTypes[i] = DBExpr.getValueClass(columns[i].getDataType()); 
         // Find Constructor
         Constructor<?> ctor = ClassUtils.findMatchingAccessibleConstructor(beanClass, paramTypes);
         return ctor;