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/03/06 10:29:22 UTC

[empire-db] branch master updated: EMPIREDB-382 Access native DBMS functions with DBColumnExpr.function() and DBColumnExpr.aggregate()

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 48b1566  EMPIREDB-382 Access native DBMS functions with DBColumnExpr.function() and DBColumnExpr.aggregate()
48b1566 is described below

commit 48b15664b516b0b6c30542cfaf08ec4f02bf0870
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Sun Mar 6 11:29:20 2022 +0100

    EMPIREDB-382 Access native DBMS functions with DBColumnExpr.function() and DBColumnExpr.aggregate()
---
 .../java/org/apache/empire/db/DBColumnExpr.java    | 98 +++++++++++++++++-----
 .../empire/db/expr/column/DBAbstractFuncExpr.java  | 11 +--
 .../empire/db/expr/column/DBConcatFuncExpr.java    |  4 +-
 .../apache/empire/db/expr/column/DBValueExpr.java  |  3 +-
 .../java/org/apache/empire/dbms/DBSqlPhrase.java   | 14 ++--
 .../org/apache/empire/dbms/h2/DBMSHandlerH2.java   |  2 +-
 .../apache/empire/dbms/hsql/DBMSHandlerHSql.java   |  2 +-
 .../apache/empire/dbms/mysql/DBMSHandlerMySQL.java |  2 +-
 .../empire/dbms/oracle/DBMSHandlerOracle.java      |  4 +-
 .../empire/dbms/postgresql/DBCommandPostgres.java  |  6 +-
 .../dbms/postgresql/DBMSHandlerPostgreSQL.java     |  8 +-
 .../empire/dbms/postgresql/PostgresSqlPhrase.java  |  4 +-
 .../empire/dbms/sqlite/DBMSHandlerSQLite.java      |  2 +-
 .../empire/dbms/sqlserver/DBMSHandlerMSSQL.java    |  2 +-
 14 files changed, 110 insertions(+), 52 deletions(-)

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 26d5284..112817f 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
@@ -959,6 +959,31 @@ public abstract class DBColumnExpr extends DBExpr
     }
 
     /**
+     * concatenates a list of expressions to the current column 
+     * @param concatExprs the expressions to concat
+     * @return the concat expression
+     */
+    public DBColumnExpr concat(DBColumnExpr... concatExprs)
+    {
+        return new DBConcatFuncExpr(this, concatExprs);
+    }
+
+    /**
+     * concatenates a list of expressions to the current column 
+     * @param separator a string to insert between each of the expressions
+     * @param concatExprs the expressions to concat
+     * @return the concat expression
+     */
+    public DBColumnExpr concat(String separator, DBColumnExpr... concatExprs)
+    {
+        return new DBConcatFuncExpr(this, separator, concatExprs);
+    }
+    
+    /*
+     * Numeric functions
+     */
+
+    /**
      * Creates and returns a sql-expression for the absolute abs() function.
      * 
      * @return the new DBFuncExpr object
@@ -1045,6 +1070,10 @@ public abstract class DBColumnExpr extends DBExpr
         return getExprFromPhrase(DBSqlPhrase.SQL_FUNC_DAY, null);
     }
 
+    /*
+     * Aggregation functions
+     */
+    
     /**
      * Creates and returns an aggregation function object
      * which calculates the sum for the current expression over a group of rows.
@@ -1130,6 +1159,10 @@ public abstract class DBColumnExpr extends DBExpr
     {
         return new DBCountExpr(this, true);
     }
+    
+    /*
+     * Case functions
+     */
 
     /**
      * Creates and returns a sql-expression that maps enum values by name or ordinal to their string representation 
@@ -1275,9 +1308,9 @@ public abstract class DBColumnExpr extends DBExpr
         return new DBCaseExpr(compExpr, this, elseExpr);
     }
 
-    // ----------------------------------------------------------
-    // --------------------- Conversion -------------------------
-    // ----------------------------------------------------------
+    /*
+     * Type conversion functions
+     */
     
     /**
      * Creates a new DBFuncExpr object (to_char SQL statement)
@@ -1328,6 +1361,42 @@ public abstract class DBColumnExpr extends DBExpr
         return convertTo(dataType, null);
     }
 
+    /*
+     * DBMS Native functions
+     */
+
+    /**
+     * Creates and returns a function from an sql template
+     * The template may consist of the following placeholders:
+     *  ? = the expression on which the function is applied (usually a column expression)
+     *  {[param-index]:[DataType]} = a function parameter. The DataType name, if supplied, must match the name of a DataType enum value.
+     * @param template the sql phrase template (see above)
+     * @param dataType the returned DataType
+     * @return the function expression
+     */
+    public final DBColumnExpr function(String template, DataType returnType, Object... params)
+    {
+        return new DBFuncExpr(this, template, params, false, returnType);
+    }
+
+    /**
+     * Creates and returns a function from an sql template
+     * The template may consist of the following placeholders:
+     *  ? = the expression on which the function is applied (usually a column expression)
+     *  {[param-index]:[DataType]} = a function parameter. The DataType name, if supplied, must match the name of a DataType enum value.
+     * @param template the sql phrase template (see above)
+     * @param dataType the returned DataType
+     * @return the aggregate expression
+     */
+    public final DBColumnExpr aggregate(String template, DataType returnType, Object... params)
+    {
+        return new DBFuncExpr(this, template, params, true, returnType);
+    }
+    
+    /*
+     *  OrderByExpr functions 
+     */
+
     /**
      * creates a new DBOrderByExpr for ascending order 
      * <P>
@@ -1347,27 +1416,10 @@ public abstract class DBColumnExpr extends DBExpr
     {
         return new DBOrderByExpr(this, true);
     }
-
-    /**
-     * concatenates a list of expressions to the current column 
-     * @param concatExprs the expressions to concat
-     * @return the concat expression
-     */
-    public DBColumnExpr concat(DBColumnExpr... concatExprs)
-    {
-        return new DBConcatFuncExpr(this, concatExprs);
-    }
-
-    /**
-     * concatenates a list of expressions to the current column 
-     * @param separator a string to insert between each of the expressions
-     * @param concatExprs the expressions to concat
-     * @return the concat expression
+    
+    /*
+     * Other
      */
-    public DBColumnExpr concat(String separator, DBColumnExpr... concatExprs)
-    {
-        return new DBConcatFuncExpr(this, separator, concatExprs);
-    }
  
     /**
      * returns a corresponding Java type for this expression
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java
index 5ff1cd4..706837c 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAbstractFuncExpr.java
@@ -221,13 +221,14 @@ public abstract class DBAbstractFuncExpr extends DBColumnExpr
                     int end = template.indexOf('}', idx);
                     if (end<idx)
                         throw new InvalidArgumentException("template", template); 
-                    // check if type is specified
+                    // check if DataType is specified
                     if (template.charAt(idx)==':')
-                    {   // DataType is specified
+                    {   // Yes, get the DataType name and look it up
                         String typeName = ((end>=idx) ? template.substring(idx+1, end) : null);
-                        DataType dataType = ((typeName!=null) ? DataType.valueOf(typeName) : null);
-                        if (dataType!=null)
-                            paramDataType = dataType;
+                        if (StringUtils.isNotEmpty(typeName) && !typeName.equals("*"))
+                            paramDataType = DataType.valueOf(typeName);
+                        else
+                            paramDataType = DataType.UNKNOWN;   /* use as literal */
                     }
                     // complete placeholder
                     ph += template.substring(idx, end+1);
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatFuncExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatFuncExpr.java
index 0ad9ec9..6638f16 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatFuncExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBConcatFuncExpr.java
@@ -63,7 +63,9 @@ public class DBConcatFuncExpr extends DBAbstractFuncExpr
     { // Get the expression name
         String name = first.getName();
         for (int i=0; i<others.length; i++)
-        { // add other names
+        {   // add other names
+            if (others[i] instanceof DBValueExpr)
+                continue; // Ignore literals
             name += "_";
             name += others[i].getName();
         }
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
index f3e69a0..5f502e6 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBValueExpr.java
@@ -21,6 +21,7 @@ package org.apache.empire.db.expr.column;
 import java.util.Set;
 
 import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
 // Java
 import org.apache.empire.data.DataType;
 import org.apache.empire.db.DBColumn;
@@ -141,7 +142,7 @@ public class DBValueExpr extends DBColumnExpr
                     break;
             }
             str = str.substring((str.charAt(0)=='-' ? 1 : 0), i);
-            if (str.length()>0)
+            if (StringUtils.isNotEmpty(str))
             {   // generate from value string
                 char c = str.charAt(0);
                 if (c>='0' && c<='9')
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/DBSqlPhrase.java b/empire-db/src/main/java/org/apache/empire/dbms/DBSqlPhrase.java
index 4f7f9e2..e75d85c 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/DBSqlPhrase.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/DBSqlPhrase.java
@@ -2,6 +2,10 @@ package org.apache.empire.dbms;
 
 /**
  * Enum for all SQL phrases that may be supplied by the dbms
+ * The phase may consist of the following placeholders:
+ *  ? = the expression on which the function is applied (usually a column expression)
+ *  {[param-index]:[DataType]} = a function parameter. The DataType name, if supplied, must match the name of a DataType enum value.
+ * @param phrase
  * @author rainer
  */
 public enum DBSqlPhrase
@@ -34,19 +38,19 @@ public enum DBSqlPhrase
 
     // functions
     SQL_FUNC_COALESCE       ("coalesce(?, {0})"),       // Oracle: nvl(?, {0})
-    SQL_FUNC_SUBSTRING      ("substring(?, {0})"),      // Oracle: substr(?,{0})
-    SQL_FUNC_SUBSTRINGEX    ("substring(?, {0}, {1})"), // Oracle: substr(?,{0},{1})
+    SQL_FUNC_SUBSTRING      ("substring(?, {0:INTEGER})"),
+    SQL_FUNC_SUBSTRINGEX    ("substring(?, {0:INTEGER}, {1:INTEGER})"),
     SQL_FUNC_REPLACE        ("replace(?, {0}, {1})"),   // Oracle: replace(?,{0},{1})
     SQL_FUNC_REVERSE        ("reverse(?)"),             // Oracle: reverse(?) 
     SQL_FUNC_STRINDEX       ("charindex({0}, ?)"),      // Oracle: instr(?, {0})
-    SQL_FUNC_STRINDEXFROM   ("charindex({0}, ?, {1})"), // Oracle: instr(?, {0}, {1}) 
+    SQL_FUNC_STRINDEXFROM   ("charindex({0}, ?, {1:INTEGER})"), // Oracle: instr(?, {0}, {1}) 
     SQL_FUNC_LENGTH         ("length(?)"),              // MSSql: len(?)
     SQL_FUNC_UPPER          ("upper(?)"),
     SQL_FUNC_LOWER          ("lower(?)"),
     SQL_FUNC_TRIM           ("trim(?)"),
     SQL_FUNC_LTRIM          ("ltrim(?)"),
     SQL_FUNC_RTRIM          ("rtrim(?)"),
-    SQL_FUNC_ESCAPE         ("? escape '{0}'"),
+    SQL_FUNC_ESCAPE         ("? escape {0:VARCHAR}"),
     SQL_FUNC_CONCAT         ("concat(?)"),
     
     // Numeric
@@ -68,7 +72,7 @@ public enum DBSqlPhrase
     SQL_FUNC_MAX            ("max(?)", true),
     SQL_FUNC_MIN            ("min(?)", true),
     SQL_FUNC_AVG            ("avg(?)", true),
-    SQL_FUNC_STRAGG         (null),                     // Not supported by default
+    SQL_FUNC_STRAGG         (null),                     // Not supported by default, please supply in DBMSHandler
 
     // Decode
     SQL_FUNC_DECODE         ("case ? {0} end"),         // Oracle: decode(? {0})
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/h2/DBMSHandlerH2.java b/empire-db/src/main/java/org/apache/empire/dbms/h2/DBMSHandlerH2.java
index 79fed13..79c6f3e 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/h2/DBMSHandlerH2.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/h2/DBMSHandlerH2.java
@@ -265,7 +265,7 @@ public class DBMSHandlerH2 extends DBMSHandlerBase
             case SQL_FUNC_TRIM:               return "trim(?)";
             case SQL_FUNC_LTRIM:              return "ltrim(?)";
             case SQL_FUNC_RTRIM:              return "rtrim(?)";
-            case SQL_FUNC_ESCAPE:             return "? escape '{0}'";
+            case SQL_FUNC_ESCAPE:             return "? escape {0:VARCHAR}";
             // Numeric
             case SQL_FUNC_ABS:                return "abs(?)";
             case SQL_FUNC_ROUND:              return "round(?,{0})";
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/hsql/DBMSHandlerHSql.java b/empire-db/src/main/java/org/apache/empire/dbms/hsql/DBMSHandlerHSql.java
index 3160a23..4c5819a 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/hsql/DBMSHandlerHSql.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/hsql/DBMSHandlerHSql.java
@@ -140,7 +140,7 @@ public class DBMSHandlerHSql extends DBMSHandlerBase
             case SQL_FUNC_TRIM:         return "trim(?)";
             case SQL_FUNC_LTRIM:        return "ltrim(?)";
             case SQL_FUNC_RTRIM:        return "rtrim(?)";
-            case SQL_FUNC_ESCAPE:       return "? escape '{0}'";
+            case SQL_FUNC_ESCAPE:       return "? escape {0:VARCHAR}";
             // Numeric
             case SQL_FUNC_ABS:          return "abs(?)";
             case SQL_FUNC_ROUND:        return "round(?,{0})";
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java b/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java
index 553beb1..0afb4ae 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/mysql/DBMSHandlerMySQL.java
@@ -1021,7 +1021,7 @@ public class DBMSHandlerMySQL extends DBMSHandlerBase
             case SQL_FUNC_TRIM:               return "trim(?)";
             case SQL_FUNC_LTRIM:              return "ltrim(?)";
             case SQL_FUNC_RTRIM:              return "rtrim(?)";
-            case SQL_FUNC_ESCAPE:             return "? escape '{0}'";
+            case SQL_FUNC_ESCAPE:             return "? escape {0:VARCHAR}";
             // Numeric
             case SQL_FUNC_ABS:                return "abs(?)";
             case SQL_FUNC_ROUND:              return "round(?,{0})";
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 2fc2d0c..b53f7c4 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
@@ -205,8 +205,8 @@ public class DBMSHandlerOracle extends DBMSHandlerBase
             case SQL_FUNC_TRIM:                 return "trim(?)";
             case SQL_FUNC_LTRIM:                return "ltrim(?)";
             case SQL_FUNC_RTRIM:                return "rtrim(?)";
-            case SQL_FUNC_ESCAPE:               return "? escape '{0}'";
-            case SQL_FUNC_CONCAT:               return " || ";
+            case SQL_FUNC_ESCAPE:               return "? escape {0:VARCHAR}";
+            case SQL_FUNC_CONCAT:               return "concat(?)"; // ATTENTION: only takes two parameters!
             // Numeric
             case SQL_FUNC_ABS:                  return "abs(?)";
             case SQL_FUNC_ROUND:                return "round(?,{0})";
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBCommandPostgres.java b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBCommandPostgres.java
index df1f45e..00f381a 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBCommandPostgres.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBCommandPostgres.java
@@ -24,7 +24,6 @@ import org.apache.empire.db.DBColumnExpr;
 import org.apache.empire.db.DBCommand;
 import org.apache.empire.db.DBRowSet;
 import org.apache.empire.db.exceptions.NoPrimaryKeyException;
-import org.apache.empire.db.expr.column.DBValueExpr;
 import org.apache.empire.db.expr.compare.DBCompareExpr;
 
 /**
@@ -49,13 +48,12 @@ public class DBCommandPostgres extends DBCommand
     
     public DBColumnExpr funcAge(DBColumnExpr expr1, DBColumnExpr expr2)
     {
-        return new PostgresFuncExpr(expr1, PostgresSqlPhrase.AGE_TWO, new Object[] { expr2 }, DataType.INTEGER);
+        return new PostgresFuncExpr(expr1, PostgresSqlPhrase.AGE_BETWEEN, new Object[] { expr2 }, DataType.INTEGER);
     }
     
     public DBColumnExpr funcExtract(PostgresExtractField field, DBColumnExpr expr)
     {
-        DBValueExpr fieldExpr = new DBValueExpr(expr.getDatabase(), field.name(), DataType.UNKNOWN);
-        return new PostgresFuncExpr(expr, PostgresSqlPhrase.EXTRACT, new Object[] { fieldExpr }, DataType.INTEGER);
+        return new PostgresFuncExpr(expr, PostgresSqlPhrase.EXTRACT, new Object[] { field.name() }, DataType.INTEGER);
     }
     
     public DBColumnExpr funcToTsquery(DBColumnExpr expr)
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBMSHandlerPostgreSQL.java b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBMSHandlerPostgreSQL.java
index f731708..c1516ee 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBMSHandlerPostgreSQL.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/DBMSHandlerPostgreSQL.java
@@ -301,19 +301,19 @@ public class DBMSHandlerPostgreSQL extends DBMSHandlerBase
             case SQL_TIMESTAMP_TEMPLATE:      return "'{0}'";
             // functions
             case SQL_FUNC_COALESCE:           return "coalesce(?, {0})";
-            case SQL_FUNC_SUBSTRING:          return "substring(?, {0})";
-            case SQL_FUNC_SUBSTRINGEX:        return "substring(?, {0}, {1})";
+            case SQL_FUNC_SUBSTRING:          return "substring(?, {0:INTEGER})";
+            case SQL_FUNC_SUBSTRINGEX:        return "substring(?, {0:INTEGER}, {1:INTEGER})";
             case SQL_FUNC_REPLACE:            return "replace(?, {0}, {1})";
             case SQL_FUNC_REVERSE:            return "reverse(?)"; // In order to use this function createReverseFunction() must be called first!
             case SQL_FUNC_STRINDEX:           return "strpos(?, {0})"; 
-            case SQL_FUNC_STRINDEXFROM:       return "strindexfrom_not_available_in_pgsql({0}, ?, {1})"; // "locate({0}, ?, {1})"; 
+            case SQL_FUNC_STRINDEXFROM:       return null;         // strindexfrom not available in pgsql 
             case SQL_FUNC_LENGTH:             return "length(?)";
             case SQL_FUNC_UPPER:              return "upper(?)";
             case SQL_FUNC_LOWER:              return "lower(?)";
             case SQL_FUNC_TRIM:               return "trim(?)";
             case SQL_FUNC_LTRIM:              return "ltrim(?)";
             case SQL_FUNC_RTRIM:              return "rtrim(?)";
-            case SQL_FUNC_ESCAPE:             return "? escape '{0}'";
+            case SQL_FUNC_ESCAPE:             return "? escape {0:VARCHAR}";
             // Numeric
             case SQL_FUNC_ABS:                return "abs(?)";
             case SQL_FUNC_ROUND:              return "round(?,{0})";
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresSqlPhrase.java b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresSqlPhrase.java
index f9c70c0..8dd79ca 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresSqlPhrase.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/postgresql/PostgresSqlPhrase.java
@@ -26,8 +26,8 @@ public enum PostgresSqlPhrase
 {
     // functions
     AGE             ("AGE(?)"),
-    AGE_TWO         ("AGE(?, {0})"),
-    EXTRACT         ("EXTRACT({0} from ?)"),
+    AGE_BETWEEN     ("AGE(?, {0})"),
+    EXTRACT         ("EXTRACT({0:*} FROM ?)"),  // :* is important!
     TO_TSQUERY      ("to_tsquery(?)"),
     TO_TSVECTOR     ("to_tsvector(?)"),
     PLAINTO_TSQUERY ("plainto_tsquery(?)");
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/sqlite/DBMSHandlerSQLite.java b/empire-db/src/main/java/org/apache/empire/dbms/sqlite/DBMSHandlerSQLite.java
index 932eac8..16b1545 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/sqlite/DBMSHandlerSQLite.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/sqlite/DBMSHandlerSQLite.java
@@ -343,7 +343,7 @@ public class DBMSHandlerSQLite extends DBMSHandlerBase
             case SQL_FUNC_TRIM:             return "trim(?)";
             case SQL_FUNC_LTRIM:            return "ltrim(?)";
             case SQL_FUNC_RTRIM:            return "rtrim(?)";
-            case SQL_FUNC_ESCAPE:           return "? escape '{0}'";
+            case SQL_FUNC_ESCAPE:           return "? escape {0:VARCHAR}";
             // Numeric
             case SQL_FUNC_ABS:              return "abs(?)";
             case SQL_FUNC_ROUND:            return "round(?,{0})";
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 11f4337..a733098 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
@@ -354,7 +354,7 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
             case SQL_FUNC_TRIM:               return "trim(?)";
             case SQL_FUNC_LTRIM:              return "ltrim(?)";
             case SQL_FUNC_RTRIM:              return "rtrim(?)";
-            case SQL_FUNC_ESCAPE:             return "? escape '{0}'";
+            case SQL_FUNC_ESCAPE:             return "? escape {0:VARCHAR}";
             // Numeric
             case SQL_FUNC_ABS:                return "abs(?)";
             case SQL_FUNC_ROUND:              return "round(?,{0})";