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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0059d61  ARROW-14335: [GLib][Ruby] Add support for expression
0059d61 is described below

commit 0059d6113ac1ab0db13733ea99ef0987c0a598a2
Author: Sutou Kouhei <[email protected]>
AuthorDate: Fri Oct 15 14:51:32 2021 +0900

    ARROW-14335: [GLib][Ruby] Add support for expression
    
    Closes #11429 from kou/glib-expression
    
    Authored-by: Sutou Kouhei <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 c_glib/arrow-glib/arrow-glib.h            |   1 +
 c_glib/arrow-glib/arrow-glib.hpp          |   2 +
 c_glib/arrow-glib/expression.cpp          | 265 ++++++++++++++++++++++++++++++
 c_glib/arrow-glib/expression.h            |  96 +++++++++++
 c_glib/arrow-glib/expression.hpp          |  30 ++++
 c_glib/arrow-glib/meson.build             |   3 +
 c_glib/doc/arrow-glib/arrow-glib-docs.xml |   1 +
 c_glib/test/test-call-expression.rb       |  42 +++++
 c_glib/test/test-field-expression.rb      |  49 ++++++
 c_glib/test/test-literal-expression.rb    |  40 +++++
 ruby/red-arrow/lib/arrow/expression.rb    |  48 ++++++
 ruby/red-arrow/lib/arrow/loader.rb        |   1 +
 ruby/red-arrow/test/test-expression.rb    |  40 +++++
 13 files changed, 618 insertions(+)

diff --git a/c_glib/arrow-glib/arrow-glib.h b/c_glib/arrow-glib/arrow-glib.h
index e25044e..57a3508 100644
--- a/c_glib/arrow-glib/arrow-glib.h
+++ b/c_glib/arrow-glib/arrow-glib.h
@@ -31,6 +31,7 @@
 #include <arrow-glib/datum.h>
 #include <arrow-glib/enums.h>
 #include <arrow-glib/error.h>
+#include <arrow-glib/expression.h>
 #include <arrow-glib/field.h>
 #include <arrow-glib/record-batch.h>
 #include <arrow-glib/scalar.h>
diff --git a/c_glib/arrow-glib/arrow-glib.hpp b/c_glib/arrow-glib/arrow-glib.hpp
index 6dc6d43..621c474 100644
--- a/c_glib/arrow-glib/arrow-glib.hpp
+++ b/c_glib/arrow-glib/arrow-glib.hpp
@@ -26,9 +26,11 @@
 #include <arrow-glib/buffer.hpp>
 #include <arrow-glib/chunked-array.hpp>
 #include <arrow-glib/codec.hpp>
+#include <arrow-glib/compute.hpp>
 #include <arrow-glib/data-type.hpp>
 #include <arrow-glib/datum.hpp>
 #include <arrow-glib/error.hpp>
+#include <arrow-glib/expression.hpp>
 #include <arrow-glib/field.hpp>
 #include <arrow-glib/record-batch.hpp>
 #include <arrow-glib/scalar.hpp>
diff --git a/c_glib/arrow-glib/expression.cpp b/c_glib/arrow-glib/expression.cpp
new file mode 100644
index 0000000..406e121
--- /dev/null
+++ b/c_glib/arrow-glib/expression.cpp
@@ -0,0 +1,265 @@
+/*
+ * 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.
+ */
+
+#include <arrow-glib/compute.hpp>
+#include <arrow-glib/datum.hpp>
+#include <arrow-glib/expression.hpp>
+#include <arrow-glib/error.hpp>
+
+G_BEGIN_DECLS
+
+/**
+ * SECTION: expression
+ * @section_id: expression
+ * @title: Expression
+ * @include: arrow-glib/arrow-glib.h
+ *
+ * #GArrowExpression is a base class for all expression classes such
+ * as #GArrowLiteralExpression.
+ *
+ * #GArrowLiteralExpression is a class for literal value.
+ *
+ * #GArrowFieldExpression is a class for field reference.
+ *
+ * #GArrowCallExpression is a class for function call.
+ *
+ * Since: 6.0.0
+ */
+
+typedef struct GArrowExpressionPrivate_ {
+  arrow::compute::Expression expression;
+} GArrowExpressionPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(GArrowExpression,
+                                    garrow_expression,
+                                    G_TYPE_OBJECT)
+
+#define GARROW_EXPRESSION_GET_PRIVATE(object)  \
+  static_cast<GArrowExpressionPrivate *>(      \
+    garrow_expression_get_instance_private(    \
+      GARROW_EXPRESSION(object)))
+
+static void
+garrow_expression_finalize(GObject *object)
+{
+  auto priv = GARROW_EXPRESSION_GET_PRIVATE(object);
+  priv->expression.~Expression();
+  G_OBJECT_CLASS(garrow_expression_parent_class)->finalize(object);
+}
+
+static void
+garrow_expression_init(GArrowExpression *object)
+{
+  auto priv = GARROW_EXPRESSION_GET_PRIVATE(object);
+  new(&priv->expression) arrow::compute::Expression();
+}
+
+static void
+garrow_expression_class_init(GArrowExpressionClass *klass)
+{
+  auto gobject_class = G_OBJECT_CLASS(klass);
+
+  gobject_class->finalize = garrow_expression_finalize;
+}
+
+/**
+ * garrow_expression_to_string:
+ * @expression: A #GArrowExpression.
+ *
+ * Returns: The formatted expression.
+ *
+ *   It should be freed with g_free() when no longer needed.
+ *
+ * Since: 6.0.0
+ */
+gchar *
+garrow_expression_to_string(GArrowExpression *expression)
+{
+  auto priv = GARROW_EXPRESSION_GET_PRIVATE(expression);
+  auto string = priv->expression.ToString();
+  return g_strndup(string.data(), string.size());
+}
+
+/**
+ * garrow_expression_equal:
+ * @expression: A #GArrowExpression.
+ * @other_expression: A #GArrowExpression.
+ *
+ * Returns: %TRUE if both of them have the same content, %FALSE
+ *   otherwise.
+ *
+ * Since: 6.0.0
+ */
+gboolean
+garrow_expression_equal(GArrowExpression *expression,
+                        GArrowExpression *other_expression)
+{
+  auto priv = GARROW_EXPRESSION_GET_PRIVATE(expression);
+  auto other_priv = GARROW_EXPRESSION_GET_PRIVATE(other_expression);
+  return priv->expression.Equals(other_priv->expression);
+}
+
+
+G_DEFINE_TYPE(GArrowLiteralExpression,
+              garrow_literal_expression,
+              GARROW_TYPE_EXPRESSION)
+
+static void
+garrow_literal_expression_init(GArrowLiteralExpression *object)
+{
+}
+
+static void
+garrow_literal_expression_class_init(GArrowLiteralExpressionClass *klass)
+{
+}
+
+/**
+ * garrow_literal_expression_new:
+ * @datum: A #GArrowDatum.
+ *
+ * Returns: A newly created #GArrowLiteralExpression.
+ *
+ * Since: 6.0.0
+ */
+GArrowLiteralExpression *
+garrow_literal_expression_new(GArrowDatum *datum)
+{
+  auto arrow_datum = garrow_datum_get_raw(datum);
+  auto arrow_expression = arrow::compute::literal(arrow_datum);
+  return 
GARROW_LITERAL_EXPRESSION(garrow_expression_new_raw(arrow_expression));
+}
+
+
+G_DEFINE_TYPE(GArrowFieldExpression,
+              garrow_field_expression,
+              GARROW_TYPE_EXPRESSION)
+
+static void
+garrow_field_expression_init(GArrowFieldExpression *object)
+{
+}
+
+static void
+garrow_field_expression_class_init(GArrowFieldExpressionClass *klass)
+{
+}
+
+/**
+ * garrow_field_expression_new:
+ * @reference: A field name or dot path.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Returns: A newly created #GArrowFieldExpression on sucess, %NULL on
+ *   error.
+ *
+ * Since: 6.0.0
+ */
+GArrowFieldExpression *
+garrow_field_expression_new(const gchar *reference,
+                            GError **error)
+{
+  if (reference && reference[0] == '.') {
+    auto arrow_reference_result = arrow::FieldRef::FromDotPath(reference);
+    if (!garrow::check(error,
+                       arrow_reference_result,
+                       "[field-expression][new]")) {
+      return NULL;
+    }
+    auto arrow_expression = arrow::compute::field_ref(*arrow_reference_result);
+    return 
GARROW_FIELD_EXPRESSION(garrow_expression_new_raw(arrow_expression));
+  } else {
+    arrow::FieldRef arrow_reference(reference);
+    auto arrow_expression = arrow::compute::field_ref(arrow_reference);
+    return 
GARROW_FIELD_EXPRESSION(garrow_expression_new_raw(arrow_expression));
+  }
+}
+
+
+G_DEFINE_TYPE(GArrowCallExpression,
+              garrow_call_expression,
+              GARROW_TYPE_EXPRESSION)
+
+static void
+garrow_call_expression_init(GArrowCallExpression *object)
+{
+}
+
+static void
+garrow_call_expression_class_init(GArrowCallExpressionClass *klass)
+{
+}
+
+/**
+ * garrow_call_expression_new:
+ * @function: A name of function to be called.
+ * @arguments: (element-type GArrowExpression): Arguments of this call.
+ * @options: (nullable): A #GArrowFunctionOptions for the called function.
+ *
+ * Returns: A newly created #GArrowCallExpression.
+ *
+ * Since: 6.0.0
+ */
+GArrowCallExpression *
+garrow_call_expression_new(const gchar *function,
+                           GList *arguments,
+                           GArrowFunctionOptions *options)
+{
+  std::vector<arrow::compute::Expression> arrow_arguments;
+  for (GList *node = arguments; node; node = node->next) {
+    auto argument = GARROW_EXPRESSION(node->data);
+    auto arrow_argument = garrow_expression_get_raw(argument);
+    arrow_arguments.push_back(*arrow_argument);
+  }
+  std::shared_ptr<arrow::compute::FunctionOptions> arrow_options;
+  if (options) {
+    arrow_options.reset(garrow_function_options_get_raw(options));
+  }
+  auto arrow_expression = arrow::compute::call(function,
+                                               arrow_arguments,
+                                               arrow_options);
+  return GARROW_CALL_EXPRESSION(garrow_expression_new_raw(arrow_expression));
+}
+
+
+G_END_DECLS
+
+GArrowExpression *
+garrow_expression_new_raw(const arrow::compute::Expression &arrow_expression)
+{
+  GType gtype = GARROW_TYPE_EXPRESSION;
+  if (arrow_expression.literal()) {
+    gtype = GARROW_TYPE_LITERAL_EXPRESSION;
+  } else if (arrow_expression.parameter()) {
+    gtype = GARROW_TYPE_FIELD_EXPRESSION;
+  } else if (arrow_expression.call()) {
+    gtype = GARROW_TYPE_CALL_EXPRESSION;
+  }
+  auto expression = GARROW_EXPRESSION(g_object_new(gtype, NULL));
+  auto priv = GARROW_EXPRESSION_GET_PRIVATE(expression);
+  priv->expression = arrow_expression;
+  return expression;
+}
+
+arrow::compute::Expression *
+garrow_expression_get_raw(GArrowExpression *expression)
+{
+  auto priv = GARROW_EXPRESSION_GET_PRIVATE(expression);
+  return &(priv->expression);
+}
diff --git a/c_glib/arrow-glib/expression.h b/c_glib/arrow-glib/expression.h
new file mode 100644
index 0000000..1c1a5fb
--- /dev/null
+++ b/c_glib/arrow-glib/expression.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <arrow-glib/compute.h>
+
+G_BEGIN_DECLS
+
+#define GARROW_TYPE_EXPRESSION (garrow_expression_get_type())
+G_DECLARE_DERIVABLE_TYPE(GArrowExpression,
+                         garrow_expression,
+                         GARROW,
+                         EXPRESSION,
+                         GObject)
+struct _GArrowExpressionClass
+{
+  GObjectClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_6_0
+gchar *
+garrow_expression_to_string(GArrowExpression *expression);
+GARROW_AVAILABLE_IN_6_0
+gboolean
+garrow_expression_equal(GArrowExpression *expression,
+                        GArrowExpression *other_expression);
+
+
+#define GARROW_TYPE_LITERAL_EXPRESSION (garrow_literal_expression_get_type())
+G_DECLARE_DERIVABLE_TYPE(GArrowLiteralExpression,
+                         garrow_literal_expression,
+                         GARROW,
+                         LITERAL_EXPRESSION,
+                         GArrowExpression)
+struct _GArrowLiteralExpressionClass
+{
+  GArrowExpressionClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_6_0
+GArrowLiteralExpression *
+garrow_literal_expression_new(GArrowDatum *datum);
+
+
+#define GARROW_TYPE_FIELD_EXPRESSION (garrow_field_expression_get_type())
+G_DECLARE_DERIVABLE_TYPE(GArrowFieldExpression,
+                         garrow_field_expression,
+                         GARROW,
+                         FIELD_EXPRESSION,
+                         GArrowExpression)
+struct _GArrowFieldExpressionClass
+{
+  GArrowExpressionClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_6_0
+GArrowFieldExpression *
+garrow_field_expression_new(const gchar *reference,
+                            GError **error);
+
+
+#define GARROW_TYPE_CALL_EXPRESSION (garrow_call_expression_get_type())
+G_DECLARE_DERIVABLE_TYPE(GArrowCallExpression,
+                         garrow_call_expression,
+                         GARROW,
+                         CALL_EXPRESSION,
+                         GArrowExpression)
+struct _GArrowCallExpressionClass
+{
+  GArrowExpressionClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_6_0
+GArrowCallExpression *
+garrow_call_expression_new(const gchar *function,
+                           GList *arguments,
+                           GArrowFunctionOptions *options);
+
+G_END_DECLS
diff --git a/c_glib/arrow-glib/expression.hpp b/c_glib/arrow-glib/expression.hpp
new file mode 100644
index 0000000..ea872bb
--- /dev/null
+++ b/c_glib/arrow-glib/expression.hpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <arrow/compute/exec/expression.h>
+
+#include <arrow-glib/expression.h>
+
+
+GArrowExpression *
+garrow_expression_new_raw(const arrow::compute::Expression &arrow_expression);
+arrow::compute::Expression *
+garrow_expression_get_raw(GArrowExpression *expression);
diff --git a/c_glib/arrow-glib/meson.build b/c_glib/arrow-glib/meson.build
index d047963..9a399c9 100644
--- a/c_glib/arrow-glib/meson.build
+++ b/c_glib/arrow-glib/meson.build
@@ -29,6 +29,7 @@ sources = files(
   'datum.cpp',
   'decimal.cpp',
   'error.cpp',
+  'expression.cpp',
   'field.cpp',
   'record-batch.cpp',
   'scalar.cpp',
@@ -86,6 +87,7 @@ c_headers = files(
   'datum.h',
   'decimal.h',
   'error.h',
+  'expression.h',
   'field.h',
   'gobject-type.h',
   'record-batch.h',
@@ -144,6 +146,7 @@ cpp_headers = files(
   'datum.hpp',
   'decimal.hpp',
   'error.hpp',
+  'expression.hpp',
   'field.hpp',
   'record-batch.hpp',
   'scalar.hpp',
diff --git a/c_glib/doc/arrow-glib/arrow-glib-docs.xml 
b/c_glib/doc/arrow-glib/arrow-glib-docs.xml
index 4c061c0..43f6a7e 100644
--- a/c_glib/doc/arrow-glib/arrow-glib-docs.xml
+++ b/c_glib/doc/arrow-glib/arrow-glib-docs.xml
@@ -84,6 +84,7 @@
       <title>Computation</title>
       <xi:include href="xml/compute.xml"/>
       <xi:include href="xml/datum.xml"/>
+      <xi:include href="xml/expression.xml"/>
     </chapter>
     <chapter id="buffer">
       <title>Buffer</title>
diff --git a/c_glib/test/test-call-expression.rb 
b/c_glib/test/test-call-expression.rb
new file mode 100644
index 0000000..a8ba2f4
--- /dev/null
+++ b/c_glib/test/test-call-expression.rb
@@ -0,0 +1,42 @@
+# 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.
+
+class TestCallExpression < Test::Unit::TestCase
+  def setup
+    @arguments = [
+      Arrow::FieldExpression.new("augend"),
+      Arrow::FieldExpression.new("addend"),
+    ]
+    @expression = Arrow::CallExpression.new("add", @arguments)
+  end
+
+  sub_test_case("==") do
+    def test_true
+      assert_equal(Arrow::CallExpression.new("now", []),
+                   Arrow::CallExpression.new("now", []))
+    end
+
+    def test_false
+      assert_not_equal(Arrow::CallExpression.new("a", []),
+                       Arrow::CallExpression.new("b", []))
+    end
+  end
+
+  def test_to_string
+    assert_equal("add(augend, addend)", @expression.to_s)
+  end
+end
diff --git a/c_glib/test/test-field-expression.rb 
b/c_glib/test/test-field-expression.rb
new file mode 100644
index 0000000..cdcfab7
--- /dev/null
+++ b/c_glib/test/test-field-expression.rb
@@ -0,0 +1,49 @@
+# 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.
+
+class TestFieldExpression < Test::Unit::TestCase
+  def setup
+    @expression = Arrow::FieldExpression.new("visible")
+  end
+
+  sub_test_case("#initialize") do
+    def test_invalid_dot_path
+      message =
+        "[field-expression][new]: Invalid: " +
+        "Dot path '.[' contained an unterminated index"
+      assert_raise(Arrow::Error::Invalid.new(message)) do
+        Arrow::FieldExpression.new(".[")
+      end
+    end
+  end
+
+  sub_test_case("==") do
+    def test_true
+      assert_equal(Arrow::FieldExpression.new("visible"),
+                   Arrow::FieldExpression.new(".visible"))
+    end
+
+    def test_false
+      assert_not_equal(@expression,
+                       Arrow::FieldExpression.new("equal"))
+    end
+  end
+
+  def test_to_string
+    assert_equal("visible", @expression.to_s)
+  end
+end
diff --git a/c_glib/test/test-literal-expression.rb 
b/c_glib/test/test-literal-expression.rb
new file mode 100644
index 0000000..7a8796f
--- /dev/null
+++ b/c_glib/test/test-literal-expression.rb
@@ -0,0 +1,40 @@
+# 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.
+
+class TestLiteralExpression < Test::Unit::TestCase
+  def setup
+    @scalar = Arrow::BooleanScalar.new(true)
+    @datum = Arrow::ScalarDatum.new(@scalar)
+    @expression = Arrow::LiteralExpression.new(@datum)
+  end
+
+  sub_test_case("==") do
+    def test_true
+      assert_equal(Arrow::LiteralExpression.new(@datum),
+                   Arrow::LiteralExpression.new(@datum))
+    end
+
+    def test_false
+      assert_not_equal(@expression,
+                       Arrow::FieldExpression.new("visible"))
+    end
+  end
+
+  def test_to_string
+    assert_equal("true", @expression.to_s)
+  end
+end
diff --git a/ruby/red-arrow/lib/arrow/expression.rb 
b/ruby/red-arrow/lib/arrow/expression.rb
new file mode 100644
index 0000000..a33cc53
--- /dev/null
+++ b/ruby/red-arrow/lib/arrow/expression.rb
@@ -0,0 +1,48 @@
+# 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.
+
+module Arrow
+  class Expression
+    class << self
+      # @api private
+      def try_convert(value)
+        case value
+        when Symbol
+          FieldExpression.new(value.to_s)
+        when ::Array
+          function_name, *arguments = value
+          case function_name
+          when String, Symbol
+            function_name = function_name.to_s
+          else
+            return nil
+          end
+          if arguments.last.is_a?(FunctionOptions)
+            options = arguments.pop
+          else
+            options = nil
+          end
+          CallExpression.new(function_name, arguments, options)
+        else
+          datum = Datum.try_convert(value)
+          return nil if datum.nil?
+          LiteralExpression.new(datum)
+        end
+      end
+    end
+  end
+end
diff --git a/ruby/red-arrow/lib/arrow/loader.rb 
b/ruby/red-arrow/lib/arrow/loader.rb
index 267f1f3..804a948 100644
--- a/ruby/red-arrow/lib/arrow/loader.rb
+++ b/ruby/red-arrow/lib/arrow/loader.rb
@@ -70,6 +70,7 @@ module Arrow
       require "arrow/dictionary-array"
       require "arrow/dictionary-data-type"
       require "arrow/equal-options"
+      require "arrow/expression"
       require "arrow/field"
       require "arrow/file-output-stream"
       require "arrow/file-system"
diff --git a/ruby/red-arrow/test/test-expression.rb 
b/ruby/red-arrow/test/test-expression.rb
new file mode 100644
index 0000000..e172e78
--- /dev/null
+++ b/ruby/red-arrow/test/test-expression.rb
@@ -0,0 +1,40 @@
+# 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.
+
+class TestExpression < Test::Unit::TestCase
+  sub_test_case(".try_convert") do
+    test("Symbol") do
+      assert_equal(Arrow::FieldExpression.new("visible"),
+                   Arrow::Expression.try_convert(:visible))
+    end
+
+    test("[String]") do
+      assert_equal(Arrow::CallExpression.new("func", []),
+                   Arrow::Expression.try_convert(["func"]))
+    end
+
+    test("[Symbol]") do
+      assert_equal(Arrow::CallExpression.new("func", []),
+                   Arrow::Expression.try_convert([:func]))
+    end
+
+    test("[String, String]") do
+      assert_equal(Arrow::CallExpression.new("func", ["argument1"]),
+                   Arrow::Expression.try_convert(["func", "argument1"]))
+    end
+  end
+end

Reply via email to