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/26 00:40:48 UTC

[empire-db] branch version3 updated: EMPIREDB-367 DBUtils queryDataList method and classes

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 8311365  EMPIREDB-367 DBUtils queryDataList method and classes
8311365 is described below

commit 83113652da07cc756eeb0640867dcc7f722e03bd
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Wed Jan 26 01:40:46 2022 +0100

    EMPIREDB-367 DBUtils queryDataList method and classes
---
 .../org/apache/empire/samples/db/SampleApp.java    |  5 ++
 .../org/apache/empire/data/list/DataListEntry.java | 54 +++++++++++-----
 .../org/apache/empire/data/list/DataListHead.java  | 60 ++++++++++++------
 .../main/java/org/apache/empire/db/DBUtils.java    | 73 +++++++++++++++++-----
 4 files changed, 143 insertions(+), 49 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 91d6b3a..0cb0f56 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
@@ -628,9 +628,14 @@ public class SampleApp
         cmd.orderBy(EMPLOYEE_FULLNAME);
         
         /*
+         * Test data list entry
+         * 
         List<DataListEntry> list = context.getUtils().queryDataList(cmd);
         for (DataListEntry dle : list)
         {
+            int empId = dle.getId(EMP);
+            int empId2 = dle.getInt(EMP.ID);
+            boolean test = dle.hasField(EMP.FIRSTNAME);
             System.out.println(dle.toString());
         }
         */
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
index b10e546..f400962 100644
--- 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
@@ -22,9 +22,6 @@ 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);
@@ -40,6 +37,12 @@ public class DataListEntry implements RecordData, Serializable
         this.values = values;
     }
     
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public <H extends DataListHead> H getHead()
+    {
+        return (H)this.head;
+    }
+    
     public Object[] getKey(Entity entity)
     {
         Column[] keyColumns = entity.getKeyColumns();
@@ -129,6 +132,11 @@ public class DataListEntry implements RecordData, Serializable
         return head.columns.length;
     }
     
+    public boolean hasField(ColumnExpr column)
+    {
+        return (head.getColumnIndex(column)>=0);
+    }
+    
     @Override
     public int getFieldIndex(ColumnExpr column)
     {
@@ -142,9 +150,11 @@ public class DataListEntry implements RecordData, Serializable
     }
     
     @Override
-    public ColumnExpr getColumnExpr(int i)
+    public ColumnExpr getColumnExpr(int index)
     {
-        return head.columns[i];
+        if (index<0 || index>=values.length)
+            throw new InvalidArgumentException("index", index);
+        return head.columns[index];
     }
     
     @Override
@@ -158,19 +168,21 @@ public class DataListEntry implements RecordData, Serializable
     @Override
     public Object getValue(ColumnExpr column)
     {
-        return getValue(getFieldIndex(column));
+        return getValue(indexOf(column));
     }
     
     @Override
     public boolean isNull(int index)
     {
+        if (index<0 || index>=values.length)
+            throw new InvalidArgumentException("index", index);
         return ObjectUtils.isEmpty(values[index]);
     }
     
     @Override
     public boolean isNull(ColumnExpr column)
     {
-        return isNull(getFieldIndex(column));
+        return isNull(indexOf(column));
     }
     
     @Override
@@ -186,7 +198,7 @@ public class DataListEntry implements RecordData, Serializable
     }
     
     /*
-     * Additional
+     * Conversion functions
      */
 
     public String getString(int index)
@@ -197,7 +209,7 @@ public class DataListEntry implements RecordData, Serializable
 
     public final String getString(ColumnExpr column)
     {
-        return getString(getFieldIndex(column));
+        return getString(indexOf(column));
     }
 
     public int getInt(int index)
@@ -208,7 +220,7 @@ public class DataListEntry implements RecordData, Serializable
     
     public final int getInt(ColumnExpr column)
     {
-        return getInt(getFieldIndex(column));
+        return getInt(indexOf(column));
     }
 
     public BigDecimal getDecimal(int index)
@@ -219,7 +231,7 @@ public class DataListEntry implements RecordData, Serializable
     
     public final BigDecimal getDecimal(ColumnExpr column)
     {
-        return getDecimal(getFieldIndex(column));
+        return getDecimal(indexOf(column));
     }
     
     public boolean getBoolean(int index)
@@ -230,7 +242,7 @@ public class DataListEntry implements RecordData, Serializable
     
     public final boolean getBoolean(ColumnExpr column)
     {
-        return getBoolean(getFieldIndex(column));
+        return getBoolean(indexOf(column));
     }
 
     public <T extends Enum<?>> T getEnum(int index, Class<T> enumType)
@@ -245,7 +257,7 @@ public class DataListEntry implements RecordData, Serializable
 
     public final <T extends Enum<?>> T getEnum(ColumnExpr column, Class<T> enumType)
     {
-        return getEnum(getFieldIndex(column), enumType);
+        return getEnum(indexOf(column), enumType);
     }
 
     @SuppressWarnings("unchecked")
@@ -256,7 +268,7 @@ public class DataListEntry implements RecordData, Serializable
         {   // Not an enum column (Attribute "enumType" has not been set)
             throw new InvalidArgumentException("column", column);
         }
-        return getEnum(getFieldIndex(column), enumType);
+        return getEnum(indexOf(column), enumType);
     }
     
     public Date getDate(int index)
@@ -267,9 +279,13 @@ public class DataListEntry implements RecordData, Serializable
         
     public final Date getDate(ColumnExpr column)
     {
-        return getDate(getFieldIndex(column));
+        return getDate(indexOf(column));
     }
     
+    /*
+     * Miscellaneous functions
+     */
+    
     @Override
     public String toString()
     {
@@ -281,5 +297,13 @@ public class DataListEntry implements RecordData, Serializable
         }
         return b.toString();
     }
+
+    protected int indexOf(ColumnExpr column)
+    {
+        int index = head.getColumnIndex(column);
+        if (index<0)
+            throw new ItemNotFoundException(column.getName());
+        return index;
+    }
     
 }
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
index d6e92d5..2d1e909 100644
--- 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
@@ -14,6 +14,7 @@ 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.ItemNotFoundException;
 import org.apache.empire.exceptions.NotSupportedException;
 import org.apache.empire.exceptions.UnsupportedTypeException;
 import org.slf4j.Logger;
@@ -29,29 +30,51 @@ public class DataListHead<T extends DataListEntry> implements Serializable
     
     protected String columnSeparator = "\t";
     
-    public DataListHead(Class<T> listEntryClass, ColumnExpr[] columns) 
+    /**
+     * findEntryConstructor
+     * @param listEntryClass
+     * @param listHeadClass
+     * @return the constructor
+     */
+    @SuppressWarnings("unchecked")
+    protected static <T extends DataListEntry> Constructor<T> findEntryConstructor(Class<?> listEntryClass, @SuppressWarnings("rawtypes") Class<? extends DataListHead> listHeadClass)
     {
-        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);
-            }
+        /*
+        Constructor<?> constructor = ClassUtils.findMatchingAccessibleConstructor(listEntryClass, new Class<?>[] { listHeadClass, int.class, Object[].class });
+        if (constructor==null)
+            throw new UnsupportedTypeException(listEntryClass);
+        return constructor;
+        */
+        try
+        {   // Find the constructor
+            return (Constructor<T>)listEntryClass.getDeclaredConstructor(listHeadClass, int.class, Object[].class);
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new UnsupportedTypeException(listEntryClass);
         }
-        else
-        {   // Must override newEntry for this to work
-            this.constructor = null;
+        catch (SecurityException e)
+        {
+            throw new UnsupportedTypeException(listEntryClass);
         }
+    }
+
+    /**
+     * Constructs a DataListHead based on an DataListEntry constructor
+     * @param constructor the DataListEntry constructor
+     * @param columns the list entry columns
+     */
+    public DataListHead(Constructor<T> constructor, ColumnExpr[] columns) 
+    {
+        this.constructor = constructor;
         this.columns = columns;
     }
     
+    public DataListHead(Class<T> listEntryClass, ColumnExpr[] columns) 
+    {
+        this(findEntryConstructor(listEntryClass, DataListHead.class), columns);
+    }
+    
     public ColumnExpr[] getColumns()
     {
         return columns; 
@@ -71,8 +94,7 @@ public class DataListHead<T extends DataListEntry> implements Serializable
         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);
+        // not found
         return -1;
     }
     
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 2098c04..0484c15 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
@@ -11,11 +11,14 @@ import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.DataType;
+import org.apache.empire.data.list.DataListEntry;
+import org.apache.empire.data.list.DataListHead;
 import org.apache.empire.db.context.DBContextAware;
 import org.apache.empire.db.exceptions.ConstraintViolationException;
 import org.apache.empire.db.exceptions.QueryFailedException;
 import org.apache.empire.db.exceptions.QueryNoResultException;
 import org.apache.empire.db.exceptions.StatementFailedException;
+import org.apache.empire.dbms.DBMSFeature;
 import org.apache.empire.dbms.DBMSHandler;
 import org.apache.empire.exceptions.InternalException;
 import org.apache.empire.exceptions.InvalidArgumentException;
@@ -97,7 +100,7 @@ public class DBUtils implements DBContextAware
             throw new StatementFailedException(dbms, sqlCmd, sqle);
         }    
     }
-
+    
     /**
      * Returns the value of the first row/column of a sql-query as an object.
      * If the query does not return a result the value ObjectUtils.NO_VALUE is returned.
@@ -291,7 +294,45 @@ public class DBUtils implements DBContextAware
         Object value = querySingleValue(cmd.getSelect(), cmd.getParamValues(), DataType.VARCHAR, true);
         return StringUtils.toString(value);
     }
-    
+
+    /**
+     * Returns the number of rows returned by executing the select statement
+     * @param cmd the select command
+     * @return the number of rows that will be returned
+     */
+    public int queryRowCount(DBCommand cmd)
+    {   // execute Native Query
+        if (cmd==null || !cmd.isValid())
+            return 0;
+        // Check for aggregation
+        boolean aggregate = false;
+        DBColumnExpr[] exprList = cmd.getSelectExprList();
+        for (int i=0; i<exprList.length; i++)
+        {
+            if (exprList[i].isAggregate())
+            {   aggregate = true;
+                break;
+            }
+        }
+        // check if aggregate 
+        if (aggregate)
+        {   // For Aggregations: Wrap  
+            DBCommand subCmd = cmd.clone();
+            subCmd.clearOrderBy();
+            String sql = "SELECT COUNT(*) FROM ("+subCmd.getSelect() + ") q";
+            return querySingleInt(sql, null, 0);
+        }
+        // find any rowset
+        DBRowSet rs = exprList[0].getUpdateColumn().getRowSet();
+        // create the count command
+        DBCommand countCmd = cmd.clone();
+        countCmd.clearSelect();
+        countCmd.clearOrderBy();
+        countCmd.select(rs.count());
+        // perform query
+        return querySingleInt(countCmd);
+    }
+
     /**
      * Adds the first column of a query result to a collection.
      * If the query has no result, an empty list is returned.
@@ -614,11 +655,11 @@ public class DBUtils implements DBContextAware
      *      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
@@ -627,7 +668,8 @@ public class DBUtils implements DBContextAware
      * @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)
+     */
+    public <T extends DataListEntry> List<T> queryDataList(DBCommand cmd, DataListHead<T> listHead, int first, int pageSize)
     {
         DBReader r = new DBReader(context);
         try
@@ -682,39 +724,40 @@ public class DBUtils implements DBContextAware
             r.close();
         }
     }
-     */
     
     /**
      * Queries a list of DataListEntry items
-    public final <T extends DataListEntry<?>> List<T> queryDataList(DBCommand cmd, Class<T> entryClass)
+     */
+    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)
+     */
+    @SuppressWarnings("unchecked")
+    public final <T extends DataListEntry> List<T> queryDataList(DBCommand cmd)
     {
-        return queryDataList(cmd, DataListEntry.class);
+        return (List<T>)queryDataList(cmd, DataListEntry.class);
     }
-     */
     
     /**
      * Queries a single DataListEntry item
-    public final <T extends DataListEntry<?>> T queryDataEntry(DBCommand cmd, Class<T> entryClass)
+     */
+    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)
+     */
+    @SuppressWarnings("unchecked")
+    public final <T extends DataListEntry> T queryDataEntry(DBCommand cmd)
     {
-        return queryDataEntry(cmd, DataListEntry.class);
+        return (T)queryDataEntry(cmd, DataListEntry.class);
     }
-     */
     
 }