1 /**
2  * @file   unit-cppapi-updates.cc
3  *
4  * @section LICENSE
5  *
6  * The MIT License
7  *
8  * @copyright Copyright (c) 2018-2021 TileDB, Inc.
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a copy
11  * of this software and associated documentation files (the "Software"), to deal
12  * in the Software without restriction, including without limitation the rights
13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the Software is
15  * furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included in
18  * all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  * THE SOFTWARE.
27  *
28  * @section DESCRIPTION
29  *
30  * Tests array updates (writes producing multiple fragments) using the C++ API.
31  */
32 
33 #include "catch.hpp"
34 #include "tiledb/sm/cpp_api/tiledb"
35 
36 using namespace tiledb;
37 
38 TEST_CASE(
39     "C++ API updates: test writing two identical fragments",
40     "[updates][updates-identical-fragments]") {
41   const std::string array_name = "updates_identical_fragments";
42   Context ctx;
43   VFS vfs(ctx);
44 
45   if (vfs.is_dir(array_name))
46     vfs.remove_dir(array_name);
47 
48   // Create
49   const int rowmin = 0, rowmax = 9, row_ext = rowmax - rowmin + 1;
50   const int colmin = 0, colmax = 9, col_ext = colmax - colmin + 1;
51 
52   Domain domain(ctx);
53   domain
54       .add_dimension(
55           Dimension::create<int>(ctx, "rows", {{rowmin, rowmax}}, row_ext))
56       .add_dimension(
57           Dimension::create<int>(ctx, "cols", {{colmin, colmax}}, col_ext));
58   ArraySchema schema(ctx, TILEDB_DENSE);
59   schema.set_domain(domain).set_order({{TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR}});
60   auto attr1 = Attribute::create<std::vector<int>>(ctx, "a1");
61   schema.add_attribute(attr1);
62   Array::create(array_name, schema);
63 
64   // Setup data
65   std::vector<int> data_a1(row_ext * col_ext);
66   std::vector<uint64_t> offsets_a1(row_ext * col_ext);
67 
68   for (int i = 0; i < (int)data_a1.size(); i++) {
69     data_a1[i] = i;
70     offsets_a1[i] = i * sizeof(int);
71   }
72 
73   // First write
74   Array array_w1(ctx, array_name, TILEDB_WRITE);
75   Query query_w1(ctx, array_w1);
76   query_w1.set_subarray({rowmin, rowmax, colmin, colmax})
77       .set_layout(TILEDB_ROW_MAJOR)
78       .set_data_buffer("a1", data_a1)
79       .set_offsets_buffer("a1", offsets_a1);
80   query_w1.submit();
81   query_w1.finalize();
82   array_w1.close();
83 
84   // Second write
85   Array array_w2(ctx, array_name, TILEDB_WRITE);
86   Query query_w2(ctx, array_w2);
87   query_w2.set_subarray({rowmin, rowmax, colmin, colmax})
88       .set_layout(TILEDB_ROW_MAJOR)
89       .set_data_buffer("a1", data_a1)
90       .set_offsets_buffer("a1", offsets_a1);
91   query_w2.submit();
92   query_w2.finalize();
93   array_w2.close();
94 
95   // Read
96   Array array(ctx, array_name, TILEDB_READ);
97   Query query(ctx, array);
98 
99   std::vector<int> subarray = {rowmin, rowmax, colmin, colmax};
100   std::vector<uint64_t> r_offsets_a1;
101   r_offsets_a1.resize(100);
102   std::vector<int> r_data_a1;
103   r_data_a1.resize(300);
104 
105   query.set_subarray(subarray)
106       .set_layout(TILEDB_ROW_MAJOR)
107       .set_data_buffer("a1", r_data_a1)
108       .set_offsets_buffer("a1", r_offsets_a1);
109   query.submit();
110   REQUIRE(query.query_status() == Query::Status::COMPLETE);
111   array.close();
112 
113   for (int i = 0; i < (int)data_a1.size(); i++)
114     REQUIRE(r_data_a1[i] == i);
115 
116   if (vfs.is_dir(array_name))
117     vfs.remove_dir(array_name);
118 }
119