[ 
https://issues.apache.org/jira/browse/ARROW-1487?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16280972#comment-16280972
 ] 

ASF GitHub Bot commented on ARROW-1487:
---------------------------------------

wesm closed pull request #1383: ARROW-1487: [C++] Implement casts from List<A> 
to List<B>, where a cast function is defined from any A to B
URL: https://github.com/apache/arrow/pull/1383
 
 
   

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/cpp/src/arrow/compute/compute-test.cc 
b/cpp/src/arrow/compute/compute-test.cc
index 84af8f7c6..3fc150186 100644
--- a/cpp/src/arrow/compute/compute-test.cc
+++ b/cpp/src/arrow/compute/compute-test.cc
@@ -801,6 +801,47 @@ TYPED_TEST(TestDictionaryCast, Basic) {
   this->CheckPass(*plain_array, *dict_array, dict_array->type(), options);
 }*/
 
+TEST_F(TestCast, ListToList) {
+  CastOptions options;
+  std::shared_ptr<Array> offsets;
+
+  vector<int32_t> offsets_values = {0, 1, 2, 5, 7, 7, 8, 10};
+  std::vector<bool> offsets_is_valid = {true, true, true, true, false, true, 
true, true};
+  ArrayFromVector<Int32Type, int32_t>(offsets_is_valid, offsets_values, 
&offsets);
+
+  shared_ptr<Array> int32_plain_array =
+      TestBase::MakeRandomArray<typename TypeTraits<Int32Type>::ArrayType>(10, 
2);
+  std::shared_ptr<Array> int32_list_array;
+  ASSERT_OK(
+      ListArray::FromArrays(*offsets, *int32_plain_array, pool_, 
&int32_list_array));
+
+  std::shared_ptr<Array> int64_plain_array;
+  ASSERT_OK(Cast(&this->ctx_, *int32_plain_array, int64(), options, 
&int64_plain_array));
+  std::shared_ptr<Array> int64_list_array;
+  ASSERT_OK(
+      ListArray::FromArrays(*offsets, *int64_plain_array, pool_, 
&int64_list_array));
+
+  std::shared_ptr<Array> float64_plain_array;
+  ASSERT_OK(
+      Cast(&this->ctx_, *int32_plain_array, float64(), options, 
&float64_plain_array));
+  std::shared_ptr<Array> float64_list_array;
+  ASSERT_OK(
+      ListArray::FromArrays(*offsets, *float64_plain_array, pool_, 
&float64_list_array));
+
+  this->CheckPass(*int32_list_array, *int64_list_array, 
int64_list_array->type(),
+                  options);
+  this->CheckPass(*int32_list_array, *float64_list_array, 
float64_list_array->type(),
+                  options);
+  this->CheckPass(*int64_list_array, *int32_list_array, 
int32_list_array->type(),
+                  options);
+  this->CheckPass(*int64_list_array, *float64_list_array, 
float64_list_array->type(),
+                  options);
+  this->CheckPass(*float64_list_array, *int32_list_array, 
int32_list_array->type(),
+                  options);
+  this->CheckPass(*float64_list_array, *int64_list_array, 
int64_list_array->type(),
+                  options);
+}
+
 // ----------------------------------------------------------------------
 // Dictionary tests
 
diff --git a/cpp/src/arrow/compute/kernels/cast.cc 
b/cpp/src/arrow/compute/kernels/cast.cc
index 465be958c..afa05485f 100644
--- a/cpp/src/arrow/compute/kernels/cast.cc
+++ b/cpp/src/arrow/compute/kernels/cast.cc
@@ -460,6 +460,49 @@ struct CastFunctor<Date32Type, Date64Type> {
   }
 };
 
+// ----------------------------------------------------------------------
+// List to List
+
+class ListCastKernel : public UnaryKernel {
+ public:
+  ListCastKernel(std::unique_ptr<UnaryKernel> child_caster,
+                 const std::shared_ptr<DataType>& out_type)
+      : child_caster_(std::move(child_caster)), out_type_(out_type) {}
+
+  Status Call(FunctionContext* ctx, const Datum& input, Datum* out) override {
+    DCHECK_EQ(Datum::ARRAY, input.kind());
+
+    const ArrayData& in_data = *input.array();
+    DCHECK_EQ(Type::LIST, in_data.type->id());
+    ArrayData* result;
+
+    if (in_data.offset != 0) {
+      return Status::NotImplemented(
+          "Casting sliced lists (non-zero offset) not yet implemented");
+    }
+
+    if (out->kind() == Datum::NONE) {
+      out->value = ArrayData::Make(out_type_, in_data.length);
+    }
+
+    result = out->array().get();
+
+    // Copy buffers from parent
+    result->buffers = in_data.buffers;
+
+    Datum casted_child;
+    RETURN_NOT_OK(child_caster_->Call(ctx, Datum(in_data.child_data[0]), 
&casted_child));
+    result->child_data.push_back(casted_child.array());
+
+    RETURN_IF_ERROR(ctx);
+    return Status::OK();
+  }
+
+ private:
+  std::unique_ptr<UnaryKernel> child_caster_;
+  std::shared_ptr<DataType> out_type_;
+};
+
 // ----------------------------------------------------------------------
 // Dictionary to other things
 
@@ -895,7 +938,6 @@ GET_CAST_FUNCTION(DATE64_CASES, Date64Type);
 GET_CAST_FUNCTION(TIME32_CASES, Time32Type);
 GET_CAST_FUNCTION(TIME64_CASES, Time64Type);
 GET_CAST_FUNCTION(TIMESTAMP_CASES, TimestampType);
-
 GET_CAST_FUNCTION(DICTIONARY_CASES, DictionaryType);
 
 #define CAST_FUNCTION_CASE(InType)                      \
@@ -903,6 +945,26 @@ GET_CAST_FUNCTION(DICTIONARY_CASES, DictionaryType);
     *kernel = Get##InType##CastFunc(out_type, options); \
     break
 
+namespace {
+
+Status GetListCastFunc(const DataType& in_type, const 
std::shared_ptr<DataType>& out_type,
+                       const CastOptions& options, 
std::unique_ptr<UnaryKernel>* kernel) {
+  if (out_type->id() != Type::LIST) {
+    // Kernel will be null
+    return Status::OK();
+  }
+  const DataType& in_value_type = *static_cast<const 
ListType&>(in_type).value_type();
+  std::shared_ptr<DataType> out_value_type =
+      static_cast<const ListType&>(*out_type).value_type();
+  std::unique_ptr<UnaryKernel> child_caster;
+  RETURN_NOT_OK(GetCastFunction(in_value_type, out_value_type, options, 
&child_caster));
+  *kernel =
+      std::unique_ptr<UnaryKernel>(new ListCastKernel(std::move(child_caster), 
out_type));
+  return Status::OK();
+}
+
+}  // namespace
+
 Status GetCastFunction(const DataType& in_type, const 
std::shared_ptr<DataType>& out_type,
                        const CastOptions& options, 
std::unique_ptr<UnaryKernel>* kernel) {
   switch (in_type.id()) {
@@ -924,6 +986,9 @@ Status GetCastFunction(const DataType& in_type, const 
std::shared_ptr<DataType>&
     CAST_FUNCTION_CASE(Time64Type);
     CAST_FUNCTION_CASE(TimestampType);
     CAST_FUNCTION_CASE(DictionaryType);
+    case Type::LIST:
+      RETURN_NOT_OK(GetListCastFunc(in_type, out_type, options, kernel));
+      break;
     default:
       break;
   }


 

----------------------------------------------------------------
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:
[email protected]


> [C++] Implement casts from List<A> to List<B>, where a cast function is 
> defined from any A to B
> -----------------------------------------------------------------------------------------------
>
>                 Key: ARROW-1487
>                 URL: https://issues.apache.org/jira/browse/ARROW-1487
>             Project: Apache Arrow
>          Issue Type: New Feature
>          Components: C++
>            Reporter: Wes McKinney
>            Assignee: Licht Takeuchi
>              Labels: pull-request-available
>             Fix For: 0.8.0
>
>
> If a cast rule for the child type is not implemented, the failure should 
> occur during kernel selection rather than at kernel evaluation time. 



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to