Repository: apache/arrow
File: cpp/src/parquet/arrow/arrow_reader_writer_test.cc (C++)

Code before:

  std::string filename;
  std::shared_ptr<DataType> decimal_type;
  std::tie(filename, decimal_type) = GetParam();

  path += "/" + filename;
  ASSERT_GT(path.size(), 0);

  auto pool = ::arrow::default_memory_pool();

  std::unique_ptr<FileReader> arrow_reader;
  ASSERT_OK_NO_THROW(
      FileReader::Make(pool, ParquetFileReader::OpenFile(path, false), &arrow_reader));
  std::shared_ptr<::arrow::Table> table;
  ASSERT_OK_NO_THROW(arrow_reader->ReadTable(&table));

  std::shared_ptr<::arrow::Schema> schema;
  ASSERT_OK_NO_THROW(arrow_reader->GetSchema(&schema));
  ASSERT_EQ(1, schema->num_fields());
  ASSERT_TRUE(schema->field(0)->type()->Equals(*decimal_type));

  ASSERT_EQ(1, table->num_columns());

  constexpr int32_t expected_length = 24;

  auto value_column = table->column(0);
  ASSERT_EQ(expected_length, value_column->length());

  ASSERT_EQ(1, value_column->num_chunks());

  auto chunk = value_column->chunk(0);

  std::shared_ptr<Array> expected_array;

  ::arrow::Decimal128Builder builder(decimal_type, pool);

  for (int32_t i = 0; i < expected_length; ++i) {
    ::arrow::Decimal128 value((i + 1) * 100);
    ASSERT_OK(builder.Append(value));
  }
  ASSERT_OK(builder.Finish(&expected_array));
  AssertArraysEqual(*expected_array, *chunk);
}

INSTANTIATE_TEST_SUITE_P(
    ReadDecimals, TestArrowReaderAdHocSparkAndHvr,
    ::testing::Values(
        std::make_tuple("int32_decimal.parquet", ::arrow::decimal128(4, 2)),
        std::make_tuple("int64_decimal.parquet", ::arrow::decimal128(10, 2)),
        std::make_tuple("fixed_length_decimal.parquet", ::arrow::decimal128(25, 2)),
        std::make_tuple("fixed_length_decimal_legacy.parquet",

Review comment (suggestion):
Would have been nice to add a validation call here.
```c++
    ASSERT_OK(table->ValidateFull());
```

Code after:
        "    repeated int32 field_id=-1 array;\n"
        "  }\n"
        "}\n";

    // Expected Arrow schema and data
    auto arrow_inner_list =
        field("array", list(field("array", ::arrow::int32(), /*nullable=*/false)),
              /*nullable=*/false);
    auto arrow_outer_list = list(arrow_inner_list);
    auto arrow_schema =
        ::arrow::schema({field("a", arrow_outer_list, /*nullable=*/false)});
    auto expected_table = TableFromJSON(arrow_schema, {R"([[[[1,2],[3,4]]]])"});

    // Verify Parquet schema
    auto root_group = file_reader->metadata()->schema()->group_node();
    ASSERT_EQ(1, root_group->field_count());
    std::stringstream nodeStr;
    PrintSchema(root_group->field(0).get(), nodeStr);
    ASSERT_EQ(kExpectedLegacyList, nodeStr.str());

    // Verify Arrow schema and data
    std::unique_ptr<FileReader> reader;
    ASSERT_OK_NO_THROW(
        FileReader::Make(default_memory_pool(), std::move(file_reader), &reader));
    std::shared_ptr<Table> table;
    ASSERT_OK(reader->ReadTable(&table));
    AssertTablesEqual(*expected_table, *table);
  };

  // Round-trip test for Parquet C++ reader and writer
  {
    // Create Parquet schema of legacy two-level encoding
    auto inner_list = GroupNode::Make("array", Repetition::REPEATED,
                                      {schema::Int32("array", Repetition::REPEATED)},
                                      LogicalType::List());
    auto outer_list =
        GroupNode::Make("a", Repetition::REQUIRED, {inner_list}, LogicalType::List());
    auto schema_node = GroupNode::Make("schema", Repetition::REQUIRED, {outer_list});

    // Create a Parquet writer to write values of nested list
    auto sink = CreateOutputStream();
    auto file_writer =
        ParquetFileWriter::Open(sink, std::dynamic_pointer_cast<GroupNode>(schema_node));
    auto row_group_writer = file_writer->AppendRowGroup();
    auto int_writer = dynamic_cast<Int32Writer*>(row_group_writer->NextColumn());
    ASSERT_TRUE(int_writer != nullptr);

    // Directly write a single row of nested list: [[1, 2],[3, 4]]
    constexpr int64_t kNumValues = 4;
    constexpr std::array<int16_t, kNumValues> kRepLevels = {0, 2, 1, 2};
    constexpr std::array<int16_t, kNumValues> kDefLevels = {2, 2, 2, 2};