tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hyun...@apache.org
Subject [3/3] git commit: TAJO-1092: Improve the function system to allow other function implementation types.
Date Wed, 15 Oct 2014 17:41:40 GMT
TAJO-1092: Improve the function system to allow other function implementation types.

Closes #178


Project: http://git-wip-us.apache.org/repos/asf/tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/tajo/commit/05ca386c
Tree: http://git-wip-us.apache.org/repos/asf/tajo/tree/05ca386c
Diff: http://git-wip-us.apache.org/repos/asf/tajo/diff/05ca386c

Branch: refs/heads/block_iteration
Commit: 05ca386c45adbb551ebc3af22592ea0dd38b1ea4
Parents: 5eb7ee1
Author: Hyunsik Choi <hyunsik@apache.org>
Authored: Wed Oct 15 09:54:14 2014 -0700
Committer: Hyunsik Choi <hyunsik@apache.org>
Committed: Wed Oct 15 10:40:59 2014 -0700

----------------------------------------------------------------------
 CHANGES                                         |  22 ++
 .../main/java/org/apache/tajo/DataTypeUtil.java | 181 ++++++++++++++
 .../org/apache/tajo/catalog/CatalogUtil.java    | 232 ++++++++++--------
 .../org/apache/tajo/catalog/FunctionDesc.java   | 167 ++++++-------
 .../exception/NoSuchFunctionException.java      |   6 +-
 .../apache/tajo/catalog/function/Function.java  |  65 -----
 .../tajo/catalog/json/CatalogGsonHelper.java    |   2 +-
 .../tajo/catalog/json/FunctionAdapter.java      |   2 +-
 .../tajo/function/ClassBaseInvocationDesc.java  |  71 ++++++
 .../java/org/apache/tajo/function/Function.java |  66 +++++
 .../tajo/function/FunctionCollection.java       |  29 +++
 .../tajo/function/FunctionInvocation.java       | 154 ++++++++++++
 .../apache/tajo/function/FunctionSignature.java | 141 +++++++++++
 .../tajo/function/FunctionSupplement.java       | 113 +++++++++
 .../org/apache/tajo/function/FunctionUtil.java  |  56 +++++
 .../apache/tajo/function/ScalarFunction.java    |  44 ++++
 .../function/StaticMethodInvocationDesc.java    | 135 +++++++++++
 .../src/main/proto/CatalogProtos.proto          |  75 ++++--
 .../apache/tajo/catalog/TestCatalogUtil.java    |  14 +-
 .../apache/tajo/catalog/TestFunctionDesc.java   |   6 +-
 .../org/apache/tajo/catalog/CatalogServer.java  |  96 ++++++--
 .../org/apache/tajo/catalog/TestCatalog.java    |  18 +-
 .../apache/tajo/cli/DescFunctionCommand.java    |  38 +--
 .../apache/tajo/json/ClassNameSerializer.java   |   3 +-
 .../java/org/apache/tajo/util/ClassUtil.java    | 201 ++++++++++++++++
 .../main/java/org/apache/tajo/util/TUtil.java   |   4 +-
 .../tajo/engine/codegen/CaseWhenEmitter.java    |  27 +--
 .../tajo/engine/codegen/EvalCodeGenerator.java  |  41 +---
 .../codegen/LegacyFunctionBindingEmitter.java   |  75 ++++++
 .../codegen/ScalarFunctionBindingEmitter.java   | 164 +++++++++++++
 .../engine/codegen/TajoGeneratorAdapter.java    |  60 +++++
 .../tajo/engine/codegen/VariablesBuilder.java   |   2 +-
 .../apache/tajo/engine/eval/AlgebraicUtil.java  |   2 +-
 .../org/apache/tajo/engine/eval/BinaryEval.java |   2 +-
 .../apache/tajo/engine/eval/FunctionEval.java   |   4 +-
 .../tajo/engine/eval/WindowFunctionEval.java    |   2 +-
 .../tajo/engine/function/AggFunction.java       |   3 +-
 .../tajo/engine/function/FunctionLoader.java    | 239 +++++++++++++++++++
 .../tajo/engine/function/GeneralFunction.java   |   3 +-
 .../tajo/engine/function/builtin/AvgInt.java    |   1 -
 .../engine/function/math/MathFunctions.java     |  46 ++++
 .../apache/tajo/engine/function/math/Pow.java   |  26 +-
 .../apache/tajo/engine/json/CoreGsonHelper.java |   2 +-
 .../optimizer/eval/rules/ConstantFolding.java   |   2 +-
 .../engine/plan/EvalTreeProtoDeserializer.java  |   4 +-
 .../tajo/engine/planner/ExprAnnotator.java      | 113 +--------
 .../tajo/engine/planner/TypeDeterminant.java    |   6 +-
 .../planner/logical/TruncateTableNode.java      |   2 +-
 .../join/GreedyHeuristicJoinOrderAlgorithm.java |   4 +-
 .../engine/planner/logical/join/JoinEdge.java   |   2 +-
 .../engine/planner/logical/join/JoinGraph.java  |   5 +-
 .../apache/tajo/engine/utils/DataTypeUtil.java  | 121 ----------
 .../java/org/apache/tajo/master/TajoMaster.java |  85 +------
 .../tajo/master/TajoMasterClientService.java    |   3 +-
 .../java/org/apache/tajo/util/ClassUtil.java    | 156 ------------
 .../main/java/org/apache/tajo/util/JSPUtil.java |   2 +-
 .../main/resources/webapps/admin/functions.jsp  |   2 +-
 .../apache/tajo/LocalTajoTestingUtility.java    |  21 ++
 .../org/apache/tajo/client/TestTajoClient.java  |   2 +-
 .../apache/tajo/engine/eval/ExprTestBase.java   |   3 +-
 .../tajo/engine/eval/TestEvalTreeUtil.java      |   3 +-
 .../engine/function/TestFunctionLoader.java     |  46 ++++
 .../tajo/engine/function/TestMathFunctions.java |   2 +
 .../tajo/engine/planner/TestExprAnnotator.java  |  12 +-
 .../engine/planner/TestLogicalOptimizer.java    |   3 +-
 .../tajo/engine/planner/TestLogicalPlanner.java |   3 +-
 .../planner/global/TestBroadcastJoinPlan.java   |   3 +-
 .../planner/physical/TestPhysicalPlanner.java   |   3 +-
 .../apache/tajo/master/TestGlobalPlanner.java   |   3 +-
 .../testFindScalarFunctions.result              |   2 +
 70 files changed, 2353 insertions(+), 900 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index ab4b5c0..42d4f90 100644
--- a/CHANGES
+++ b/CHANGES
@@ -19,6 +19,28 @@ Block Iteration - branch
 
     TAJO-907: Implement off-heap tuple block and zero-copy tuple. 
     (hyunsik)
+    
+    TAJO-1092: Improve the function system to allow other function 
+    implementation types. (hyunsik)
+
+
+Release 0.9.1 - unreleased
+
+  NEW FEATURES
+
+
+  IMPROVEMENT
+
+    TAJO-1092: Improve the function system to allow other function 
+    implementation types. (hyunsik)
+
+
+  BUG FIXES
+
+
+  TASKS
+
+
 
 Release 0.9.0 - unreleased
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java
new file mode 100644
index 0000000..c12aa29
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java
@@ -0,0 +1,181 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo;
+
+import com.google.common.collect.Maps;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.util.TUtil;
+
+import java.util.Map;
+
+import static org.apache.tajo.common.TajoDataTypes.Type;
+import static org.apache.tajo.common.TajoDataTypes.Type.*;
+
+public class DataTypeUtil {
+
+  public static final Map<Type, Map<Type, Boolean>> FUNCTION_ACCEPTABLE_PARAM_MAP = Maps.newHashMap();
+
+  private static void putAcceptableType(Type given, Type define) {
+    TUtil.putToNestedMap(FUNCTION_ACCEPTABLE_PARAM_MAP, given, define, true);
+  }
+
+  static {
+    putAcceptableType(BOOLEAN, BOOLEAN);
+
+    putAcceptableType(INT1, INT1);
+    putAcceptableType(INT1, INT2);
+    putAcceptableType(INT1, INT4);
+    putAcceptableType(INT1, INT8);
+    putAcceptableType(INT1, FLOAT4);
+    putAcceptableType(INT1, FLOAT8);
+
+    putAcceptableType(INT2, INT2);
+    putAcceptableType(INT2, INT4);
+    putAcceptableType(INT2, INT8);
+    putAcceptableType(INT2, FLOAT4);
+    putAcceptableType(INT2, FLOAT8);
+
+    putAcceptableType(INT4, INT4);
+    putAcceptableType(INT4, INT8);
+    putAcceptableType(INT4, FLOAT4);
+    putAcceptableType(INT4, FLOAT8);
+
+    putAcceptableType(INT8, INT8);
+    putAcceptableType(INT8, FLOAT4);
+    putAcceptableType(INT8, FLOAT8);
+
+    putAcceptableType(FLOAT4, FLOAT4);
+    putAcceptableType(FLOAT4, FLOAT8);
+
+    putAcceptableType(FLOAT8, FLOAT8);
+
+    putAcceptableType(TIMESTAMP, TIMESTAMP);
+    putAcceptableType(TIME, TIME);
+    putAcceptableType(DATE, DATE);
+
+    putAcceptableType(TEXT, TEXT);
+
+    putAcceptableType(INET4, INET4);
+  }
+
+  public static boolean isUpperCastable(Type define, Type given) {
+    if (given == define) {
+      return true;
+    }
+
+    return TUtil.containsInNestedMap(FUNCTION_ACCEPTABLE_PARAM_MAP, given, define);
+  }
+
+  /**
+   * This is verified by ExprsVerifier.checkArithmeticOperand().
+   */
+  public static TajoDataTypes.DataType determineType(TajoDataTypes.DataType left, TajoDataTypes.DataType right) {
+    switch (left.getType()) {
+
+    case INT1:
+    case INT2:
+    case INT4: {
+      switch(right.getType()) {
+      case INT1:
+      case INT2:
+      case INT4: return CatalogUtil.newSimpleDataType(Type.INT4);
+      case INT8: return CatalogUtil.newSimpleDataType(Type.INT8);
+      case FLOAT4: return CatalogUtil.newSimpleDataType(Type.FLOAT4);
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      case DATE: return CatalogUtil.newSimpleDataType(Type.DATE);
+      case INTERVAL: return CatalogUtil.newSimpleDataType(Type.INTERVAL);
+      }
+    }
+
+    case INT8: {
+      switch(right.getType()) {
+      case INT1:
+      case INT2:
+      case INT4:
+      case INT8: return CatalogUtil.newSimpleDataType(Type.INT8);
+      case FLOAT4: return CatalogUtil.newSimpleDataType(Type.FLOAT4);
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      case DATE: return CatalogUtil.newSimpleDataType(Type.DATE);
+      case INTERVAL: return CatalogUtil.newSimpleDataType(Type.INTERVAL);
+      }
+    }
+
+    case FLOAT4: {
+      switch(right.getType()) {
+      case INT1:
+      case INT2:
+      case INT4: return CatalogUtil.newSimpleDataType(Type.FLOAT4);
+      case INT8: return CatalogUtil.newSimpleDataType(Type.FLOAT4);
+      case FLOAT4: return CatalogUtil.newSimpleDataType(Type.FLOAT4);
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      case INTERVAL: return CatalogUtil.newSimpleDataType(Type.INTERVAL);
+      }
+    }
+
+    case FLOAT8: {
+      switch(right.getType()) {
+      case INT1:
+      case INT2:
+      case INT4:
+      case INT8:
+      case FLOAT4:
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      case INTERVAL: return CatalogUtil.newSimpleDataType(Type.INTERVAL);
+      }
+    }
+
+    case DATE: {
+      switch(right.getType()) {
+      case INT2:
+      case INT4:
+      case INT8: return CatalogUtil.newSimpleDataType(Type.DATE);
+      case INTERVAL:
+      case TIME: return CatalogUtil.newSimpleDataType(Type.TIMESTAMP);
+      case DATE: return CatalogUtil.newSimpleDataType(Type.INT4);
+      }
+    }
+
+    case TIME: {
+      switch(right.getType()) {
+      case INTERVAL: return CatalogUtil.newSimpleDataType(Type.TIME);
+      case TIME: return CatalogUtil.newSimpleDataType(Type.INTERVAL);
+      case DATE: return CatalogUtil.newSimpleDataType(Type.INT4);
+      }
+    }
+
+    case TIMESTAMP: {
+      switch (right.getType()) {
+      case INTERVAL: return CatalogUtil.newSimpleDataType(Type.TIMESTAMP);
+      case TIMESTAMP: return CatalogUtil.newSimpleDataType(Type.INTERVAL);
+      }
+    }
+
+    case INTERVAL: {
+      switch (right.getType()) {
+      case INTERVAL:
+      case FLOAT4:
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.INTERVAL);
+      }
+    }
+
+    default: return left;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
index 96dac62..259415d 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
@@ -18,7 +18,9 @@
 
 package org.apache.tajo.catalog;
 
+import com.google.common.collect.Maps;
 import org.apache.hadoop.fs.Path;
+import org.apache.tajo.DataTypeUtil;
 import org.apache.tajo.TajoConstants;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
@@ -30,15 +32,13 @@ import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.exception.InvalidOperationException;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.StringUtils;
+import org.apache.tajo.util.TUtil;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import static org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import static org.apache.tajo.common.TajoDataTypes.Type;
@@ -257,25 +257,6 @@ public class CatalogUtil {
     return sb.toString();
   }
 
-  public static String getCanonicalSignature(String functionName, Collection<DataType> paramTypes) {
-    DataType [] types = paramTypes.toArray(new DataType[paramTypes.size()]);
-    return getCanonicalSignature(functionName, types);
-  }
-  public static String getCanonicalSignature(String signature, DataType... paramTypes) {
-    StringBuilder sb = new StringBuilder(signature);
-    sb.append("(");
-    int i = 0;
-    for (DataType type : paramTypes) {
-      sb.append(type.getType().name().toLowerCase());
-      if(i < paramTypes.length - 1) {
-        sb.append(",");
-      }
-      i++;
-    }
-    sb.append(")");
-    return sb.toString();
-  }
-
   public static StoreType getStoreType(final String typeStr) {
     return StoreType.valueOf(typeStr.toUpperCase());
   }
@@ -443,9 +424,14 @@ public class CatalogUtil {
       for (int i = 0,j = (definedSize - 1); j < givenParamSize; i++, j++) {
         varLengthTypesOfGivenParams[i] = givenTypes.get(j).getType();
 
-        // chooses one basis type for checking the variable part
-        if (givenTypes.get(j).getType() != Type.NULL_TYPE) {
+        // chooses the first non-null type as the basis type.
+        if (givenTypes.get(j).getType() != Type.NULL_TYPE && basisTypeOfVarLengthType == null) {
           basisTypeOfVarLengthType = givenTypes.get(j).getType();
+        } else if (basisTypeOfVarLengthType != null) {
+          // If there are more than one type, we choose the most widen type as the basis type.
+          basisTypeOfVarLengthType =
+              getWidestType(CatalogUtil.newSimpleDataTypeArray(basisTypeOfVarLengthType, givenTypes.get(j).getType()))
+              .getType();
         }
       }
 
@@ -463,7 +449,7 @@ public class CatalogUtil {
 
       // If all parameters are equivalent to the basis type
       for (TajoDataTypes.Type type : varLengthTypesOfGivenParams) {
-        if (type != Type.NULL_TYPE && !isCompatibleType(basisTypeOfVarLengthType, type)) {
+        if (type != Type.NULL_TYPE && !isCompatibleType(primitiveTypeOfLastDefinedParam, type)) {
           return false;
         }
       }
@@ -578,79 +564,67 @@ public class CatalogUtil {
   }
 
   public static boolean isCompatibleType(final Type definedType, final Type givenType) {
-    boolean flag = false;
-    if (givenType == Type.NULL_TYPE) {
-      flag = true;
-    } else if (definedType == Type.ANY) {
-      flag = true;
-    } else if (givenType.getNumber() > definedType.getNumber()) {
-      // NO POINT IN GOING FORWARD BECAUSE THE DATA TYPE CANNOT BE UPPER CASTED
-      flag = false;
-    } else {
-      //argType.getNumber() < exitingType.getNumber()
-      int exitingTypeNumber = definedType.getNumber();
-      int argTypeNumber = givenType.getNumber();
-
-      if (Type.INT1.getNumber() <= exitingTypeNumber && exitingTypeNumber <= Type.INT8.getNumber()) {
-        // INT1 ==> INT2 ==> INT4 ==> INT8
-        if (Type.INT1.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.UINT1.getNumber() <= exitingTypeNumber && exitingTypeNumber <= Type.UINT8.getNumber()) {
-        // UINT1 ==> UINT2 ==> UINT4 ==> UINT8
-        if (Type.UINT1.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.FLOAT4.getNumber() <= exitingTypeNumber && exitingTypeNumber <= Type.NUMERIC.getNumber()) {
-        // FLOAT4 ==> FLOAT8 ==> NUMERIC ==> DECIMAL
-        if (Type.FLOAT4.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.CHAR.getNumber() <= exitingTypeNumber && exitingTypeNumber <= Type.TEXT.getNumber()) {
-        // CHAR ==> NCHAR ==> VARCHAR ==> NVARCHAR ==> TEXT
-        if (Type.CHAR.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.BIT.getNumber() <= exitingTypeNumber && exitingTypeNumber <= Type.VARBINARY.getNumber()) {
-        // BIT ==> VARBIT ==> BINARY ==> VARBINARY
-        if (Type.BIT.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.INT1_ARRAY.getNumber() <= exitingTypeNumber
-          && exitingTypeNumber <= Type.INT8_ARRAY.getNumber()) {
-        // INT1_ARRAY ==> INT2_ARRAY ==> INT4_ARRAY ==> INT8_ARRAY
-        if (Type.INT1_ARRAY.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.UINT1_ARRAY.getNumber() <= exitingTypeNumber
-          && exitingTypeNumber <= Type.UINT8_ARRAY.getNumber()) {
-        // UINT1_ARRAY ==> UINT2_ARRAY ==> UINT4_ARRAY ==> UINT8_ARRAY
-        if (Type.UINT1_ARRAY.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.FLOAT4_ARRAY.getNumber() <= exitingTypeNumber
-          && exitingTypeNumber <= Type.FLOAT8_ARRAY.getNumber()) {
-        // FLOAT4_ARRAY ==> FLOAT8_ARRAY ==> NUMERIC_ARRAY ==> DECIMAL_ARRAY
-        if (Type.FLOAT4_ARRAY.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
-        }
-      } else if (Type.CHAR_ARRAY.getNumber() <= exitingTypeNumber
-          && exitingTypeNumber <= Type.TEXT_ARRAY.getNumber()) {
-        // CHAR_ARRAY ==> NCHAR_ARRAY ==> VARCHAR_ARRAY ==> NVARCHAR_ARRAY ==> TEXT_ARRAY
-        if (Type.TEXT_ARRAY.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) {
-          flag = true;
+
+    // No point in going forward because the data type cannot be upper casted.
+    if (givenType.getNumber() > definedType.getNumber()) {
+      return false;
+    }
+
+    boolean flag = definedType == givenType; // if both are the same to each other
+    flag |= givenType == Type.NULL_TYPE;     // NULL value is acceptable in any parameter type
+    flag |= definedType == Type.ANY;         // ANY can accept any given value.
+
+    if (flag) {
+      return true;
+    }
+
+    // Checking if a given type can be casted to a corresponding defined type.
+
+    Type actualType = definedType;
+    // if definedType is variable length or array, get a primitive type.
+    if (CatalogUtil.isArrayType(definedType)) {
+      actualType = CatalogUtil.getPrimitiveTypeOf(definedType);
+    }
+
+    flag |= DataTypeUtil.isUpperCastable(actualType, givenType);
+
+    return flag;
+  }
+
+  /**
+   * It picks out the widest range type among given <code>types</code>.
+   *
+   * Example:
+   * <ul>
+   *   <li>int, int8  -> int8 </li>
+   *   <li>int4, int8, float4  -> float4 </li>
+   *   <li>float4, float8 -> float8</li>
+   *   <li>float4, text -> exception!</li>
+   * </ul>
+   *
+   * @param types A list of DataTypes
+   * @return The widest DataType
+   */
+  public static DataType getWidestType(DataType...types) {
+    DataType widest = types[0];
+    for (int i = 1; i < types.length; i++) {
+
+      if (widest.getType() == Type.NULL_TYPE) { // if null, skip this type
+        widest = types[i];
+        continue;
+      }
+
+      if (types[i].getType() != Type.NULL_TYPE) {
+        Type candidate = TUtil.getFromNestedMap(OPERATION_CASTING_MAP, widest.getType(), types[i].getType());
+        if (candidate == null) {
+          throw new InvalidOperationException("No matched operation for those types: " + TUtil.arrayToString
+              (types));
         }
-      } else if (givenType == Type.BOOLEAN && (definedType == Type.BOOLEAN || definedType == Type.BOOLEAN_ARRAY)) {
-        flag = true;
-      } else if (givenType == Type.DATE && (definedType == Type.DATE || definedType == Type.DATE_ARRAY)) {
-        flag = true;
-      } else if (givenType == Type.TIME && (definedType == Type.TIME || definedType == Type.TIME_ARRAY)) {
-        flag = true;
-      } else if (givenType == Type.TIMESTAMP && (definedType == Type.TIMESTAMP || definedType == Type.TIMESTAMP_ARRAY)) {
-        flag = true;
+        widest = newSimpleDataType(candidate);
       }
     }
-    return flag;
+
+    return widest;
   }
 
   public static CatalogProtos.TableIdentifierProto buildTableIdentifier(String databaseName, String tableName) {
@@ -747,4 +721,70 @@ public class CatalogUtil {
     alterTableDesc.setAlterTableType(alterTableType);
     return alterTableDesc;
   }
+
+  /* It is the relationship graph of type conversions. */
+  public static final Map<Type, Map<Type, Type>> OPERATION_CASTING_MAP = Maps.newHashMap();
+
+  static {
+    // Type Conversion Map
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.BOOLEAN, Type.BOOLEAN, Type.BOOLEAN);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT1, Type.INT1, Type.INT1);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT1, Type.INT2, Type.INT2);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT1, Type.INT4, Type.INT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT1, Type.INT8, Type.INT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT1, Type.FLOAT4, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT1, Type.FLOAT8, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT1, Type.TEXT, Type.TEXT);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT2, Type.INT1, Type.INT2);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT2, Type.INT2, Type.INT2);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT2, Type.INT4, Type.INT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT2, Type.INT8, Type.INT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT2, Type.FLOAT4, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT2, Type.FLOAT8, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT2, Type.TEXT, Type.TEXT);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT4, Type.INT1, Type.INT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT4, Type.INT2, Type.INT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT4, Type.INT4, Type.INT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT4, Type.INT8, Type.INT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT4, Type.FLOAT4, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT4, Type.FLOAT8, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT4, Type.TEXT, Type.TEXT);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT8, Type.INT1, Type.INT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT8, Type.INT2, Type.INT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT8, Type.INT4, Type.INT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT8, Type.INT8, Type.INT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT8, Type.FLOAT4, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT8, Type.FLOAT8, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INT8, Type.TEXT, Type.TEXT);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT4, Type.INT1, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT4, Type.INT2, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT4, Type.INT4, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT4, Type.INT8, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT4, Type.FLOAT4, Type.FLOAT4);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT4, Type.FLOAT8, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT4, Type.TEXT, Type.TEXT);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.INT1, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.INT2, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.INT4, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.INT8, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.FLOAT4, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.FLOAT8, Type.FLOAT8);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.FLOAT8, Type.TEXT, Type.TEXT);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.TIMESTAMP, Type.TIMESTAMP);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TIMESTAMP, Type.TIMESTAMP, Type.TIMESTAMP);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TIMESTAMP, Type.TEXT, Type.TEXT);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TEXT, Type.TEXT, Type.TEXT);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.TIME, Type.TIME, Type.TIME);
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.DATE, Type.DATE, Type.DATE);
+
+    TUtil.putToNestedMap(OPERATION_CASTING_MAP, Type.INET4, Type.INET4, Type.INET4);
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
index 3d9bc99..23d39f2 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
@@ -20,8 +20,9 @@ package org.apache.tajo.catalog;
 
 import com.google.common.base.Objects;
 import com.google.gson.annotations.Expose;
+import org.apache.tajo.annotation.NotNull;
+import org.apache.tajo.function.*;
 import org.apache.tajo.json.GsonObject;
-import org.apache.tajo.catalog.function.Function;
 import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
@@ -30,55 +31,60 @@ import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.exception.InternalException;
 
 import java.lang.reflect.Constructor;
-import java.util.Arrays;
-import java.util.List;
 
-public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable, GsonObject {
+/**
+ * FunctionDesc specifies the description of a function used in Tajo. It consists of three parts:
+ * function definition, invocation description (how to invoke this function), and supplement.
+ *
+ */
+public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable, GsonObject, Comparable<FunctionDesc> {
   private FunctionDescProto.Builder builder = FunctionDescProto.newBuilder();
-  
-  @Expose private String signature;
-  @Expose private Class<? extends Function> funcClass;
-  @Expose private FunctionType funcType;
-  @Expose private DataType returnType;
-  @Expose private DataType [] params;
-  @Expose private String description;
-  @Expose private String detail;
-  @Expose private String example;
+
+  @Expose private FunctionSignature signature;
+  @Expose private FunctionInvocation invocation;
+  @Expose private FunctionSupplement supplement;
 
   public FunctionDesc() {
   }
 
   public FunctionDesc(String signature, Class<? extends Function> clazz,
-      FunctionType funcType, DataType retType,
-      DataType [] params) {
-    this.signature = signature.toLowerCase();
-    this.funcClass = clazz;
-    this.funcType = funcType;
-    this.returnType = retType;
-    this.params = params;
+      FunctionType funcType, DataType retType, @NotNull DataType [] params) {
+    this.signature = new FunctionSignature(funcType, signature.toLowerCase(), retType, params);
+    this.invocation = new FunctionInvocation();
+    this.invocation.setLegacy(new ClassBaseInvocationDesc<Function>(clazz));
+    this.supplement = new FunctionSupplement();
   }
 
   public FunctionDesc(FunctionDescProto proto) throws ClassNotFoundException {
-    this(proto.getSignature(), proto.getClassName(), proto.getType(),
-        proto.getReturnType(),
-        proto.getParameterTypesList().toArray(new DataType[proto.getParameterTypesCount()]));
-    if (proto.hasDescription()) {
-      this.description = proto.getDescription();
-    }
-    if (proto.hasDetail()) {
-      this.detail = proto.getDetail();
-    }
-    if (proto.hasExample()) {
-      this.example = proto.getExample();
-    }
+    this.signature = new FunctionSignature(proto.getSignature());
+    this.invocation = new FunctionInvocation(proto.getInvocation());
+    this.supplement = new FunctionSupplement(proto.getSupplement());
   }
 
   public FunctionDesc(String signature, String className, FunctionType type,
                       DataType retType,
-                      DataType... argTypes) throws ClassNotFoundException {
+                      @NotNull DataType... argTypes) throws ClassNotFoundException {
     this(signature, (Class<? extends Function>) Class.forName(className), type, retType, argTypes);
   }
 
+  public FunctionDesc(FunctionSignature signature, FunctionInvocation invocation, FunctionSupplement supplement) {
+    this.signature = signature;
+    this.invocation = invocation;
+    this.supplement = supplement;
+  }
+
+  public FunctionSignature getSignature() {
+    return signature;
+  }
+
+  public FunctionInvocation getInvocation() {
+    return invocation;
+  }
+
+  public FunctionSupplement getSupplement() {
+    return supplement;
+  }
+
   /**
    * 
    * @return Function Instance
@@ -93,54 +99,66 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable,
     }
   }
 
-  public String getSignature() {
-    return this.signature;
-  }
+  ////////////////////////////////////////
+  // Function Signature
+  ////////////////////////////////////////
 
-  @SuppressWarnings("unchecked")
-  public Class<? extends Function> getFuncClass() {
-    return this.funcClass;
+  public FunctionType getFuncType() {
+    return signature.getFunctionType();
   }
 
-  public FunctionType getFuncType() {
-    return this.funcType;
+  public String getFunctionName() {
+    return signature.getName();
   }
 
   public DataType [] getParamTypes() {
-    return this.params;
+    return signature.getParamTypes();
   }
 
   public DataType getReturnType() {
-    return this.returnType;
+    return signature.getReturnType();
+  }
+
+  ////////////////////////////////////////
+  // Invocation
+  ////////////////////////////////////////
+
+  @SuppressWarnings("unchecked")
+  public Class<? extends Function> getFuncClass() {
+    return invocation.getLegacy().getFunctionClass();
   }
 
+  ////////////////////////////////////////
+  // Supplement
+  ////////////////////////////////////////
+
   public String getDescription() {
-    return description;
+    return supplement.getShortDescription();
   }
 
   public String getDetail() {
-    return detail;
+    return supplement.getDetail();
   }
 
   public String getExample() {
-    return example;
+    return supplement.getExample();
   }
 
   public void setDescription(String description) {
-    this.description = description;
+    supplement.setShortDescription(description);
   }
 
   public void setDetail(String detail) {
-    this.detail = detail;
+    supplement.setDetail(detail);
   }
 
   public void setExample(String example) {
-    this.example = example;
+    supplement.setExample(example);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hashCode(signature, Objects.hashCode(params));
+    return Objects.hashCode(signature);
   }
   
   @Override
@@ -157,14 +175,10 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable,
   public Object clone() throws CloneNotSupportedException{
     FunctionDesc desc  = (FunctionDesc)super.clone();
     
-    desc.signature = this.signature;
-    desc.params = params.clone();
-    desc.description = this.description;
-    desc.example = this.example;
-    desc.detail = this.detail;
-    desc.returnType = this.returnType;
-    desc.funcClass = this.funcClass;
-    
+    desc.signature = signature.clone();
+    desc.supplement = supplement.clone();
+    desc.invocation = this.invocation;
+
     return desc;
   }
 
@@ -175,22 +189,9 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable,
     } else {
       builder.clear();
     }
-    builder.setSignature(this.signature);
-    builder.setClassName(this.funcClass.getName());
-    builder.setType(this.funcType);
-    builder.setReturnType(this.returnType);
-    if(this.description != null) {
-      builder.setDescription(this.description);
-    }
-    if (this.detail != null) {
-      builder.setDetail(this.detail);
-    }
-    if (this.example != null) {
-      builder.setExample(this.example);
-    }
-    if (this.params != null) { // repeated field
-      builder.addAllParameterTypes(Arrays.asList(params));
-    }
+    builder.setSignature(signature.getProto());
+    builder.setSupplement(supplement.getProto());
+    builder.setInvocation(invocation.getProto());
     return builder.build();
   }
   
@@ -204,21 +205,11 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable,
   }
 
   public String getHelpSignature() {
-    return returnType.getType() + " " + CatalogUtil.getCanonicalSignature(signature, getParamTypes());
+    return signature.toString();
   }
 
-  public static String dataTypesToStr(List<DataType> parameterTypesList) {
-    StringBuilder result = new StringBuilder();
-    for (int i = 0; i < parameterTypesList.size(); i++) {
-      DataType eachType = parameterTypesList.get(i);
-
-      if (i > 0) {
-        result.append(",");
-      }
-      result.append(eachType.getType().toString());
-
-    }
-
-    return result.toString();
+  @Override
+  public int compareTo(FunctionDesc o) {
+    return signature.compareTo(o.getSignature());
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
index d109470..e91e41d 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
@@ -18,8 +18,8 @@
 
 package org.apache.tajo.catalog.exception;
 
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.function.FunctionUtil;
 
 import java.util.Collection;
 
@@ -31,10 +31,10 @@ public class NoSuchFunctionException extends RuntimeException {
   }
 
   public NoSuchFunctionException(String funcName, TajoDataTypes.DataType [] parameters) {
-    super("function " + CatalogUtil.getCanonicalSignature(funcName, parameters) + " does not exist");
+    super("function " + FunctionUtil.buildSimpleFunctionSignature(funcName, parameters) + " does not exist");
   }
 
 	public NoSuchFunctionException(String funcName, Collection<TajoDataTypes.DataType> parameters) {
-		super("function " + CatalogUtil.getCanonicalSignature(funcName, parameters) + " does not exist");
+		super("function " + FunctionUtil.buildSimpleFunctionSignature(funcName, parameters) + " does not exist");
 	}
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java
deleted file mode 100644
index 562f064..0000000
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/function/Function.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.catalog.function;
-
-import com.google.common.base.Objects;
-import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.json.GsonObject;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.json.CatalogGsonHelper;
-import org.apache.tajo.datum.Datum;
-import org.apache.tajo.util.TUtil;
-
-public abstract class Function<T extends Datum> implements Cloneable, GsonObject {
-  @Expose protected Column[] definedParams;
-  public final static Column [] NoArgs = new Column [] {};
-
-  public Function(Column[] definedArgs) {
-    this.definedParams = definedArgs;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (obj instanceof Function) {
-      Function other = (Function) obj;
-      return TUtil.checkEquals(definedParams, other.definedParams);
-    } else {
-      return false;
-    }
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(definedParams);
-  }
-
-  public Object clone() throws CloneNotSupportedException {
-    Function func = (Function) super.clone();
-    func.definedParams = definedParams != null ? definedParams.clone() : null;
-    return func;
-  }
-
-  @Override
-  public String toJson() {
-    return CatalogGsonHelper.toJson(this, Function.class);
-  }
-
-  public abstract CatalogProtos.FunctionType getFunctionType();
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
index 94bfdbe..2ecbe98 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
@@ -22,7 +22,7 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.catalog.TableMeta;
-import org.apache.tajo.catalog.function.Function;
+import org.apache.tajo.function.Function;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.json.*;

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
index ed5ff49..46ddd18 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/FunctionAdapter.java
@@ -19,7 +19,7 @@
 package org.apache.tajo.catalog.json;
 
 import com.google.gson.*;
-import org.apache.tajo.catalog.function.Function;
+import org.apache.tajo.function.Function;
 import org.apache.tajo.json.GsonSerDerAdapter;
 
 import java.lang.reflect.Type;

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ClassBaseInvocationDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ClassBaseInvocationDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ClassBaseInvocationDesc.java
new file mode 100644
index 0000000..dccf789
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ClassBaseInvocationDesc.java
@@ -0,0 +1,71 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.common.ProtoObject;
+
+import static org.apache.tajo.catalog.proto.CatalogProtos.ClassBaseInvocationDescProto;
+
+public class ClassBaseInvocationDesc<T> implements ProtoObject<ClassBaseInvocationDescProto> {
+  @Expose
+  private Class<? extends T> functionClass;
+
+  public ClassBaseInvocationDesc(Class<? extends T> functionClass) {
+    this.functionClass = functionClass;
+  }
+
+  public ClassBaseInvocationDesc(ClassBaseInvocationDescProto proto) {
+    try {
+      this.functionClass = (Class<? extends T>) Class.forName(proto.getClassName());
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public Class<? extends T> getFunctionClass() {
+    return functionClass;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ClassBaseInvocationDesc) {
+      ClassBaseInvocationDesc other = (ClassBaseInvocationDesc) obj;
+      return functionClass.equals(other.functionClass);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return functionClass.getCanonicalName().hashCode();
+  }
+
+  public String toString() {
+    return functionClass.getCanonicalName();
+  }
+
+  @Override
+  public ClassBaseInvocationDescProto getProto() {
+    ClassBaseInvocationDescProto.Builder builder = ClassBaseInvocationDescProto.newBuilder();
+    builder.setClassName(functionClass.getName());
+    return builder.build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/Function.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/Function.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/Function.java
new file mode 100644
index 0000000..6a538b8
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/Function.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.util.TUtil;
+
+@Deprecated
+public abstract class Function<T extends Datum> implements Cloneable, GsonObject {
+  @Expose protected Column[] definedParams;
+  public final static Column [] NoArgs = new Column [] {};
+
+  public Function(Column[] definedArgs) {
+    this.definedParams = definedArgs;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof Function) {
+      Function other = (Function) obj;
+      return TUtil.checkEquals(definedParams, other.definedParams);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(definedParams);
+  }
+
+  public Object clone() throws CloneNotSupportedException {
+    Function func = (Function) super.clone();
+    func.definedParams = definedParams != null ? definedParams.clone() : null;
+    return func;
+  }
+
+  @Override
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, Function.class);
+  }
+
+  public abstract CatalogProtos.FunctionType getFunctionType();
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionCollection.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionCollection.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionCollection.java
new file mode 100644
index 0000000..6d1f772
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionCollection.java
@@ -0,0 +1,29 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface FunctionCollection {
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionInvocation.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionInvocation.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionInvocation.java
new file mode 100644
index 0000000..653bdb6
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionInvocation.java
@@ -0,0 +1,154 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.common.ProtoObject;
+
+import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionInvocationProto;
+
+public class FunctionInvocation implements ProtoObject<FunctionInvocationProto> {
+  @Expose
+  ClassBaseInvocationDesc<Function> legacy;
+  @Expose
+  StaticMethodInvocationDesc scalar;
+  @Expose
+  ClassBaseInvocationDesc<?> aggregation;
+  @Expose
+  StaticMethodInvocationDesc scalarJIT;
+  @Expose
+  ClassBaseInvocationDesc<?> aggregationJIT;
+
+  public FunctionInvocation() {
+  }
+
+  public FunctionInvocation(FunctionInvocationProto proto) {
+    if (proto.hasLegacy()) {
+      this.legacy = new ClassBaseInvocationDesc(proto.getLegacy());
+    }
+    if (proto.hasScalar()) {
+      this.scalar = new StaticMethodInvocationDesc(proto.getScalar());
+    }
+    if (proto.hasAggregation()) {
+      this.aggregation = new ClassBaseInvocationDesc(proto.getAggregation());
+    }
+    if (proto.hasScalarJIT()) {
+      this.scalarJIT = new StaticMethodInvocationDesc(proto.getScalarJIT());
+    }
+    if (proto.hasAggregationJIT()) {
+      this.aggregationJIT = new ClassBaseInvocationDesc(proto.getAggregation());
+    }
+  }
+
+  public boolean isAvailable() {
+    return legacy != null && scalar != null && scalarJIT != null;
+  }
+
+  public boolean hasLegacy() {
+    return legacy != null;
+  }
+
+  public void setLegacy(ClassBaseInvocationDesc<Function> legacy) {
+    this.legacy = legacy;
+  }
+
+  public ClassBaseInvocationDesc<Function> getLegacy() {
+    return legacy;
+  }
+
+  public boolean hasScalar() {
+    return scalar != null;
+  }
+
+  public void setScalar(StaticMethodInvocationDesc scalar) {
+    this.scalar = scalar;
+  }
+
+  public StaticMethodInvocationDesc getScalar() {
+    return scalar;
+  }
+
+  public boolean hasAggregation() {
+    return aggregation != null;
+  }
+
+  public void setAggregation(ClassBaseInvocationDesc<?> aggregation) {
+    this.aggregation = aggregation;
+  }
+
+  public ClassBaseInvocationDesc<?> getAggregation() {
+    return aggregation;
+  }
+
+  public boolean hasScalarJIT() {
+    return scalarJIT != null;
+  }
+
+  public void setScalarJIT(StaticMethodInvocationDesc scalarJIT) {
+    this.scalarJIT = scalarJIT;
+  }
+
+  public StaticMethodInvocationDesc getScalarJIT() {
+    return scalarJIT;
+  }
+
+  public boolean hasAggregationJIT() {
+    return aggregationJIT != null;
+  }
+
+  public void setAggregationJIT(ClassBaseInvocationDesc<?> aggregationJIT) {
+    this.aggregationJIT = aggregationJIT;
+  }
+
+  public ClassBaseInvocationDesc<?> getAggregationJIT() {
+    return aggregationJIT;
+  }
+
+  @Override
+  public FunctionInvocationProto getProto() {
+    FunctionInvocationProto.Builder builder = FunctionInvocationProto.newBuilder();
+    if (hasLegacy()) {
+      builder.setLegacy(legacy.getProto());
+    }
+    if (hasScalar()) {
+      builder.setScalar(scalar.getProto());
+    }
+    if (hasAggregation()) {
+      builder.setAggregation(aggregation.getProto());
+    }
+    if (hasScalarJIT()) {
+      builder.setScalarJIT(scalarJIT.getProto());
+    }
+    if (hasAggregationJIT()) {
+      builder.setAggregationJIT(aggregationJIT.getProto());
+    }
+    return builder.build();
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(legacy, scalar, scalarJIT);
+  }
+
+  public String toString() {
+    return "legacy=" + hasLegacy() + ",scalar=" + hasScalar() + ",agg=" + hasAggregation() +
+        ",scalarJIT=" + hasScalarJIT() + ",aggJIT=" + hasAggregationJIT();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java
new file mode 100644
index 0000000..fc3a056
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSignature.java
@@ -0,0 +1,141 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.annotation.NotNull;
+import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.util.TUtil;
+
+import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionSignatureProto;
+import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+
+public class FunctionSignature implements Comparable<FunctionSignature>, ProtoObject<FunctionSignatureProto>,
+    Cloneable {
+
+  @Expose
+  private FunctionType functionType;
+  @Expose
+  private String name;
+  @Expose
+  private DataType[] paramTypes;
+  @Expose
+  private DataType returnType;
+
+  public FunctionSignature(FunctionType type, String name, DataType returnType, @NotNull DataType... params) {
+    this.functionType = type;
+    this.name = name;
+    this.returnType = returnType;
+    this.paramTypes = params;
+  }
+
+  public FunctionSignature(FunctionSignatureProto proto) {
+    this.functionType = proto.getType();
+    this.name = proto.getName();
+    this.paramTypes = proto.getParameterTypesList().toArray(new DataType[proto.getParameterTypesCount()]);
+    this.returnType = proto.getReturnType();
+  }
+
+  public FunctionType getFunctionType() {
+    return functionType;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public DataType[] getParamTypes() {
+    return paramTypes;
+  }
+
+  public DataType getReturnType() {
+    return returnType;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(functionType, name, returnType, Objects.hashCode(paramTypes));
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof FunctionSignature) {
+      FunctionSignature other = (FunctionSignature) obj;
+
+      boolean eq = functionType.equals(other.functionType);
+      eq = eq && name.equals(other.name);
+      eq = eq && TUtil.checkEquals(paramTypes, other.paramTypes);
+      eq = eq && returnType.equals(other.returnType);
+      return eq;
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public String toString() {
+    return FunctionUtil.buildFQFunctionSignature(name, returnType, paramTypes);
+  }
+
+  public FunctionSignature clone() throws CloneNotSupportedException {
+    FunctionSignature newSignature = (FunctionSignature) super.clone();
+    newSignature.functionType = functionType;
+    newSignature.name = name;
+    newSignature.returnType = returnType;
+    newSignature.paramTypes = paramTypes;
+    return newSignature;
+  }
+
+  @Override
+  public FunctionSignatureProto getProto() {
+    FunctionSignatureProto.Builder builder = FunctionSignatureProto.newBuilder();
+    builder.setType(functionType);
+    builder.setName(name);
+    builder.addAllParameterTypes(TUtil.newList(paramTypes));
+    builder.setReturnType(returnType);
+    return builder.build();
+  }
+
+  @Override
+  public int compareTo(FunctionSignature o) {
+    int cmpVal = name.compareTo(o.name);
+
+    if (cmpVal != 0) {
+      return cmpVal;
+    }
+
+    cmpVal = returnType.getType().compareTo(o.returnType.getType());
+
+    if (cmpVal != 0) {
+      return cmpVal;
+    }
+
+    for (int i = 0; i < Math.min(paramTypes.length, o.paramTypes.length); i++) {
+      cmpVal = paramTypes[i].getType().compareTo(o.paramTypes[i].getType());
+
+      if (cmpVal != 0) {
+        return cmpVal;
+      }
+    }
+
+    return o.paramTypes.length - paramTypes.length;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSupplement.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSupplement.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSupplement.java
new file mode 100644
index 0000000..33cf908
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionSupplement.java
@@ -0,0 +1,113 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.common.ProtoObject;
+
+import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionSupplementProto;
+
+/**
+ * Supplement information for a function
+ */
+public class FunctionSupplement implements ProtoObject<FunctionSupplementProto>, Cloneable {
+
+  @Expose
+  private String shortDescription;
+  @Expose
+  private String detail;
+  @Expose
+  private String example;
+
+  public FunctionSupplement() {
+    this("", "", "");
+  }
+
+  public FunctionSupplement(String shortDescription, String detail, String example) {
+    this.shortDescription = shortDescription;
+    this.detail = detail;
+    this.example = example;
+  }
+
+  public FunctionSupplement(FunctionSupplementProto proto) {
+    if (proto.hasShortDescription()) {
+      shortDescription = proto.getShortDescription();
+    } else {
+      shortDescription = "";
+    }
+    if (proto.hasDetail()) {
+      detail = proto.getDetail();
+    } else {
+      detail = "";
+    }
+    if (proto.hasExample()) {
+      example = proto.getExample();
+    } else {
+      example = "";
+    }
+  }
+
+  public void setShortDescription(String shortDescription) {
+    this.shortDescription = shortDescription;
+  }
+
+  public String getShortDescription() {
+    return shortDescription;
+  }
+
+  public void setDetail(String detail) {
+    this.detail = detail;
+  }
+
+  public String getDetail() {
+    return detail;
+  }
+
+  public void setExample(String example) {
+    this.example = example;
+  }
+
+  public String getExample() {
+    return example;
+  }
+
+  @Override
+  public FunctionSupplementProto getProto() {
+    FunctionSupplementProto.Builder builder = FunctionSupplementProto.newBuilder();
+    if (shortDescription != null) {
+      builder.setShortDescription(shortDescription);
+    }
+    if (detail != null) {
+      builder.setDetail(detail);
+    }
+    if (example != null) {
+      builder.setExample(example);
+    }
+    return builder.build();
+  }
+
+  @Override
+  public FunctionSupplement clone() throws CloneNotSupportedException {
+    FunctionSupplement newSupplement = (FunctionSupplement) super.clone();
+    newSupplement.shortDescription = shortDescription;
+    newSupplement.detail = detail;
+    newSupplement.example = example;
+    return newSupplement;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionUtil.java
new file mode 100644
index 0000000..dee5d1c
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/FunctionUtil.java
@@ -0,0 +1,56 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import java.util.Collection;
+
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+
+public class FunctionUtil {
+
+  public static String buildFQFunctionSignature(String funcName, DataType returnType, DataType... paramTypes) {
+    return returnType.getType().name().toLowerCase() + " " + buildSimpleFunctionSignature(funcName, paramTypes);
+  }
+
+  public static String buildSimpleFunctionSignature(String functionName, Collection<DataType> paramTypes) {
+    DataType [] types = paramTypes.toArray(new DataType[paramTypes.size()]);
+    return buildSimpleFunctionSignature(functionName, types);
+  }
+
+  public static String buildSimpleFunctionSignature(String signature, DataType... paramTypes) {
+    return signature + "(" + buildParamTypeString(paramTypes) + ")";
+  }
+
+  public static String buildParamTypeString(DataType [] paramTypes) {
+    StringBuilder sb = new StringBuilder();
+    int i = 0;
+    for (DataType type : paramTypes) {
+      sb.append(type.getType().name().toLowerCase());
+      if(i < paramTypes.length - 1) {
+        sb.append(",");
+      }
+      i++;
+    }
+    return sb.toString();
+  }
+
+  public static boolean isNullableParam(Class<?> clazz) {
+    return !clazz.isPrimitive();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ScalarFunction.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ScalarFunction.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ScalarFunction.java
new file mode 100644
index 0000000..554ed4d
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/ScalarFunction.java
@@ -0,0 +1,44 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static org.apache.tajo.common.TajoDataTypes.Type;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface ScalarFunction {
+  String name();
+
+  String [] synonyms() default {};
+
+  Type returnType();
+
+  Type [] paramTypes() default {};
+
+  String shortDescription() default "";
+
+  String detail() default "";
+
+  String example() default "";
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/StaticMethodInvocationDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/StaticMethodInvocationDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/StaticMethodInvocationDesc.java
new file mode 100644
index 0000000..b909878
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/function/StaticMethodInvocationDesc.java
@@ -0,0 +1,135 @@
+/***
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.function;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Maps;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.util.ClassUtil;
+import org.apache.tajo.util.TUtil;
+
+import java.util.Map;
+
+import static org.apache.tajo.catalog.proto.CatalogProtos.StaticMethodInvocationDescProto;
+
+
+/**
+ * StaticMethodInvokeDesc
+ * ClassBaseInvokeDesc
+ */
+public class StaticMethodInvocationDesc implements ProtoObject<StaticMethodInvocationDescProto> {
+  @Expose
+  private Class baseClassName;
+  @Expose
+  private String methodName;
+  @Expose
+  private Class returnClass;
+  @Expose
+  private Class [] paramClasses;
+  
+  public static final Map<String, Class> PRIMITIVE_CLASS_MAP = Maps.newHashMap();
+  
+  static {
+    PRIMITIVE_CLASS_MAP.put("int", Integer.TYPE );
+    PRIMITIVE_CLASS_MAP.put("long", Long.TYPE );
+    PRIMITIVE_CLASS_MAP.put("double", Double.TYPE );
+    PRIMITIVE_CLASS_MAP.put("float", Float.TYPE );
+    PRIMITIVE_CLASS_MAP.put("bool", Boolean.TYPE );
+    PRIMITIVE_CLASS_MAP.put("char", Character.TYPE );
+    PRIMITIVE_CLASS_MAP.put("byte", Byte.TYPE );
+    PRIMITIVE_CLASS_MAP.put("void", Void.TYPE );
+    PRIMITIVE_CLASS_MAP.put("short", Short.TYPE );
+
+  }
+
+  public StaticMethodInvocationDesc(Class baseClassName, String methodName, Class returnClass, Class[] paramClasses) {
+    this.baseClassName = baseClassName;
+    this.methodName = methodName;
+    this.returnClass = returnClass;
+    this.paramClasses = paramClasses;
+  }
+
+  public StaticMethodInvocationDesc(StaticMethodInvocationDescProto proto) {
+    try {
+      baseClassName = Class.forName(proto.getClassName());
+      methodName = proto.getMethodName();
+      returnClass = ClassUtil.forName(proto.getReturnClass());
+      paramClasses = new Class[proto.getParamClassesCount()];
+      for (int i = 0; i < proto.getParamClassesCount(); i++) {
+        paramClasses[i] = ClassUtil.forName(proto.getParamClasses(i));
+      }
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public Class getBaseClassName() {
+    return baseClassName;
+  }
+
+  public String getMethodName() {
+    return methodName;
+  }
+
+  public Class getReturnClass() {
+    return returnClass;
+  }
+
+  public Class [] getParamClasses() {
+    return paramClasses;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof StaticMethodInvocationDesc) {
+      StaticMethodInvocationDesc other = (StaticMethodInvocationDesc) obj;
+      return
+          baseClassName.equals(other.baseClassName) &&
+              methodName.equals(other.methodName) &&
+              returnClass.equals(other.returnClass) &&
+              TUtil.checkEquals(paramClasses, other.paramClasses);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(baseClassName, methodName, returnClass, Objects.hashCode(paramClasses));
+  }
+
+  public String toString() {
+    return baseClassName.getCanonicalName() + "::" + methodName;
+  } 
+
+
+  @Override
+  public StaticMethodInvocationDescProto getProto() {
+    StaticMethodInvocationDescProto.Builder builder = StaticMethodInvocationDescProto.newBuilder();
+    builder.setClassName(baseClassName.getName());
+    builder.setMethodName(methodName);
+    builder.setReturnClass(returnClass.getName());
+
+    for (Class<?> c : paramClasses) {
+      builder.addParamClasses(c.getName());
+    }
+    return builder.build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto b/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
index 2cfc1a8..9e37acd 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
+++ b/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
@@ -117,28 +117,6 @@ message NamespaceProto {
   optional string namespace = 2;
 }
 
-enum FunctionType {
-  GENERAL = 0;
-  AGGREGATION = 1;
-  DISTINCT_AGGREGATION = 2;
-  WINDOW = 3;
-  UDF = 4;
-  UDA = 5;
-  DISTINCT_UDA = 6;
-  WINDOW_UDA = 7;
-}
-
-message FunctionDescProto {
-  required string signature = 1;
-  required string className = 2;
-  required FunctionType type = 3;
-  repeated DataType parameterTypes = 4;
-  required DataType returnType = 5;
-  optional string description = 6;
-  optional string example = 7;
-  optional string detail = 8;
-}
-
 message IndexDescProto {
   required TableIdentifierProto tableIdentifier = 1;
   required string indexName = 2;
@@ -302,3 +280,56 @@ message AlterColumnProto {
   required string oldColumnName = 1;
   required string newColumnName = 2;
 }
+
+////////////////////////////////////////////////
+// Function and UDF Section
+////////////////////////////////////////////////
+
+enum FunctionType {
+  GENERAL = 0;
+  AGGREGATION = 1;
+  DISTINCT_AGGREGATION = 2;
+  WINDOW = 3;
+  UDF = 4;
+  UDA = 5;
+  DISTINCT_UDA = 6;
+  WINDOW_UDA = 7;
+}
+
+message FunctionDescProto {
+  required FunctionSignatureProto signature = 1;
+  required FunctionSupplementProto supplement = 2;
+  required FunctionInvocationProto invocation = 3;
+}
+
+message FunctionSignatureProto {
+  required FunctionType type = 1;
+  required string name = 2;
+  required DataType returnType = 3;
+  repeated DataType parameterTypes = 4;
+}
+
+message FunctionSupplementProto {
+  optional string shortDescription = 1;
+  optional string detail = 2;
+  optional string example = 3;
+}
+
+message FunctionInvocationProto {
+  optional ClassBaseInvocationDescProto legacy = 1;
+  optional StaticMethodInvocationDescProto scalar = 2;
+  optional ClassBaseInvocationDescProto aggregation = 3;
+  optional StaticMethodInvocationDescProto scalarJIT = 4;
+  optional ClassBaseInvocationDescProto aggregationJIT = 5;
+}
+
+message ClassBaseInvocationDescProto {
+  required string className = 1;
+}
+
+message StaticMethodInvocationDescProto {
+  required string className = 1;
+  required string methodName = 2;
+  required string returnClass = 3;
+  repeated string paramClasses = 4;
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
index 3c0536b..0a7fd0a 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
@@ -19,6 +19,7 @@
 package org.apache.tajo.catalog;
 
 import org.apache.tajo.common.TajoDataTypes.Type;
+import org.apache.tajo.function.FunctionUtil;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -28,7 +29,7 @@ import static org.junit.Assert.*;
 public class TestCatalogUtil {
   @Test
   public final void testGetCanonicalName() {
-    String canonical = CatalogUtil.getCanonicalSignature("sum", CatalogUtil.newSimpleDataTypeArray(Type.INT4,
+    String canonical = FunctionUtil.buildSimpleFunctionSignature("sum", CatalogUtil.newSimpleDataTypeArray(Type.INT4,
         Type.INT8));
     assertEquals("sum(int4,int8)", canonical);
   }
@@ -61,7 +62,7 @@ public class TestCatalogUtil {
     assertFalse(CatalogUtil.isCompatibleType(Type.FLOAT4, Type.FLOAT8));
     assertTrue(CatalogUtil.isCompatibleType(Type.FLOAT8, Type.FLOAT4));
 
-    assertFalse(CatalogUtil.isCompatibleType(Type.FLOAT8, Type.INT4));
+    assertTrue(CatalogUtil.isCompatibleType(Type.FLOAT8, Type.INT4));
 
     assertFalse(CatalogUtil.isCompatibleType(Type.FLOAT8_ARRAY, Type.TEXT_ARRAY));
     assertFalse(CatalogUtil.isCompatibleType(Type.TEXT_ARRAY, Type.FLOAT8_ARRAY));
@@ -70,15 +71,18 @@ public class TestCatalogUtil {
   @Test
   public final void testCompareDataTypeIncludeVariableLength() {
     assertTrue(CatalogUtil.isMatchedFunction(
-        Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT8, Type.INT4)), Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT4, Type.INT4))
+        Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT8, Type.INT4)),
+        Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT4, Type.INT4))
     ));
 
   assertFalse(CatalogUtil.isMatchedFunction(
-      Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT4, Type.INT4)), Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT8, Type.INT4))
+      Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT4, Type.INT4)),
+      Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT8, Type.INT4))
   ));
 
     assertTrue(CatalogUtil.isMatchedFunction(
-        Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT8, Type.INT8_ARRAY)), Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT4, Type.INT4, Type.INT4))
+        Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT8, Type.INT8_ARRAY)),
+        Arrays.asList(CatalogUtil.newSimpleDataTypeArray(Type.FLOAT4, Type.INT4, Type.INT4))
     ));
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
index 53a6796..92d2aa4 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestFunctionDesc.java
@@ -18,7 +18,7 @@
 
 package org.apache.tajo.catalog;
 
-import org.apache.tajo.catalog.function.Function;
+import org.apache.tajo.function.Function;
 import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionDescProto;
@@ -67,7 +67,7 @@ public class TestFunctionDesc {
     desc.setExample("example");
     desc.setDetail("detail");
 
-    assertEquals("sum", desc.getSignature());
+    assertEquals("sum", desc.getFunctionName());
     assertEquals(TestSum.class, desc.getFuncClass());
     assertEquals(FunctionType.GENERAL, desc.getFuncType());
     assertEquals(Type.INT4, desc.getReturnType().getType());
@@ -83,7 +83,7 @@ public class TestFunctionDesc {
 
     FunctionDesc newDesc = new FunctionDesc(proto);
 
-    assertEquals("sum", newDesc.getSignature());
+    assertEquals("sum", newDesc.getFunctionName());
     assertEquals(TestSum.class, newDesc.getFuncClass());
     assertEquals(FunctionType.GENERAL, newDesc.getFuncType());
     assertEquals(Type.INT4, newDesc.getReturnType().getType());

http://git-wip-us.apache.org/repos/asf/tajo/blob/05ca386c/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
index cf3ea6f..03ae920 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
@@ -20,6 +20,7 @@ package org.apache.tajo.catalog;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
 import com.google.protobuf.RpcController;
 import com.google.protobuf.ServiceException;
 import org.apache.commons.logging.Log;
@@ -94,7 +95,7 @@ public class CatalogServer extends AbstractService {
   private static BoolProto BOOL_FALSE = BoolProto.newBuilder().
       setValue(false).build();
 
-  private List<FunctionDesc> builtingFuncs;
+  private Collection<FunctionDesc> builtingFuncs;
 
   public CatalogServer() throws IOException {
     super(CatalogServer.class.getName());
@@ -102,7 +103,7 @@ public class CatalogServer extends AbstractService {
     this.builtingFuncs = new ArrayList<FunctionDesc>();
   }
 
-  public CatalogServer(List<FunctionDesc> sqlFuncs) throws IOException {
+  public CatalogServer(Collection<FunctionDesc> sqlFuncs) throws IOException {
     this();
     this.builtingFuncs = sqlFuncs;
   }
@@ -162,7 +163,7 @@ public class CatalogServer extends AbstractService {
         + catalogUri;
   }
 
-  private void initBuiltinFunctions(List<FunctionDesc> functions)
+  private void initBuiltinFunctions(Collection<FunctionDesc> functions)
       throws ServiceException {
     for (FunctionDesc desc : functions) {
       handler.createFunction(null, desc.getProto());
@@ -847,10 +848,13 @@ public class CatalogServer extends AbstractService {
     }
 
     private FunctionDescProto findFunction(String signature, List<TajoDataTypes.DataType> params) {
+      List<FunctionDescProto> candidates = Lists.newArrayList();
+
       if (functions.containsKey(signature)) {
-        for (FunctionDescProto existing : functions.get(signature)) {
-          if (existing.getParameterTypesList() != null && existing.getParameterTypesList().equals(params)) {
-            return existing;
+        for (FunctionDescProto func : functions.get(signature)) {
+          if (func.getSignature().getParameterTypesList() != null &&
+              func.getSignature().getParameterTypesList().equals(params)) {
+            candidates.add(func);
           }
         }
       }
@@ -865,39 +869,88 @@ public class CatalogServer extends AbstractService {
        *
        * */
       if (functions.containsKey(signature)) {
-        for (FunctionDescProto existing : functions.get(signature)) {
-          if (existing.getParameterTypesList() != null &&
-              CatalogUtil.isMatchedFunction(existing.getParameterTypesList(), params)) {
-            return existing;
+        for (FunctionDescProto func : functions.get(signature)) {
+          if (func.getSignature().getParameterTypesList() != null &&
+              CatalogUtil.isMatchedFunction(func.getSignature().getParameterTypesList(), params)) {
+            candidates.add(func);
           }
         }
+
+        // if there are more than one function candidates, we choose the nearest matched function.
+        if (candidates.size() > 0) {
+          return findNearestMatchedFunction(candidates);
+        } else {
+          return null;
+        }
       }
+
       return null;
     }
 
     private FunctionDescProto findFunction(String signature, FunctionType type, List<TajoDataTypes.DataType> params,
                                            boolean strictTypeCheck) {
+      List<FunctionDescProto> candidates = Lists.newArrayList();
+
       if (functions.containsKey(signature)) {
         if (strictTypeCheck) {
-          for (FunctionDescProto existing : functions.get(signature)) {
-            if (existing.getType() == type && existing.getParameterTypesList().equals(params)) {
-              return existing;
+          for (FunctionDescProto func : functions.get(signature)) {
+            if (func.getSignature().getType() == type &&
+                func.getSignature().getParameterTypesList().equals(params)) {
+              candidates.add(func);
             }
           }
         } else {
-          for (FunctionDescProto existing : functions.get(signature)) {
-            if (existing.getParameterTypesList() != null &&
-                CatalogUtil.isMatchedFunction(existing.getParameterTypesList(), params)) {
-              return existing;
+          for (FunctionDescProto func : functions.get(signature)) {
+            if (func.getSignature().getParameterTypesList() != null &&
+                CatalogUtil.isMatchedFunction(func.getSignature().getParameterTypesList(), params)) {
+              candidates.add(func);
             }
           }
         }
       }
-      return null;
+
+      // if there are more than one function candidates, we choose the nearest matched function.
+      if (candidates.size() > 0) {
+        return findNearestMatchedFunction(candidates);
+      } else {
+        return null;
+      }
+    }
+
+    /**
+     * Find the nearest matched function
+     *
+     * @param candidates Candidate Functions
+     * @return
+     */
+    private FunctionDescProto findNearestMatchedFunction(List<FunctionDescProto> candidates) {
+      Collections.sort(candidates, new NearestParamsComparator());
+      return candidates.get(0);
+    }
+
+    private class NearestParamsComparator implements Comparator<FunctionDescProto> {
+      @Override
+      public int compare(FunctionDescProto o1, FunctionDescProto o2) {
+        List<DataType> types1 = o1.getSignature().getParameterTypesList();
+        List<DataType> types2 = o2.getSignature().getParameterTypesList();
+
+        int minLen = Math.min(types1.size(), types2.size());
+
+        for (int i = 0; i < minLen; i++) {
+          int cmpVal = types1.get(i).getType().getNumber() - types2.get(i).getType().getNumber();
+
+          if (cmpVal != 0) {
+            return cmpVal;
+          }
+        }
+
+        return types1.size() - types2.size();
+      }
     }
 
     private FunctionDescProto findFunctionStrictType(FunctionDescProto target, boolean strictTypeCheck) {
-      return findFunction(target.getSignature(), target.getType(), target.getParameterTypesList(), strictTypeCheck);
+      return findFunction(target.getSignature().getName(), target.getSignature().getType(),
+          target.getSignature().getParameterTypesList(), strictTypeCheck);
     }
 
     @Override
@@ -912,7 +965,7 @@ public class CatalogServer extends AbstractService {
         }
       }
 
-      TUtil.putToNestedList(functions, funcDesc.getSignature(), funcDesc);
+      TUtil.putToNestedList(functions, funcDesc.getSignature().getName(), funcDesc);
       if (LOG.isDebugEnabled()) {
         LOG.info("Function " + signature + " is registered.");
       }
@@ -979,7 +1032,8 @@ public class CatalogServer extends AbstractService {
     }
 
     public static FunctionSignature create(FunctionDescProto proto) {
-      return new FunctionSignature(proto.getSignature(), proto.getType(), proto.getParameterTypesList());
+      return new FunctionSignature(proto.getSignature().getName(),
+          proto.getSignature().getType(), proto.getSignature().getParameterTypesList());
     }
 
     public static FunctionSignature create (GetFunctionMetaRequest proto) {


Mime
View raw message