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 2025/10/04 14:11:55 UTC

(empire-db) branch master updated: EMPIREDB-477 Rorganized into DBColumnExpr

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3c0c6cf9 EMPIREDB-477 Rorganized into DBColumnExpr
3c0c6cf9 is described below

commit 3c0c6cf9bcb4c3bf5b7a69cbb08448b3efbe1a92
Author: Rainer Döbele <rd...@users.noreply.github.com>
AuthorDate: Sat Oct 4 16:11:52 2025 +0200

    EMPIREDB-477
    Rorganized into DBColumnExpr
---
 .../org/apache/empire/commons/ColumnUtils.java     | 211 ++++-----------------
 .../main/java/org/apache/empire/data/Column.java   |   5 +-
 .../main/java/org/apache/empire/db/DBColumn.java   |  47 +++--
 .../java/org/apache/empire/db/DBColumnExpr.java    | 115 ++++++++++-
 .../main/java/org/apache/empire/db/DBCommand.java  |  23 +++
 .../java/org/apache/empire/db/DBCommandExpr.java   |  41 +++-
 .../apache/empire/db/expr/column/DBFuncExpr.java   |   4 +
 .../java/org/apache/empire/dbms/DBMSHandler.java   |  10 +
 .../org/apache/empire/dbms/DBMSHandlerBase.java    |  17 ++
 .../empire/dbms/oracle/OracleDDLGenerator.java     |  12 ++
 10 files changed, 278 insertions(+), 207 deletions(-)

diff --git a/empire-db/src/main/java/org/apache/empire/commons/ColumnUtils.java b/empire-db/src/main/java/org/apache/empire/commons/ColumnUtils.java
index a384d282..9281dc6d 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ColumnUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ColumnUtils.java
@@ -25,13 +25,11 @@ import java.util.Locale;
 import org.apache.empire.data.Column;
 import org.apache.empire.data.ColumnExpr;
 import org.apache.empire.data.DataType;
-import org.apache.empire.db.DBColumn;
-import org.apache.empire.db.DBColumnExpr;
 import org.apache.empire.exceptions.NotSupportedException;
 
 /**
  * ColumnUtils
- * This class contains a set of helper functions for Columns
+ * This class contains a set of generic functions for Columns
  * @author doebele
  */
 public class ColumnUtils
@@ -52,46 +50,6 @@ public class ColumnUtils
     {
         instance = columnUtils;
     }
-    
-    /**
-     * Returns true if the columnExpr is Column
-     * @param columnExpr the columnExpr expression
-     * @return true if the columnExpr is a Column
-     */
-    public static boolean isColumn(ColumnExpr columnExpr)
-    {
-        return (ObjectUtils.unwrap(columnExpr) instanceof Column); 
-    }
-    
-    /**
-     * Returns true if the columnExpr either is a Column or has an update column assigned
-     * @param columnExpr the columnExpr expression
-     * @return true if the columnExpr is a Column or has an update column
-     */
-    public static boolean hasColumn(ColumnExpr columnExpr)
-    {
-        return (columnExpr.getUpdateColumn()!=null); 
-    }
-    
-    /**
-     * Returns true if the columnExpr is a text columnExpr
-     * @param columnExpr the columnExpr
-     * @return true if the columnExpr is a text columnExpr
-     */
-    public static boolean isText(ColumnExpr columnExpr)
-    {
-        return columnExpr.getDataType().isText();
-    }
-    
-    /**
-     * Return the maximum character length of a columnExpr
-     * @param columnExpr the columnExpr 
-     * @return the max number or characters 
-     */
-    public static int getMaxLength(ColumnExpr columnExpr)
-    {
-        return instance.getColumnMaxLength(columnExpr);
-    }
 
     /**
      * Returns the minimum length, usually 0 
@@ -103,98 +61,15 @@ public class ColumnUtils
         Object value = instance.getColumnAttribute(columnExpr, Column.COLATTR_MINLENGTH);
         return ((value instanceof Number) ? ((Number)value).intValue() : 0);
     }
-
-    /**
-     * Returns the text to display if the field value is null 
-     * @param columnExpr the columnExpr
-     * @return the text for null 
-     */
-    public static String getNullText(ColumnExpr columnExpr)
-    {
-        Object value = instance.getColumnAttribute(columnExpr, Column.COLATTR_NULLTEXT);
-        return (value!=null ? value.toString() : StringUtils.EMPTY);
-    }
     
     /**
-     * Sets the text to display if the field value is null 
-     * @param columnExpr the columnExpr
-     * @param nullText the null text
-     * @return return the columnExpr
-     */
-    public static <T extends ColumnExpr> T setNullText(T columnExpr, String nullText)
-    {
-        return columnExpr.setAttribute(Column.COLATTR_NULLTEXT, nullText);
-    }
-    
-    /**
-     * Returns whether or not a columnExpr is case sensitive
-     * If not explicitly set, the case sensitivity is true for all text fields (VARCHAR, CLOB) except if an EnumType is set.
-     * @return true if the columnExpr is case sensitive or false if not
-     */
-    public static boolean isCaseSensitive(ColumnExpr columnExpr)
-    {
-        if (columnExpr instanceof DBColumn)
-        {   // ask the column
-            return ((DBColumn)columnExpr).isCaseSensitive();
-        }
-        // only for text expressions
-        if (!isText(columnExpr))
-            return false;
-        // check attribute
-        Object value = instance.getColumnAttribute(columnExpr, Column.COLATTR_CASESENSITIVE);
-        if (value!=null)
-            return ObjectUtils.getBoolean(value);
-        // default is true for VARCHAR and CLOB except if Options or EnumType are set
-        return (columnExpr.getOptions()==null && columnExpr.getEnumType()==null);
-    }
-    
-    /**
-     * Sets one or more columns to case insensitive
-     * @param columns the list of columns
-     */
-    public static void setCaseInsensitive(ColumnExpr... columns)
-    {
-        for (int i=0; i<columns.length; i++)
-        {
-            ColumnExpr columnExpr = columns[i];
-            if (columnExpr==null || !isText(columnExpr))
-                continue;
-            // set as insensitive
-            columnExpr.setAttribute(Column.COLATTR_CASESENSITIVE, false);
-        }
-    }
-    
-    /**
-     * Returns the normalized column for the columnExpr (if any)
-     * The column expression must be a column otherwise null is returned
-     * @return the normalized column or null
-     */
-    public static DBColumnExpr getNormalizedColumn(DBColumnExpr columnExpr)
-    {
-        return ((columnExpr instanceof DBColumn) ? ((DBColumn)columnExpr).getNormalizedColumn() : null);
-    }
-        
-    /**
-     * Returns the sort expression for a given column expression
-     * This function checks if columnExpr is a column and callse column.getSortExpr().
-     * If columnExpr is not a colunn, the columnExpr itself is returned
-     * 
-     * @param columnExpr the columnExpr for which to retrieve the sort expression
-     * @return the sort expression or the column itself if not sort expression is set
-     */
-    public static DBColumnExpr getSortExpr(DBColumnExpr columnExpr)
-    {
-        return ((columnExpr instanceof DBColumn) ? ((DBColumn)columnExpr).getSortExpr() : columnExpr);
-    }
-
-    /**
-     * Returns true if the columnExpr is a numeric columnExpr
-     * @param columnExpr the columnExpr to check
-     * @return true if the columnExpr is numeric
+     * Return the maximum character length of a columnExpr
+     * @param columnExpr the columnExpr 
+     * @return the max number or characters 
      */
-    public static boolean isNumeric(ColumnExpr columnExpr)
+    public static int getMaxLength(ColumnExpr columnExpr)
     {
-        return columnExpr.getDataType().isText();
+        return instance.getColumnMaxLength(columnExpr);
     }
     
     /**
@@ -202,8 +77,12 @@ public class ColumnUtils
      * @param columnExpr the columnExpr
      * @return the minimum value 
      */
-    public static BigDecimal getMinValue(ColumnExpr columnExpr)
+    public static Number getMinValue(ColumnExpr columnExpr)
     {
+        // check numeric
+        if (!columnExpr.getDataType().isNumeric())
+            return null;
+        // convert to decimal
         Object value = instance.getColumnAttribute(columnExpr, Column.COLATTR_MINVALUE);
         return ObjectUtils.getDecimal(value);
     }
@@ -213,11 +92,21 @@ public class ColumnUtils
      * @param columnExpr the columnExpr
      * @return the maximum value 
      */
-    public static BigDecimal getMaxValue(ColumnExpr columnExpr)
+    public static Number getMaxValue(ColumnExpr columnExpr)
     {
+        // check numeric
+        if (!columnExpr.getDataType().isNumeric())
+            return null;
+        if (columnExpr.getDataType()==DataType.AUTOINC)
+            return Long.MAX_VALUE;
+        // convert to decimal
         Object value = instance.getColumnAttribute(columnExpr, Column.COLATTR_MAXVALUE);
-        long maxVal = isNumeric(columnExpr) ? 10l^((long)instance.getColumnSize(columnExpr)) : 10^12;
-        return ObjectUtils.getDecimal(value, BigDecimal.valueOf(maxVal));
+        long digits = (long)instance.getColumnSize(columnExpr);
+        long maxVal = (digits!=0) ? 10l^digits : 10^12;
+        if (columnExpr.getDataType()==DataType.INTEGER)
+            return ObjectUtils.getLong(value, maxVal);
+        else
+            return ObjectUtils.getDecimal(value, BigDecimal.valueOf(maxVal));
     }
     
     /**
@@ -227,36 +116,15 @@ public class ColumnUtils
      * @param maxValue the max value
      * @return the columnExpr
      */
-    public static <T extends ColumnExpr> T setMinMaxValue(T columnExpr, BigDecimal minValue, BigDecimal maxValue)
+    public static <T extends ColumnExpr> T setMinMaxValue(T columnExpr, Number minValue, Number maxValue)
     {
-        if (!isNumeric(columnExpr))
+        if (!columnExpr.getDataType().isNumeric())
             throw new NotSupportedException(columnExpr, "setMinMaxValue");
         // set the min and max values
         columnExpr.setAttribute(Column.COLATTR_MINVALUE, minValue);
         columnExpr.setAttribute(Column.COLATTR_MAXVALUE, maxValue);
         return columnExpr;
     }
-
-    /**
-     * Returns the number type assigned to this column expression
-     * @param columnExpr the columnExpr
-     * @return the number type
-     */
-    public static String getNumberType(ColumnExpr columnExpr)
-    {
-        Object value = instance.getColumnAttribute(columnExpr, Column.COLATTR_NUMBER_TYPE);
-        if (value==null)
-        {   // from data type
-            DataType dt = columnExpr.getDataType();
-            if (dt==DataType.INTEGER || dt==DataType.AUTOINC)
-                return DataType.INTEGER.name();
-            if (dt==DataType.DECIMAL || dt==DataType.FLOAT)
-                return DataType.DECIMAL.name();
-            // Not a number
-            return null;
-        }
-        return value.toString();
-    }
     
     /**
      * Returns the number format for a particular columnExpr
@@ -276,10 +144,13 @@ public class ColumnUtils
      * @param true groupSeparator should be used 
      * @return the columnExpr
      */
-    public static <T extends Column> T setNumberFormat(T column, String numberType, boolean groupSeparator)
+    public static <T extends ColumnExpr> T setNumberFormat(T columnExpr, String numberType, boolean groupSeparator)
     {
-        instance.setColumnNumberFormat(column, numberType, groupSeparator);
-        return column;
+        if (!columnExpr.getDataType().isNumeric())
+            throw new NotSupportedException(columnExpr, "setNumberFormat");
+        // set format
+        instance.setColumnNumberFormat(columnExpr, numberType, groupSeparator);
+        return columnExpr;
     }
 
     /*
@@ -413,19 +284,21 @@ public class ColumnUtils
      * (non-Javadoc)
      * @see org.apache.empire.commons.ColumnUtils#setColumnNumberFormat(ColumnExpr, String, boolean)
      */
-    public void setColumnNumberFormat(Column column, String numberType, boolean groupSeparator)
+    public void setColumnNumberFormat(ColumnExpr columnExpr, String numberType, boolean groupSeparator)
     {
-        if (!isNumeric(column))
-            throw new NotSupportedException(column, "setNumberFormat");
         // Number type
-        column.setAttribute(Column.COLATTR_NUMBER_TYPE, numberType);
-        column.setAttribute(Column.COLATTR_NUMBER_GROUPSEP, groupSeparator);
-        if (column.getDataType()==DataType.DECIMAL || column.getDataType()==DataType.FLOAT)
+        columnExpr.setAttribute(Column.COLATTR_NUMBER_TYPE, numberType);
+        columnExpr.setAttribute(Column.COLATTR_NUMBER_GROUPSEP, groupSeparator);
+        if (columnExpr.getDataType()==DataType.DECIMAL || columnExpr.getDataType()==DataType.FLOAT)
         {   // set fraction digits
-            double size = column.getSize();
+            double size = getColumnSize(columnExpr);
             int intDigits = (int)size;
             int fracDigits = ((int)(size*10)-(intDigits*10));
-            column.setAttribute(Column.COLATTR_FRACTION_DIGITS, fracDigits);
+            columnExpr.setAttribute(Column.COLATTR_FRACTION_DIGITS, fracDigits);
+        }
+        else
+        {   // Integer
+            columnExpr.setAttribute(Column.COLATTR_FRACTION_DIGITS, 0);
         }
     }
     
diff --git a/empire-db/src/main/java/org/apache/empire/data/Column.java b/empire-db/src/main/java/org/apache/empire/data/Column.java
index df88ec8c..e33515d7 100644
--- a/empire-db/src/main/java/org/apache/empire/data/Column.java
+++ b/empire-db/src/main/java/org/apache/empire/data/Column.java
@@ -42,6 +42,7 @@ public interface Column extends ColumnExpr
     public static final String COLATTR_NORMCOLUMN      = "normColumn";           // normalized column
     public static final String COLATTR_REFCOLUMNS      = "refColumns";           // reference columns
     public static final String COLATTR_CASESENSITIVE   = "caseSensitive";        // true/false
+    public static final String COLATTR_SORTDESCENDING  = "sortDescending";       // default sort order (true for descending)
     public static final String COLATTR_SORTEXPRESSION  = "sortExpression";       // sort function template for DBFunc
 
     public static final String COLATTR_MINLENGTH       = "minLength";
@@ -54,8 +55,8 @@ public interface Column extends ColumnExpr
     public static final String COLATTR_FRACTION_DIGITS = "numberFractionDigits"; // integer
     public static final String COLATTR_INTEGER_DIGITS  = "numberIntegerDigits";  // integer
     public static final String COLATTR_CURRENCY_CODE   = "currencyCode";         // "ISO 4217 code of the currency"
-    public static final String COLATTR_DATETIMEPATTERN = "dateTimePattern";      // default is yyyy-MM-dd HH:mm:ss
-
+    // public static final String COLATTR_DATETIMEPATTERN = "dateTimePattern";   // unused, not needed
+    
     public static final String NUMTYPE_INTEGER   = DataType.INTEGER.name(); 
     public static final String NUMTYPE_DECIMAL   = DataType.DECIMAL.name(); 
     public static final String NUMTYPE_CURRENCY  = "CURRENCY"; 
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBColumn.java b/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
index b69a6460..c4897a2b 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
@@ -23,7 +23,6 @@ import java.util.Set;
 import java.util.regex.Pattern;
 
 import org.apache.empire.commons.Attributes;
-import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.Column;
@@ -439,24 +438,6 @@ public abstract class DBColumn extends DBColumnExpr
         return super.getJavaType();
     }
     
-    /**
-     * Returns whether or not a columnExpr is case sensitive
-     * If not explicitly set, the case sensitivity is true for all text fields (VARCHAR, CLOB) except if an EnumType is set.
-     * @return true if the columnExpr is case sensitive or false if not
-     */
-    public boolean isCaseSensitive()
-    {
-        // only for text expressions
-        if (!getDataType().isText())
-            return false;
-        // check attribute
-        Object value = getAttribute(Column.COLATTR_CASESENSITIVE);
-        if (value!=null)
-            return ObjectUtils.getBoolean(value);
-        // default is true for VARCHAR and CLOB except if Options or EnumType are set
-        return (getOptions()==null && getEnumType()==null);
-    }
-    
     /**
      * Sets the case sensitivity of the columnExpr
      * @param caseSensitiv the character casing. This may be true, false or null (default)
@@ -482,6 +463,22 @@ public abstract class DBColumn extends DBColumnExpr
         return setCaseSensitive(false);
     }
 
+    /**
+     * Sets the number type to a given value
+     * @param numberType the number type. See Column.NUMTYPE_... constants
+     * @return self (this)
+     */
+    @SuppressWarnings("unchecked")
+    public final <T extends DBColumn> T setNumberType(String numberType)
+    {
+        // only for text expressions
+        if (!getDataType().isNumeric())
+            throw new NotSupportedException(this, "setNumberType");
+        // set now
+        setAttribute(Column.COLATTR_NUMBER_TYPE, numberType);
+        return (T)this;
+    }
+
     /**
      * Returns the maximum allowed value 
      * @return the minimum length 
@@ -534,8 +531,11 @@ public abstract class DBColumn extends DBColumnExpr
     public DBColumnExpr getSortExpr()
     {
         Object value = getAttribute(Column.COLATTR_SORTEXPRESSION);
-        // create a sort expression
-        if (value instanceof DBColumnExpr)
+        if (value==null)
+        {   // not set
+            return this;
+        }
+        else if (value instanceof DBColumnExpr)
         {   // return expression
             return ((DBColumnExpr)value); 
         }
@@ -544,12 +544,11 @@ public abstract class DBColumn extends DBColumnExpr
             String sortFunctionTemplate = StringUtils.toString(value);
             return new DBFuncExpr(this, sortFunctionTemplate, null, false, getDataType());
         }
-        else if (value!=null)
+        else
         {   // unknown value
             log.warn("Invalid value for {}: {}", Column.COLATTR_SORTEXPRESSION, value);
+            return this; 
         }
-        // not changed
-        return this; 
     }
     
     /**
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 5f327f69..eae8492a 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
@@ -49,6 +49,7 @@ import org.apache.empire.db.expr.compare.DBCompareColExpr;
 import org.apache.empire.db.expr.compare.DBCompareExpr;
 import org.apache.empire.db.expr.join.DBColumnJoinExpr;
 import org.apache.empire.db.expr.order.DBOrderByExpr;
+import org.apache.empire.dbms.DBMSHandler;
 import org.apache.empire.dbms.DBSqlPhrase;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.NotSupportedException;
@@ -157,6 +158,19 @@ public abstract class DBColumnExpr extends DBExpr
         return column.getAttribute(name);
     }
 
+    /**
+     * Returns the value of a column attribute and converts it to the desired type
+     * 
+     * @param name the attribute name
+     * @param type the desired Java type 
+     * @return value of the attribute 
+     */
+    public <T> T getAttribute(String name, Class<T> type)
+    {
+        Object value = getAttribute(name);
+        return (value!=null ? ObjectUtils.convert(type, value) : null);
+    }
+    
     /**
      * Sets the value of a column attribute.
      * Same as Column.setAttribute but with different name to avoid name clash 
@@ -284,6 +298,88 @@ public abstract class DBColumnExpr extends DBExpr
         this.beanPropertyName = propertyName; 
         return (T)this;
     }
+    
+    /**
+     * Returns the default sort order
+     * FALSE is for ascending, TRUE for descending
+     * @return true if the default sort order is descending
+     */
+    public boolean getDefaultSortOrder()
+    {
+        Object value = getAttribute(Column.COLATTR_SORTDESCENDING);
+        return ObjectUtils.getBoolean(value);
+    }
+
+    /**
+     * Sets the default sort order
+     * @param descending true if the default sort order is ascending or false if descending
+     * @return returns self (this)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends DBColumnExpr> T setDefaultSortOrder(Boolean descending)
+    {
+        setAttribute(Column.COLATTR_SORTDESCENDING, descending);
+        return (T)this;
+    }
+    
+    /**
+     * Returns whether or not a columnExpr is case sensitive
+     * If not explicitly set, the case sensitivity is true for all text fields (VARCHAR, CLOB) except if an EnumType is set.
+     * @return true if the columnExpr is case sensitive or false if not
+     */
+    public boolean isCaseSensitive()
+    {
+        // only for text expressions
+        if (!getDataType().isText())
+            return false;
+        // check attribute
+        Object value = getAttribute(Column.COLATTR_CASESENSITIVE);
+        if (value!=null)
+            return ObjectUtils.getBoolean(value);
+        // default is true for VARCHAR and CLOB except if Options or EnumType are set
+        return (getOptions()==null && getEnumType()==null);
+    }
+    
+    /**
+     * Returns an expression which ignores the case
+     * Only for case sensitive columns!
+     * Default is upper(expr)
+     * @return the ignore case expression or the expression itself
+     */
+    public DBColumnExpr getIgnoreCaseExpr()
+    {
+        // only for text expressions
+        if (!isCaseSensitive())
+            return this;
+        // let handler decide
+        DBMSHandler dbms = getDatabase().getDbms();
+        return (dbms!=null ? dbms.getIgnoreCaseExpr(this) : upper());
+    }
+
+    /**
+     * Returns the number type assigned to this column expression
+     * @param columnExpr the columnExpr
+     * @return the number type
+     */
+    public String getNumberType(ColumnExpr columnExpr)
+    {
+        // only for text expressions
+        if (!getDataType().isNumeric())
+            return null;
+        // check attribute
+        Object value = getAttribute(Column.COLATTR_NUMBER_TYPE);
+        if (value==null)
+        {   // from data type
+            DataType dt = columnExpr.getDataType();
+            if (dt==DataType.INTEGER || dt==DataType.AUTOINC)
+                return DataType.INTEGER.name();
+            if (dt==DataType.DECIMAL || dt==DataType.FLOAT)
+                return DataType.DECIMAL.name();
+            // Not a number
+            return null;
+        }
+        return value.toString();
+    }
 
     /**
      * creates a new DBAliasExpr which renames the current expression to the supplied name. 
@@ -331,27 +427,32 @@ public abstract class DBColumnExpr extends DBExpr
     }
 
     /**
-     * Creates and returns a new comparison object for the SQL "like" operator.
-     * By converting column value and comparison value to upper case 
-     * the like is effectively case insensitive.   
+     * Creates and returns a new case insensitive comparison for the SQL "like" operator.
+     * Case insensitivity is achieved by calling getIgnoreCaseExpr()
+     * Hence the case insensitive operation is determined by the DBMSHandler
+     * Default is upper(value)
      *
      * @param value the Object value
      * @return the new DBCompareColExpr object
      */
     public DBCompareColExpr likeUpper(String value)
     { 
-        DBValueExpr expr = getDatabase().getValueExpr(value, DataType.VARCHAR);
-        return new DBCompareColExpr(this.upper(), DBCmpType.LIKE, expr.upper());
+        DBColumnExpr colExpr = getIgnoreCaseExpr();
+        DBColumnExpr valExpr = getDatabase().getValueExpr(value, DataType.VARCHAR);
+        valExpr = valExpr.getIgnoreCaseExpr();
+        return new DBCompareColExpr(colExpr, DBCmpType.LIKE, valExpr);
     }
 
     /**
      * Creates and returns a new comparison object for the SQL "like" operator.
-     * By converting column value and comparison value to lower case 
-     * the like is effectively case insensitive.   
+     * Converts the column value and comparison value to lower case
+     * 
+     * @deprecated Always user likeUpper() for case insensitive comparions
      *
      * @param value the Object value
      * @return the new DBCompareColExpr object
      */
+    @Deprecated
     public DBCompareColExpr likeLower(String value)
     { 
         DBValueExpr expr = getDatabase().getValueExpr(value, DataType.VARCHAR);
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 113353a8..770f1842 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
@@ -1433,6 +1433,7 @@ public abstract class DBCommand extends DBCommandExpr
 
     /**
      * Overridden to change return type from DBCommandExpr to DBCommand
+     * @see org.apache.empire.db.DBCommandExpr#orderBy(org.apache.empire.db.expr.order.DBOrderByExpr...)
      */
     @Override
     public DBCommand orderBy(DBOrderByExpr... exprs)
@@ -1442,6 +1443,17 @@ public abstract class DBCommand extends DBCommandExpr
 
     /**
      * Overridden to change return type from DBCommandExpr to DBCommand
+     * @see org.apache.empire.db.DBCommandExpr#orderBy(org.apache.empire.db.DBColumnExpr)
+     */
+    @Override
+    public DBCommand orderBy(DBColumnExpr expr)
+    {
+        return (DBCommand)super.orderBy(expr);
+    }
+
+    /**
+     * Overridden to change return type from DBCommandExpr to DBCommand
+     * @see org.apache.empire.db.DBCommandExpr#orderBy(org.apache.empire.db.DBColumnExpr...)
      */
     @Override
     public DBCommand orderBy(DBColumnExpr... exprs)
@@ -1451,6 +1463,7 @@ public abstract class DBCommand extends DBCommandExpr
 
     /**
      * Overridden to change return type from DBCommandExpr to DBCommand
+     * @see org.apache.empire.db.DBCommandExpr#orderBy(org.apache.empire.db.DBColumnExpr, boolean)
      */
     @Override
     public DBCommand orderBy(DBColumnExpr expr, boolean desc)
@@ -1458,6 +1471,16 @@ public abstract class DBCommand extends DBCommandExpr
         return (DBCommand)super.orderBy(expr, desc);
     }
 
+    /**
+     * Overridden to change return type from DBCommandExpr to DBCommand
+     * @see org.apache.empire.db.DBCommandExpr#orderByUpper(org.apache.empire.db.DBColumnExpr, boolean)
+     */
+    @Override
+    public DBCommand orderByUpper(DBColumnExpr expr, boolean desc)
+    {
+        return (DBCommand)super.orderByUpper(expr, desc);
+    }
+
     /**
      * Overridden to change return type from DBCommandExpr to DBCommand
      */
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 73fd1963..a61f6e8e 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
@@ -558,30 +558,61 @@ public abstract class DBCommandExpr extends DBExpr
         return this;
     }
 
+    /**
+     * Adds an order by with ascending or descending order
+     * 
+     * @param expr the expression for ordering
+     * @param desc if true, the results from select statement will sort top down
+     * @return itself (this)
+     */
+    public DBCommandExpr orderBy(DBColumnExpr expr, boolean desc)
+    {
+        if (expr instanceof DBColumn)
+            expr = ((DBColumn)expr).getSortExpr();
+        // create order by now
+        return orderBy(new DBOrderByExpr(expr, desc));
+    }
+
+    /**
+     * Adds a column expression to the orderBy clause
+     * 
+     * @param expr the sort order expression
+     * @return itself (this)
+     */
+    public DBCommandExpr orderBy(DBColumnExpr expr)
+    {
+        return orderBy(expr, expr.getDefaultSortOrder());
+    }
+
     /**
      * Adds a list of columns to the orderBy clause in ascending order
      * 
-     * @param exprs vararg of column expressions
+     * @param exprs vararg of order by expressions
      * @return itself (this)
      */
     public DBCommandExpr orderBy(DBColumnExpr... exprs)
     {
         for (DBColumnExpr expr : exprs)
         {
-            orderBy(new DBOrderByExpr(expr, false));
+            orderBy(expr, expr.getDefaultSortOrder());
         }
         return this;
     }
 
     /**
-     * Adds an order by with ascending or descending order
+     * Adds a case insensitive order by with ascending or descending order
      * 
-     * @param expr the DBColumnExpr object
+     * @param expr the expression for ordering
      * @param desc if true, the results from select statement will sort top down
      * @return itself (this)
      */
-    public DBCommandExpr orderBy(DBColumnExpr expr, boolean desc)
+    public DBCommandExpr orderByUpper(DBColumnExpr expr, boolean desc)
     {
+        if (expr instanceof DBColumn)
+            expr = ((DBColumn)expr).getSortExpr();
+        // make case insensitive
+        expr = expr.getIgnoreCaseExpr();
+        // create order by now
         return orderBy(new DBOrderByExpr(expr, desc));
     }
 
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBFuncExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBFuncExpr.java
index 7ecddb7b..90ee21ca 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBFuncExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBFuncExpr.java
@@ -153,6 +153,10 @@ public class DBFuncExpr extends DBAbstractFuncExpr
         {   // UPPER and LOWER are not case sensitive
             return false;
         }
+        else if (phrase==DBSqlPhrase.SQL_FUNC_TRUNC && Column.COLATTR_NUMBER_TYPE.equals(name) && getDataType().isNumeric())
+        {   // Truncate will produce an Integer
+            return DataType.INTEGER.name();
+        }
         return super.getAttribute(name);
     }
 
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java
index 9ea5b623..1b4371e1 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandler.java
@@ -24,6 +24,7 @@ import java.sql.SQLException;
 import java.sql.Timestamp;
 
 import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBColumnExpr;
 import org.apache.empire.db.DBCommand;
 import org.apache.empire.db.DBCommandExpr;
 import org.apache.empire.db.DBDDLGenerator.DDLActionType;
@@ -144,6 +145,15 @@ public interface DBMSHandler
      * @return the auto-generated value
      */
     Object getColumnAutoValue(DBDatabase db, DBTableColumn column, Connection conn);
+
+    /**
+     * Returns an expression that ignores the case of a column expression
+     * Only for text columns.
+     * Default is upper(expr)
+     * @param expr the expression for which to ignore the case
+     * @return the ignore case expression
+     */
+    DBColumnExpr getIgnoreCaseExpr(DBColumnExpr expr);
     
     /**
      * Executes an select SQL-command that returns only one scalar value
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
index 7aefab60..eecabcdd 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/DBMSHandlerBase.java
@@ -512,6 +512,23 @@ public abstract class DBMSHandlerBase implements DBMSHandler
         // Other types
         throw new NotSupportedException(this, "getColumnAutoValue for "+column.getFullName());
     }
+
+    /**
+     * Returns an expression that ignores the case of a column expression
+     * Only for text columns.
+     * Default is upper(expr)
+     * @param expr the expression for which to ignore the case
+     * @return the ignore case expression or the expression itself
+     */
+    @Override
+    public DBColumnExpr getIgnoreCaseExpr(DBColumnExpr expr)
+    {
+        if (expr==null || !expr.getDataType().isText())
+        {   // not a CHAR or VARCHAR
+            return expr; 
+        }
+        return expr.upper();
+    }
     
     /**
      * Reads a single column value from the given JDBC ResultSet and returns a value object of desired data type.<BR> 
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDDLGenerator.java b/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDDLGenerator.java
index db150d22..6d82c9a1 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDDLGenerator.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDDLGenerator.java
@@ -111,7 +111,19 @@ public class OracleDDLGenerator extends DBDDLGenerator<DBMSHandlerOracle>
             sql.append(")");
         }
         else
+        {
             super.appendColumnDesc(c, alter, sql);
+        }
+        // more options
+        if (c.getDataType().isText())
+        {   // append collation
+            String collation = c.getAttribute("COLLATE", String.class);
+            if (collation!=null && collation.length()>0)
+            {   // append collation
+                sql.append(" COLLATE ");
+                sql.append(collation);
+            }
+        }
     }
 
     @Override