Skip to content

Commit

Permalink
apacheGH-37812: [MATLAB] Add arrow.type.ListType MATLAB class (apac…
Browse files Browse the repository at this point in the history
…he#38189)

### Rationale for this change

In support of adding an [`arrow.array.ListArray`](apache#37815) MATLAB class, this pull request adds a new `arrow.type.ListType` MATLAB class.

### What changes are included in this PR?

1. New `arrow.list(<type>)` MATLAB construction function.
2. New `arrow.list.ListType` MATLAB class. `ListType` has a property named `Type` which indicates the inner type of the `List`. `Type` can be set to any subclass `arrow.type.Type` (including `arrow.type.ListType`, to support nested lists).
3. New `arrow.type.ID.List` type ID enumeration value.
4. New `arrow.type.traits.ListTraits` type traits class. Some of the properties, such as `ArrayConstructor` and `ArrayProxyClassName`, are set to `missing` because they are dependent on adding [`arrow.array.ListArray`](apache#37815) first.

**Example**
```matlab
% Create a simple List<String> type.
>> stringListType = arrow.list(arrow.string())

stringListType = 

  ListType with properties:

      ID: List
    Type: [1x1 arrow.type.StringType]

% Create a nested List<List<Boolean>> type.
>> nestedListType = arrow.list(arrow.list(arrow.boolean()))

nestedListType = 

  ListType with properties:

      ID: List
    Type: [1x1 arrow.type.ListType]

% Extract the first-level, inner type, which is List<Boolean>.
>> innerType = nestedListType.Type

innerType = 

  ListType with properties:

      ID: List
    Type: [1x1 arrow.type.BooleanType]

% Extract the second-level, nested inner type, which is Boolean.
>> innerType.Type  

ans = 

  BooleanType with properties:

    ID: Boolean
```

### Are these changes tested?

Yes.

1. Added `tListType.m`.
2. Added `tListTraits.m`.
3. Updated `tField.m` to include `arrow.list`.
4. Updated `tID.m` to include `arrow.type.ID.List`.
6. Updated `tTypeDisplay.m` to include `arrow.type.ListType`.
7. Updated `ttraits.m` to include `arrow.type.traits.ListTraits`.

### Are there any user-facing changes?

Yes.

Client MATLAB code can now creates instances of `arrow.type.ListType` by using the `arrow.list(<type>)` construction function.

### Future Directions

1. apache#37815
* Closes: apache#37812

Authored-by: Kevin Gurney <[email protected]>
Signed-off-by: Kevin Gurney <[email protected]>
  • Loading branch information
kevingurney authored Oct 11, 2023
1 parent 757cf3e commit 852f09d
Show file tree
Hide file tree
Showing 18 changed files with 463 additions and 24 deletions.
1 change: 1 addition & 0 deletions matlab/src/cpp/arrow/matlab/error/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ namespace arrow::matlab::error {
static const char* INVALID_TIME_UNIT = "arrow:type:InvalidTimeUnit";
static const char* FIELD_FAILED_TO_CREATE_TYPE_PROXY = "arrow:field:FailedToCreateTypeProxy";
static const char* ARRAY_FAILED_TO_CREATE_TYPE_PROXY = "arrow:array:FailedToCreateTypeProxy";
static const char* LIST_TYPE_FAILED_TO_CREATE_VALUE_TYPE_PROXY = "arrow:type:list:FailedToCreateValueTypeProxy";
static const char* ARROW_TABULAR_SCHEMA_AMBIGUOUS_FIELD_NAME = "arrow:tabular:schema:AmbiguousFieldName";
static const char* UNKNOWN_PROXY_FOR_ARRAY_TYPE = "arrow:array:UnknownProxyForArrayType";
static const char* RECORD_BATCH_NUMERIC_INDEX_WITH_EMPTY_RECORD_BATCH = "arrow:tabular:recordbatch:NumericIndexWithEmptyRecordBatch";
Expand Down
2 changes: 2 additions & 0 deletions matlab/src/cpp/arrow/matlab/proxy/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "arrow/matlab/type/proxy/time32_type.h"
#include "arrow/matlab/type/proxy/time64_type.h"
#include "arrow/matlab/type/proxy/struct_type.h"
#include "arrow/matlab/type/proxy/list_type.h"
#include "arrow/matlab/type/proxy/field.h"
#include "arrow/matlab/io/feather/proxy/writer.h"
#include "arrow/matlab/io/feather/proxy/reader.h"
Expand Down Expand Up @@ -89,6 +90,7 @@ libmexclass::proxy::MakeResult Factory::make_proxy(const ClassName& class_name,
REGISTER_PROXY(arrow.type.proxy.Date32Type , arrow::matlab::type::proxy::Date32Type);
REGISTER_PROXY(arrow.type.proxy.Date64Type , arrow::matlab::type::proxy::Date64Type);
REGISTER_PROXY(arrow.type.proxy.StructType , arrow::matlab::type::proxy::StructType);
REGISTER_PROXY(arrow.type.proxy.ListType , arrow::matlab::type::proxy::ListType);
REGISTER_PROXY(arrow.io.feather.proxy.Writer , arrow::matlab::io::feather::proxy::Writer);
REGISTER_PROXY(arrow.io.feather.proxy.Reader , arrow::matlab::io::feather::proxy::Reader);
REGISTER_PROXY(arrow.io.csv.proxy.TableWriter , arrow::matlab::io::csv::proxy::TableWriter);
Expand Down
64 changes: 64 additions & 0 deletions matlab/src/cpp/arrow/matlab/type/proxy/list_type.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// 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/matlab/type/proxy/list_type.h"
#include "arrow/matlab/type/proxy/wrap.h"
#include "libmexclass/proxy/ProxyManager.h"
#include "arrow/matlab/error/error.h"

namespace arrow::matlab::type::proxy {

ListType::ListType(std::shared_ptr<arrow::ListType> list_type) : Type(std::move(list_type)) {
REGISTER_METHOD(ListType, getValueType);
}

void ListType::getValueType(libmexclass::proxy::method::Context& context) {
namespace mda = ::matlab::data;
mda::ArrayFactory factory;

const auto list_type = std::static_pointer_cast<arrow::ListType>(data_type);
const auto value_type = list_type->value_type();
const auto value_type_id = static_cast<int32_t>(value_type->id());

MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto value_type_proxy,
type::proxy::wrap(value_type),
context,
error::LIST_TYPE_FAILED_TO_CREATE_VALUE_TYPE_PROXY);
const auto value_type_proxy_id = libmexclass::proxy::ProxyManager::manageProxy(value_type_proxy);

mda::StructArray output = factory.createStructArray({1, 1}, {"ValueTypeProxyID", "ValueTypeID"});
output[0]["ValueTypeProxyID"] = factory.createScalar(value_type_proxy_id);
output[0]["ValueTypeID"] = factory.createScalar(value_type_id);

context.outputs[0] = output;
}

libmexclass::proxy::MakeResult ListType::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {
namespace mda = ::matlab::data;
using namespace libmexclass::proxy;
using ListTypeProxy = arrow::matlab::type::proxy::ListType;

mda::StructArray args = constructor_arguments[0];
const mda::TypedArray<uint64_t> value_type_proxy_id_mda = args[0]["ValueTypeProxyID"];
const auto value_type_proxy_id = value_type_proxy_id_mda[0];
const auto proxy = ProxyManager::getProxy(value_type_proxy_id);
const auto value_type_proxy = std::static_pointer_cast<type::proxy::Type>(proxy);
const auto value_type = value_type_proxy->unwrap();
const auto list_type = std::static_pointer_cast<arrow::ListType>(arrow::list(value_type));
return std::make_shared<ListTypeProxy>(std::move(list_type));
}
}
36 changes: 36 additions & 0 deletions matlab/src/cpp/arrow/matlab/type/proxy/list_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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/matlab/type/proxy/type.h"

namespace arrow::matlab::type::proxy {

class ListType : public arrow::matlab::type::proxy::Type {

public:
ListType(std::shared_ptr<arrow::ListType> list_type);

~ListType() {}

void getValueType(libmexclass::proxy::method::Context& context);

static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments);
};

}
4 changes: 2 additions & 2 deletions matlab/src/cpp/arrow/matlab/type/proxy/struct_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ namespace arrow::matlab::type::proxy {
~StructType() {}

static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments);
};
};

}
}
5 changes: 4 additions & 1 deletion matlab/src/cpp/arrow/matlab/type/proxy/wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "arrow/matlab/type/proxy/date32_type.h"
#include "arrow/matlab/type/proxy/date64_type.h"
#include "arrow/matlab/type/proxy/string_type.h"
#include "arrow/matlab/type/proxy/list_type.h"
#include "arrow/matlab/type/proxy/struct_type.h"

namespace arrow::matlab::type::proxy {
Expand Down Expand Up @@ -65,7 +66,9 @@ namespace arrow::matlab::type::proxy {
return std::make_shared<Date64Type>(std::static_pointer_cast<arrow::Date64Type>(type));
case ID::STRING:
return std::make_shared<StringType>(std::static_pointer_cast<arrow::StringType>(type));
case ID::STRUCT:
case ID::LIST:
return std::make_shared<ListType>(std::static_pointer_cast<arrow::ListType>(type));
case ID::STRUCT:
return std::make_shared<StructType>(std::static_pointer_cast<arrow::StructType>(type));
default:
return arrow::Status::NotImplemented("Unsupported DataType: " + type->ToString());
Expand Down
30 changes: 30 additions & 0 deletions matlab/src/matlab/+arrow/+type/+traits/ListTraits.m
Original file line number Diff line number Diff line change
@@ -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.

classdef ListTraits < arrow.type.traits.TypeTraits

properties (Constant)
ArrayConstructor = missing
ArrayClassName = missing
ArrayProxyClassName = missing
ArrayStaticConstructor = missing
TypeConstructor = @arrow.type.ListType
TypeClassName = "arrow.type.ListType"
TypeProxyClassName = "arrow.type.proxy.ListType"
MatlabConstructor = missing
MatlabClassName = missing
end

end
4 changes: 3 additions & 1 deletion matlab/src/matlab/+arrow/+type/+traits/traits.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
typeTraits = Date32Traits();
case ID.Date64
typeTraits = Date64Traits();
case ID.List
typeTraits = ListTraits();
case ID.Struct
typeTraits = StructTraits();
otherwise
Expand Down Expand Up @@ -100,4 +102,4 @@
error("arrow:type:traits:UnsupportedInputType", "The input argument to the traits function " + ...
"must be a MATLAB class string or an arrow.type.ID enumeration.");
end
end
end
40 changes: 20 additions & 20 deletions matlab/src/matlab/+arrow/+type/ID.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,31 @@

classdef ID < uint64
enumeration
Boolean (1)
UInt8 (2)
Int8 (3)
UInt16 (4)
Int16 (5)
UInt32 (6)
Int32 (7)
UInt64 (8)
Int64 (9)
% Float16 (10) not yet supported
Float32 (11)
Float64 (12)
String (13)
% Binary (14)
Boolean (1)
UInt8 (2)
Int8 (3)
UInt16 (4)
Int16 (5)
UInt32 (6)
Int32 (7)
UInt64 (8)
Int64 (9)
% Float16 (10)
Float32 (11)
Float64 (12)
String (13)
% Binary (14)
% FixedSizeBinary (15)
Date32 (16)
Date64 (17)
Timestamp (18)
Time32 (19)
Time64 (20)
Date32 (16)
Date64 (17)
Timestamp (18)
Time32 (19)
Time64 (20)
% IntervalMonths (21)
% IntervalDayTime (22)
% Decimal128 (23)
% Decimal256 (24)
% List (25)
List (25)
Struct (26)
end
end
57 changes: 57 additions & 0 deletions matlab/src/matlab/+arrow/+type/ListType.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
% 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.

classdef ListType < arrow.type.Type

properties (Dependent, GetAccess=public, SetAccess=private)
% The inner element type T of the List<T>.
% For example: for List<UInt64>, ValueType = UInt64.
ValueType
end

methods
function obj = ListType(proxy)
arguments
proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, "arrow.type.proxy.ListType")}
end
import arrow.internal.proxy.validate
[email protected](proxy);
end
end

methods(Access = protected)
function groups = getDisplayPropertyGroups(~)
targets = ["ID", "ValueType"];
groups = matlab.mixin.util.PropertyGroup(targets);
end
end


methods
function valueType = get.ValueType(obj)
valueTypeStruct = obj.Proxy.getValueType();
traits = arrow.type.traits.traits(arrow.type.ID(valueTypeStruct.ValueTypeID));
proxy = libmexclass.proxy.Proxy(Name=traits.TypeProxyClassName, ID=valueTypeStruct.ValueTypeProxyID);
valueType = traits.TypeConstructor(proxy);
end
end

methods (Hidden)
function data = preallocateMATLABArray(~, numElements)
% Preallocate an empty cell array.
data = cell(numElements, 1);
end
end
end
26 changes: 26 additions & 0 deletions matlab/src/matlab/+arrow/list.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
%LIST Creates an arrow.type.ListType object

% 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.
function listType = list(valueType)
arguments
valueType(1, 1) arrow.type.Type
end

valueTypeProxyID = valueType.Proxy.ID;
args = struct(ValueTypeProxyID=valueTypeProxyID);
proxy = arrow.internal.proxy.create("arrow.type.proxy.ListType", args);
listType = arrow.type.ListType(proxy);
end
1 change: 1 addition & 0 deletions matlab/test/arrow/type/tField.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function TestSupportedTypes(testCase)
arrow.float64, ...
arrow.string, ...
arrow.timestamp, ...
arrow.list(arrow.uint64()), ...
arrow.struct(arrow.field("A", arrow.float32()))
};
for ii = 1:numel(supportedTypes)
Expand Down
1 change: 1 addition & 0 deletions matlab/test/arrow/type/tID.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function CastToUInt64(testCase)
ID.Timestamp, 18, ...
ID.Time32, 19, ...
ID.Time64, 20, ...
ID.List, 25, ...
ID.Struct, 26 ...
);

Expand Down
Loading

0 comments on commit 852f09d

Please sign in to comment.