asfgit closed pull request #6337: [FLINK-9853] [table] Add HEX support 
URL: https://github.com/apache/flink/pull/6337
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/docs/dev/table/sql.md b/docs/dev/table/sql.md
index 148f30727d9..09b9b261b68 100644
--- a/docs/dev/table/sql.md
+++ b/docs/dev/table/sql.md
@@ -1675,6 +1675,17 @@ BIN(numeric)
       </td>
     </tr>
 
+    <tr>
+      <td>
+{% highlight text %}
+HEX(numeric)
+HEX(string)
+      {% endhighlight %}
+      </td>
+      <td>
+        <p>Returns a string representation of an integer numeric value or a 
string in hex format. Returns null if numeric is null. E.g. For numeric "20" 
leads to "14", "100" leads to "64", and for string "hello,world" leads to 
"68656c6c6f2c776f726c64".</p>
+      </td>
+    </tr>
   </tbody>
 </table>
 
diff --git a/docs/dev/table/tableApi.md b/docs/dev/table/tableApi.md
index b702dddcde5..b5dd4164a7d 100644
--- a/docs/dev/table/tableApi.md
+++ b/docs/dev/table/tableApi.md
@@ -2333,6 +2333,17 @@ NUMERIC.bin()
     </td>
    </tr>
     
+    <tr>
+     <td>
+       {% highlight java %}
+NUMERIC.hex()
+STRING.hex()
+{% endhighlight %}
+     </td>
+    <td>
+      <p>Returns a string representation of an integer numeric value or a 
string in hex format. Returns null if numeric is null. E.g. For numeric "20" 
leads to "14", "100" leads to "64", and for string "hello,world" leads to 
"68656c6c6f2c776f726c64".</p>
+    </td>
+   </tr>
   </tbody>
 </table>
 
@@ -3921,6 +3932,17 @@ NUMERIC.bin()
     </td>
    </tr>
 
+    <tr>
+     <td>
+       {% highlight scala %}
+NUMERIC.hex()
+STRING.hex()
+{% endhighlight %}
+     </td>
+    <td>
+      <p>Returns a string representation of an integer numeric value or a 
string in hex format. Returns null if numeric is null. E.g. For numeric "20" 
leads to "14", "100" leads to "64", and for string "hello,world" leads to 
"68656c6c6f2c776f726c64".</p>
+    </td>
+   </tr>
   </tbody>
 </table>
 
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/api/scala/expressionDsl.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/api/scala/expressionDsl.scala
index c7c805f6743..1df30d98d11 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/api/scala/expressionDsl.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/api/scala/expressionDsl.scala
@@ -406,6 +406,13 @@ trait ImplicitExpressionOperations {
     */
   def bin() = Bin(expr)
 
+  /**
+    * Returns a string representation of an integer numeric value or a string 
in hex format.
+    * Returns null if numeric or string is null. E.g. For numeric "20" leads 
to "14",
+    * "100" leads to "64", and for string "hello,world" leads to 
"68656c6c6f2c776f726c64".
+    */
+  def hex() = Hex(expr)
+
   // String operations
 
   /**
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/BuiltInMethods.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/BuiltInMethods.scala
index f5ed9b387de..1e21bfe7830 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/BuiltInMethods.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/BuiltInMethods.scala
@@ -132,6 +132,11 @@ object BuiltInMethods {
 
   val BIN = Types.lookupMethod(classOf[JLong], "toBinaryString", classOf[Long])
 
+  val HEX = Types.lookupMethod(classOf[ScalarFunctions], "hex", classOf[Long])
+
+  val HEX_STRING =
+    Types.lookupMethod(classOf[ScalarFunctions], "hexString", classOf[String])
+
   val FROMBASE64 = Types.lookupMethod(classOf[ScalarFunctions], "fromBase64", 
classOf[String])
 
   val TOBASE64 = Types.lookupMethod(classOf[ScalarFunctions], "toBase64", 
classOf[String])
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/FunctionGenerator.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/FunctionGenerator.scala
index 74b69d6afcc..47f54fb229c 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/FunctionGenerator.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/codegen/calls/FunctionGenerator.scala
@@ -455,6 +455,18 @@ object FunctionGenerator {
     STRING_TYPE_INFO,
     BuiltInMethods.BIN)
 
+  addSqlFunctionMethod(
+    ScalarSqlFunctions.HEX,
+    Seq(LONG_TYPE_INFO),
+    STRING_TYPE_INFO,
+    BuiltInMethods.HEX)
+
+  addSqlFunctionMethod(
+    ScalarSqlFunctions.HEX,
+    Seq(STRING_TYPE_INFO),
+    STRING_TYPE_INFO,
+    BuiltInMethods.HEX_STRING)
+
   // 
----------------------------------------------------------------------------------------------
   // Temporal functions
   // 
----------------------------------------------------------------------------------------------
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/expressions/mathExpressions.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/expressions/mathExpressions.scala
index cf3efa938a6..728eac62e71 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/expressions/mathExpressions.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/expressions/mathExpressions.scala
@@ -422,3 +422,21 @@ case class Bin(child: Expression) extends UnaryExpression {
     relBuilder.call(ScalarSqlFunctions.BIN, child.toRexNode)
   }
 }
+
+case class Hex(child: Expression) extends UnaryExpression {
+  override private[flink] def resultType: TypeInformation[_] = 
BasicTypeInfo.STRING_TYPE_INFO
+
+  override private[flink] def validateInput(): ValidationResult = {
+    if (TypeCheckUtils.isIntegerFamily(child.resultType) ||
+      TypeCheckUtils.isString(child.resultType)) {
+      ValidationSuccess
+    } else {
+      ValidationFailure(s"hex requires integer or string types but was 
'${child.resultType}'.")
+    }
+  }
+  override def toString: String = s"hex($child)"
+
+  override private[flink] def toRexNode(implicit relBuilder: RelBuilder): 
RexNode = {
+    relBuilder.call(ScalarSqlFunctions.HEX, child.toRexNode)
+  }
+}
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/functions/sql/ScalarSqlFunctions.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/functions/sql/ScalarSqlFunctions.scala
index 21793e3351c..a0b6c9c67cf 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/functions/sql/ScalarSqlFunctions.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/functions/sql/ScalarSqlFunctions.scala
@@ -42,6 +42,15 @@ object ScalarSqlFunctions {
     OperandTypes.family(SqlTypeFamily.INTEGER),
     SqlFunctionCategory.NUMERIC)
 
+  val HEX = new SqlFunction(
+    "HEX",
+    SqlKind.OTHER_FUNCTION,
+    ReturnTypes.cascade(ReturnTypes.explicit(SqlTypeName.VARCHAR), 
SqlTypeTransforms.TO_NULLABLE),
+    InferTypes.RETURN_TYPE,
+    OperandTypes.or(OperandTypes.family(SqlTypeFamily.INTEGER),
+      OperandTypes.family(SqlTypeFamily.STRING)),
+    SqlFunctionCategory.NUMERIC)
+
   val CONCAT = new SqlFunction(
     "CONCAT",
     SqlKind.OTHER_FUNCTION,
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/runtime/functions/ScalarFunctions.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/runtime/functions/ScalarFunctions.scala
index 03ee62ce224..491fdd7b405 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/runtime/functions/ScalarFunctions.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/runtime/functions/ScalarFunctions.scala
@@ -19,8 +19,9 @@ package org.apache.flink.table.runtime.functions
 
 import scala.annotation.varargs
 import java.math.{BigDecimal => JBigDecimal}
-import java.lang.StringBuilder
+import java.lang.{Long => JLong, StringBuilder}
 
+import org.apache.commons.codec.binary.Hex
 import org.apache.commons.codec.binary.Base64
 
 /**
@@ -202,6 +203,13 @@ object ScalarFunctions {
     new String(data)
   }
 
+  /**
+    * Returns the string str that is encoded as hex string of x.
+    */
+  def hex(x: Long): String = JLong.toHexString(x).toUpperCase()
+
+  def hexString(x: String): String = 
Hex.encodeHexString(x.getBytes).toUpperCase()
+
   /**
     * Returns the base string decoded with base64.
     */
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/validate/FunctionCatalog.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/validate/FunctionCatalog.scala
index bca156c261a..a446401f31c 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/validate/FunctionCatalog.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/table/validate/FunctionCatalog.scala
@@ -239,6 +239,7 @@ object FunctionCatalog {
     "rand" -> classOf[Rand],
     "randInteger" -> classOf[RandInteger],
     "bin" -> classOf[Bin],
+    "hex" -> classOf[Hex],
 
     // temporal functions
     "extract" -> classOf[Extract],
@@ -438,6 +439,7 @@ class BasicOperatorTable extends ReflectiveSqlOperatorTable 
{
     ScalarSqlFunctions.CONCAT,
     ScalarSqlFunctions.CONCAT_WS,
     ScalarSqlFunctions.BIN,
+    ScalarSqlFunctions.HEX,
     SqlStdOperatorTable.TIMESTAMP_ADD,
     ScalarSqlFunctions.LOG,
     ScalarSqlFunctions.LPAD,
diff --git 
a/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/expressions/ScalarFunctionsTest.scala
 
b/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/expressions/ScalarFunctionsTest.scala
index 6f9a9ae81b9..7f5b156202a 100644
--- 
a/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/expressions/ScalarFunctionsTest.scala
+++ 
b/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/expressions/ScalarFunctionsTest.scala
@@ -392,6 +392,93 @@ class ScalarFunctionsTest extends ScalarTypesTestBase {
       "รครครค1234512345")
   }
 
+  @Test
+  def testHex(): Unit = {
+    testAllApis(
+      100.hex(),
+      "100.hex()",
+      "HEX(100)",
+      "64")
+
+    testAllApis(
+      'f2.hex(),
+      "f2.hex()",
+      "HEX(f2)",
+      "2A")
+
+    testAllApis(
+      Null(Types.BYTE).hex(),
+      "hex(Null(BYTE))",
+      "HEX(CAST(NULL AS TINYINT))",
+      "null")
+
+    testAllApis(
+      'f3.hex(),
+      "f3.hex()",
+      "HEX(f3)",
+      "2B")
+
+    testAllApis(
+      'f4.hex(),
+      "f4.hex()",
+      "HEX(f4)",
+      "2C")
+
+    testAllApis(
+      'f7.hex(),
+      "f7.hex()",
+      "HEX(f7)",
+      "3")
+
+    testAllApis(
+      12.hex(),
+      "12.hex()",
+      "HEX(12)",
+      "C")
+
+    testAllApis(
+      10.hex(),
+      "10.hex()",
+      "HEX(10)",
+      "A")
+
+    testAllApis(
+      0.hex(),
+      "0.hex()",
+      "HEX(0)",
+      "0")
+
+    testAllApis(
+      'f32.hex(),
+      "f32.hex()",
+      "HEX(f32)",
+      "FFFFFFFFFFFFFFFF")
+
+    testAllApis(
+      'f0.hex(),
+      "f0.hex()",
+      "HEX(f0)",
+      "546869732069732061207465737420537472696E672E")
+
+    testAllApis(
+      'f8.hex(),
+      "f8.hex()",
+      "HEX(f8)",
+      "20546869732069732061207465737420537472696E672E20")
+
+    testAllApis(
+      'f23.hex(),
+      "f23.hex()",
+      "HEX(f23)",
+      "25546869732069732061207465737420537472696E672E")
+
+    testAllApis(
+      'f24.hex(),
+      "f24.hex()",
+      "HEX(f24)",
+      "2A5F546869732069732061207465737420537472696E672E")
+  }
+
   @Test
   def testBin(): Unit = {
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to