spuerx hace 9 años
padre
commit
7cff3db3ec

+ 15 - 9
src/main/java/org/es/sql/dsl/helper/ElasticSqlMethodInvokeHelper.java

@@ -7,12 +7,14 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.es.sql.dsl.enums.SortOption;
 import org.es.sql.dsl.exception.ElasticSql2DslException;
+import org.es.sql.dsl.parser.query.method.MethodInvocation;
 
 import java.util.List;
 
 public class ElasticSqlMethodInvokeHelper {
     public static final List<String> DATE_METHOD = ImmutableList.of("date", "to_date", "toDate");
     public static final List<String> NVL_METHOD = ImmutableList.of("nvl", "is_null", "isnull");
+    public static final List<String> SCRIPT_SORT_METHOD = ImmutableList.of("script_sort", "scriptSort");
 
     public static final List<String> AGG_TERMS_METHOD = ImmutableList.of("terms", "terms_agg");
     public static final List<String> AGG_RANGE_METHOD = ImmutableList.of("range", "range_agg");
@@ -42,6 +44,10 @@ public class ElasticSqlMethodInvokeHelper {
         return methodAlias.equalsIgnoreCase(method);
     }
 
+    public static void checkScriptSortMethod(MethodInvocation scriptSortMethodInvocation) {
+        // todo
+    }
+
     public static void checkTermsAggMethod(SQLMethodInvokeExpr aggInvokeExpr) {
         if (!isMethodOf(AGG_TERMS_METHOD, aggInvokeExpr.getMethodName())) {
             throw new ElasticSql2DslException("[syntax error] Sql not support method:" + aggInvokeExpr.getMethodName());
@@ -91,18 +97,18 @@ public class ElasticSqlMethodInvokeHelper {
         }
     }
 
-    public static void checkNvlMethod(SQLMethodInvokeExpr nvlInvokeExpr) {
-        if (!isMethodOf(NVL_METHOD, nvlInvokeExpr.getMethodName())) {
+    public static void checkNvlMethod(MethodInvocation nvlMethodInvocation) {
+        if (!isMethodOf(NVL_METHOD, nvlMethodInvocation.getMethodName())) {
             throw new ElasticSql2DslException("[syntax error] Sql sort condition only support nvl method invoke");
         }
 
-        if (CollectionUtils.isEmpty(nvlInvokeExpr.getParameters()) || nvlInvokeExpr.getParameters().size() > 3) {
-            throw new ElasticSql2DslException(String.format("[syntax error] There is no %s args method named nvl",
-                    nvlInvokeExpr.getParameters() != null ? nvlInvokeExpr.getParameters().size() : 0));
+        int methodParameterCount = nvlMethodInvocation.getParameterCount();
+        if (methodParameterCount == 0 || methodParameterCount > 3) {
+            throw new ElasticSql2DslException(String.format("[syntax error] There is no %s args method named nvl", methodParameterCount));
         }
 
-        SQLExpr fieldArg = nvlInvokeExpr.getParameters().get(0);
-        SQLExpr valueArg = nvlInvokeExpr.getParameters().get(1);
+        SQLExpr fieldArg = nvlMethodInvocation.getParameter(0);
+        SQLExpr valueArg = nvlMethodInvocation.getParameter(1);
 
         if (!(fieldArg instanceof SQLPropertyExpr) && !(fieldArg instanceof SQLIdentifierExpr)) {
             throw new ElasticSql2DslException("[syntax error] The first arg of nvl method should be field param name");
@@ -112,8 +118,8 @@ public class ElasticSqlMethodInvokeHelper {
             throw new ElasticSql2DslException("[syntax error] The second arg of nvl method should be number or string");
         }
 
-        if (nvlInvokeExpr.getParameters().size() == 3) {
-            SQLExpr sortModArg = nvlInvokeExpr.getParameters().get(2);
+        if (methodParameterCount == 3) {
+            SQLExpr sortModArg = nvlMethodInvocation.getParameter(2);
             if (!(sortModArg instanceof SQLCharExpr)) {
                 throw new ElasticSql2DslException("[syntax error] The third arg of nvl method should be string");
             }

+ 2 - 4
src/main/java/org/es/sql/dsl/parser/query/method/AbstractFieldSpecificMethodQueryParser.java

@@ -1,17 +1,17 @@
 package org.es.sql.dsl.parser.query.method;
 
-import com.alibaba.druid.sql.ast.SQLExpr;
 import org.elasticsearch.index.query.FilterBuilder;
 import org.es.sql.dsl.bean.AtomFilter;
 import org.es.sql.dsl.bean.ElasticSqlQueryField;
 import org.es.sql.dsl.enums.QueryFieldType;
 import org.es.sql.dsl.exception.ElasticSql2DslException;
 import org.es.sql.dsl.listener.ParseActionListener;
+import org.es.sql.dsl.parser.query.method.expr.FieldSpecificMethodExpression;
 import org.es.sql.dsl.parser.sql.QueryFieldParser;
 
 import java.util.Map;
 
-public abstract class AbstractFieldSpecificMethodQueryParser extends ParameterizedMethodQueryParser {
+public abstract class AbstractFieldSpecificMethodQueryParser extends ParameterizedMethodQueryParser implements FieldSpecificMethodExpression {
 
     protected ParseActionListener parseActionListener;
 
@@ -21,8 +21,6 @@ public abstract class AbstractFieldSpecificMethodQueryParser extends Parameteriz
 
     protected abstract FilterBuilder buildQuery(MethodInvocation invocation, String fieldName, Map<String, String> extraParams);
 
-    protected abstract SQLExpr defineFieldExpr(MethodInvocation invocation);
-
     @Override
     protected String defineExtraParamString(MethodInvocation invocation) {
         //ignore extra params, subclass can override if necessary

+ 0 - 28
src/main/java/org/es/sql/dsl/parser/query/method/CheckableMethodQueryParser.java

@@ -1,28 +0,0 @@
-package org.es.sql.dsl.parser.query.method;
-
-import org.es.sql.dsl.bean.AtomFilter;
-import org.es.sql.dsl.exception.ElasticSql2DslException;
-import org.es.sql.dsl.helper.ElasticSqlMethodInvokeHelper;
-
-public abstract class CheckableMethodQueryParser implements MethodQueryParser {
-
-    protected abstract void checkMethodInvokeArgs(MethodInvocation invocation) throws ElasticSql2DslException;
-
-    protected abstract AtomFilter parseMethodQueryWithCheck(MethodInvocation invocation) throws ElasticSql2DslException;
-
-    @Override
-    public boolean isMatchMethodInvocation(MethodInvocation invocation) {
-        return ElasticSqlMethodInvokeHelper.isMethodOf(defineMethodNames(), invocation.getMethodName());
-    }
-
-    @Override
-    public AtomFilter parseAtomMethodQuery(MethodInvocation invocation) throws ElasticSql2DslException {
-        if (!isMatchMethodInvocation(invocation)) {
-            throw new ElasticSql2DslException(
-                    String.format("[syntax error] Expected method name is one of [%s],but get [%s]",
-                            defineMethodNames(), invocation.getMethodName()));
-        }
-        checkMethodInvokeArgs(invocation);
-        return parseMethodQueryWithCheck(invocation);
-    }
-}

+ 2 - 8
src/main/java/org/es/sql/dsl/parser/query/method/MethodQueryParser.java

@@ -2,14 +2,8 @@ package org.es.sql.dsl.parser.query.method;
 
 import org.es.sql.dsl.bean.AtomFilter;
 import org.es.sql.dsl.exception.ElasticSql2DslException;
+import org.es.sql.dsl.parser.query.method.expr.MethodExpression;
 
-import java.util.List;
-
-public interface MethodQueryParser {
-
-    List<String> defineMethodNames();
-
-    boolean isMatchMethodInvocation(MethodInvocation invocation);
-
+public interface MethodQueryParser extends MethodExpression {
     AtomFilter parseAtomMethodQuery(MethodInvocation invocation) throws ElasticSql2DslException;
 }

+ 14 - 40
src/main/java/org/es/sql/dsl/parser/query/method/ParameterizedMethodQueryParser.java

@@ -1,18 +1,13 @@
 package org.es.sql.dsl.parser.query.method;
 
-import com.google.common.collect.Maps;
-import org.apache.commons.lang.StringUtils;
 import org.es.sql.dsl.bean.AtomFilter;
 import org.es.sql.dsl.exception.ElasticSql2DslException;
+import org.es.sql.dsl.helper.ElasticSqlMethodInvokeHelper;
+import org.es.sql.dsl.parser.query.method.expr.AbstractParameterizedMethodExpression;
 
-import java.util.Collections;
 import java.util.Map;
 
-public abstract class ParameterizedMethodQueryParser extends CheckableMethodQueryParser {
-
-    protected static final String COMMA = ",";
-
-    protected static final String COLON = ":";
+public abstract class ParameterizedMethodQueryParser extends AbstractParameterizedMethodExpression implements MethodQueryParser {
 
     protected abstract String defineExtraParamString(MethodInvocation invocation);
 
@@ -20,41 +15,20 @@ public abstract class ParameterizedMethodQueryParser extends CheckableMethodQuer
             MethodInvocation invocation, Map<String, String> extraParamMap) throws ElasticSql2DslException;
 
     @Override
-    protected AtomFilter parseMethodQueryWithCheck(MethodInvocation invocation) {
-        Map<String, String> extraParamMap = buildExtraParamMap(invocation);
-        return parseMethodQueryWithExtraParams(invocation, extraParamMap);
+    public boolean isMatchMethodInvocation(MethodInvocation invocation) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(defineMethodNames(), invocation.getMethodName());
     }
 
-    private Map<String, String> buildExtraParamMap(MethodInvocation invocation) {
-        String extraParamString = defineExtraParamString(invocation);
-
-        if (StringUtils.isBlank(extraParamString)) {
-            return Collections.emptyMap();
-        }
-
-        Map<String, String> extraParamMap = Maps.newHashMap();
-        for (String paramPair : extraParamString.split(COMMA)) {
-            String[] paramPairArr = paramPair.split(COLON);
-            if (paramPairArr.length == 2) {
-                extraParamMap.put(paramPairArr[0].trim(), paramPairArr[1].trim());
-            }
-            else {
-                throw new ElasticSql2DslException("Failed to parse query method extra param string!");
-            }
+    @Override
+    public AtomFilter parseAtomMethodQuery(MethodInvocation invocation) throws ElasticSql2DslException {
+        if (!isMatchMethodInvocation(invocation)) {
+            throw new ElasticSql2DslException(
+                    String.format("[syntax error] Expected method name is one of [%s],but get [%s]",
+                            defineMethodNames(), invocation.getMethodName()));
         }
-        return extraParamMap;
-    }
+        checkMethodInvocation(invocation);
 
-    protected Boolean isExtraParamsString(String extraParams) {
-        if (StringUtils.isBlank(extraParams)) {
-            return Boolean.FALSE;
-        }
-        for (String paramPair : extraParams.split(COMMA)) {
-            String[] paramPairArr = paramPair.split(COLON);
-            if (paramPairArr.length != 2) {
-                return Boolean.FALSE;
-            }
-        }
-        return Boolean.TRUE;
+        Map<String, String> extraParamMap = generateParameterMap(invocation);
+        return parseMethodQueryWithExtraParams(invocation, extraParamMap);
     }
 }

+ 67 - 0
src/main/java/org/es/sql/dsl/parser/query/method/expr/AbstractParameterizedMethodExpression.java

@@ -0,0 +1,67 @@
+package org.es.sql.dsl.parser.query.method.expr;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.NumberUtils;
+import org.es.sql.dsl.exception.ElasticSql2DslException;
+import org.es.sql.dsl.parser.query.method.MethodInvocation;
+
+import java.util.Collections;
+import java.util.Map;
+
+public abstract class AbstractParameterizedMethodExpression implements ParameterizedMethodExpression {
+
+    protected static final String COMMA = ",";
+
+    protected static final String COLON = ":";
+
+    protected abstract String defineExtraParamString(MethodInvocation invocation);
+
+    public Map<String, String> generateParameterMap(MethodInvocation invocation) {
+        String extraParamString = defineExtraParamString(invocation);
+
+        if (StringUtils.isBlank(extraParamString)) {
+            return Collections.emptyMap();
+        }
+
+        Map<String, String> extraParamMap = Maps.newHashMap();
+        for (String paramPair : extraParamString.split(COMMA)) {
+            String[] paramPairArr = paramPair.split(COLON);
+            if (paramPairArr.length == 2) {
+                extraParamMap.put(paramPairArr[0].trim(), paramPairArr[1].trim());
+            }
+            else {
+                throw new ElasticSql2DslException("Failed to parse query method extra param string!");
+            }
+        }
+        return extraParamMap;
+    }
+
+    public Map<String, Object> generateRawTypeParameterMap(MethodInvocation invocation) {
+        Map<String, String> extraParamMap = generateParameterMap(invocation);
+        if (MapUtils.isNotEmpty(extraParamMap)) {
+            return Maps.transformEntries(extraParamMap, new Maps.EntryTransformer<String, String, Object>() {
+                @Override
+                public Object transformEntry(String key, String value) {
+                    return NumberUtils.isNumber(value) ? NumberUtils.createNumber(value) : value;
+                }
+            });
+        }
+
+        return Collections.emptyMap();
+    }
+
+    protected Boolean isExtraParamsString(String extraParams) {
+        if (StringUtils.isBlank(extraParams)) {
+            return Boolean.FALSE;
+        }
+        for (String paramPair : extraParams.split(COMMA)) {
+            String[] paramPairArr = paramPair.split(COLON);
+            if (paramPairArr.length != 2) {
+                return Boolean.FALSE;
+            }
+        }
+        return Boolean.TRUE;
+    }
+}

+ 8 - 0
src/main/java/org/es/sql/dsl/parser/query/method/expr/FieldSpecificMethodExpression.java

@@ -0,0 +1,8 @@
+package org.es.sql.dsl.parser.query.method.expr;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import org.es.sql.dsl.parser.query.method.MethodInvocation;
+
+public interface FieldSpecificMethodExpression extends MethodExpression {
+    SQLExpr defineFieldExpr(MethodInvocation invocation);
+}

+ 14 - 0
src/main/java/org/es/sql/dsl/parser/query/method/expr/MethodExpression.java

@@ -0,0 +1,14 @@
+package org.es.sql.dsl.parser.query.method.expr;
+
+import org.es.sql.dsl.exception.ElasticSql2DslException;
+import org.es.sql.dsl.parser.query.method.MethodInvocation;
+
+import java.util.List;
+
+public interface MethodExpression {
+    List<String> defineMethodNames();
+
+    boolean isMatchMethodInvocation(MethodInvocation invocation);
+
+    void checkMethodInvocation(MethodInvocation invocation) throws ElasticSql2DslException;
+}

+ 9 - 0
src/main/java/org/es/sql/dsl/parser/query/method/expr/ParameterizedMethodExpression.java

@@ -0,0 +1,9 @@
+package org.es.sql.dsl.parser.query.method.expr;
+
+import org.es.sql.dsl.parser.query.method.MethodInvocation;
+
+import java.util.Map;
+
+public interface ParameterizedMethodExpression extends MethodExpression {
+    Map<String, String> generateParameterMap(MethodInvocation methodInvocation);
+}

+ 2 - 9
src/main/java/org/es/sql/dsl/parser/query/method/script/ScriptAtomQueryParser.java

@@ -1,10 +1,8 @@
 package org.es.sql.dsl.parser.query.method.script;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
 import org.elasticsearch.index.query.FilterBuilders;
 import org.es.sql.dsl.bean.AtomFilter;
 import org.es.sql.dsl.exception.ElasticSql2DslException;
@@ -32,7 +30,7 @@ public class ScriptAtomQueryParser extends ParameterizedMethodQueryParser {
     }
 
     @Override
-    protected void checkMethodInvokeArgs(MethodInvocation invocation) throws ElasticSql2DslException {
+    public void checkMethodInvocation(MethodInvocation invocation) throws ElasticSql2DslException {
         if (invocation.getParameterCount() != 1 && invocation.getParameterCount() != 2) {
             throw new ElasticSql2DslException(
                     String.format("[syntax error] There's no %s args method named [%s].",
@@ -50,12 +48,7 @@ public class ScriptAtomQueryParser extends ParameterizedMethodQueryParser {
         String script = invocation.getParameterAsString(0);
 
         if (MapUtils.isNotEmpty(extraParamMap)) {
-            Map<String, Object> scriptParamMap = Maps.transformEntries(extraParamMap, new Maps.EntryTransformer<String, String, Object>() {
-                @Override
-                public Object transformEntry(String key, String value) {
-                    return NumberUtils.isNumber(value) ? NumberUtils.createNumber(value) : value;
-                }
-            });
+            Map<String, Object> scriptParamMap = generateRawTypeParameterMap(invocation);
             return new AtomFilter(FilterBuilders.scriptFilter(script).cache(false).params(scriptParamMap));
         }
         return new AtomFilter(FilterBuilders.scriptFilter(script).cache(false));

+ 2 - 2
src/main/java/org/es/sql/dsl/parser/query/method/term/PrefixAtomQueryParser.java

@@ -27,12 +27,12 @@ public class PrefixAtomQueryParser extends AbstractFieldSpecificMethodQueryParse
     }
 
     @Override
-    protected SQLExpr defineFieldExpr(MethodInvocation invocation) {
+    public SQLExpr defineFieldExpr(MethodInvocation invocation) {
         return invocation.getParameter(0);
     }
 
     @Override
-    protected void checkMethodInvokeArgs(MethodInvocation invocation) {
+    public void checkMethodInvocation(MethodInvocation invocation) {
         if (invocation.getParameterCount() != 2) {
             throw new ElasticSql2DslException(
                     String.format("[syntax error] There's no %s args method named [%s].",

+ 2 - 2
src/main/java/org/es/sql/dsl/parser/query/method/term/RegexpAtomQueryParser.java

@@ -31,7 +31,7 @@ public class RegexpAtomQueryParser extends AbstractFieldSpecificMethodQueryParse
     }
 
     @Override
-    protected SQLExpr defineFieldExpr(MethodInvocation invocation) {
+    public SQLExpr defineFieldExpr(MethodInvocation invocation) {
         return invocation.getParameter(0);
     }
 
@@ -44,7 +44,7 @@ public class RegexpAtomQueryParser extends AbstractFieldSpecificMethodQueryParse
     }
 
     @Override
-    protected void checkMethodInvokeArgs(MethodInvocation invocation) throws ElasticSql2DslException {
+    public void checkMethodInvocation(MethodInvocation invocation) throws ElasticSql2DslException {
         if (invocation.getParameterCount() != 2 && invocation.getParameterCount() != 3) {
             throw new ElasticSql2DslException(
                     String.format("[syntax error] There's no %s args method named [%s].",

+ 2 - 2
src/main/java/org/es/sql/dsl/parser/query/method/term/TermAtomQueryParser.java

@@ -27,12 +27,12 @@ public class TermAtomQueryParser extends AbstractFieldSpecificMethodQueryParser
     }
 
     @Override
-    protected SQLExpr defineFieldExpr(MethodInvocation invocation) {
+    public SQLExpr defineFieldExpr(MethodInvocation invocation) {
         return invocation.getParameter(0);
     }
 
     @Override
-    protected void checkMethodInvokeArgs(MethodInvocation invocation) throws ElasticSql2DslException {
+    public void checkMethodInvocation(MethodInvocation invocation) throws ElasticSql2DslException {
         if (invocation.getParameterCount() != 2 && invocation.getParameterCount() != 3) {
             throw new ElasticSql2DslException(
                     String.format("[syntax error] There's no %s args method named [%s].",

+ 2 - 2
src/main/java/org/es/sql/dsl/parser/query/method/term/TermsAtomQueryParser.java

@@ -28,7 +28,7 @@ public class TermsAtomQueryParser extends AbstractFieldSpecificMethodQueryParser
     }
 
     @Override
-    protected SQLExpr defineFieldExpr(MethodInvocation invocation) {
+    public SQLExpr defineFieldExpr(MethodInvocation invocation) {
         return invocation.getParameter(0);
     }
 
@@ -42,7 +42,7 @@ public class TermsAtomQueryParser extends AbstractFieldSpecificMethodQueryParser
     }
 
     @Override
-    protected void checkMethodInvokeArgs(MethodInvocation invocation) {
+    public void checkMethodInvocation(MethodInvocation invocation) {
         if (invocation.getParameterCount() <= 1) {
             throw new ElasticSql2DslException(
                     String.format("[syntax error] There's no %s args method named [%s].",

+ 56 - 37
src/main/java/org/es/sql/dsl/parser/sql/QueryOrderConditionParser.java

@@ -3,26 +3,25 @@ package org.es.sql.dsl.parser.sql;
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.SQLOrderBy;
 import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
-import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
 import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
 import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
 import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections.CollectionUtils;
+import org.elasticsearch.search.sort.FieldSortBuilder;
+import org.elasticsearch.search.sort.SortBuilder;
+import org.elasticsearch.search.sort.SortBuilders;
+import org.elasticsearch.search.sort.SortOrder;
+import org.es.sql.druid.ElasticSqlSelectQueryBlock;
 import org.es.sql.dsl.bean.ElasticDslContext;
 import org.es.sql.dsl.bean.ElasticSqlQueryField;
 import org.es.sql.dsl.enums.QueryFieldType;
 import org.es.sql.dsl.enums.SortOption;
 import org.es.sql.dsl.exception.ElasticSql2DslException;
-import org.es.sql.dsl.helper.ElasticSqlArgTransferHelper;
 import org.es.sql.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.es.sql.dsl.listener.ParseActionListener;
-import org.elasticsearch.search.sort.FieldSortBuilder;
-import org.elasticsearch.search.sort.SortBuilder;
-import org.elasticsearch.search.sort.SortBuilders;
-import org.elasticsearch.search.sort.SortOrder;
-import org.es.sql.druid.ElasticSqlSelectQueryBlock;
+import org.es.sql.dsl.parser.query.method.MethodInvocation;
 
 import java.util.List;
 
@@ -57,67 +56,87 @@ public class QueryOrderConditionParser implements QueryParser {
                 public FieldSortBuilder buildSort(String queryFieldName) {
                     if (SQLOrderingSpecification.ASC == orderByItem.getType()) {
                         return SortBuilders.fieldSort(queryFieldName).order(SortOrder.ASC);
-                    } else {
+                    }
+                    else {
                         return SortBuilders.fieldSort(queryFieldName).order(SortOrder.DESC);
                     }
                 }
             });
         }
         if (orderByItem.getExpr() instanceof SQLMethodInvokeExpr) {
-            SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) orderByItem.getExpr();
+            MethodInvocation sortMethodInvocation = new MethodInvocation((SQLMethodInvokeExpr) orderByItem.getExpr(), queryAs, sqlArgs);
+
             //nvl method
-            if (ElasticSqlMethodInvokeHelper.isMethodOf(ElasticSqlMethodInvokeHelper.NVL_METHOD, methodInvokeExpr.getMethodName())) {
-                ElasticSqlMethodInvokeHelper.checkNvlMethod(methodInvokeExpr);
-                Object valueArg = ElasticSqlArgTransferHelper.transferSqlArg(methodInvokeExpr.getParameters().get(1), sqlArgs);
-                return parseCondition(methodInvokeExpr.getParameters().get(0), queryAs, new ConditionSortBuilder() {
-                    @Override
-                    public FieldSortBuilder buildSort(String idfName) {
-                        FieldSortBuilder fieldSortBuilder = null;
-
-                        if (SQLOrderingSpecification.ASC == orderByItem.getType()) {
-                            fieldSortBuilder = SortBuilders.fieldSort(idfName).order(SortOrder.ASC).missing(valueArg);
-                        } else {
-                            fieldSortBuilder = SortBuilders.fieldSort(idfName).order(SortOrder.DESC).missing(valueArg);
-                        }
-
-                        if (methodInvokeExpr.getParameters().size() == 3) {
-                            SQLExpr sortModArg = methodInvokeExpr.getParameters().get(2);
-                            String sortModeText = ((SQLCharExpr) sortModArg).getText();
-                            fieldSortBuilder.sortMode(SortOption.get(sortModeText).mode());
-                        }
-
-                        return fieldSortBuilder;
-                    }
-                });
+            if (ElasticSqlMethodInvokeHelper.isMethodOf(ElasticSqlMethodInvokeHelper.NVL_METHOD, sortMethodInvocation.getMethodName())) {
+                return buildNvlSortBuilder(sortMethodInvocation, orderByItem);
+            }
+
+            //script sort
+            if (ElasticSqlMethodInvokeHelper.isMethodOf(ElasticSqlMethodInvokeHelper.SCRIPT_SORT_METHOD, sortMethodInvocation.getMethodName())) {
+                return buildScriptSortBuilder(sortMethodInvocation, orderByItem);
             }
         }
         throw new ElasticSql2DslException("[syntax error] can not support sort type: " + orderByItem.getExpr().getClass());
     }
 
+    private SortBuilder buildScriptSortBuilder(MethodInvocation scriptSortMethodInvocation, SQLSelectOrderByItem orderByItem) {
+        ElasticSqlMethodInvokeHelper.checkScriptSortMethod(scriptSortMethodInvocation);
+
+        String script = scriptSortMethodInvocation.getParameterAsString(0);
+        String type = scriptSortMethodInvocation.getParameterAsString(1);
+
+        if (SQLOrderingSpecification.ASC == orderByItem.getType()) {
+            return SortBuilders.scriptSort(script, type).order(SortOrder.ASC);
+        }
+        return SortBuilders.scriptSort(script, type).order(SortOrder.DESC);
+    }
+
+    private SortBuilder buildNvlSortBuilder(MethodInvocation sortMethodInvocation, SQLSelectOrderByItem orderByItem) {
+        ElasticSqlMethodInvokeHelper.checkNvlMethod(sortMethodInvocation);
+
+        Object valueArg = sortMethodInvocation.getParameterAsObject(1);
+        return parseCondition(sortMethodInvocation.getParameter(0), sortMethodInvocation.getQueryAs(), new ConditionSortBuilder() {
+            @Override
+            public FieldSortBuilder buildSort(String idfName) {
+                FieldSortBuilder fieldSortBuilder = null;
+                if (SQLOrderingSpecification.ASC == orderByItem.getType()) {
+                    fieldSortBuilder = SortBuilders.fieldSort(idfName).order(SortOrder.ASC).missing(valueArg);
+                }
+                else {
+                    fieldSortBuilder = SortBuilders.fieldSort(idfName).order(SortOrder.DESC).missing(valueArg);
+                }
+
+                if (sortMethodInvocation.getParameterCount() == 3) {
+                    String sortModeText = sortMethodInvocation.getParameterAsString(2);
+                    fieldSortBuilder.sortMode(SortOption.get(sortModeText).mode());
+                }
+                return fieldSortBuilder;
+            }
+        });
+    }
+
     private SortBuilder parseCondition(SQLExpr sqlExpr, String queryAs, ConditionSortBuilder sortBuilder) {
         QueryFieldParser queryFieldParser = new QueryFieldParser();
         ElasticSqlQueryField sortField = queryFieldParser.parseConditionQueryField(sqlExpr, queryAs);
 
         SortBuilder rtnSortBuilder = null;
-        if(sortField.getQueryFieldType() == QueryFieldType.RootDocField || sortField.getQueryFieldType() == QueryFieldType.InnerDocField) {
+        if (sortField.getQueryFieldType() == QueryFieldType.RootDocField || sortField.getQueryFieldType() == QueryFieldType.InnerDocField) {
             rtnSortBuilder = sortBuilder.buildSort(sortField.getQueryFieldFullName());
         }
 
-        if(sortField.getQueryFieldType() == QueryFieldType.NestedDocField) {
+        if (sortField.getQueryFieldType() == QueryFieldType.NestedDocField) {
             FieldSortBuilder originalSort = sortBuilder.buildSort(sortField.getQueryFieldFullName());
             originalSort.setNestedPath(sortField.getNestedDocContextPath());
             rtnSortBuilder = originalSort;
         }
 
-        if(rtnSortBuilder == null) {
+        if (rtnSortBuilder == null) {
             throw new ElasticSql2DslException(String.format("[syntax error] sort condition field can not support type[%s]", sortField.getQueryFieldType()));
         }
 
         return rtnSortBuilder;
     }
 
-
-    @FunctionalInterface
     private interface ConditionSortBuilder {
         FieldSortBuilder buildSort(String idfName);
     }