This is an automated email from the ASF dual-hosted git repository.
sgilmore pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new ce0fa3dfcc GH-38213: [MATLAB] Create a superclass for tabular type
MATLAB tests (i.e. for `Table` and `RecordBatch`) (#47107)
ce0fa3dfcc is described below
commit ce0fa3dfcc204d8868ef51c89943dee2e3a12181
Author: Sarah Gilmore <[email protected]>
AuthorDate: Tue Jul 15 15:29:48 2025 -0400
GH-38213: [MATLAB] Create a superclass for tabular type MATLAB tests (i.e.
for `Table` and `RecordBatch`) (#47107)
### Rationale for this change
Many of the tests for `Table` and `RecordBatch `are similar. To reduce code
duplication and ensure consistency, we could consider adding a shared
superclass for tabular type tests.
### What changes are included in this PR?
Refactored `tTable` and `tRecordBatch` to inherit from `hTabular`.
`hTabular` i a new MATLAB test class that defines shared tests for `Table` and
`RecordBatch`.
### Are these changes tested?
Yes (see the MATLAB GitHub Actions workflow runs).
### Are there any user-facing changes?
No.
* GitHub Issue: #38213
Lead-authored-by: Sarah Gilmore
<[email protected]>
Co-authored-by: Sarah Gilmore <[email protected]>
Co-authored-by: Kevin Gurney <[email protected]>
Signed-off-by: Sarah Gilmore <[email protected]>
---
matlab/test/arrow/tabular/hTabular.m | 651 ++++++++++++++++++++++++++++
matlab/test/arrow/tabular/tRecordBatch.m | 525 +----------------------
matlab/test/arrow/tabular/tTable.m | 699 ++-----------------------------
3 files changed, 709 insertions(+), 1166 deletions(-)
diff --git a/matlab/test/arrow/tabular/hTabular.m
b/matlab/test/arrow/tabular/hTabular.m
new file mode 100644
index 0000000000..e2ca16a90b
--- /dev/null
+++ b/matlab/test/arrow/tabular/hTabular.m
@@ -0,0 +1,651 @@
+%HTABULAR Shared test class for tabular types.
+
+% 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 hTabular < matlab.unittest.TestCase
+
+ properties (Abstract)
+ % Must be a handle function to the fromArrays construction
+ % function (i.e. @arrow.tabular.Table.fromArrays)
+ FromArraysFcn
+ % Must be a handle function to the convenience construction
+ % function. (i.e. @arrow.table)
+ ConstructionFcn
+ % Must be full class name (i.e. "arrow.tabular.Table").
+ ClassName(1, 1) string
+ end
+
+ properties
+ ShortClassName(1, 1) string
+ ErrorIdentifierPrefix(1, 1) string
+ end
+
+ methods (TestClassSetup)
+ function initializeShortClassName(tc)
+ dotPos = strfind(tc.ClassName, ".");
+ tc.ShortClassName = extractAfter(tc.ClassName, dotPos(end));
+ end
+
+ function initializeErrorIdentifierPrefix(tc)
+ tc.ErrorIdentifierPrefix = "arrow:tabular:" +
lower(tc.ShortClassName) + ":";
+ end
+
+ end
+
+ methods (Abstract)
+ % Used by test methods to verify arrowTabularObj has the expected
+ % value. Subclasses of hTabular are responsible for implementing
+ % this method.
+ %
+ % columnNames is a string array containing the expected ColumnNames
+ % property value of arrowTabularObj.
+ %
+ % columnTraits is a cell array where each element is an
+ % arrow.type.traits.TypeTraits instance. Each TypeTraits instance
+ % corresponds to a column in arrowTabularObj.
+ %
+ % matlabTable is the expected output of calling the
+ % toMATLAB() method on arrowTabularObj.
+ verifyTabularObject(tc, arrowTabularObj, columnNames, columnTraits,
matlabTable)
+
+ % Used to verify the output of the arrow.tabular.Tabular/column()
+ % method. Subclasses of hTabular are responsible for implementing
+ % this method.
+ %
+ % This method must accept an arrow.array.Array as input and
+ % convert it to an instance of the Arrow type that the column()
+ % method returns.
+ col = makeColumnFromArray(tc, array)
+ end
+
+ methods (Test, TestTags={'construction'})
+ function ConstructionFunction(tc)
+ % Verify the convenience construction function creates an
+ % instance of the expected tabular type when provided a
+ % MATLAB table as input.
+ T = table([1, 2, 3]');
+ obj = tc.ConstructionFcn(T);
+ className = string(class(obj));
+ tc.verifyEqual(className, tc.ClassName);
+ end
+
+ function ConstructionFunctionZeroArguments(tc)
+ % Verify the convenience construction function creates an
+ % instance of the expected tabular type when provided zero
+ % input arguments.
+ obj = tc.ConstructionFcn();
+ className = string(class(obj));
+ tc.verifyEqual(className, tc.ClassName);
+ tc.verifyEqual(obj.NumRows, int64(0));
+ tc.verifyEqual(obj.NumColumns, int32(0));
+ end
+
+ function EmptyTabularObject(tc)
+ % Verify the convenience construction function creates a
+ % tabular object (of the correct type) when provided an empty
+ % MATLAB table as input.
+ matlabTable = table.empty(0, 0);
+ tabularObj = tc.ConstructionFcn(matlabTable);
+ tc.verifyEqual(tabularObj.NumRows, int64(0));
+ tc.verifyEqual(tabularObj.NumColumns, int32(0));
+ tc.verifyEqual(tabularObj.ColumnNames, string.empty(1, 0));
+ tc.verifyEqual(toMATLAB(tabularObj), matlabTable);
+
+ matlabTable = table.empty(1, 0);
+ tabularObj = tc.ConstructionFcn(matlabTable);
+ tc.verifyEqual(tabularObj.NumRows, int64(0));
+ tc.verifyEqual(tabularObj.NumColumns, int32(0));
+ tc.verifyEqual(tabularObj.ColumnNames, string.empty(1, 0));
+
+ matlabTable = table.empty(0, 1);
+ tabularObj = tc.ConstructionFcn(matlabTable);
+ tc.verifyEqual(tabularObj.NumRows, int64(0));
+ tc.verifyEqual(tabularObj.NumColumns, int32(1));
+ tc.verifyEqual(tabularObj.ColumnNames, "Var1");
+ end
+
+ function SupportedTypes(tc)
+ % Verify the convenience construction function creates an
+ % instance of the expected tabular type when provided a MATLAB
+ % table containing all MATLAB types that can be converted to
+ % Arrow Arrays.
+ import arrow.internal.test.tabular.createTableWithSupportedTypes
+ import arrow.type.traits.traits
+
+ matlabTable = createTableWithSupportedTypes();
+ arrowTabularObj = tc.ConstructionFcn(matlabTable);
+ expectedColumnNames = string(matlabTable.Properties.VariableNames);
+
+ % For each variable in the input MATLAB table, look up the
+ % corresponding Arrow Type using type traits.
+ expectedColumnTraits = varfun(@(var) traits(string(class(var))),
...
+ matlabTable, OutputFormat="cell");
+ tc.verifyTabularObject(arrowTabularObj, expectedColumnNames,
expectedColumnTraits, matlabTable);
+ end
+
+ end
+
+ methods (Test, TestTags={'Properties'})
+
+ function ColumnNames(tc)
+ % Verify ColumnNames is set to the expected value.
+ columnNames = ["A", "B", "C"];
+ TOriginal = table(1, 2, 3, VariableNames=columnNames);
+ tabularObj = tc.ConstructionFcn(TOriginal);
+ tc.verifyEqual(tabularObj.ColumnNames, columnNames);
+ end
+
+ function UnicodeColumnNames(tc)
+ % Verify column names can contain non-ascii characters.
+ smiley = "😀";
+ tree = "🌲";
+ mango = "ðŸ¥";
+ columnNames = [smiley, tree, mango];
+ TOriginal = table(1, 2, 3, VariableNames=columnNames);
+ tabularObj = tc.ConstructionFcn(TOriginal);
+ tc.verifyEqual(tabularObj.ColumnNames, columnNames);
+ TConverted = tabularObj.toMATLAB();
+ tc.verifyEqual(TOriginal, TConverted);
+ end
+
+ function ColumnNamesNoSetter(tc)
+ % Verify ColumnNames is not settable.
+ t = table([1; 2; 3]);
+ tabularObj = tc.ConstructionFcn(t);
+ tc.verifyError(@() setfield(tabularObj, "ColumnNames", "x"), ...
+ "MATLAB:class:SetProhibited");
+ end
+
+ function NumRows(tc)
+ % Verify the NumRows property is set to the expected value.
+ numRows = int64([1, 5, 100]);
+ for expectedNumRows = numRows
+ matlabTable = array2table(ones(expectedNumRows, 1));
+ arrowTable = arrow.table(matlabTable);
+ tc.verifyEqual(arrowTable.NumRows, expectedNumRows);
+ end
+ end
+
+ function NumRowsNoSetter(tc)
+ % Verify NumRows is not settable.
+ t = table([1; 2; 3]);
+ tabularObj = tc.ConstructionFcn(t);
+ tc.verifyError(@() setfield(tabularObj, "NumRows", 10), ...
+ "MATLAB:class:SetProhibited");
+ end
+
+ function NumColumns(tc)
+ % Verify the NumColumns property is set to the expected value.
+ numColumns = int32([1, 5, 100]);
+ for nc = numColumns
+ T = array2table(ones(1, nc));
+ tabularObj = tc.ConstructionFcn(T);
+ tc.verifyEqual(tabularObj.NumColumns, nc);
+ end
+ end
+
+ function NumColumnsNoSetter(tc)
+ % Verify the NumColumns property is not settable.
+ t = table([1; 2; 3]);
+ tabularObj = tc.ConstructionFcn(t);
+ tc.verifyError(@() setfield(tabularObj, "NumColumns", 10), ...
+ "MATLAB:class:SetProhibited");
+ end
+
+ function Schema(tc)
+ % Verify the Schema property is an instance of
+ % arrow.tabular.Schema and correctly configured.
+ matlabTable = table(...
+ ["A"; "B"; "C"], ...
+ [1; 2; 3], ...
+ [true; false; true], ...
+ VariableNames=["A", "B", "C"] ...
+ );
+ tabularObj = tc.ConstructionFcn(matlabTable);
+ schema = tabularObj.Schema;
+ tc.verifyEqual(schema.NumFields, int32(3));
+ tc.verifyEqual(schema.field(1).Type.ID, arrow.type.ID.String);
+ tc.verifyEqual(schema.field(1).Name, "A");
+ tc.verifyEqual(schema.field(2).Type.ID, arrow.type.ID.Float64);
+ tc.verifyEqual(schema.field(2).Name, "B");
+ tc.verifyEqual(schema.field(3).Type.ID, arrow.type.ID.Boolean);
+ tc.verifyEqual(schema.field(3).Name, "C");
+ end
+
+ function SchemaNoSetter(tc)
+ % Verify the Schema property is not settable.
+ t = table([1; 2; 3]);
+ tabularObj = tc.ConstructionFcn(t);
+ tc.verifyError(@() setfield(tabularObj, "Schema", "Value"), ...
+ "MATLAB:class:SetProhibited");
+ end
+ end
+
+ methods (Test, TestTags={'Conversion functions'})
+
+ function ToMATLAB(tc)
+ % Verify the toMATLAB() method returns the expected MATLAB table.
+ expectedMatlabTable = table([1, 2, 3]');
+ arrowTabularObj = tc.ConstructionFcn(expectedMatlabTable);
+ actualMatlabTable = arrowTabularObj.toMATLAB();
+ tc.verifyEqual(actualMatlabTable, expectedMatlabTable);
+ end
+
+ function Table(tc)
+ % Verify the table() method returns the expected MATLAB table.
+ TOriginal = table([1, 2, 3]');
+ arrowTable = tc.ConstructionFcn(TOriginal);
+ TConverted = table(arrowTable);
+ tc.verifyEqual(TOriginal, TConverted);
+ end
+
+ end
+
+ methods (Test, TestTags={'fromArrays'})
+
+ function FromArraysColumnNamesNotProvided(tc)
+ % Verify the fromArrays function creates the expected
+ % Tabular object when given a comma-separated list of
+ % arrow.array.Array instances.
+ import arrow.type.traits.traits
+ import arrow.internal.test.tabular.createAllSupportedArrayTypes
+
+ [arrowArrays, matlabData] = createAllSupportedArrayTypes();
+ TOriginal = table(matlabData{:});
+
+ tabularObj = tc.FromArraysFcn(arrowArrays{:});
+ columnNames = compose("Column%d", 1:width(TOriginal));
+ TOriginal.Properties.VariableNames = columnNames;
+ columnTraits = cellfun(@(array) traits(array.Type.ID),
arrowArrays, UniformOutput=false);
+ tc.verifyTabularObject(tabularObj, columnNames, columnTraits,
TOriginal);
+ end
+
+ function FromArraysWithColumnNamesProvided(tc)
+ % Verify the fromArrays function creates the expected
+ % Tabular object when given a comma-separated list of
+ % arrow.array.Array instances and the ColumnNames nv-argument
+ % is provided.
+ import arrow.type.traits.traits
+ import arrow.internal.test.tabular.createAllSupportedArrayTypes
+
+ [arrowArrays, matlabData] = createAllSupportedArrayTypes();
+ TOriginal = table(matlabData{:});
+
+ columnNames = compose("MyVar%d", 1:numel(arrowArrays));
+ tabularObj = tc.FromArraysFcn(arrowArrays{:},
ColumnNames=columnNames);
+ TOriginal.Properties.VariableNames = columnNames;
+ columnTraits = cellfun(@(array) traits(array.Type.ID),
arrowArrays, UniformOutput=false);
+ tc.verifyTabularObject(tabularObj, columnNames, columnTraits,
TOriginal);
+ end
+
+ function FromArraysUnequalArrayLengthsError(tc)
+ % Verify the fromArrays function throws an exception with the
+ % identifier "arrow:tabular:UnequalArrayLengths" if the
+ % arrays provided have different sizes.
+ A1 = arrow.array([1, 2]);
+ A2 = arrow.array(["A", "B", "C"]);
+ fcn = @() tc.FromArraysFcn(A1, A2);
+ tc.verifyError(fcn, "arrow:tabular:UnequalArrayLengths");
+ end
+
+ function FromArraysWrongNumberColumnNamesError(tc)
+ % Verify the fromArrays function throws an exception with the
+ % identifier "arrow:tabular:WrongNumberColumnNames" if the
+ % size of ColumnNames does not match the number of arrays
+ % provided.
+ A1 = arrow.array([1, 2]);
+ A2 = arrow.array(["A", "B"]);
+ fcn = @() tc.FromArraysFcn(A1, A2, columnNames=["A", "B", "C"]);
+ tc.verifyError(fcn, "arrow:tabular:WrongNumberColumnNames");
+ end
+
+ function FromArraysColumnNamesHasMissingString(tc)
+ % Verify the fromArrays function throws an exception with the
+ % identifier "MATLAB:validators:mustBeNonmissing" if
+ % ColumnNames is a string array with missing values.
+ A1 = arrow.array([1, 2]);
+ A2 = arrow.array(["A", "B"]);
+ fcn = @() tc.FromArraysFcn(A1, A2, columnNames=["A", missing]);
+ tc.verifyError(fcn, "MATLAB:validators:mustBeNonmissing");
+ end
+
+ function FromArraysNoInputs(tc)
+ % Verify the fromArrays function constructs the expected
+ % Tabular object when zero input arguments are provided.
+ tabularObj = tc.FromArraysFcn();
+ tc.verifyEqual(tabularObj.NumRows, int64(0));
+ tc.verifyEqual(tabularObj.NumColumns, int32(0));
+ tc.verifyEqual(tabularObj.ColumnNames, string.empty(1, 0));
+ end
+
+ end
+
+ methods (Test, TestTags={'get.Column'})
+
+ function GetColumnByName(tc)
+ % Verify that columns can be accessed by name.
+ matlabArray1 = [1; 2; 3];
+ matlabArray2 = ["A"; "B"; "C"];
+ matlabArray3 = [true; false; true];
+
+ arrowArray1 = arrow.array(matlabArray1);
+ arrowArray2 = arrow.array(matlabArray2);
+ arrowArray3 = arrow.array(matlabArray3);
+
+ tabularObj = tc.FromArraysFcn(...
+ arrowArray1, ...
+ arrowArray2, ...
+ arrowArray3, ...
+ ColumnNames=["A", "B", "C"] ...
+ );
+
+ actual = tabularObj.column("A");
+ tc.verifyEqual(actual, tc.makeColumnFromArray(arrowArray1));
+
+ actual = tabularObj.column("B");
+ tc.verifyEqual(actual, tc.makeColumnFromArray(arrowArray2));
+
+ actual = tabularObj.column("C");
+ tc.verifyEqual(actual, tc.makeColumnFromArray(arrowArray3));
+ end
+
+ function GetColumnByNameWithEmptyString(tc)
+ % Verify that a column whose name is the empty string ("")
+ % can be accessed using the column() method.
+ matlabArray1 = [1; 2; 3];
+ matlabArray2 = ["A"; "B"; "C"];
+ matlabArray3 = [true; false; true];
+
+ arrowArray1 = arrow.array(matlabArray1);
+ arrowArray2 = arrow.array(matlabArray2);
+ arrowArray3 = arrow.array(matlabArray3);
+
+ tabularObj = tc.FromArraysFcn(...
+ arrowArray1, ...
+ arrowArray2, ...
+ arrowArray3, ...
+ ColumnNames=["A", "", "C"] ...
+ );
+
+ column = tabularObj.column("");
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray2));
+ end
+
+ function GetColumnByNameWithWhitespace(tc)
+ % Verify that a column whose name contains only whitespace
+ % characters can be accessed using the column() method.
+ matlabArray1 = [1; 2; 3];
+ matlabArray2 = ["A"; "B"; "C"];
+ matlabArray3 = [true; false; true];
+
+ arrowArray1 = arrow.array(matlabArray1);
+ arrowArray2 = arrow.array(matlabArray2);
+ arrowArray3 = arrow.array(matlabArray3);
+
+ tabularObj = tc.FromArraysFcn(...
+ arrowArray1, ...
+ arrowArray2, ...
+ arrowArray3, ...
+ ColumnNames=[" ", " ", " "] ...
+ );
+
+ column = tabularObj.column(" ");
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray1));
+
+ column = tabularObj.column(" ");
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray2));
+
+ column = tabularObj.column(" ");
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray3));
+ end
+
+ function GetColumnErrorIfColumnNameDoesNotExist(tc)
+ % Verify that an error is thrown when trying to access a column
+ % with a name that is not part of the Schema of the Tabular
+ % object.
+ matlabArray1 = [1; 2; 3];
+ matlabArray2 = ["A"; "B"; "C"];
+ matlabArray3 = [true; false; true];
+
+ arrowArray1 = arrow.array(matlabArray1);
+ arrowArray2 = arrow.array(matlabArray2);
+ arrowArray3 = arrow.array(matlabArray3);
+
+ tabularObj = tc.FromArraysFcn(...
+ arrowArray1, ...
+ arrowArray2, ...
+ arrowArray3, ...
+ ColumnNames=["A", "B", "C"] ...
+ );
+
+ % Matching should be case-sensitive.
+ name = "a";
+ tc.verifyError(@() tabularObj.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
+
+ name = "aA";
+ tc.verifyError(@() tabularObj.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
+
+ name = "D";
+ tc.verifyError(@() tabularObj.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
+
+ name = "";
+ tc.verifyError(@() tabularObj.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
+
+ name = " ";
+ tc.verifyError(@() tabularObj.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
+ end
+
+ function GetColumnErrorIfAmbiguousColumnName(tc)
+ % Verify that an error is thrown when trying to access a column
+ % with a name that is ambiguous / occurs more than once in the
+ % Schema of the Tabular object.
+ tabularObj = tc.FromArraysFcn(...
+ arrow.array([1, 2, 3]), ...
+ arrow.array(["A", "B", "C"]), ...
+ arrow.array([true, false, true]), ...
+ arrow.array([days(1), days(2), days(3)]), ...
+ ColumnNames=["A", "A", "B", "B"] ...
+ );
+
+ name = "A";
+ tc.verifyError(@() tabularObj.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
+
+ name = "B";
+ tc.verifyError(@() tabularObj.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
+ end
+
+ function GetColumnByNameWithChar(tc)
+ % Verify that the column method works when supplied a char
+ % vector as input.
+ matlabArray1 = [1; 2; 3];
+ matlabArray2 = ["A"; "B"; "C"];
+ matlabArray3 = [true; false; true];
+
+ arrowArray1 = arrow.array(matlabArray1);
+ arrowArray2 = arrow.array(matlabArray2);
+ arrowArray3 = arrow.array(matlabArray3);
+
+ tabularObj = tc.FromArraysFcn(...
+ arrowArray1, ...
+ arrowArray2, ...
+ arrowArray3, ...
+ ColumnNames=["", "B", "123"] ...
+ );
+
+ % Should match the first column whose name is the
+ % empty string ("").
+ name = char.empty(0, 0);
+ column = tabularObj.column(name);
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray1));
+
+ name = char.empty(0, 1);
+ column = tabularObj.column(name);
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray1));
+
+ name = char.empty(1, 0);
+ column = tabularObj.column(name);
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray1));
+
+ % Should match the second column whose name is "B".
+ name = 'B';
+ column = tabularObj.column(name);
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray2));
+
+ % Should match the third column whose name is "123".
+ name = '123';
+ column = tabularObj.column(name);
+ tc.verifyEqual(column, tc.makeColumnFromArray(arrowArray3));
+ end
+
+ function GetColumnErrorIfColumnNameIsNonScalar(tc)
+ % Verify that an error is thrown if a nonscalar string array is
+ % specified as a column name to the column method.
+ tabularObj = tc.FromArraysFcn(...
+ arrow.array([1, 2, 3]), ...
+ arrow.array(["A", "B", "C"]), ...
+ arrow.array([true, false, true]), ...
+ ColumnNames=["A", "B", "C"] ...
+ );
+
+ name = ["A", "B", "C"];
+ tc.verifyError(@() tabularObj.column(name),
"arrow:badsubscript:NonScalar");
+
+ name = ["A"; "B"; "C"];
+ tc.verifyError(@() tabularObj.column(name),
"arrow:badsubscript:NonScalar");
+ end
+
+ function GetColumnEmptyTabularObjectColumnIndexError(tc)
+ % Verify an exception is thrown when the column() method is
+ % invoked on a Tabular object with zero columns.
+ TOriginal = table();
+ tabularObj = tc.ConstructionFcn(TOriginal);
+ fcn = @() tabularObj.column(1);
+ id = tc.ErrorIdentifierPrefix + "NumericIndexWithEmpty" +
tc.ShortClassName;
+ tc.verifyError(fcn, id);
+ end
+
+ function GetColumnInvalidNumericIndexError(tc)
+ % Verify an exception is thrown if the column method is called
+ % with a numeric index value that is greater than the number of
+ % columns.
+ TOriginal = table(1, 2, 3);
+ tabularObj = tc.ConstructionFcn(TOriginal);
+ fcn = @() tabularObj.column(4);
+ tc.verifyError(fcn, tc.ErrorIdentifierPrefix +
"InvalidNumericColumnIndex");
+ end
+
+ function GetColumnUnsupportedColumnIndexType(tc)
+ % Verify an exception is thrown if the column method is called
+ % with an invalid datatype as the column index.
+ TOriginal = table(1, 2, 3);
+ tabularObj = tc.ConstructionFcn(TOriginal);
+ fcn = @() tabularObj.column(datetime(2022, 1, 3));
+ tc.verifyError(fcn, "arrow:badsubscript:UnsupportedIndexType");
+ end
+
+ function GetColumnErrorIfIndexIsNonScalar(tc)
+ % Verify an exception is thrown if the column method is called
+ % with a non-scalar index value.
+ TOriginal = table(1, 2, 3);
+ tabularObj = tc.ConstructionFcn(TOriginal);
+ fcn = @() tabularObj.column([1 2]);
+ tc.verifyError(fcn, "arrow:badsubscript:NonScalar");
+ end
+
+ function GetColumnErrorIfIndexIsNonPositive(tc)
+ % Verify an exception is thrown if the column method is called
+ % with a non-positive index value.
+ TOriginal = table(1, 2, 3);
+ tabularObj = tc.ConstructionFcn(TOriginal);
+ fcn = @() tabularObj.column(-1);
+ tc.verifyError(fcn, "arrow:badsubscript:NonPositive");
+ end
+
+ end
+
+ methods (Test, TestTags={'isequal'})
+
+ function TestIsEqualTrue(tc)
+ % Verify two tabular objects are considered equal if:
+ % 1. They have the same schema
+ % 2. Their corresponding columns are equal
+
+ a1 = arrow.array([1 2 3]);
+ a2 = arrow.array(["A" "B" "C"]);
+ a3 = arrow.array([true true false]);
+
+ tabularObj1 = tc.FromArraysFcn(a1, a2, a3, ...
+ ColumnNames=["A", "B", "C"]);
+ tabularObj2 = tc.FromArraysFcn(a1, a2, a3, ...
+ ColumnNames=["A", "B", "C"]);
+ tc.verifyTrue(isequal(tabularObj1, tabularObj2));
+
+ % Compare tabular objects that have zero columns.
+ tabularObj3 = tc.FromArraysFcn();
+ tabularObj4 = tc.FromArraysFcn();
+ tc.verifyTrue(isequal(tabularObj3, tabularObj4));
+
+ % Compare tabular objects that have zero rows
+ a4 = arrow.array([]);
+ a5 = arrow.array(strings(0, 0));
+ rb5 = tc.FromArraysFcn(a4, a5, ColumnNames=["D" "E"]);
+ rb6 = tc.FromArraysFcn(a4, a5, ColumnNames=["D" "E"]);
+ tc.verifyTrue(isequal(rb5, rb6));
+
+ % Call isequal with more than two arguments
+ tc.verifyTrue(isequal(tabularObj3, tabularObj4, tabularObj3,
tabularObj4));
+ end
+
+ function TestIsEqualFalse(tc)
+ % Verify isequal returns false when expected.
+ a1 = arrow.array([1 2 3]);
+ a2 = arrow.array(["A" "B" "C"]);
+ a3 = arrow.array([true true false]);
+ a4 = arrow.array(["A" missing "C"]);
+ a5 = arrow.array([1 2]);
+ a6 = arrow.array(["A" "B"]);
+ a7 = arrow.array([true true]);
+
+ tabularObj1 = tc.FromArraysFcn(a1, a2, a3, ...
+ ColumnNames=["A", "B", "C"]);
+ tabularObj2 = tc.FromArraysFcn(a1, a2, a3, ...
+ ColumnNames=["D", "E", "F"]);
+ tabularObj3 = tc.FromArraysFcn(a1, a4, a3, ...
+ ColumnNames=["A", "B", "C"]);
+ tabularObj4 = tc.FromArraysFcn(a5, a6, a7, ...
+ ColumnNames=["A", "B", "C"]);
+ tabularObj5 = tc.FromArraysFcn(a1, a2, a3, a1, ...
+ ColumnNames=["A", "B", "C", "D"]);
+
+ % The column names are not equal
+ tc.verifyFalse(isequal(tabularObj1, tabularObj2));
+
+ % The columns are not equal
+ tc.verifyFalse(isequal(tabularObj1, tabularObj3));
+
+ % The number of rows are not equal
+ tc.verifyFalse(isequal(tabularObj1, tabularObj4));
+
+ % The number of columns are not equal
+ tc.verifyFalse(isequal(tabularObj1, tabularObj5));
+
+ % Call isequal with more than two arguments
+ tc.verifyFalse(isequal(tabularObj1, tabularObj2, tabularObj3,
tabularObj4));
+ end
+
+ end
+
+end
\ No newline at end of file
diff --git a/matlab/test/arrow/tabular/tRecordBatch.m
b/matlab/test/arrow/tabular/tRecordBatch.m
index f2f0fb4d87..5719c27b52 100644
--- a/matlab/test/arrow/tabular/tRecordBatch.m
+++ b/matlab/test/arrow/tabular/tRecordBatch.m
@@ -1,3 +1,5 @@
+%TRECORDBATCH Test class for arrow.tabular.RecordBatch
+
% 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.
@@ -13,514 +15,33 @@
% implied. See the License for the specific language governing
% permissions and limitations under the License.
-classdef tRecordBatch < matlab.unittest.TestCase
-% Test class containing tests for arrow.tabular.RecordBatch
-
- methods(Test)
-
- function Basic(tc)
- T = table([1, 2, 3]');
- arrowRecordBatch = arrow.recordBatch(T);
- className = string(class(arrowRecordBatch));
- tc.verifyEqual(className, "arrow.tabular.RecordBatch");
- end
-
- function ConvenienceConstructorZeroArguments(tc)
- % Verify the arrow.recordBatch function returns an
- % arrow.tabular.RecordBatch instance with zero rows and zero
- % columns if called with zero input arguments.
- recordBatch = arrow.recordBatch();
- className = string(class(recordBatch));
- tc.verifyEqual(className, "arrow.tabular.RecordBatch");
- tc.verifyEqual(recordBatch.NumRows, int64(0));
- tc.verifyEqual(recordBatch.NumColumns, int32(0));
- end
-
- function SupportedTypes(tc)
- % Create a table all supported MATLAB types.
- import arrow.internal.test.tabular.createTableWithSupportedTypes
- import arrow.type.traits.traits
-
- TOriginal = createTableWithSupportedTypes();
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- expectedColumnNames = string(TOriginal.Properties.VariableNames);
-
- % For each variable in the input MATLAB table, look up the
- % corresponding Arrow Array type using type traits.
- expectedArrayClasses = varfun(@(var)
traits(string(class(var))).ArrayClassName, ...
- TOriginal, OutputFormat="uniform");
- tc.verifyRecordBatch(arrowRecordBatch, expectedColumnNames,
expectedArrayClasses, TOriginal);
- end
-
- function ToMATLAB(tc)
- TOriginal = table([1, 2, 3]');
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- TConverted = arrowRecordBatch.toMATLAB();
- tc.verifyEqual(TOriginal, TConverted);
- end
-
- function Table(tc)
- TOriginal = table([1, 2, 3]');
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- TConverted = table(arrowRecordBatch);
- tc.verifyEqual(TOriginal, TConverted);
- end
-
- function ColumnNames(tc)
- columnNames = ["A", "B", "C"];
- TOriginal = table(1, 2, 3, VariableNames=columnNames);
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- tc.verifyEqual(arrowRecordBatch.ColumnNames, columnNames);
- end
-
- function NumRows(testCase)
- % Verify that the NumRows property of arrow.tabular.RecordBatch
- % returns the expected number of rows.
- numRows = int64([1, 5, 100]);
-
- for expectedNumRows = numRows
- matlabTable = array2table(ones(expectedNumRows, 1));
- arrowRecordBatch = arrow.recordBatch(matlabTable);
- testCase.verifyEqual(arrowRecordBatch.NumRows,
expectedNumRows);
- end
-
- end
-
- function NumColumns(tc)
- numColumns = int32([1, 5, 100]);
-
- for nc = numColumns
- T = array2table(ones(1, nc));
- arrowRecordBatch = arrow.recordBatch(T);
- tc.verifyEqual(arrowRecordBatch.NumColumns, nc);
- end
- end
+classdef tRecordBatch < hTabular
- function UnicodeColumnNames(tc)
- smiley = "😀";
- tree = "🌲";
- mango = "ðŸ¥";
- columnNames = [smiley, tree, mango];
- TOriginal = table(1, 2, 3, VariableNames=columnNames);
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- tc.verifyEqual(arrowRecordBatch.ColumnNames, columnNames);
- TConverted = arrowRecordBatch.toMATLAB();
- tc.verifyEqual(TOriginal, TConverted);
- end
-
- function EmptyRecordBatch(testCase)
- % Verify that an arrow.tabular.RecordBatch can be created from
- % an empty MATLAB table.
- matlabTable = table.empty(0, 0);
- arrowRecordBatch = arrow.recordBatch(matlabTable);
- testCase.verifyEqual(arrowRecordBatch.NumRows, int64(0));
- testCase.verifyEqual(arrowRecordBatch.NumColumns, int32(0));
- testCase.verifyEqual(arrowRecordBatch.ColumnNames, string.empty(1,
0));
- testCase.verifyEqual(toMATLAB(arrowRecordBatch), matlabTable);
-
- matlabTable = table.empty(1, 0);
- arrowRecordBatch = arrow.recordBatch(matlabTable);
- testCase.verifyEqual(arrowRecordBatch.NumRows, int64(0));
- testCase.verifyEqual(arrowRecordBatch.NumColumns, int32(0));
- testCase.verifyEqual(arrowRecordBatch.ColumnNames, string.empty(1,
0));
-
- matlabTable = table.empty(0, 1);
- arrowRecordBatch = arrow.recordBatch(matlabTable);
- testCase.verifyEqual(arrowRecordBatch.NumRows, int64(0));
- testCase.verifyEqual(arrowRecordBatch.NumColumns, int32(1));
- testCase.verifyEqual(arrowRecordBatch.ColumnNames, "Var1");
- end
-
- function EmptyRecordBatchColumnIndexError(tc)
- TOriginal = table();
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- fcn = @() arrowRecordBatch.column(1);
- tc.verifyError(fcn,
"arrow:tabular:recordbatch:NumericIndexWithEmptyRecordBatch");
- end
-
- function InvalidNumericIndexError(tc)
- TOriginal = table(1, 2, 3);
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- fcn = @() arrowRecordBatch.column(4);
- tc.verifyError(fcn,
"arrow:tabular:recordbatch:InvalidNumericColumnIndex");
- end
-
- function UnsupportedColumnIndexType(tc)
- TOriginal = table(1, 2, 3);
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- fcn = @() arrowRecordBatch.column(datetime(2022, 1, 3));
- tc.verifyError(fcn, "arrow:badsubscript:UnsupportedIndexType");
- end
-
- function ErrorIfIndexIsNonScalar(tc)
- TOriginal = table(1, 2, 3);
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- fcn = @() arrowRecordBatch.column([1 2]);
- tc.verifyError(fcn, "arrow:badsubscript:NonScalar");
- end
-
- function ErrorIfIndexIsNonPositive(tc)
- TOriginal = table(1, 2, 3);
- arrowRecordBatch = arrow.recordBatch(TOriginal);
- fcn = @() arrowRecordBatch.column(-1);
- tc.verifyError(fcn, "arrow:badsubscript:NonPositive");
- end
-
- function FromArraysColumnNamesNotProvided(tc)
- % Verify arrow.tabular.RecordBatch.fromArrays creates the expected
- % RecordBatch when given a comma-separated list of
- % arrow.array.Array values.
- import arrow.tabular.RecordBatch
- import arrow.internal.test.tabular.createAllSupportedArrayTypes
-
- [arrowArrays, matlabData] = createAllSupportedArrayTypes();
- TOriginal = table(matlabData{:});
-
- arrowRecordBatch = RecordBatch.fromArrays(arrowArrays{:});
- expectedColumnNames = compose("Column%d", 1:width(TOriginal));
- TOriginal.Properties.VariableNames = expectedColumnNames;
- expectedArrayClasses = cellfun(@(c) string(class(c)), arrowArrays,
UniformOutput=true);
- tc.verifyRecordBatch(arrowRecordBatch, expectedColumnNames,
expectedArrayClasses, TOriginal);
- end
-
- function FromArraysWithColumnNamesProvided(tc)
- % Verify arrow.tabular.RecordBatch.fromArrays creates the expected
- % RecordBatch when given a comma-separated list of
- % arrow.array.Array values and the ColumnNames nv-pair is provided.
- import arrow.tabular.RecordBatch
- import arrow.internal.test.tabular.createAllSupportedArrayTypes
-
- [arrowArrays, matlabData] = createAllSupportedArrayTypes();
- TOriginal = table(matlabData{:});
-
- columnNames = compose("MyVar%d", 1:numel(arrowArrays));
- arrowRecordBatch = RecordBatch.fromArrays(arrowArrays{:},
ColumnNames=columnNames);
- TOriginal.Properties.VariableNames = columnNames;
- expectedArrayClasses = cellfun(@(c) string(class(c)), arrowArrays,
UniformOutput=true);
- tc.verifyRecordBatch(arrowRecordBatch, columnNames,
expectedArrayClasses, TOriginal);
- end
-
- function FromArraysUnequalArrayLengthsError(tc)
- % Verify arrow.tabular.RecordBatch.fromArrays throws an error whose
- % identifier is "arrow:tabular:UnequalArrayLengths" if the arrays
- % provided don't all have the same length.
- import arrow.tabular.RecordBatch
-
- A1 = arrow.array([1, 2]);
- A2 = arrow.array(["A", "B", "C"]);
- fcn = @() RecordBatch.fromArrays(A1, A2);
- tc.verifyError(fcn, "arrow:tabular:UnequalArrayLengths");
- end
-
- function FromArraysWrongNumberColumnNamesError(tc)
- % Verify arrow.tabular.RecordBatch.fromArrays throws an error whose
- % identifier is "arrow:tabular:WrongNumberColumnNames" if the
- % ColumnNames provided doesn't have one element per array.
- import arrow.tabular.RecordBatch
-
- A1 = arrow.array([1, 2]);
- A2 = arrow.array(["A", "B"]);
- fcn = @() RecordBatch.fromArrays(A1, A2, columnNames=["A", "B",
"C"]);
- tc.verifyError(fcn, "arrow:tabular:WrongNumberColumnNames");
- end
-
- function FromArraysColumnNamesHasMissingString(tc)
- % Verify arrow.tabular.RecordBatch.fromArrays throws an error whose
- % identifier is "MATLAB:validators:mustBeNonmissing" if the
- % ColumnNames provided has a missing string value.
- import arrow.tabular.RecordBatch
-
- A1 = arrow.array([1, 2]);
- A2 = arrow.array(["A", "B"]);
- fcn = @() RecordBatch.fromArrays(A1, A2, columnNames=["A",
missing]);
- tc.verifyError(fcn, "MATLAB:validators:mustBeNonmissing");
- end
-
- function FromArraysNoInputs(testCase)
- % Verify that an empty RecordBatch is returned when calling
- % fromArrays with no input arguments.
- arrowRecordBatch = arrow.tabular.RecordBatch.fromArrays();
- testCase.verifyEqual(arrowRecordBatch.NumRows, int64(0));
- testCase.verifyEqual(arrowRecordBatch.NumColumns, int32(0));
- testCase.verifyEqual(arrowRecordBatch.ColumnNames, string.empty(1,
0));
- end
-
- function Schema(tc)
- % Verify that the public Schema property returns an appropriate
- % instance of arrow.tabular.Schema.
- t = table(["A"; "B"; "C"], ...
- [1; 2; 3], ...
- [true; false; true], ...
- VariableNames=["A", "B", "C"]);
- recordBatch = arrow.recordBatch(t);
- schema = recordBatch.Schema;
- tc.verifyEqual(schema.NumFields, int32(3));
- tc.verifyEqual(schema.field(1).Type.ID, arrow.type.ID.String);
- tc.verifyEqual(schema.field(1).Name, "A");
- tc.verifyEqual(schema.field(2).Type.ID, arrow.type.ID.Float64);
- tc.verifyEqual(schema.field(2).Name, "B");
- tc.verifyEqual(schema.field(3).Type.ID, arrow.type.ID.Boolean);
- tc.verifyEqual(schema.field(3).Name, "C");
- end
-
- function SchemaNoSetter(tc)
- % Verify that trying to set the value of the public Schema property
- % results in an error of type "MATLAB:class:SetProhibited".
- t = table([1; 2; 3]);
- recordBatch = arrow.recordBatch(t);
- tc.verifyError(@() setfield(recordBatch, "Schema", "Value"), ...
- "MATLAB:class:SetProhibited");
- end
-
- function GetColumnByName(testCase)
- % Verify that columns can be accessed by name.
- recordBatch = arrow.tabular.RecordBatch.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- ColumnNames=["A", "B", "C"] ...
- );
-
- expected = arrow.array([1, 2, 3]);
- actual = recordBatch.column("A");
- testCase.verifyEqual(actual, expected);
-
- expected = arrow.array(["A", "B", "C"]);
- actual = recordBatch.column("B");
- testCase.verifyEqual(actual, expected);
-
- expected = arrow.array([true, false, true]);
- actual = recordBatch.column("C");
- testCase.verifyEqual(actual, expected);
- end
-
- function GetColumnByNameWithEmptyString(testCase)
- % Verify that a column whose name is the empty string ("")
- % can be accessed using the column() method.
- recordBatch = arrow.tabular.RecordBatch.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- ColumnNames=["A", "", "C"] ...
- );
-
- expected = arrow.array(["A", "B", "C"]);
- actual = recordBatch.column("");
- testCase.verifyEqual(actual, expected)
- end
-
- function GetColumnByNameWithWhitespace(testCase)
- % Verify that a column whose name contains only whitespace
- % characters can be accessed using the column() method.
- recordBatch = arrow.tabular.RecordBatch.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- ColumnNames=[" ", " ", " "] ...
- );
-
- expected = arrow.array([1, 2, 3]);
- actual = recordBatch.column(" ");
- testCase.verifyEqual(actual, expected);
-
- expected = arrow.array(["A", "B", "C"]);
- actual = recordBatch.column(" ");
- testCase.verifyEqual(actual, expected);
-
- expected = arrow.array([true, false, true]);
- actual = recordBatch.column(" ");
- testCase.verifyEqual(actual, expected);
- end
-
- function ErrorIfColumnNameDoesNotExist(testCase)
- % Verify that an error is thrown when trying to access a column
- % with a name that is not part of the Schema of the RecordBatch.
- recordBatch = arrow.tabular.RecordBatch.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- ColumnNames=["A", "B", "C"] ...
- );
-
- % Matching should be case-sensitive.
- name = "a";
- testCase.verifyError(@() recordBatch.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "aA";
- testCase.verifyError(@() recordBatch.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "D";
- testCase.verifyError(@() recordBatch.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "";
- testCase.verifyError(@() recordBatch.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = " ";
- testCase.verifyError(@() recordBatch.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
- end
-
- function ErrorIfAmbiguousColumnName(testCase)
- % Verify that an error is thrown when trying to access a column
- % with a name that is ambiguous / occurs more than once in the
- % Schema of the RecordBatch.
- recordBatch = arrow.tabular.RecordBatch.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- arrow.array([days(1), days(2), days(3)]), ...
- ColumnNames=["A", "A", "B", "B"] ...
- );
-
- name = "A";
- testCase.verifyError(@() recordBatch.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "B";
- testCase.verifyError(@() recordBatch.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
- end
-
- function GetColumnByNameWithChar(testCase)
- % Verify that the column method works when supplied a char
- % vector as input.
- recordBatch = arrow.tabular.RecordBatch.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- ColumnNames=["", "B", "123"] ...
- );
-
- % Should match the first column whose name is the
- % empty string ("").
- name = char.empty(0, 0);
- expected = arrow.array([1, 2, 3]);
- actual = recordBatch.column(name);
- testCase.verifyEqual(actual, expected);
-
- name = char.empty(0, 1);
- expected = arrow.array([1, 2, 3]);
- actual = recordBatch.column(name);
- testCase.verifyEqual(actual, expected);
-
- name = char.empty(1, 0);
- expected = arrow.array([1, 2, 3]);
- actual = recordBatch.column(name);
- testCase.verifyEqual(actual, expected);
+ properties
+ FromArraysFcn = @arrow.tabular.RecordBatch.fromArrays
+ ConstructionFcn = @arrow.recordBatch
+ ClassName = "arrow.tabular.RecordBatch"
+ end
- % Should match the second column whose name is "B".
- name = 'B';
- expected = arrow.array(["A", "B", "C"]);
- actual = recordBatch.column(name);
- testCase.verifyEqual(actual, expected);
+ methods
- % Should match the third column whose name is "123".
- name = '123';
- expected = arrow.array([true, false, true]);
- actual = recordBatch.column(name);
- testCase.verifyEqual(actual, expected);
+ function verifyTabularObject(tc, arrowTabularObj, columnNames,
columnTraits, matlabTable)
+ tc.verifyInstanceOf(arrowTabularObj, tc.ClassName);
+ tc.verifyEqual(arrowTabularObj.NumColumns,
int32(width(matlabTable)));
+ tc.verifyEqual(arrowTabularObj.ColumnNames, columnNames);
+ convertedTable = arrowTabularObj.table();
+ tc.verifyEqual(convertedTable, matlabTable);
+ for ii = 1:arrowTabularObj.NumColumns
+ column = arrowTabularObj.column(ii);
+ tc.verifyEqual(column.toMATLAB(), matlabTable{:, ii});
+ tc.verifyInstanceOf(column, columnTraits{ii}.ArrayClassName);
+ end
end
-
- function ErrorIfColumnNameIsNonScalar(testCase)
- % Verify that an error is thrown if a nonscalar string array is
- % specified as a column name to the column method.
- recordBatch = arrow.tabular.RecordBatch.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- ColumnNames=["A", "B", "C"] ...
- );
-
- name = ["A", "B", "C"];
- testCase.verifyError(@() recordBatch.column(name),
"arrow:badsubscript:NonScalar");
-
- name = ["A"; "B"; "C"];
- testCase.verifyError(@() recordBatch.column(name),
"arrow:badsubscript:NonScalar");
+
+ function col = makeColumnFromArray(~, array)
+ col = array;
end
- function TestIsEqualTrue(testCase)
- % Verify two record batches are considered equal if:
- % 1. They have the same schema
- % 2. Their corresponding columns are equal
- import arrow.tabular.RecordBatch
-
- a1 = arrow.array([1 2 3]);
- a2 = arrow.array(["A" "B" "C"]);
- a3 = arrow.array([true true false]);
-
- rb1 = RecordBatch.fromArrays(a1, a2, a3, ...
- ColumnNames=["A", "B", "C"]);
- rb2 = RecordBatch.fromArrays(a1, a2, a3, ...
- ColumnNames=["A", "B", "C"]);
- testCase.verifyTrue(isequal(rb1, rb2));
-
- % Compare zero-column record batches
- rb3 = RecordBatch.fromArrays();
- rb4 = RecordBatch.fromArrays();
- testCase.verifyTrue(isequal(rb3, rb4));
-
- % Compare zero-row record batches
- a4 = arrow.array([]);
- a5 = arrow.array(strings(0, 0));
- rb5 = RecordBatch.fromArrays(a4, a5, ColumnNames=["D" "E"]);
- rb6 = RecordBatch.fromArrays(a4, a5, ColumnNames=["D" "E"]);
- testCase.verifyTrue(isequal(rb5, rb6));
-
- % Call isequal with more than two arguments
- testCase.verifyTrue(isequal(rb3, rb4, rb3, rb4));
- end
-
- function TestIsEqualFalse(testCase)
- % Verify isequal returns false when expected.
- import arrow.tabular.RecordBatch
-
- a1 = arrow.array([1 2 3]);
- a2 = arrow.array(["A" "B" "C"]);
- a3 = arrow.array([true true false]);
- a4 = arrow.array(["A" missing "C"]);
- a5 = arrow.array([1 2]);
- a6 = arrow.array(["A" "B"]);
- a7 = arrow.array([true true]);
-
- rb1 = RecordBatch.fromArrays(a1, a2, a3, ...
- ColumnNames=["A", "B", "C"]);
- rb2 = RecordBatch.fromArrays(a1, a2, a3, ...
- ColumnNames=["D", "E", "F"]);
- rb3 = RecordBatch.fromArrays(a1, a4, a3, ...
- ColumnNames=["A", "B", "C"]);
- rb4 = RecordBatch.fromArrays(a5, a6, a7, ...
- ColumnNames=["A", "B", "C"]);
- rb5 = RecordBatch.fromArrays(a1, a2, a3, a1, ...
- ColumnNames=["A", "B", "C", "D"]);
-
- % The column names are not equal
- testCase.verifyFalse(isequal(rb1, rb2));
-
- % The columns are not equal
- testCase.verifyFalse(isequal(rb1, rb3));
-
- % The number of rows are not equal
- testCase.verifyFalse(isequal(rb1, rb4));
-
- % The number of columns are not equal
- testCase.verifyFalse(isequal(rb1, rb5));
-
- % Call isequal with more than two arguments
- testCase.verifyFalse(isequal(rb1, rb2, rb3, rb4));
- end
-
-
end
- methods
- function verifyRecordBatch(tc, recordBatch, expectedColumnNames,
expectedArrayClasses, expectedTable)
- tc.verifyEqual(recordBatch.NumColumns,
int32(width(expectedTable)));
- tc.verifyEqual(recordBatch.ColumnNames, expectedColumnNames);
- convertedTable = recordBatch.table();
- tc.verifyEqual(convertedTable, expectedTable);
- for ii = 1:recordBatch.NumColumns
- column = recordBatch.column(ii);
- tc.verifyEqual(column.toMATLAB(), expectedTable{:, ii});
- tc.verifyInstanceOf(column, expectedArrayClasses(ii));
- end
- end
- end
end
-
diff --git a/matlab/test/arrow/tabular/tTable.m
b/matlab/test/arrow/tabular/tTable.m
index 8e5883232e..b3b0067113 100644
--- a/matlab/test/arrow/tabular/tTable.m
+++ b/matlab/test/arrow/tabular/tTable.m
@@ -16,653 +16,17 @@
% implied. See the License for the specific language governing
% permissions and limitations under the License.
-classdef tTable < matlab.unittest.TestCase
+classdef tTable < hTabular
- methods(Test)
-
- function Basic(testCase)
- % Verify that an arrow.tabular.Table can be created
- % from a MATLAB table using the arrow.table construction
- % function.
- matlabTable = table(...
- [1, 2, 3]', ...
- ["A", "B", "C"]', ...
- [true, false, true]' ...
- );
- arrowTable = arrow.table(matlabTable);
- testCase.verifyInstanceOf(arrowTable, "arrow.tabular.Table");
- end
-
- function SupportedTypes(testCase)
- % Verify that a MATLAB table containing all types
- % supported for conversion to Arrow Arrays can be round-tripped
- % from an arrow.tabular.Table to a MATLAB table and back.
- import arrow.internal.test.tabular.createTableWithSupportedTypes
- import arrow.type.traits.traits
-
- matlabTable = createTableWithSupportedTypes();
- arrowTable = arrow.table(matlabTable);
- expectedColumnNames = string(matlabTable.Properties.VariableNames);
-
- % For each variable in the input MATLAB table, look up the
- % corresponding Arrow Type of the corresponding ChunkedArray using
type traits.
- expectedChunkedArrayTypes = varfun(@(var)
traits(string(class(var))).TypeClassName, ...
- matlabTable, OutputFormat="uniform");
- testCase.verifyTable(arrowTable, expectedColumnNames,
expectedChunkedArrayTypes, matlabTable);
- end
-
- function ToMATLAB(testCase)
- % Verify that the toMATLAB method converts
- % an arrow.tabular.Table to a MATLAB table as expected.
- expectedMatlabTable = table([1, 2, 3]');
- arrowTable = arrow.table(expectedMatlabTable);
- actualMatlabTable = arrowTable.toMATLAB();
- testCase.verifyEqual(actualMatlabTable, expectedMatlabTable);
- end
-
- function Table(testCase)
- % Verify that the toMATLAB method converts
- % an arrow.tabular.Table to a MATLAB table as expected.
- TOriginal = table([1, 2, 3]');
- arrowTable = arrow.table(TOriginal);
- TConverted = table(arrowTable);
- testCase.verifyEqual(TOriginal, TConverted);
- end
-
- function NumRows(testCase)
- % Verify that the NumRows property of arrow.tabular.Table
- % returns the expected number of rows.
- numRows = int64([1, 5, 100]);
-
- for expectedNumRows = numRows
- matlabTable = array2table(ones(expectedNumRows, 1));
- arrowTable = arrow.table(matlabTable);
- testCase.verifyEqual(arrowTable.NumRows, expectedNumRows);
- end
-
- end
-
- function NumColumns(testCase)
- % Verify that the NumColumns property of arrow.tabular.Table
- % returns the expected number of columns.
- numColumns = int32([1, 5, 100]);
-
- for expectedNumColumns = numColumns
- matlabTable = array2table(ones(1, expectedNumColumns));
- arrowTable = arrow.table(matlabTable);
- testCase.verifyEqual(arrowTable.NumColumns,
expectedNumColumns);
- end
-
- end
-
- function ColumnNames(testCase)
- % Verify that the ColumnNames property of arrow.tabular.Table
- % returns the expected string array of column names.
- columnNames = ["A", "B", "C"];
- matlabTable = table(1, 2, 3, VariableNames=columnNames);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyEqual(arrowTable.ColumnNames, columnNames);
- end
-
- function UnicodeColumnNames(testCase)
- % Verify that an arrow.tabular.Table can be created from
- % a MATLAB table with Unicode VariableNames.
- smiley = "😀";
- tree = "🌲";
- mango = "ðŸ¥";
- columnNames = [smiley, tree, mango];
- matlabTable = table(1, 2, 3, VariableNames=columnNames);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyEqual(arrowTable.ColumnNames, columnNames);
- end
-
- function EmptyTable(testCase)
- % Verify that an arrow.tabular.Table can be created from an
- % empty MATLAB table.
- matlabTable = table.empty(0, 0);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyEqual(arrowTable.NumRows, int64(0));
- testCase.verifyEqual(arrowTable.NumColumns, int32(0));
- testCase.verifyEqual(arrowTable.ColumnNames, string.empty(1, 0));
- testCase.verifyEqual(toMATLAB(arrowTable), matlabTable);
-
- matlabTable = table.empty(1, 0);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyEqual(arrowTable.NumRows, int64(0));
- testCase.verifyEqual(arrowTable.NumColumns, int32(0));
- testCase.verifyEqual(arrowTable.ColumnNames, string.empty(1, 0));
-
- matlabTable = table.empty(0, 1);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyEqual(arrowTable.NumRows, int64(0));
- testCase.verifyEqual(arrowTable.NumColumns, int32(1));
- testCase.verifyEqual(arrowTable.ColumnNames, "Var1");
- end
-
- function EmptyTableColumnIndexError(tc)
- % Verify that an "arrow:tabular:table:NumericIndexWithEmptyTable"
error
- % is thrown when calling the column method on an empty Table.
- matlabTable = table();
- arrowTable = arrow.table(matlabTable);
- fcn = @() arrowTable.column(1);
- tc.verifyError(fcn,
"arrow:tabular:table:NumericIndexWithEmptyTable");
- end
-
- function InvalidNumericIndexError(tc)
- % Verify that an "arrow:tabular:table:InvalidNumericColumnIndex"
error
- % is thrown when providing an index to the column
- % method that is outside the range of valid column indices
- % (e.g. greater than the number of columns).
- matlabTable = table(1, 2, 3);
- arrowTable = arrow.table(matlabTable);
- fcn = @() arrowTable.column(4);
- tc.verifyError(fcn,
"arrow:tabular:table:InvalidNumericColumnIndex");
- end
-
- function UnsupportedColumnIndexType(tc)
- % Verify that an "arrow:badsubscript:UnsupportedIndexType" error
- % is thrown when providing an index to the column
- % method that is not a positive scalar integer.
- matlabTable = table(1, 2, 3);
- arrowTable = arrow.table(matlabTable);
- fcn = @() arrowTable.column(datetime(2022, 1, 3));
- tc.verifyError(fcn, "arrow:badsubscript:UnsupportedIndexType");
- end
-
- function ErrorIfIndexIsNonScalar(tc)
- % Verify that an "arrow:badsubscript:NonScalar" error
- % is thrown when providing a non-scalar index to the column
- % method.
- matlabtable = table(1, 2, 3);
- arrowTable = arrow.table(matlabtable);
- fcn = @() arrowTable.column([1 2]);
- tc.verifyError(fcn, "arrow:badsubscript:NonScalar");
- end
-
- function ErrorIfIndexIsNonPositive(tc)
- % Verify that an "arrow:badsubscript:NonPositive" error
- % is thrown when providing a non-positive index to the column
- % method.
- matlabTable = table(1, 2, 3);
- arrowTable = arrow.table(matlabTable);
- fcn = @() arrowTable.column(-1);
- tc.verifyError(fcn, "arrow:badsubscript:NonPositive");
- end
-
- function GetColumnByName(testCase)
- % Verify that columns can be accessed by name.
- matlabArray1 = [1; 2; 3];
- matlabArray2 = ["A"; "B"; "C"];
- matlabArray3 = [true; false; true];
-
- arrowArray1 = arrow.array(matlabArray1);
- arrowArray2 = arrow.array(matlabArray2);
- arrowArray3 = arrow.array(matlabArray3);
-
- arrowTable = arrow.tabular.Table.fromArrays(...
- arrowArray1, ...
- arrowArray2, ...
- arrowArray3, ...
- ColumnNames=["A", "B", "C"] ...
- );
-
- column = arrowTable.column("A");
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.float64();
- testCase.verifyChunkedArray(column, ...
- matlabArray1, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- column = arrowTable.column("B");
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.string();
- testCase.verifyChunkedArray(column, ...
- matlabArray2, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- column = arrowTable.column("C");
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.boolean();
- testCase.verifyChunkedArray(column, ...
- matlabArray3, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
- end
-
- function GetColumnByNameWithEmptyString(testCase)
- % Verify that a column whose name is the empty string ("")
- % can be accessed using the column() method.
- matlabArray1 = [1; 2; 3];
- matlabArray2 = ["A"; "B"; "C"];
- matlabArray3 = [true; false; true];
-
- arrowArray1 = arrow.array(matlabArray1);
- arrowArray2 = arrow.array(matlabArray2);
- arrowArray3 = arrow.array(matlabArray3);
-
- arrowTable = arrow.tabular.Table.fromArrays(...
- arrowArray1, ...
- arrowArray2, ...
- arrowArray3, ...
- ColumnNames=["A", "", "C"] ...
- );
-
- column = arrowTable.column("");
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.string();
- testCase.verifyChunkedArray(column, ...
- matlabArray2, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
- end
-
- function GetColumnByNameWithWhitespace(testCase)
- % Verify that a column whose name contains only whitespace
- % characters can be accessed using the column() method.
- matlabArray1 = [1; 2; 3];
- matlabArray2 = ["A"; "B"; "C"];
- matlabArray3 = [true; false; true];
-
- arrowArray1 = arrow.array(matlabArray1);
- arrowArray2 = arrow.array(matlabArray2);
- arrowArray3 = arrow.array(matlabArray3);
-
- arrowTable = arrow.tabular.Table.fromArrays(...
- arrowArray1, ...
- arrowArray2, ...
- arrowArray3, ...
- ColumnNames=[" ", " ", " "] ...
- );
-
- column = arrowTable.column(" ");
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.float64();
- testCase.verifyChunkedArray(column, ...
- matlabArray1, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- column = arrowTable.column(" ");
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.string();
- testCase.verifyChunkedArray(column, ...
- matlabArray2, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- column = arrowTable.column(" ");
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.boolean();
- testCase.verifyChunkedArray(column, ...
- matlabArray3, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
- end
-
- function ErrorIfColumnNameDoesNotExist(testCase)
- % Verify that an error is thrown when trying to access a column
- % with a name that is not part of the Schema of the Table.
- matlabArray1 = [1; 2; 3];
- matlabArray2 = ["A"; "B"; "C"];
- matlabArray3 = [true; false; true];
-
- arrowArray1 = arrow.array(matlabArray1);
- arrowArray2 = arrow.array(matlabArray2);
- arrowArray3 = arrow.array(matlabArray3);
-
- arrowTable = arrow.tabular.Table.fromArrays(...
- arrowArray1, ...
- arrowArray2, ...
- arrowArray3, ...
- ColumnNames=["A", "B", "C"] ...
- );
-
- % Matching should be case-sensitive.
- name = "a";
- testCase.verifyError(@() arrowTable.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "aA";
- testCase.verifyError(@() arrowTable.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "D";
- testCase.verifyError(@() arrowTable.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "";
- testCase.verifyError(@() arrowTable.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = " ";
- testCase.verifyError(@() arrowTable.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
- end
-
- function ErrorIfAmbiguousColumnName(testCase)
- % Verify that an error is thrown when trying to access a column
- % with a name that is ambiguous / occurs more than once in the
- % Schema of the Table.
- arrowTable = arrow.tabular.Table.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- arrow.array([days(1), days(2), days(3)]), ...
- ColumnNames=["A", "A", "B", "B"] ...
- );
-
- name = "A";
- testCase.verifyError(@() arrowTable.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
-
- name = "B";
- testCase.verifyError(@() arrowTable.column(name),
"arrow:tabular:schema:AmbiguousFieldName");
- end
-
- function GetColumnByNameWithChar(testCase)
- % Verify that the column method works when supplied a char
- % vector as input.
- matlabArray1 = [1; 2; 3];
- matlabArray2 = ["A"; "B"; "C"];
- matlabArray3 = [true; false; true];
- arrowArray1 = arrow.array(matlabArray1);
- arrowArray2 = arrow.array(matlabArray2);
- arrowArray3 = arrow.array(matlabArray3);
-
- arrowTable = arrow.tabular.Table.fromArrays(...
- arrowArray1, ...
- arrowArray2, ...
- arrowArray3, ...
- ColumnNames=["", "B", "123"] ...
- );
-
- % Should match the first column whose name is the
- % empty string ("").
- name = char.empty(0, 0);
- column = arrowTable.column(name);
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.float64();
- testCase.verifyChunkedArray(column, ...
- matlabArray1, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- name = char.empty(0, 1);
- column = arrowTable.column(name);
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.float64();
- testCase.verifyChunkedArray(column, ...
- matlabArray1, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- name = char.empty(1, 0);
- column = arrowTable.column(name);
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.float64();
- testCase.verifyChunkedArray(column, ...
- matlabArray1, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- % Should match the second column whose name is "B".
- name = 'B';
- column = arrowTable.column(name);
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.string();
- testCase.verifyChunkedArray(column, ...
- matlabArray2, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
-
- % Should match the third column whose name is "123".
- name = '123';
- column = arrowTable.column(name);
- expectedNumChunks = int32(1);
- expectedNumElements = int64(3);
- expectedArrowType = arrow.boolean();
- testCase.verifyChunkedArray(column, ...
- matlabArray3, ...
- expectedNumChunks, ...
- expectedNumElements, ...
- expectedArrowType);
- end
-
- function ErrorIfColumnNameIsNonScalar(testCase)
- % Verify that an error is thrown if a nonscalar string array is
- % specified as a column name to the column method.
- arrowTable = arrow.tabular.Table.fromArrays(...
- arrow.array([1, 2, 3]), ...
- arrow.array(["A", "B", "C"]), ...
- arrow.array([true, false, true]), ...
- ColumnNames=["A", "B", "C"] ...
- );
-
- name = ["A", "B", "C"];
- testCase.verifyError(@() arrowTable.column(name),
"arrow:badsubscript:NonScalar");
-
- name = ["A"; "B"; "C"];
- testCase.verifyError(@() arrowTable.column(name),
"arrow:badsubscript:NonScalar");
- end
-
- function FromArraysWithNoColumnNames(testCase)
- % Verify arrow.tabular.Table.fromArrays creates the expected
- % Table when given a comma-separated list of arrow.array.Array
values.
- import arrow.tabular.Table
- import arrow.internal.test.tabular.createAllSupportedArrayTypes
-
- [arrowArrays, matlabData] = createAllSupportedArrayTypes();
- matlabTable = table(matlabData{:});
-
- arrowTable = Table.fromArrays(arrowArrays{:});
- expectedColumnNames = compose("Column%d", 1:width(matlabTable));
- testCase.verifyEqual(arrowTable.ColumnNames, expectedColumnNames)
- end
-
- function FromArraysWithColumnNames(testCase)
- % Verify arrow.tabular.Table.fromArrays creates the expected
- % Table when given a comma-separated list of arrow.array.Array
values
- % and when the ColumnNames nv-pair is provided.
- import arrow.tabular.Table
- import arrow.internal.test.tabular.createAllSupportedArrayTypes
-
- [arrowArrays, ~] = createAllSupportedArrayTypes();
-
- expectedColumnNames = compose("MyVar%d", 1:numel(arrowArrays));
- arrowTable = Table.fromArrays(arrowArrays{:},
ColumnNames=expectedColumnNames);
- testCase.verifyEqual(arrowTable.ColumnNames, expectedColumnNames)
- end
-
- function FromArraysUnequalArrayLengthsError(testCase)
- % Verify arrow.tabular.Table.fromArrays throws an error whose
- % identifier is "arrow:tabular:UnequalArrayLengths" if the arrays
- % provided don't all have the same length.
- import arrow.tabular.Table
-
- A1 = arrow.array([1, 2]);
- A2 = arrow.array(["A", "B", "C"]);
- fcn = @() Table.fromArrays(A1, A2);
- testCase.verifyError(fcn, "arrow:tabular:UnequalArrayLengths");
- end
-
- function FromArraysWrongNumberColumnNamesError(testCase)
- % Verify arrow.tabular.Table.fromArrays throws an error whose
- % identifier is "arrow:tabular:WrongNumberColumnNames" if the
- % ColumnNames provided doesn't have one element per array.
- import arrow.tabular.Table
-
- A1 = arrow.array([1, 2]);
- A2 = arrow.array(["A", "B"]);
- fcn = @() Table.fromArrays(A1, A2, ColumnNames=["A", "B", "C"]);
- testCase.verifyError(fcn, "arrow:tabular:WrongNumberColumnNames");
- end
-
- function FromArraysColumnNamesHasMissingString(testCase)
- % Verify arrow.tabular.Table.fromArrays throws an error whose
- % identifier is "MATLAB:validators:mustBeNonmissing" if the
- % ColumnNames provided has a missing string value.
- import arrow.tabular.Table
-
- A1 = arrow.array([1, 2]);
- A2 = arrow.array(["A", "B"]);
- fcn = @() Table.fromArrays(A1, A2, ColumnNames=["A", missing]);
- testCase.verifyError(fcn, "MATLAB:validators:mustBeNonmissing");
- end
-
- function FromArraysNoInputs(testCase)
- % Verify that an empty Table is returned when calling fromArrays
- % with no input arguments.
- arrowTable = arrow.tabular.Table.fromArrays();
- testCase.verifyEqual(arrowTable.NumRows, int64(0));
- testCase.verifyEqual(arrowTable.NumColumns, int32(0));
- testCase.verifyEqual(arrowTable.ColumnNames, string.empty(1, 0));
- end
-
- function ConstructionFunctionNoInputs(testCase)
- % Verify that an empty Table is returned when calling
- % the arrow.table construction function with no inputs.
- arrowTable = arrow.table();
- testCase.verifyEqual(arrowTable.NumRows, int64(0));
- testCase.verifyEqual(arrowTable.NumColumns, int32(0));
- testCase.verifyEqual(arrowTable.ColumnNames, string.empty(1, 0));
- end
-
- function Schema(testCase)
- % Verify that the public Schema property returns an appropriate
- % instance of arrow.tabular.Table.
- matlabTable = table(...
- ["A"; "B"; "C"], ...
- [1; 2; 3], ...
- [true; false; true], ...
- VariableNames=["A", "B", "C"] ...
- );
- arrowTable = arrow.table(matlabTable);
- schema = arrowTable.Schema;
- testCase.verifyEqual(schema.NumFields, int32(3));
- testCase.verifyEqual(schema.field(1).Type.ID,
arrow.type.ID.String);
- testCase.verifyEqual(schema.field(1).Name, "A");
- testCase.verifyEqual(schema.field(2).Type.ID,
arrow.type.ID.Float64);
- testCase.verifyEqual(schema.field(2).Name, "B");
- testCase.verifyEqual(schema.field(3).Type.ID,
arrow.type.ID.Boolean);
- testCase.verifyEqual(schema.field(3).Name, "C");
- end
-
- function NoColumnsNoSetter(testCase)
- % Verify that trying to set the value of the public NumColumns
property
- % results in an error of type "MATLAB:class:SetProhibited".
- matlabTable = table([1; 2; 3]);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyError(@() setfield(arrowTable, "NumColumns",
int32(100)), ...
- "MATLAB:class:SetProhibited");
- end
-
- function SchemaNoSetter(testCase)
- % Verify that trying to set the value of the public Schema property
- % results in an error of type "MATLAB:class:SetProhibited".
- matlabTable = table([1; 2; 3]);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyError(@() setfield(arrowTable, "Schema", "Value"),
...
- "MATLAB:class:SetProhibited");
- end
-
- function ColumnNamesNoSetter(testCase)
- % Verify that trying to set the value of the public ColumnNames
property
- % results in an error of type "MATLAB:class:SetProhibited".
- matlabTable = table([1; 2; 3]);
- arrowTable = arrow.table(matlabTable);
- testCase.verifyError(@() setfield(arrowTable, "ColumnNames",
"Value"), ...
- "MATLAB:class:SetProhibited");
- end
-
- function TestIsEqualTrue(testCase)
- % Verify two tables are considered equal if:
- % 1. They have the same schema
- % 2. Their corresponding columns are equal
- import arrow.tabular.Table
-
- a1 = arrow.array([1 2 3]);
- a2 = arrow.array(["A" "B" "C"]);
- a3 = arrow.array([true true false]);
-
- t1 = Table.fromArrays(a1, a2, a3, ...
- ColumnNames=["A", "B", "C"]);
- t2 = Table.fromArrays(a1, a2, a3, ...
- ColumnNames=["A", "B", "C"]);
- testCase.verifyTrue(isequal(t1, t2));
-
- % Compare zero-column tables
- t3 = Table.fromArrays();
- t4 = Table.fromArrays();
- testCase.verifyTrue(isequal(t3, t4));
-
- % Compare zero-row tables
- a4 = arrow.array([]);
- a5 = arrow.array(strings(0, 0));
- t5 = Table.fromArrays(a4, a5, ColumnNames=["D" "E"]);
- t6 = Table.fromArrays(a4, a5, ColumnNames=["D" "E"]);
- testCase.verifyTrue(isequal(t5, t6));
-
- % Call isequal with more than two arguments
- testCase.verifyTrue(isequal(t3, t4, t3, t4));
- end
-
- function TestIsEqualFalse(testCase)
- % Verify isequal returns false when expected.
- import arrow.tabular.Table
-
- a1 = arrow.array([1 2 3]);
- a2 = arrow.array(["A" "B" "C"]);
- a3 = arrow.array([true true false]);
- a4 = arrow.array(["A" missing "C"]);
- a5 = arrow.array([1 2]);
- a6 = arrow.array(["A" "B"]);
- a7 = arrow.array([true true]);
-
- t1 = Table.fromArrays(a1, a2, a3, ...
- ColumnNames=["A", "B", "C"]);
- t2 = Table.fromArrays(a1, a2, a3, ...
- ColumnNames=["D", "E", "F"]);
- t3 = Table.fromArrays(a1, a4, a3, ...
- ColumnNames=["A", "B", "C"]);
- t4 = Table.fromArrays(a5, a6, a7, ...
- ColumnNames=["A", "B", "C"]);
- t5 = Table.fromArrays(a1, a2, a3, a1, ...
- ColumnNames=["A", "B", "C", "D"]);
-
- % The column names are not equal
- testCase.verifyFalse(isequal(t1, t2));
-
- % The columns are not equal
- testCase.verifyFalse(isequal(t1, t3));
-
- % The number of rows are not equal
- testCase.verifyFalse(isequal(t1, t4));
+ properties
+ FromArraysFcn = @arrow.tabular.Table.fromArrays
+ ConstructionFcn = @arrow.table
+ ClassName = "arrow.tabular.Table"
+ end
- % The number of columns are not equal
- testCase.verifyFalse(isequal(t1, t5));
- % Call isequal with more than two arguments
- testCase.verifyFalse(isequal(t1, t2, t3, t4));
- end
+ methods(Test)
function FromRecordBatchesZeroInputsError(testCase)
% Verify the arrow.tabular.Table.fromRecordBatches function
@@ -678,10 +42,14 @@ classdef tTable < matlab.unittest.TestCase
% returns the expected arrow.tabular.Table instance when
% provided a single RecordBatch as input.
import arrow.tabular.Table
+ import arrow.type.traits.traits
+
matlabTable = table([1; 2], ["A"; "B"], VariableNames=["Number"
"Letter"]);
recordBatch = arrow.recordBatch(matlabTable);
arrowTable = Table.fromRecordBatches(recordBatch);
- testCase.verifyTable(arrowTable, ["Number", "Letter"],
["arrow.type.Float64Type", "arrow.type.StringType"], matlabTable);
+ expectedColumnTraits = varfun(@(var) traits(string(class(var))),
...
+ matlabTable, OutputFormat="cell");
+ testCase.verifyTabularObject(arrowTable, ["Number", "Letter"],
expectedColumnTraits, matlabTable);
end
function FromRecordBatchesMultipleInputs(testCase)
@@ -689,6 +57,8 @@ classdef tTable < matlab.unittest.TestCase
% returns the expected arrow.tabular.Table instance when
% provided mulitple RecordBatches as input.
import arrow.tabular.Table
+ import arrow.type.traits.traits
+
matlabTable1 = table([1; 2], ["A"; "B"], VariableNames=["Number"
"Letter"]);
matlabTable2 = table([10; 20; 30], ["A1"; "B1"; "C1"],
VariableNames=["Number" "Letter"]);
matlabTable3 = table([100; 200], ["A2"; "B2"],
VariableNames=["Number" "Letter"]);
@@ -698,7 +68,9 @@ classdef tTable < matlab.unittest.TestCase
recordBatch3 = arrow.recordBatch(matlabTable3);
arrowTable = Table.fromRecordBatches(recordBatch1, recordBatch2,
recordBatch3);
- testCase.verifyTable(arrowTable, ["Number", "Letter"],
["arrow.type.Float64Type", "arrow.type.StringType"], [matlabTable1;
matlabTable2; matlabTable3]);
+ expectedColumnTraits = varfun(@(var) traits(string(class(var))),
...
+ matlabTable1, OutputFormat="cell");
+ testCase.verifyTabularObject(arrowTable, ["Number", "Letter"],
expectedColumnTraits, [matlabTable1; matlabTable2; matlabTable3]);
end
function FromRecordBatchesInconsistentSchemaError(testCase)
@@ -719,26 +91,25 @@ classdef tTable < matlab.unittest.TestCase
methods
- function verifyTable(testCase, arrowTable, expectedColumnNames,
expectedArrayClasses, expectedMatlabTable)
- testCase.verifyEqual(arrowTable.NumColumns,
int32(width(expectedMatlabTable)));
- testCase.verifyEqual(arrowTable.ColumnNames, expectedColumnNames);
- matlabTable = table(arrowTable);
- testCase.verifyEqual(matlabTable, expectedMatlabTable);
- for ii = 1:arrowTable.NumColumns
- column = arrowTable.column(ii);
- testCase.verifyEqual(column.toMATLAB(), expectedMatlabTable{:,
ii});
- testCase.verifyInstanceOf(column.Type,
expectedArrayClasses(ii));
- end
- end
-
- function verifyChunkedArray(testCase, chunkedArray,
expectedMatlabData, expectedNumChunks, expectedNumElements, expectedArrowType)
- testCase.verifyInstanceOf(chunkedArray,
"arrow.array.ChunkedArray");
- testCase.verifyEqual(toMATLAB(chunkedArray), expectedMatlabData);
- testCase.verifyEqual(chunkedArray.NumChunks, expectedNumChunks)
- testCase.verifyEqual(chunkedArray.NumElements,
expectedNumElements);
- testCase.verifyEqual(chunkedArray.Type, expectedArrowType);
+ function verifyTabularObject(tc, arrowTabularObj, columnNames,
columnTraits, matlabTable)
+ tc.verifyInstanceOf(arrowTabularObj, tc.ClassName);
+ tc.verifyEqual(arrowTabularObj.NumColumns,
int32(width(matlabTable)));
+ tc.verifyEqual(arrowTabularObj.ColumnNames, columnNames);
+ convertedTable = arrowTabularObj.table();
+ tc.verifyEqual(convertedTable, matlabTable);
+ for ii = 1:arrowTabularObj.NumColumns
+ column = arrowTabularObj.column(ii);
+ tc.verifyEqual(column.toMATLAB(), matlabTable{:, ii});
+ tc.verifyInstanceOf(column, "arrow.array.ChunkedArray");
+ tc.verifyInstanceOf(column.Type,
columnTraits{ii}.TypeClassName);
+ end
+ end
+
+ function col = makeColumnFromArray(~, array)
+ % Each column in an arrow.tabular.Table is an
+ % arrow.array.ChunkedArray.
+ col = arrow.array.ChunkedArray.fromArrays(array);
end
end
-
end