1+ // ===----------------------------------------------------------------------===//
2+ //
3+ // Peloton
4+ //
5+ // layout_catalog.cpp
6+ //
7+ // Identification: src/catalog/layout_catalog.cpp
8+ //
9+ // Copyright (c) 2015-2018, Carnegie Mellon University Database Group
10+ //
11+ // ===----------------------------------------------------------------------===//
12+
13+ #include " catalog/layout_catalog.h"
14+
15+ #include " catalog/catalog.h"
16+ #include " catalog/system_catalogs.h"
17+ #include " concurrency/transaction_context.h"
18+ #include " executor/logical_tile.h"
19+ #include " storage/data_table.h"
20+ #include " storage/layout.h"
21+
22+ namespace peloton {
23+ namespace catalog {
24+
25+ /* * @brief Constructor invoked by the SystemsCatalog constructor.
26+ * @param pg_catalog The database to which this pg_layout belongs.
27+ */
28+ LayoutCatalog::LayoutCatalog (
29+ storage::Database *pg_catalog, UNUSED_ATTRIBUTE type::AbstractPool *pool,
30+ UNUSED_ATTRIBUTE concurrency::TransactionContext *txn)
31+ : AbstractCatalog(LAYOUT_CATALOG_OID, LAYOUT_CATALOG_NAME,
32+ InitializeSchema ().release(), pg_catalog) {
33+ // Add indexes for pg_attribute
34+ AddIndex ({ColumnId::TABLE_OID, ColumnId::LAYOUT_OID}, LAYOUT_CATALOG_PKEY_OID,
35+ LAYOUT_CATALOG_NAME " _pkey" , IndexConstraintType::PRIMARY_KEY);
36+ AddIndex ({ColumnId::TABLE_OID}, LAYOUT_CATALOG_SKEY0_OID,
37+ LAYOUT_CATALOG_NAME " _skey0" , IndexConstraintType::DEFAULT);
38+ }
39+ /* * @brief Destructor. Do nothing. Layouts will be dropped by DropTable. */
40+ LayoutCatalog::~LayoutCatalog () {}
41+
42+ /* * @brief Initilailizes the schema for the pg_layout table.
43+ * @return unique_ptr of the schema for pg_layout.
44+ */
45+ std::unique_ptr<catalog::Schema> LayoutCatalog::InitializeSchema () {
46+ const std::string primary_key_constraint_name = " primary_key" ;
47+ const std::string not_null_constraint_name = " not_null" ;
48+
49+ auto table_id_column = catalog::Column (
50+ type::TypeId::INTEGER, type::Type::GetTypeSize (type::TypeId::INTEGER),
51+ " table_oid" , true );
52+ table_id_column.AddConstraint (catalog::Constraint (
53+ ConstraintType::PRIMARY, primary_key_constraint_name));
54+ table_id_column.AddConstraint (
55+ catalog::Constraint (ConstraintType::NOTNULL, not_null_constraint_name));
56+
57+ auto layout_oid_column = catalog::Column (
58+ type::TypeId::INTEGER, type::Type::GetTypeSize (type::TypeId::INTEGER),
59+ " layout_oid" , true );
60+ layout_oid_column.AddConstraint (catalog::Constraint (
61+ ConstraintType::PRIMARY, primary_key_constraint_name));
62+ layout_oid_column.AddConstraint (
63+ catalog::Constraint (ConstraintType::NOTNULL, not_null_constraint_name));
64+
65+ auto num_columns_column = catalog::Column (
66+ type::TypeId::INTEGER, type::Type::GetTypeSize (type::TypeId::INTEGER),
67+ " num_columns" , true );
68+ num_columns_column.AddConstraint (
69+ catalog::Constraint (ConstraintType::NOTNULL, not_null_constraint_name));
70+
71+ auto column_map_column = catalog::Column (
72+ type::TypeId::VARCHAR, type::Type::GetTypeSize (type::TypeId::VARCHAR),
73+ " column_map" , false );
74+ column_map_column.AddConstraint (
75+ catalog::Constraint (ConstraintType::NOTNULL, not_null_constraint_name));
76+
77+ std::unique_ptr<catalog::Schema> column_catalog_schema (
78+ new catalog::Schema ({table_id_column, layout_oid_column,
79+ num_columns_column, column_map_column}));
80+
81+ return column_catalog_schema;
82+ }
83+
84+ /* * @brief Insert a layout into the pg_layout table.
85+ * @param table_oid oid of the table to which the new layout belongs.
86+ * @param layout layout to be added to the pg_layout table.
87+ * @param pool to allocate memory for the column_map column.
88+ * @param txn TransactionContext for adding the layout.
89+ * @return true on success.
90+ */
91+ bool LayoutCatalog::InsertLayout (oid_t table_oid,
92+ std::shared_ptr<const storage::Layout> layout,
93+ type::AbstractPool *pool,
94+ concurrency::TransactionContext *txn) {
95+ // Create the tuple first
96+ std::unique_ptr<storage::Tuple> tuple (
97+ new storage::Tuple (catalog_table_->GetSchema (), true ));
98+
99+ auto val0 = type::ValueFactory::GetIntegerValue (table_oid);
100+ auto val1 = type::ValueFactory::GetIntegerValue (layout->GetOid ());
101+ auto val2 = type::ValueFactory::GetIntegerValue (layout->GetColumnCount ());
102+ auto val3 = type::ValueFactory::GetVarcharValue (layout->SerializeColumnMap (),
103+ nullptr );
104+
105+ tuple->SetValue (LayoutCatalog::ColumnId::TABLE_OID, val0, pool);
106+ tuple->SetValue (LayoutCatalog::ColumnId::LAYOUT_OID, val1, pool);
107+ tuple->SetValue (LayoutCatalog::ColumnId::NUM_COLUMNS, val2, pool);
108+ tuple->SetValue (LayoutCatalog::ColumnId::COLUMN_MAP, val3, pool);
109+
110+ // Insert the tuple
111+ return InsertTuple (std::move (tuple), txn);
112+ }
113+
114+ /* * @brief Delete a layout from the pg_layout table.
115+ * @param table_oid oid of the table to which the old layout belongs.
116+ * @param layout_oid oid of the layout to be deleted.
117+ * @param txn TransactionContext for deleting the layout.
118+ * @return true on success.
119+ */
120+ bool LayoutCatalog::DeleteLayout (oid_t table_oid, oid_t layout_oid,
121+ concurrency::TransactionContext *txn) {
122+ oid_t index_offset = IndexId::PRIMARY_KEY; // Index of table_oid & layout_oid
123+
124+ std::vector<type::Value> values;
125+ values.push_back (type::ValueFactory::GetIntegerValue (table_oid).Copy ());
126+ values.push_back (type::ValueFactory::GetIntegerValue (layout_oid).Copy ());
127+
128+ auto pg_table = Catalog::GetInstance ()
129+ ->GetSystemCatalogs (database_oid)
130+ ->GetTableCatalog ();
131+
132+ // delete column from cache
133+ auto table_object = pg_table->GetTableObject (table_oid, txn);
134+ table_object->EvictLayout (layout_oid);
135+
136+ return DeleteWithIndexScan (index_offset, values, txn);
137+ }
138+
139+ /* * @brief Delete all layouts correponding to a table from the pg_layout.
140+ * @param table_oid oid of the table to delete all layouts.
141+ * @param txn TransactionContext for deleting the layouts.
142+ * @return true on success.
143+ */
144+ bool LayoutCatalog::DeleteLayouts (oid_t table_oid,
145+ concurrency::TransactionContext *txn) {
146+ oid_t index_offset = IndexId::SKEY_TABLE_OID; // Index of table_oid
147+ std::vector<type::Value> values;
148+ values.push_back (type::ValueFactory::GetIntegerValue (table_oid).Copy ());
149+
150+ // delete layouts from cache
151+ auto pg_table = Catalog::GetInstance ()
152+ ->GetSystemCatalogs (database_oid)
153+ ->GetTableCatalog ();
154+ auto table_object = pg_table->GetTableObject (table_oid, txn);
155+ table_object->EvictAllLayouts ();
156+
157+ return DeleteWithIndexScan (index_offset, values, txn);
158+ }
159+
160+ /* * @brief Get all layouts correponding to a table from the pg_layout.
161+ * @param table_oid oid of the table to fetch all layouts.
162+ * @param txn TransactionContext for getting the layouts.
163+ * @return unordered_map containing a layout_oid -> layout mapping.
164+ */
165+ const std::unordered_map<oid_t , std::shared_ptr<const storage::Layout>>
166+ LayoutCatalog::GetLayouts (oid_t table_oid,
167+ concurrency::TransactionContext *txn) {
168+ // Try to find the layouts in the cache
169+ auto pg_table = Catalog::GetInstance ()
170+ ->GetSystemCatalogs (database_oid)
171+ ->GetTableCatalog ();
172+ auto table_object = pg_table->GetTableObject (table_oid, txn);
173+ PELOTON_ASSERT (table_object && table_object->GetTableOid () == table_oid);
174+ auto layout_objects = table_object->GetLayouts (true );
175+ if (layout_objects.size () != 0 ) {
176+ return layout_objects;
177+ }
178+
179+ // Cache miss, get from pg_catalog
180+ std::vector<oid_t > column_ids (all_column_ids);
181+ oid_t index_offset = IndexId::SKEY_TABLE_OID; // Index of table_oid
182+ std::vector<type::Value> values;
183+ values.push_back (type::ValueFactory::GetIntegerValue (table_oid).Copy ());
184+
185+ auto result_tiles =
186+ GetResultWithIndexScan (column_ids, index_offset, values, txn);
187+
188+ for (auto &tile : (*result_tiles)) { // Iterate through the result_tiles
189+ for (auto tuple_id : *tile) {
190+ oid_t layout_oid =
191+ tile->GetValue (tuple_id, LayoutCatalog::ColumnId::LAYOUT_OID)
192+ .GetAs <oid_t >();
193+ oid_t num_columns =
194+ tile->GetValue (tuple_id, LayoutCatalog::ColumnId::NUM_COLUMNS)
195+ .GetAs <oid_t >();
196+ std::string column_map_str =
197+ tile->GetValue (tuple_id, LayoutCatalog::ColumnId::COLUMN_MAP)
198+ .ToString ();
199+ auto column_map =
200+ storage::Layout::DeserializeColumnMap (num_columns, column_map_str);
201+ auto layout_object =
202+ std::make_shared<const storage::Layout>(column_map, layout_oid);
203+ table_object->InsertLayout (layout_object);
204+ }
205+ }
206+
207+ return table_object->GetLayouts ();
208+ }
209+
210+ /* * @brief Get the layout by layout_oid from the pg_layout.
211+ * @param table_oid oid of the table to fetch the layout.
212+ * @param layout_oid oid of the layout being queried.
213+ * @param txn TransactionContext for getting the layout.
214+ * @return shared_ptr corresponding to the layout_oid if found.
215+ * nullptr otherwise.
216+ */
217+ std::shared_ptr<const storage::Layout> LayoutCatalog::GetLayoutWithOid (
218+ oid_t table_oid, oid_t layout_oid, concurrency::TransactionContext *txn) {
219+ auto table_layouts = GetLayouts (table_oid, txn);
220+ for (const auto &layout_entry : table_layouts) {
221+ if (layout_entry.second ->GetOid () == layout_oid) {
222+ return layout_entry.second ;
223+ }
224+ }
225+ return nullptr ;
226+ }
227+
228+ } // namespace catalog
229+ } // namespace peloton
0 commit comments