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 21:58:08 UTC

[empire-db] branch version3 updated: EMPIREDB-362 Entity interface

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 a9fcd0b  EMPIREDB-362 Entity interface
a9fcd0b is described below

commit a9fcd0b9d80733f73cb4fee741b31938a9f1458e
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Tue Jan 25 22:58:06 2022 +0100

    EMPIREDB-362 Entity interface
---
 .../org/apache/empire/samples/db/SampleApp.java    |   9 +
 .../empire/jsf2/utils/TagEncodingHelper.java       |   6 +
 .../java/org/apache/empire/data/ColumnExpr.java    |   8 +-
 .../main/java/org/apache/empire/data/Entity.java   |  12 +
 .../org/apache/empire/data/bean/BeanClass.java     |  34 ++-
 .../org/apache/empire/data/bean/BeanProperty.java  |  11 +
 .../org/apache/empire/data/list/DataListEntry.java | 285 +++++++++++++++++++++
 .../org/apache/empire/data/list/DataListHead.java  | 155 +++++++++++
 .../java/org/apache/empire/db/DBColumnExpr.java    |  10 +
 .../main/java/org/apache/empire/db/DBCommand.java  |  16 +-
 .../main/java/org/apache/empire/db/DBRowSet.java   |   6 +-
 .../main/java/org/apache/empire/db/DBUtils.java    | 114 ++++++++-
 .../apache/empire/db/expr/column/DBAliasExpr.java  |  60 +++--
 .../empire/db/expr/compare/DBCompareColExpr.java   |   4 +-
 .../empire/dbms/oracle/DBMSHandlerOracle.java      |   2 +-
 .../empire/dbms/oracle/OracleDBModelChecker.java   |  20 +-
 .../empire/dbms/sqlserver/DBMSHandlerMSSQL.java    |   2 +-
 .../empire/dbms/sqlserver/MSSqlDBModelChecker.java |   3 +-
 .../exceptions/UnsupportedTypeException.java       |  15 ++
 19 files changed, 704 insertions(+), 68 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 2fc7d42..91d6b3a 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
@@ -27,6 +27,7 @@ import java.util.List;
 
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.bean.BeanResult;
+import org.apache.empire.data.list.DataListEntry;
 import org.apache.empire.db.DBColumnExpr;
 import org.apache.empire.db.DBCommand;
 import org.apache.empire.db.DBContext;
@@ -625,6 +626,14 @@ public class SampleApp
         cmd.where(EMP.LASTNAME.length().isGreaterThan(0));
         // Order by
         cmd.orderBy(EMPLOYEE_FULLNAME);
+        
+        /*
+        List<DataListEntry> list = context.getUtils().queryDataList(cmd);
+        for (DataListEntry dle : list)
+        {
+            System.out.println(dle.toString());
+        }
+        */
 
         /*
          * Example for limitRows() and skipRows()
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
index 8c8f01c..eb999cb 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
@@ -149,6 +149,12 @@ public class TagEncodingHelper implements NamingContainer
         }
 
         @Override
+        public ColumnExpr unwrap()
+        {
+            return expr.unwrap();  
+        }
+
+        @Override
         public double getSize()
         {
             return 0;
diff --git a/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java b/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java
index a045c87..e092a54 100644
--- a/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java
@@ -26,7 +26,6 @@ import org.apache.empire.commons.Options;
  */
 public interface ColumnExpr
 {
-
     /**
      * Returns the column's data type.
      * @see DataType
@@ -78,5 +77,10 @@ public interface ColumnExpr
      * @return the column on which this expression is based or null if not applicable.
      */
     Column getSourceColumn();
-
+    
+    /**
+     * This helper function unwraps an alias expression
+     * @return the original expresion before renaming
+     */
+    ColumnExpr unwrap();
 }
diff --git a/empire-db/src/main/java/org/apache/empire/data/Entity.java b/empire-db/src/main/java/org/apache/empire/data/Entity.java
new file mode 100644
index 0000000..7344fbf
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/Entity.java
@@ -0,0 +1,12 @@
+package org.apache.empire.data;
+
+import java.util.List;
+
+public interface Entity
+{
+    String getName(); 
+
+    List<? extends Column> getColumns();
+    
+    Column[] getKeyColumns();
+}
diff --git a/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java b/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java
index 443efbf..d945199 100644
--- a/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java
+++ b/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java
@@ -24,7 +24,7 @@ import java.util.List;
 
 import org.apache.empire.data.Column;
 import org.apache.empire.data.DataType;
-
+import org.apache.empire.data.Entity;
 
 /**
  * BeanObject
@@ -33,7 +33,7 @@ import org.apache.empire.data.DataType;
  * A metadata definition consists primarily of the class name and a list of properties.  
  * @author Rainer
  */
-public abstract class BeanClass
+public abstract class BeanClass implements Entity
 {
     private final String name;
     private final List<BeanProperty> properties = new ArrayList<BeanProperty>();
@@ -102,12 +102,33 @@ public abstract class BeanClass
      * returns the name of this class
      * @return the class name
      */
+    @Override
     public String getName() 
     {
         return name;
     }
 
     /**
+     * returns the list of key columns (if any)
+     * @return the list of key columns or null.
+     */
+    @Override
+    public List<BeanProperty> getColumns()
+    {
+        return Collections.unmodifiableList(this.properties);
+    }
+
+    /**
+     * returns the list of key columns (if any)
+     * @return the list of key columns or null.
+     */
+    @Override
+    public Column[] getKeyColumns()
+    {
+        return keyColumns;
+    }
+
+    /**
      * returns the list of properties for this class.
      * @return the list of properties for this class.
      */
@@ -124,13 +145,4 @@ public abstract class BeanClass
     {
         return domain;
     }
-
-    /**
-     * returns the list of key columns (if any)
-     * @return the list of key columns or null.
-     */
-    public Column[] getKeyColumns()
-    {
-        return keyColumns;
-    }
 }
diff --git a/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java b/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
index c38d3d2..b417375 100644
--- a/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
+++ b/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
@@ -22,6 +22,7 @@ import org.apache.empire.commons.Attributes;
 import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.Options;
 import org.apache.empire.data.Column;
+import org.apache.empire.data.ColumnExpr;
 import org.apache.empire.data.DataType;
 import org.apache.empire.db.exceptions.FieldNotNullException;
 
@@ -198,6 +199,16 @@ public class BeanProperty implements Column
         return this;
     }
 
+    /**
+     * This helper function unwraps an alias expression
+     * @return the original expresion before renaming
+     */
+    @Override
+    public ColumnExpr unwrap()
+    {   // Nothing to unwrap
+        return this; 
+    }
+
     // --- Column interface implementation ---
     
     @Override
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
new file mode 100644
index 0000000..b10e546
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
@@ -0,0 +1,285 @@
+/*
+ * ESTEAM Software GmbH, 25.01.2022
+ */
+package org.apache.empire.data.list;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Date;
+
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.Column;
+import org.apache.empire.data.ColumnExpr;
+import org.apache.empire.data.Entity;
+import org.apache.empire.data.RecordData;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.ItemNotFoundException;
+import org.apache.empire.exceptions.NotImplementedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataListEntry implements RecordData, Serializable
+{
+    /**
+     * Comment for <code>serialVersionUID</code>
+     */
+    private static final long serialVersionUID = 1L;
+    
+    private static final Logger log  = LoggerFactory.getLogger(DataListEntry.class);
+    
+    protected final DataListHead<? extends DataListEntry> head;
+    protected final int rownum;
+    protected final Object values[];
+    
+    public DataListEntry(DataListHead<? extends DataListEntry> head, int rownum, Object values[])
+    {
+        this.head = head;
+        this.rownum = rownum;
+        this.values = values;
+    }
+    
+    public Object[] getKey(Entity entity)
+    {
+        Column[] keyColumns = entity.getKeyColumns();
+        Object[] key = new Object[keyColumns.length];
+        for (int i=0; i<key.length; i++)
+            key[i] = this.getValue(keyColumns[i]);
+        return key;
+    }
+
+    public int getId(Entity entity)
+    {
+        Column[] keyColumns = entity.getKeyColumns();
+        if (keyColumns.length!=1)
+            throw new InvalidArgumentException("entity", entity.getName());
+        // return id
+        return ObjectUtils.getInteger(getValue(keyColumns[0]));
+    }
+    
+    public boolean compareKey(Column[] keyColumns, Object[] keyValues)
+    {
+        for (int i=0; i<keyColumns.length; i++)
+        {   // find field
+            int index = getFieldIndex(keyColumns[i]);
+            if (index<0)
+                throw new ItemNotFoundException(keyColumns[i].getName());
+            // compare
+            if (!ObjectUtils.compareEqual(values[index], keyValues[i]))
+                return false; // not equal
+        }
+        // found
+        return true;
+    }
+    
+    public void updateData(RecordData recData)
+    {
+        ColumnExpr[] cols = head.getColumns(); 
+        for (int i=0; i<cols.length; i++)
+        {
+            ColumnExpr col = cols[i].unwrap();
+            // must be a column!
+            if (!(col instanceof Column))
+            {   // not a true column
+                log.info("Column expression {} is not a column. Skipping update.", col.getName());
+                continue;
+            }
+            int ri = recData.getFieldIndex(col);
+            if (ri<0)
+                continue;
+            // update
+            try {
+                values[i] = recData.getValue(ri);
+            } catch(Exception e) {
+                log.error("Failed to update value for column {}", cols[i].getName());
+            }
+        }
+    }
+    
+    public void modifyValue(ColumnExpr col, Object value)
+    {
+        int i = getFieldIndex(col);
+        if (i<0)
+            throw new ItemNotFoundException(col);
+        // update
+        values[i] = value;
+    }
+    
+    public int getRownum()
+    {
+        return rownum;
+    }
+
+    public String val(String name)
+    {
+        int idx = getFieldIndex(name);
+        return head.formatValue(idx, values[idx]);
+    }
+
+    public String val(ColumnExpr col)
+    {
+        int idx = getFieldIndex(col);
+        return head.formatValue(idx, values[idx]);
+    }
+
+    @Override
+    public int getFieldCount()
+    {
+        return head.columns.length;
+    }
+    
+    @Override
+    public int getFieldIndex(ColumnExpr column)
+    {
+        return head.getColumnIndex(column);
+    }
+    
+    @Override
+    public int getFieldIndex(String column)
+    {
+        return head.getColumnIndex(column);
+    }
+    
+    @Override
+    public ColumnExpr getColumnExpr(int i)
+    {
+        return head.columns[i];
+    }
+    
+    @Override
+    public Object getValue(int index)
+    {
+        if (index<0 || index>=values.length)
+            throw new InvalidArgumentException("index", index);
+        return values[index];
+    }
+    
+    @Override
+    public Object getValue(ColumnExpr column)
+    {
+        return getValue(getFieldIndex(column));
+    }
+    
+    @Override
+    public boolean isNull(int index)
+    {
+        return ObjectUtils.isEmpty(values[index]);
+    }
+    
+    @Override
+    public boolean isNull(ColumnExpr column)
+    {
+        return isNull(getFieldIndex(column));
+    }
+    
+    @Override
+    public int setBeanProperties(Object bean, Collection<? extends ColumnExpr> ignoreList)
+    {
+        throw new NotImplementedException(this, "setBeanProperties");
+    }
+    
+    @Override
+    public int setBeanProperties(Object bean)
+    {
+        return setBeanProperties(bean, null);
+    }
+    
+    /*
+     * Additional
+     */
+
+    public String getString(int index)
+    {   // Get String value
+        Object o = getValue(index);
+        return StringUtils.toString(o);
+    }
+
+    public final String getString(ColumnExpr column)
+    {
+        return getString(getFieldIndex(column));
+    }
+
+    public int getInt(int index)
+    {   // Get Integer value
+        Object o = getValue(index);
+        return ObjectUtils.getInteger(o);
+    }
+    
+    public final int getInt(ColumnExpr column)
+    {
+        return getInt(getFieldIndex(column));
+    }
+
+    public BigDecimal getDecimal(int index)
+    {   // Get Integer value
+        Object o = getValue(index);
+        return ObjectUtils.getDecimal(o);
+    }
+    
+    public final BigDecimal getDecimal(ColumnExpr column)
+    {
+        return getDecimal(getFieldIndex(column));
+    }
+    
+    public boolean getBoolean(int index)
+    {   // Get Integer value
+        Object o = getValue(index);
+        return ObjectUtils.getBoolean(o);
+    }
+    
+    public final boolean getBoolean(ColumnExpr column)
+    {
+        return getBoolean(getFieldIndex(column));
+    }
+
+    public <T extends Enum<?>> T getEnum(int index, Class<T> enumType)
+    {   // check for null
+        if (isNull(index))
+            return null;
+        // check column data type
+        ColumnExpr col = getColumnExpr(index);
+        boolean numeric = col.getDataType().isNumeric();
+        return ObjectUtils.getEnum(enumType, (numeric ? getInt(index) : getValue(index)));
+    }
+
+    public final <T extends Enum<?>> T getEnum(ColumnExpr column, Class<T> enumType)
+    {
+        return getEnum(getFieldIndex(column), enumType);
+    }
+
+    @SuppressWarnings("unchecked")
+    public final <T extends Enum<?>> T getEnum(Column column)
+    {
+        Class<T> enumType = (Class<T>)column.getEnumType();
+        if (enumType==null)
+        {   // Not an enum column (Attribute "enumType" has not been set)
+            throw new InvalidArgumentException("column", column);
+        }
+        return getEnum(getFieldIndex(column), enumType);
+    }
+    
+    public Date getDate(int index)
+    {
+        Object o = getValue(index);
+        return ObjectUtils.getDate(o);
+    }
+        
+    public final Date getDate(ColumnExpr column)
+    {
+        return getDate(getFieldIndex(column));
+    }
+    
+    @Override
+    public String toString()
+    {
+        StringBuilder b = new StringBuilder();
+        for (int i=0; i<values.length; i++)
+        {
+            b.append(head.formatValue(i, values[i]));
+            b.append(head.columnSeparator);
+        }
+        return b.toString();
+    }
+    
+}
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
new file mode 100644
index 0000000..d6e92d5
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
@@ -0,0 +1,155 @@
+/*
+ * ESTEAM Software GmbH, 25.01.2022
+ */
+package org.apache.empire.data.list;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.Options;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.ColumnExpr;
+import org.apache.empire.data.RecordData;
+import org.apache.empire.exceptions.InternalException;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.NotSupportedException;
+import org.apache.empire.exceptions.UnsupportedTypeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataListHead<T extends DataListEntry> implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+    private static final Logger log  = LoggerFactory.getLogger(DataListHead.class);
+    
+    final Constructor<T> constructor;
+    final ColumnExpr[] columns;
+    
+    protected String columnSeparator = "\t";
+    
+    public DataListHead(Class<T> listEntryClass, ColumnExpr[] columns) 
+    {
+        if (listEntryClass!=null)
+        {   try
+            {   // Find the constructor
+                this.constructor = listEntryClass.getDeclaredConstructor(DataListHead.class, int.class, Object[].class);
+            }
+            catch (NoSuchMethodException e)
+            {
+                throw new UnsupportedTypeException(listEntryClass);
+            }
+            catch (SecurityException e)
+            {
+                throw new UnsupportedTypeException(listEntryClass);
+            }
+        }
+        else
+        {   // Must override newEntry for this to work
+            this.constructor = null;
+        }
+        this.columns = columns;
+    }
+    
+    public ColumnExpr[] getColumns()
+    {
+        return columns; 
+    }
+
+    public int getColumnIndex(ColumnExpr column)
+    {
+        for (int i=0; i<columns.length; i++)
+            if (columns[i]==column)
+                return i; 
+        // Not found, try by name
+        return getColumnIndex(column.getName());
+    }
+    
+    public int getColumnIndex(String columnName)
+    {
+        for (int i=0; i<columns.length; i++)
+            if (columnName.equalsIgnoreCase(columns[i].getName()))
+                return i; 
+        // Not found
+        log.warn("Column \"{}\" not found in DataListEntry!", columnName);
+        return -1;
+    }
+    
+    public T newEntry(int rownum, Object[] values)
+    {   try
+        {   // check
+            if (columns.length!=values.length)
+                throw new InvalidArgumentException("values", values);
+            // must override newEntry if no listEntryClass is provided
+            if (constructor==null)
+                throw new NotSupportedException(this, "newEntry");
+            // create item
+            return constructor.newInstance(this, rownum, values);
+        }
+        catch (InstantiationException e)
+        {
+            throw new InternalException(e);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new InternalException(e);
+        }
+        catch (IllegalArgumentException e)
+        {
+            throw new InternalException(e);
+        }
+        catch (InvocationTargetException e)
+        {
+            throw new InternalException(e);
+        }
+    }
+
+    public final T newEntry(int rownum, RecordData data)
+    {   // check
+        if (columns.length!=data.getFieldCount())
+            throw new InvalidArgumentException("data", data);
+        // copy values
+        Object[] values = new Object[columns.length];
+        for (int i=0; i<columns.length; i++)
+            values[i] = data.getValue(i);
+        // create
+        return newEntry(rownum, values);
+    }
+    
+    public String formatValue(int idx, Object value)
+    {   // check empty
+        if (ObjectUtils.isEmpty(value))
+            return StringUtils.EMPTY;
+        // check options
+        Options options = columns[idx].getOptions();
+        if (options!=null && options.has(value))
+        {   // lookup option
+            value = options.get(value);
+        }
+        // Escape
+        return escape(String.valueOf(value));
+    }
+    
+    /**
+     * Escapes the formatted value
+     * Default is a simple HTML escape
+     */
+    protected String escape(String text)
+    {
+        if (text==null || text.length()==0)
+            return StringUtils.EMPTY;
+        // &amp;
+        if (text.indexOf('&')>=0)
+            text = StringUtils.replaceAll(text, "&", "&amp;");
+        // &lt;
+        if (text.indexOf('<')>=0)
+            text = StringUtils.replaceAll(text, "<", "&lt;");
+        // &gt;
+        if (text.indexOf('>')>=0)
+            text = StringUtils.replaceAll(text, ">", "&gt;");
+        // done
+        return text;
+    }
+    
+}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
index 55b084d..7192abc 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
@@ -110,6 +110,16 @@ public abstract class DBColumnExpr extends DBExpr
     public abstract Element addXml(Element parent, long flags);
 
     /**
+     * This helper function unwraps an alias expression
+     * @return the original expresion before renaming
+     */
+    @Override
+    public DBColumnExpr unwrap()
+    {   // Noting to unwrap
+        return this;
+    }
+
+    /**
      * Returns the value of a column attribute.
      * Column attributes are used to provide metadata for a column.
      * 
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 39862e5..8928be6 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
@@ -369,6 +369,20 @@ public abstract class DBCommand extends DBCommandExpr
     }
     
     /**
+     * Checks whether or not there are any aggregate functions in the Select
+     * @return true if at least on of the selected expressions is an aggregate
+     */
+    public boolean hasAggegation() 
+    {
+        for (DBColumnExpr expr : this.select)
+        {
+            if (expr.isAggregate())
+                return true;
+        }
+        return false;
+    }
+    
+    /**
      * returns true if prepared statements are enabled for this database
      */
     protected boolean isPreparedStatementsEnabled()
@@ -985,7 +999,7 @@ public abstract class DBCommand extends DBCommandExpr
      * @return an array of all DBColumnExpr objects or <code>null</code> if there is nothing to select
      */
     @Override
-    protected DBColumnExpr[] getSelectExprList()
+    public DBColumnExpr[] getSelectExprList()
     {
         int count = (select != null) ? select.size() : 0;
         if (count < 1)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
index 897cd7d..bef4ede 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
@@ -32,6 +32,7 @@ import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.Column;
 import org.apache.empire.data.DataType;
+import org.apache.empire.data.Entity;
 import org.apache.empire.db.DBRelation.DBCascadeAction;
 import org.apache.empire.db.DBRelation.DBReference;
 import org.apache.empire.db.exceptions.FieldIsReadOnlyException;
@@ -64,7 +65,7 @@ import org.slf4j.LoggerFactory;
  * 
  *
  */
-public abstract class DBRowSet extends DBExpr
+public abstract class DBRowSet extends DBExpr implements Entity
 {
     // *Deprecated* private static final long serialVersionUID = 1L;
 
@@ -227,6 +228,7 @@ public abstract class DBRowSet extends DBExpr
 
     // ------- Abstract Methods -------
     
+    @Override
     public abstract String getName();
     
     public abstract String getAlias();
@@ -275,6 +277,7 @@ public abstract class DBRowSet extends DBExpr
      * <P>
      * @return all columns of this rowset
      */
+    @Override
     public List<DBColumn> getColumns()
     {
         return Collections.unmodifiableList(columns);
@@ -360,6 +363,7 @@ public abstract class DBRowSet extends DBExpr
      * 
      * @return an array of all primary key columns
      */
+    @Override
     public DBColumn[] getKeyColumns()
     {
         return ((primaryKey != null) ? primaryKey.getColumns() : null);
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
index 8bf06dd..2098c04 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
@@ -29,7 +29,10 @@ public class DBUtils implements DBContextAware
     protected static final Logger log = LoggerFactory.getLogger(DBDatabase.class);
     
     // Threshold for long running queries in milliseconds
-    protected long longRunndingStmtThreshold = 30000;
+    protected static long longRunndingStmtThreshold = 30000;
+    // Max-Rows for list queries
+    protected static int  MAX_QUERY_ROWS  = 999;
+    
     // the context
     protected final DBContext context;
     // the dbms
@@ -605,4 +608,113 @@ public class DBUtils implements DBContextAware
         } 
     }
 
+    /**
+     * Crates a default DataListHead for a DataListEntry class
+     * The DataListEntry class must provide the following constructor
+     *      DataListEntry(DataListHead<? extends DataListEntry> head, int rownum, Object values[])
+     * @param entryClass the entryClass for which to create the list head 
+     * @return
+    protected <T extends DataListEntry> DataListHead<T> createDefaultDataListHead(DBCommand cmd, Class<T> entryClass) 
+    {
+        return new DataListHead<T>(entryClass, cmd.getSelectExprList());
+    }
+     */
+    
+    /**
+     * Executes a query and returns a list of DataListEntry items
+     * @param sqlCmd the SQL-Command for the query
+     * @param listHead the HeadInfo to be used for each list item
+     * @param first the number of records to skip from the beginning of the result
+     * @param pageSize the maximum number of item to return
+     * @return the list 
+    public <T extends DataListEntry<?>> List<T> queryDataList(DBCommand cmd, DataListHead<T> listHead, int first, int pageSize)
+    {
+        DBReader r = new DBReader(context);
+        try
+        {   // check pageSize
+            if (pageSize==0)
+            {   log.warn("PageSize must not be 0. Setting to -1 for all records!");
+                pageSize = -1;
+            }
+            // set range
+            DBMSHandler dbms = cmd.getDatabase().getDbms();
+            if (pageSize>0 && dbms.isSupported(DBMSFeature.QUERY_LIMIT_ROWS))
+            {   // let the database limit the rows
+                if (first>0 && dbms.isSupported(DBMSFeature.QUERY_SKIP_ROWS))
+                {   // let the database skip the rows
+                    cmd.skipRows(first);
+                    // no need to skip rows
+                    first = 0;
+                }
+                cmd.limitRows(first+pageSize);
+            }
+            // Runquery
+            r.open(cmd);
+            if (first>0) 
+            {   // skip rows
+                r.skipRows(first);
+            }
+            // Create a list of data entries
+            int maxCount = (pageSize>=0) ? pageSize : MAX_QUERY_ROWS;
+            ArrayList<T> list = new ArrayList<T>((pageSize>=0) ? pageSize : 10);
+            // add data
+            int rownum = 0;
+            while (r.moveNext() && maxCount != 0)
+            {   // Create bean an init
+                T entry = listHead.newEntry(++rownum, r);
+                // add entry
+                list.add(entry);
+                // Decrease count
+                if (maxCount > 0)
+                    maxCount--;
+            }
+            // check
+            if (rownum==MAX_QUERY_ROWS)
+            {
+                log.warn("********************************************************");
+                log.warn("Query Result was limited to {} by MAX_QUERY_ROWS", rownum);
+                log.warn("********************************************************");
+            }
+            return list;
+        }
+        finally
+        {
+            r.close();
+        }
+    }
+     */
+    
+    /**
+     * Queries a list of DataListEntry items
+    public final <T extends DataListEntry<?>> List<T> queryDataList(DBCommand cmd, Class<T> entryClass)
+    {
+        return queryDataList(cmd, createDefaultDataListHead(cmd, entryClass), 0, -1);
+    }
+     */
+    
+    /**
+     * Queries a list of DataListEntry items
+    public final List<DataListEntry> queryDataList(DBCommand cmd)
+    {
+        return queryDataList(cmd, DataListEntry.class);
+    }
+     */
+    
+    /**
+     * Queries a single DataListEntry item
+    public final <T extends DataListEntry<?>> T queryDataEntry(DBCommand cmd, Class<T> entryClass)
+    {
+        List<T> dle = queryDataList(cmd, createDefaultDataListHead(cmd, entryClass), 0, 1);
+        return (dle.isEmpty() ? null : dle.get(0));
+    }
+     */
+    
+    /**
+     * Queries a single DataListEntry item
+    public final DataListEntry<?> queryDataEntry(DBCommand cmd)
+    {
+        return queryDataEntry(cmd, DataListEntry.class);
+    }
+     */
+    
 }
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java
index b21ac62..f13310b 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java
@@ -30,9 +30,6 @@ import org.apache.empire.dbms.DBMSHandler;
 import org.apache.empire.dbms.DBSqlPhrase;
 import org.w3c.dom.Element;
 
-// XML
-
-
 /**
  * This class allows column renaming in SQL.
  * <P>
@@ -97,42 +94,25 @@ public class DBAliasExpr extends DBColumnExpr
     }
 
     /**
-     * This helper function returns the underlying column expression.
-     *
-     * @return the underlying column expression
-     */
-    public DBColumnExpr getExpr()
-    {
-        return expr;
-    }
-
-    /**
-     * This function set the alias name to the XML tag.
+     * Returns the DBColunm object.
      *
-     * @return the XML tag (with the alias name)
+     * @return the DBColunm object
      */
     @Override
-    public Element addXml(Element parent, long flags)
-    { // Set name to Alias
-        Element field = expr.addXml(parent, flags);
-        if (field != null)
-        {   // Set Name
-            if (field.hasAttribute("name"))
-                field.setAttribute("source", StringUtils.toString(field.getAttribute("name")));
-            field.setAttribute("name", alias);
-        }
-        return field;
+    public DBColumn getUpdateColumn()
+    {
+        return expr.getUpdateColumn();
     }
 
     /**
-     * Returns the DBColunm object.
+     * This helper function returns the underlying column expression.
      *
-     * @return the DBColunm object
+     * @return the underlying column expression
      */
     @Override
-    public DBColumn getUpdateColumn()
+    public DBColumnExpr unwrap()
     {
-        return expr.getUpdateColumn();
+        return expr;
     }
 
     /**
@@ -181,7 +161,25 @@ public class DBAliasExpr extends DBColumnExpr
             expr.addSQL(buf, context);
         }
     }
-    
+
+    /**
+     * This function set the alias name to the XML tag.
+     *
+     * @return the XML tag (with the alias name)
+     */
+    @Override
+    public Element addXml(Element parent, long flags)
+    { // Set name to Alias
+        Element field = expr.addXml(parent, flags);
+        if (field != null)
+        {   // Set Name
+            if (field.hasAttribute("name"))
+                field.setAttribute("source", StringUtils.toString(field.getAttribute("name")));
+            field.setAttribute("name", alias);
+        }
+        return field;
+    }
+   
     /**
      * Overrides the equals method
      * 
@@ -197,7 +195,7 @@ public class DBAliasExpr extends DBColumnExpr
         {   // Compare with another alias expression
             DBAliasExpr otherExpr = ((DBAliasExpr)other);
             return this.alias.equalsIgnoreCase(otherExpr.getName()) &&
-                   this.expr.equals(otherExpr.getExpr());
+                   this.expr.equals(otherExpr.unwrap());
         }
         return false;
     }
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 a89d9df..53da6d9 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
@@ -257,9 +257,9 @@ public class DBCompareColExpr extends DBCompareExpr
     		// unwrap
             DBColumnExpr texpr = expr;
             if (texpr instanceof DBAliasExpr)
-                texpr = ((DBAliasExpr) texpr).getExpr();
+                texpr = ((DBAliasExpr) texpr).unwrap();
             if (oexpr instanceof DBAliasExpr)
-                oexpr = ((DBAliasExpr) oexpr).getExpr();
+                oexpr = ((DBAliasExpr) oexpr).unwrap();
             // check function expression
             boolean tfunc = (texpr instanceof DBAbstractFuncExpr);
             boolean ofunc = (oexpr instanceof DBAbstractFuncExpr); 
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java b/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java
index 44a3ccc..0ec6447 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java
@@ -538,7 +538,7 @@ public class DBMSHandlerOracle extends DBMSHandlerBase
         if (StringUtils.isEmpty(schemaPattern))
             throw new InvalidPropertyException("schemaName", null);
         // the default model checker
-        return new OracleDBModelChecker(db, schemaPattern);
+        return new OracleDBModelChecker(schemaPattern, getBooleanType());
     }
 
 }
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java b/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java
index 282bae6..646b692 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java
@@ -23,12 +23,9 @@ import java.sql.SQLException;
 
 import org.apache.empire.data.DataType;
 import org.apache.empire.db.DBColumn;
-import org.apache.empire.db.DBDatabase;
 import org.apache.empire.db.validation.DBModelChecker;
 import org.apache.empire.db.validation.DBModelErrorHandler;
-import org.apache.empire.dbms.DBMSHandler;
 import org.apache.empire.dbms.oracle.DBMSHandlerOracle.BooleanType;
-import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.InvalidPropertyException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,22 +37,15 @@ public class OracleDBModelChecker extends DBModelChecker
 {
     private static final Logger log = LoggerFactory.getLogger(OracleDBModelChecker.class);
     
-    private BooleanType booleanType = BooleanType.NUMBER;
+    private final BooleanType booleanType;
     
-    public OracleDBModelChecker(DBDatabase db, String schemaName)
+    public OracleDBModelChecker(String schemaName, BooleanType booleanType)
     {
         super(null, schemaName);
         // Detect boolean type
-        DBMSHandler dbms = db.getDbms();
-        if (dbms instanceof DBMSHandlerOracle)
-        {
-            booleanType = ((DBMSHandlerOracle)dbms).getBooleanType();
-        }
-        else
-        {   // Illegal DBMSHandler
-            log.error("The database is not attached to a DBMSHandlerOracle");
-            throw new InvalidArgumentException("db", db);
-        }
+        this.booleanType = booleanType;
+        // ok
+        log.info("OracleDBModelChecker created for {} with booleanType {}", schemaName, booleanType);
     }
 
     /**
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
index fd59293..6b7234b 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
@@ -557,7 +557,7 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
             schema  = catalog.substring(schemaSep+1);
         }
         // the default model checker
-        return new MSSqlDBModelChecker(db, catalog, schema);
+        return new MSSqlDBModelChecker(catalog, schema);
     }
 
 }
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java
index aa858bc..1dc83e0 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java
@@ -22,7 +22,6 @@ import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
 import org.apache.empire.commons.StringUtils;
-import org.apache.empire.db.DBDatabase;
 import org.apache.empire.db.validation.DBModelChecker;
 
 /**
@@ -37,7 +36,7 @@ public class MSSqlDBModelChecker extends DBModelChecker
      * @param db the database 
      * @param catalog the catalog
      */
-    public MSSqlDBModelChecker(DBDatabase db, String catalog, String schema)
+    public MSSqlDBModelChecker(String catalog, String schema)
     {
         super(catalog, StringUtils.coalesce(schema, "DBO"));
     }
diff --git a/empire-db/src/main/java/org/apache/empire/exceptions/UnsupportedTypeException.java b/empire-db/src/main/java/org/apache/empire/exceptions/UnsupportedTypeException.java
new file mode 100644
index 0000000..81754e9
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/exceptions/UnsupportedTypeException.java
@@ -0,0 +1,15 @@
+package org.apache.empire.exceptions;
+
+import org.apache.empire.commons.ErrorType;
+
+public class UnsupportedTypeException extends EmpireException
+{
+    private static final long serialVersionUID = 1L;
+    
+    public static final ErrorType errorType = new ErrorType("error.typeNotSupported", "The type {0} is not supported.");
+    
+    public UnsupportedTypeException(Class<?> clazz)
+    {
+       super(errorType, new String[] { clazz.getSimpleName() } );
+    }
+}