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

danny0405 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new 468f019  [CALCITE-3647] MySQL COMPRESS function support (ritesh-kapoor)
468f019 is described below

commit 468f0190bbd1777671916c0adc57c7c6bd23a7a0
Author: Ritesh Kapoor <riteshkapoor.opensou...@gmail.com>
AuthorDate: Fri Mar 6 11:44:48 2020 +0530

    [CALCITE-3647] MySQL COMPRESS function support (ritesh-kapoor)
    
    close apache/calcite#1847
---
 .../calcite/adapter/enumerable/RexImpTable.java    |  4 ++
 .../calcite/runtime/CompressionFunctions.java      | 65 ++++++++++++++++++++++
 .../calcite/sql/fun/SqlLibraryOperators.java       |  6 ++
 .../org/apache/calcite/util/BuiltInMethod.java     |  2 +
 .../calcite/sql/test/SqlOperatorBaseTest.java      | 17 ++++++
 core/src/test/resources/sql/functions.iq           | 13 +++++
 site/_docs/reference.md                            |  1 +
 7 files changed, 108 insertions(+)

diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index dc2a6d2..2d713da 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -97,6 +97,7 @@ import static 
org.apache.calcite.linq4j.tree.ExpressionType.OrElse;
 import static org.apache.calcite.linq4j.tree.ExpressionType.Subtract;
 import static org.apache.calcite.linq4j.tree.ExpressionType.UnaryPlus;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.CHR;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.COMPRESS;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.COSH;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.DAYNAME;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.DIFFERENCE;
@@ -546,6 +547,9 @@ public class RexImpTable {
     defineMethod(CURRENT_VALUE, BuiltInMethod.SEQUENCE_CURRENT_VALUE.method, 
NullPolicy.STRICT);
     defineMethod(NEXT_VALUE, BuiltInMethod.SEQUENCE_NEXT_VALUE.method, 
NullPolicy.STRICT);
 
+    // Compression Operators
+    defineMethod(COMPRESS, BuiltInMethod.COMPRESS.method, NullPolicy.ARG0);
+
     // Xml Operators
     defineMethod(EXTRACT_VALUE, BuiltInMethod.EXTRACT_VALUE.method, 
NullPolicy.ARG0);
     defineMethod(XML_TRANSFORM, BuiltInMethod.XML_TRANSFORM.method, 
NullPolicy.ARG0);
diff --git 
a/core/src/main/java/org/apache/calcite/runtime/CompressionFunctions.java 
b/core/src/main/java/org/apache/calcite/runtime/CompressionFunctions.java
new file mode 100644
index 0000000..d16c434
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/runtime/CompressionFunctions.java
@@ -0,0 +1,65 @@
+/*
+ * 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.calcite.runtime;
+
+import org.apache.calcite.avatica.util.ByteString;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+import java.util.zip.DeflaterOutputStream;
+
+/**
+ * A collection of functions used in compression and decompression.
+ */
+public class CompressionFunctions {
+
+  private CompressionFunctions() {
+  }
+
+  /**
+   * MySql Compression is based on zlib.
+   * <a 
href="https://docs.oracle.com/javase/8/docs/api/java/util/zip/Deflater.html";>Deflater</a>
+   * is used to implement compression.
+   */
+  public static ByteString compress(String data) {
+    try {
+      if (data == null) {
+        return null;
+      }
+      if (StringUtils.isEmpty(data)) {
+        return new ByteString(new byte[0]);
+      }
+      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+      ByteBuffer dataLength = ByteBuffer.allocate(4);
+      dataLength.order(ByteOrder.LITTLE_ENDIAN);
+      dataLength.putInt(data.length());
+      outputStream.write(dataLength.array());
+      DeflaterOutputStream inflaterStream = new 
DeflaterOutputStream(outputStream);
+      inflaterStream.write(data.getBytes(Charset.defaultCharset()));
+      inflaterStream.close();
+      return new ByteString(outputStream.toByteArray());
+    } catch (IOException e) {
+      return null;
+    }
+  }
+
+}
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
index 3768323..b5a83bb 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
@@ -173,6 +173,12 @@ public abstract class SqlLibraryOperators {
   public static final SqlFunction REGEXP_REPLACE = new 
SqlRegexpReplaceFunction();
 
   @LibraryOperator(libraries = {MYSQL})
+  public static final SqlFunction COMPRESS = new SqlFunction("COMPRESS", 
SqlKind.OTHER_FUNCTION,
+      ReturnTypes.cascade(ReturnTypes.explicit(SqlTypeName.VARBINARY),
+          SqlTypeTransforms.TO_NULLABLE), null, OperandTypes.STRING, 
SqlFunctionCategory.STRING);
+
+
+  @LibraryOperator(libraries = {MYSQL})
   public static final SqlFunction EXTRACT_VALUE = new SqlFunction(
       "EXTRACTVALUE", SqlKind.OTHER_FUNCTION,
       ReturnTypes.cascade(ReturnTypes.VARCHAR_2000, 
SqlTypeTransforms.FORCE_NULLABLE),
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java 
b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index bb226a0..d2e2499 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -79,6 +79,7 @@ import org.apache.calcite.runtime.ArrayBindable;
 import org.apache.calcite.runtime.Automaton;
 import org.apache.calcite.runtime.BinarySearch;
 import org.apache.calcite.runtime.Bindable;
+import org.apache.calcite.runtime.CompressionFunctions;
 import org.apache.calcite.runtime.Enumerables;
 import org.apache.calcite.runtime.FlatLists;
 import org.apache.calcite.runtime.JsonFunctions;
@@ -324,6 +325,7 @@ public enum BuiltInMethod {
   FROM_BASE64(SqlFunctions.class, "fromBase64", String.class),
   MD5(SqlFunctions.class, "md5", String.class),
   SHA1(SqlFunctions.class, "sha1", String.class),
+  COMPRESS(CompressionFunctions.class, "compress", String.class),
   EXTRACT_VALUE(XmlFunctions.class, "extractValue", String.class, 
String.class),
   XML_TRANSFORM(XmlFunctions.class, "xmlTransform", String.class, 
String.class),
   EXTRACT_XML(XmlFunctions.class, "extractXml", String.class, String.class, 
String.class),
diff --git 
a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java 
b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 8ad9f30..436aab8 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -5175,6 +5175,23 @@ public abstract class SqlOperatorBaseTest {
     tester.checkBoolean("'[]' is not json scalar", true);
   }
 
+  @Test public void testCompress() {
+    SqlTester sqlTester = tester(SqlLibrary.MYSQL);
+    sqlTester.checkNull("COMPRESS(NULL)");
+    sqlTester.checkString("COMPRESS('')", "",
+        "VARBINARY NOT NULL");
+
+    sqlTester.checkString("COMPRESS(REPEAT('a',1000))",
+        "e8030000789c4b4c1c05a360140c770000f9d87af8", "VARBINARY NOT NULL");
+    sqlTester.checkString("COMPRESS(REPEAT('a',16))",
+        "10000000789c4b4c44050033980611", "VARBINARY NOT NULL");
+
+    sqlTester.checkString("COMPRESS('sample')",
+        "06000000789c2b4ecc2dc849050008de0283", "VARBINARY NOT NULL");
+    sqlTester.checkString("COMPRESS('example')",
+        "07000000789c4bad48cc2dc84905000bc002ed", "VARBINARY NOT NULL");
+  }
+
   @Test public void testExtractValue() {
     SqlTester mySqlTester = tester(SqlLibrary.MYSQL);
     mySqlTester.checkNull("ExtractValue(NULL, '//b')");
diff --git a/core/src/test/resources/sql/functions.iq 
b/core/src/test/resources/sql/functions.iq
index 2f16e14..c9a14b8 100644
--- a/core/src/test/resources/sql/functions.iq
+++ b/core/src/test/resources/sql/functions.iq
@@ -54,6 +54,19 @@ SELECT ExtractValue('<a>c</a>', '//a');
 
 !ok
 
+# Compression Functions
+
+SELECT COMPRESS('sample');
++--------------------------------------+
+| EXPR$0                               |
++--------------------------------------+
+| 06000000789c2b4ecc2dc849050008de0283 |
++--------------------------------------+
+(1 row)
+
+!ok
+
+
 !use oraclefunc
 
 # COSH
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index b0dbace..efeda04 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -2323,6 +2323,7 @@ semantics.
 | o | CHR(integer) | Returns the character having the binary equivalent to 
*integer* as a CHAR value
 | o | COSH(numeric)                                  | Returns the hyperbolic 
cosine of *numeric*
 | m o p | CONCAT(string [, string ]*)                | Concatenates two or 
more strings
+| m | COMPRESS(string)                               | Compresses a string 
using zlib compression and returns the result as a binary string.
 | p | CONVERT_TIMEZONE(tz1, tz2, datetime)           | Converts the timezone 
of *datetime* from *tz1* to *tz2*
 | m | DAYNAME(datetime)                              | Returns the name, in 
the connection's locale, of the weekday in *datetime*; for example, it returns 
'星期日' for both DATE '2020-02-10' and TIMESTAMP '2020-02-10 10:10:10'
 | o | DECODE(value, value1, result1 [, valueN, resultN ]* [, default ]) | 
Compares *value* to each *valueN* value one by one; if *value* is equal to a 
*valueN*, returns the corresponding *resultN*, else returns *default*, or NULL 
if *default* is not specified

Reply via email to