OmniSciDB  bf83d84833
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DdlCommandExecutor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "DdlCommandExecutor.h"
18 
19 #include <boost/algorithm/string/predicate.hpp>
20 
21 #include "rapidjson/document.h"
22 
23 // Note: avoid adding #include(s) that require thrift
24 
25 #include "Catalog/Catalog.h"
26 #include "Catalog/SysCatalog.h"
28 #include "LockMgr/LockMgr.h"
29 #include "Parser/ParserNode.h"
30 #include "Shared/StringTransform.h"
31 
32 #include "QueryEngine/Execute.h" // Executor::getArenaBlockSize()
34 
35 extern bool g_enable_fsi;
36 extern bool g_enable_s3_fsi;
37 
38 bool DdlCommand::isDefaultServer(const std::string& server_name) {
39  return boost::iequals(server_name.substr(0, 7), "omnisci");
40 }
41 
42 namespace {
43 template <class LockType>
44 std::tuple<const TableDescriptor*,
45  std::unique_ptr<lockmgr::TableSchemaLockContainer<LockType>>>
47  const std::string& table_name,
48  const bool populate_fragmenter) {
49  const TableDescriptor* td{nullptr};
50  std::unique_ptr<lockmgr::TableSchemaLockContainer<LockType>> td_with_lock =
51  std::make_unique<lockmgr::TableSchemaLockContainer<LockType>>(
53  cat, table_name, populate_fragmenter));
54  CHECK(td_with_lock);
55  td = (*td_with_lock)();
56  CHECK(td);
57  return std::make_tuple(td, std::move(td_with_lock));
58 }
59 
61  int32_t min_epoch;
62  int32_t max_epoch;
63  int32_t min_epoch_floor;
64  int32_t max_epoch_floor;
65 
67  : File_Namespace::StorageStats(storage_stats)
68  , min_epoch(storage_stats.epoch)
69  , max_epoch(storage_stats.epoch)
70  , min_epoch_floor(storage_stats.epoch_floor)
71  , max_epoch_floor(storage_stats.epoch_floor) {}
72 
73  void aggregate(const File_Namespace::StorageStats& storage_stats) {
74  metadata_file_count += storage_stats.metadata_file_count;
75  total_metadata_file_size += storage_stats.total_metadata_file_size;
76  total_metadata_page_count += storage_stats.total_metadata_page_count;
77  if (storage_stats.total_free_metadata_page_count) {
78  if (total_free_metadata_page_count) {
79  total_free_metadata_page_count.value() +=
80  storage_stats.total_free_metadata_page_count.value();
81  } else {
82  total_free_metadata_page_count = storage_stats.total_free_metadata_page_count;
83  }
84  }
85  data_file_count += storage_stats.data_file_count;
86  total_data_file_size += storage_stats.total_data_file_size;
87  total_data_page_count += storage_stats.total_data_page_count;
88  if (storage_stats.total_free_data_page_count) {
89  if (total_free_data_page_count) {
90  total_free_data_page_count.value() +=
91  storage_stats.total_free_data_page_count.value();
92  } else {
93  total_free_data_page_count = storage_stats.total_free_data_page_count;
94  }
95  }
96  min_epoch = std::min(min_epoch, storage_stats.epoch);
97  max_epoch = std::max(max_epoch, storage_stats.epoch);
98  min_epoch_floor = std::min(min_epoch_floor, storage_stats.epoch_floor);
99  max_epoch_floor = std::max(max_epoch_floor, storage_stats.epoch_floor);
100  }
101 };
102 
104  const Catalog_Namespace::Catalog* catalog) {
105  const auto global_file_mgr = catalog->getDataMgr().getGlobalFileMgr();
106  std::optional<AggregratedStorageStats> agg_storage_stats;
107  if (td->nShards > 0) {
108  const auto physical_tables = catalog->getPhysicalTablesDescriptors(td);
109  CHECK_EQ(static_cast<size_t>(td->nShards), physical_tables.size());
110 
111  for (const auto physical_table : physical_tables) {
112  auto storage_stats = global_file_mgr->getStorageStats(catalog->getDatabaseId(),
113  physical_table->tableId);
114  if (agg_storage_stats) {
115  agg_storage_stats.value().aggregate(storage_stats);
116  } else {
117  agg_storage_stats = storage_stats;
118  }
119  }
120  } else {
121  agg_storage_stats =
122  global_file_mgr->getStorageStats(catalog->getDatabaseId(), td->tableId);
123  }
124  CHECK(agg_storage_stats.has_value());
125  return agg_storage_stats.value();
126 }
127 
128 std::unique_ptr<RexLiteral> genLiteralStr(std::string val) {
129  return std::unique_ptr<RexLiteral>(
130  new RexLiteral(val, SQLTypes::kTEXT, SQLTypes::kTEXT, 0, 0, 0, 0));
131 }
132 
133 std::unique_ptr<RexLiteral> genLiteralTimestamp(time_t val) {
134  return std::unique_ptr<RexLiteral>(new RexLiteral(
135  (int64_t)val, SQLTypes::kTIMESTAMP, SQLTypes::kTIMESTAMP, 0, 8, 0, 8));
136 }
137 
138 std::unique_ptr<RexLiteral> genLiteralBigInt(int64_t val) {
139  return std::unique_ptr<RexLiteral>(
140  new RexLiteral(val, SQLTypes::kBIGINT, SQLTypes::kBIGINT, 0, 8, 0, 8));
141 }
142 
143 std::unique_ptr<RexLiteral> genLiteralBoolean(bool val) {
144  return std::unique_ptr<RexLiteral>(
145  // new RexLiteral(val, SQLTypes::kBOOLEAN, SQLTypes::kBOOLEAN, 0, 0, 0, 0));
146  new RexLiteral(
147  (int64_t)(val ? 1 : 0), SQLTypes::kBIGINT, SQLTypes::kBIGINT, 0, 8, 0, 8));
148 }
149 
151  std::vector<TargetMetaInfo>& label_infos,
152  const std::vector<std::tuple<std::string, SQLTypes, bool>>& headers) {
153  for (const auto& header : headers) {
154  auto [_val, _type, _notnull] = header;
155  if (_type == kBIGINT || _type == kTEXT || _type == kTIMESTAMP || _type == kBOOLEAN) {
156  label_infos.emplace_back(_val, SQLTypeInfo(_type, _notnull));
157  } else {
158  UNREACHABLE() << "Unsupported type provided for header. SQL type: "
159  << to_string(_type);
160  }
161  }
162 }
163 
164 void add_table_details(std::vector<RelLogicalValues::RowValues>& logical_values,
165  const TableDescriptor* logical_table,
166  const AggregratedStorageStats& agg_storage_stats) {
167  bool is_sharded_table = (logical_table->nShards > 0);
168  logical_values.emplace_back(RelLogicalValues::RowValues{});
169  logical_values.back().emplace_back(genLiteralBigInt(logical_table->tableId));
170  logical_values.back().emplace_back(genLiteralStr(logical_table->tableName));
171  logical_values.back().emplace_back(genLiteralBigInt(logical_table->nColumns));
172  logical_values.back().emplace_back(genLiteralBoolean(is_sharded_table));
173  logical_values.back().emplace_back(genLiteralBigInt(logical_table->nShards));
174  logical_values.back().emplace_back(genLiteralBigInt(logical_table->maxRows));
175  logical_values.back().emplace_back(genLiteralBigInt(logical_table->maxFragRows));
176  logical_values.back().emplace_back(genLiteralBigInt(logical_table->maxRollbackEpochs));
177  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.min_epoch));
178  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.max_epoch));
179  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.min_epoch_floor));
180  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.max_epoch_floor));
181  logical_values.back().emplace_back(
182  genLiteralBigInt(agg_storage_stats.metadata_file_count));
183  logical_values.back().emplace_back(
184  genLiteralBigInt(agg_storage_stats.total_metadata_file_size));
185  logical_values.back().emplace_back(
186  genLiteralBigInt(agg_storage_stats.total_metadata_page_count));
187 
188  if (agg_storage_stats.total_free_metadata_page_count) {
189  logical_values.back().emplace_back(
190  genLiteralBigInt(agg_storage_stats.total_free_metadata_page_count.value()));
191  } else {
192  logical_values.back().emplace_back(genLiteralBigInt(NULL_BIGINT));
193  }
194 
195  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.data_file_count));
196  logical_values.back().emplace_back(
197  genLiteralBigInt(agg_storage_stats.total_data_file_size));
198  logical_values.back().emplace_back(
199  genLiteralBigInt(agg_storage_stats.total_data_page_count));
200 
201  if (agg_storage_stats.total_free_data_page_count) {
202  logical_values.back().emplace_back(
203  genLiteralBigInt(agg_storage_stats.total_free_data_page_count.value()));
204  } else {
205  logical_values.back().emplace_back(genLiteralBigInt(NULL_BIGINT));
206  }
207 }
208 
209 // -----------------------------------------------------------------------
210 // class: JsonColumnSqlType
211 // Defined & Implemented here to avoid exposing rapidjson in the header file
212 // -----------------------------------------------------------------------
213 
216  public:
217  JsonColumnSqlType(const rapidjson::Value& data_type)
218  : ddl_utils::SqlType(getSqlType(data_type),
219  getParam1(data_type),
220  getParam2(data_type),
221  isArray(data_type),
222  getArraySize(data_type)) {}
223 
224  private:
225  static SQLTypes getSqlType(const rapidjson::Value& data_type);
226  static SQLTypes getSqlType(const std::string& type);
227  static int getParam1(const rapidjson::Value& data_type);
228  static int getParam2(const rapidjson::Value& data_type);
229  static bool isArray(const rapidjson::Value& data_type);
230  static int getArraySize(const rapidjson::Value& data_type);
231 };
232 
234  public:
235  JsonColumnEncoding(const rapidjson::Value& data_type)
236  : ddl_utils::Encoding(getEncodingName(data_type), getEncodingParam(data_type)) {}
237 
238  private:
239  static std::string* getEncodingName(const rapidjson::Value& data_type);
240  static int getEncodingParam(const rapidjson::Value& data_type);
241 };
242 
243 // -----------------------------------------------------------------------
244 // class DdlCommandDataImpl:
245 //
246 // Concrete class to cache parse data
247 // Defined & Implemented here to avoid exposing rapidjson in the header file
248 // Helper/access fns available to get useful pieces of cache data
249 // -----------------------------------------------------------------------
251  public:
252  DdlCommandDataImpl(const std::string& ddl_statement);
254 
255  // The full query available for futher analysis
256  const rapidjson::Value& query() const;
257 
258  // payload as extracted from the query
259  const rapidjson::Value& payload() const;
260 
261  // commandStr extracted from the payload
262  virtual std::string commandStr() override;
263 
264  rapidjson::Document ddl_query;
265 };
266 
267 DdlCommandDataImpl::DdlCommandDataImpl(const std::string& ddl_statement)
268  : DdlCommandData(ddl_statement) {
269  ddl_query.Parse(ddl_statement);
270 }
271 
273 
274 const rapidjson::Value& DdlCommandDataImpl::query() const {
275  return ddl_query;
276 }
277 
278 const rapidjson::Value& DdlCommandDataImpl::payload() const {
279  CHECK(ddl_query.HasMember("payload"));
280  CHECK(ddl_query["payload"].IsObject());
281  return ddl_query["payload"];
282 }
283 
285  if (ddl_query.IsObject() && ddl_query.HasMember("payload") &&
286  ddl_query["payload"].IsObject()) {
287  auto& payload = ddl_query["payload"];
288  if (payload.HasMember("command") && payload["command"].IsString()) {
289  return payload["command"].GetString();
290  }
291  }
292  return "";
293 }
294 
295 // Helper Fn to get the payload from the abstract base class
296 const rapidjson::Value& extractPayload(const DdlCommandData& ddl_data) {
297  const DdlCommandDataImpl* data = static_cast<const DdlCommandDataImpl*>(&ddl_data);
298  return data->payload();
299 }
300 
301 const rapidjson::Value* extractFilters(const rapidjson::Value& payload) {
302  const rapidjson::Value* filters = nullptr;
303  if (payload.HasMember("filters") && payload["filters"].IsArray()) {
304  filters = &payload["filters"];
305  }
306  return filters;
307 }
308 
309 } // namespace
310 
312  const std::string& ddl_statement,
313  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
314  : session_ptr_(session_ptr) {
315  CHECK(!ddl_statement.empty());
316  ddl_statement_ = ddl_statement;
317 
318  // parse the incoming query,
319  // cache the parsed rapidjson object inside a DdlCommandDataImpl
320  // store the "abstract/base class" reference in ddl_data_
321  DdlCommandDataImpl* ddl_query_data = new DdlCommandDataImpl(ddl_statement);
322  ddl_data_ = std::unique_ptr<DdlCommandData>(ddl_query_data);
323 
324  VLOG(2) << "Parsing JSON DDL from Calcite: " << ddl_statement;
325  auto& ddl_query = ddl_query_data->query();
326  CHECK(ddl_query.IsObject()) << ddl_statement;
327  CHECK(ddl_query.HasMember("payload"));
328  CHECK(ddl_query["payload"].IsObject());
329  const auto& payload = ddl_query["payload"].GetObject();
330  CHECK(payload.HasMember("command"));
331  CHECK(payload["command"].IsString());
332  ddl_command_ = payload["command"].GetString();
333 }
334 
337 
338  // the following commands use parser node locking to ensure safe concurrent access
339  if (ddl_command_ == "CREATE_TABLE") {
340  auto create_table_stmt = Parser::CreateTableStmt(extractPayload(*ddl_data_));
341  create_table_stmt.execute(*session_ptr_);
342  return result;
343  } else if (ddl_command_ == "CREATE_VIEW") {
344  auto create_view_stmt = Parser::CreateViewStmt(extractPayload(*ddl_data_));
345  create_view_stmt.execute(*session_ptr_);
346  return result;
347  } else if (ddl_command_ == "DROP_TABLE") {
348  auto drop_table_stmt = Parser::DropTableStmt(extractPayload(*ddl_data_));
349  drop_table_stmt.execute(*session_ptr_);
350  return result;
351  } else if (ddl_command_ == "DROP_VIEW") {
352  auto drop_view_stmt = Parser::DropViewStmt(extractPayload(*ddl_data_));
353  drop_view_stmt.execute(*session_ptr_);
354  return result;
355  }
356 
357  // the following commands require a global unique lock until proper table locking has
358  // been implemented and/or verified
359  auto execute_write_lock = mapd_unique_lock<mapd_shared_mutex>(
362  // TODO(vancouver): add appropriate table locking
363 
364  if (ddl_command_ == "CREATE_SERVER") {
365  result = CreateForeignServerCommand{*ddl_data_, session_ptr_}.execute();
366  } else if (ddl_command_ == "DROP_SERVER") {
367  result = DropForeignServerCommand{*ddl_data_, session_ptr_}.execute();
368  } else if (ddl_command_ == "CREATE_FOREIGN_TABLE") {
369  result = CreateForeignTableCommand{*ddl_data_, session_ptr_}.execute();
370  } else if (ddl_command_ == "DROP_FOREIGN_TABLE") {
371  result = DropForeignTableCommand{*ddl_data_, session_ptr_}.execute();
372  } else if (ddl_command_ == "SHOW_TABLES") {
373  result = ShowTablesCommand{*ddl_data_, session_ptr_}.execute();
374  } else if (ddl_command_ == "SHOW_TABLE_DETAILS") {
375  result = ShowTableDetailsCommand{*ddl_data_, session_ptr_}.execute();
376  } else if (ddl_command_ == "SHOW_DATABASES") {
377  result = ShowDatabasesCommand{*ddl_data_, session_ptr_}.execute();
378  } else if (ddl_command_ == "SHOW_SERVERS") {
379  result = ShowForeignServersCommand{*ddl_data_, session_ptr_}.execute();
380  } else if (ddl_command_ == "ALTER_SERVER") {
381  result = AlterForeignServerCommand{*ddl_data_, session_ptr_}.execute();
382  } else if (ddl_command_ == "ALTER_FOREIGN_TABLE") {
383  result = AlterForeignTableCommand{*ddl_data_, session_ptr_}.execute();
384  } else if (ddl_command_ == "REFRESH_FOREIGN_TABLES") {
385  result = RefreshForeignTablesCommand{*ddl_data_, session_ptr_}.execute();
386  } else if (ddl_command_ == "SHOW_QUERIES") {
387  LOG(ERROR) << "SHOW QUERIES DDL is not ready yet!\n";
388  } else if (ddl_command_ == "SHOW_DISK_CACHE_USAGE") {
389  result = ShowDiskCacheUsageCommand{*ddl_data_, session_ptr_}.execute();
390  } else if (ddl_command_ == "KILL_QUERY") {
391  auto& ddl_payload = extractPayload(*ddl_data_);
392  CHECK(ddl_payload.HasMember("querySession"));
393  const std::string& querySessionPayload = ddl_payload["querySession"].GetString();
394  auto querySession = querySessionPayload.substr(1, 8);
395  CHECK_EQ(querySession.length(),
396  (unsigned long)8); // public_session_id's length + two quotes
397  LOG(ERROR) << "TRY TO KILL QUERY " << querySession
398  << " BUT KILL QUERY DDL is not ready yet!\n";
399  } else {
400  throw std::runtime_error("Unsupported DDL command");
401  }
402 
403  return result;
404 }
405 
407  return (ddl_command_ == "SHOW_USER_SESSIONS");
408 }
409 
411  return (ddl_command_ == "SHOW_QUERIES");
412 }
413 
415  return (ddl_command_ == "KILL_QUERY");
416 }
417 
419  DistributedExecutionDetails execution_details;
420  if (ddl_command_ == "CREATE_TABLE" || ddl_command_ == "DROP_TABLE" ||
421  ddl_command_ == "CREATE_VIEW" || ddl_command_ == "DROP_VIEW") {
423  execution_details.aggregation_type = AggregationType::NONE;
424  } else if (ddl_command_ == "SHOW_TABLE_DETAILS") {
426  execution_details.aggregation_type = AggregationType::UNION;
427  } else {
429  execution_details.aggregation_type = AggregationType::NONE;
430  }
431  return execution_details;
432 }
433 
435  // caller should check whether DDL indicates KillQuery request
436  // i.e., use isKillQuery() before calling this function
437  auto& ddl_payload = extractPayload(*ddl_data_);
438  CHECK(isKillQuery());
439  CHECK(ddl_payload.HasMember("querySession"));
440  const std::string& query_session = ddl_payload["querySession"].GetString();
441  // regex matcher for public_session: start_time{3}-session_id{4} (Example:819-4RDo)
442  boost::regex session_id_regex{R"([0-9]{3}-[a-zA-Z0-9]{4})",
443  boost::regex::extended | boost::regex::icase};
444  if (!boost::regex_match(query_session, session_id_regex)) {
445  throw std::runtime_error(
446  "Please provide the correct session ID of the query that you want to interrupt.");
447  }
448  return query_session;
449 }
450 
451 const std::string DdlCommandExecutor::commandStr() {
452  return ddl_command_;
453 }
454 
456  const DdlCommandData& ddl_data,
457  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
458  : DdlCommand(ddl_data, session_ptr) {
459  auto& ddl_payload = extractPayload(ddl_data_);
460  CHECK(ddl_payload.HasMember("serverName"));
461  CHECK(ddl_payload["serverName"].IsString());
462  CHECK(ddl_payload.HasMember("dataWrapper"));
463  CHECK(ddl_payload["dataWrapper"].IsString());
464  CHECK(ddl_payload.HasMember("options"));
465  CHECK(ddl_payload["options"].IsObject());
466  CHECK(ddl_payload.HasMember("ifNotExists"));
467  CHECK(ddl_payload["ifNotExists"].IsBool());
468 }
469 
472 
473  auto& ddl_payload = extractPayload(ddl_data_);
474  std::string server_name = ddl_payload["serverName"].GetString();
475  if (isDefaultServer(server_name)) {
476  throw std::runtime_error{"Server names cannot start with \"omnisci\"."};
477  }
478  bool if_not_exists = ddl_payload["ifNotExists"].GetBool();
479  if (session_ptr_->getCatalog().getForeignServer(server_name)) {
480  if (if_not_exists) {
481  return result;
482  } else {
483  throw std::runtime_error{"A foreign server with name \"" + server_name +
484  "\" already exists."};
485  }
486  }
487  // check access privileges
488  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::ServerDBObjectType,
490  throw std::runtime_error("Server " + std::string(server_name) +
491  " will not be created. User has no create privileges.");
492  }
493 
494  auto& current_user = session_ptr_->get_currentUser();
495  auto foreign_server = std::make_unique<foreign_storage::ForeignServer>();
496  foreign_server->data_wrapper_type = to_upper(ddl_payload["dataWrapper"].GetString());
497  foreign_server->name = server_name;
498  foreign_server->user_id = current_user.userId;
499  foreign_server->populateOptionsMap(ddl_payload["options"]);
500  foreign_server->validate();
501 
502  auto& catalog = session_ptr_->getCatalog();
503  catalog.createForeignServer(std::move(foreign_server),
504  ddl_payload["ifNotExists"].GetBool());
506  current_user, server_name, ServerDBObjectType, catalog);
507 
508  return result;
509 }
510 
512  const DdlCommandData& ddl_data,
513  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
514  : DdlCommand(ddl_data, session_ptr) {
515  auto& ddl_payload = extractPayload(ddl_data_);
516  CHECK(ddl_payload.HasMember("serverName"));
517  CHECK(ddl_payload["serverName"].IsString());
518  CHECK(ddl_payload.HasMember("alterType"));
519  CHECK(ddl_payload["alterType"].IsString());
520  if (ddl_payload["alterType"] == "SET_OPTIONS") {
521  CHECK(ddl_payload.HasMember("options"));
522  CHECK(ddl_payload["options"].IsObject());
523  } else if (ddl_payload["alterType"] == "SET_DATA_WRAPPER") {
524  CHECK(ddl_payload.HasMember("dataWrapper"));
525  CHECK(ddl_payload["dataWrapper"].IsString());
526  } else if (ddl_payload["alterType"] == "RENAME_SERVER") {
527  CHECK(ddl_payload.HasMember("newServerName"));
528  CHECK(ddl_payload["newServerName"].IsString());
529  } else if (ddl_payload["alterType"] == "CHANGE_OWNER") {
530  CHECK(ddl_payload.HasMember("newOwner"));
531  CHECK(ddl_payload["newOwner"].IsString());
532  } else {
533  UNREACHABLE(); // not-implemented alterType
534  }
535 }
536 
538  auto& ddl_payload = extractPayload(ddl_data_);
539  std::string server_name = ddl_payload["serverName"].GetString();
540  if (isDefaultServer(server_name)) {
541  throw std::runtime_error{"OmniSci default servers cannot be altered."};
542  }
543  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
544  throw std::runtime_error{"Foreign server with name \"" + server_name +
545  "\" does not exist and can not be altered."};
546  }
547  if (!hasAlterServerPrivileges()) {
548  throw std::runtime_error("Server " + server_name +
549  " can not be altered. User has no ALTER SERVER privileges.");
550  }
551  std::string alter_type = ddl_payload["alterType"].GetString();
552  if (alter_type == "CHANGE_OWNER") {
554  } else if (alter_type == "SET_DATA_WRAPPER") {
556  } else if (alter_type == "SET_OPTIONS") {
558  } else if (alter_type == "RENAME_SERVER") {
560  }
561 
562  return ExecutionResult();
563 }
564 
566  auto& ddl_payload = extractPayload(ddl_data_);
567  std::string server_name = ddl_payload["serverName"].GetString();
568  std::string new_owner = ddl_payload["newOwner"].GetString();
569  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
570  if (!session_ptr_->get_currentUser().isSuper) {
571  throw std::runtime_error(
572  "Only a super user can change a foreign server's owner. "
573  "Current user is not a super-user. "
574  "Foreign server with name \"" +
575  server_name + "\" will not have owner changed.");
576  }
577  Catalog_Namespace::UserMetadata user, original_owner;
578  if (!sys_cat.getMetadataForUser(new_owner, user)) {
579  throw std::runtime_error("User with username \"" + new_owner + "\" does not exist. " +
580  "Foreign server with name \"" + server_name +
581  "\" can not have owner changed.");
582  }
583  auto& cat = session_ptr_->getCatalog();
584  // get original owner metadata
585  bool original_owner_exists = sys_cat.getMetadataForUserById(
586  cat.getForeignServer(server_name)->user_id, original_owner);
587  // update catalog
588  cat.changeForeignServerOwner(server_name, user.userId);
589  try {
590  // update permissions
591  DBObject db_object(server_name, DBObjectType::ServerDBObjectType);
592  sys_cat.changeDBObjectOwnership(
593  user, original_owner, db_object, cat, original_owner_exists);
594  } catch (const std::runtime_error& e) {
595  // update permissions failed, revert catalog update
596  cat.changeForeignServerOwner(server_name, original_owner.userId);
597  throw;
598  }
599 }
600 
602  auto& ddl_payload = extractPayload(ddl_data_);
603  std::string server_name = ddl_payload["serverName"].GetString();
604  std::string new_server_name = ddl_payload["newServerName"].GetString();
605  if (isDefaultServer(new_server_name)) {
606  throw std::runtime_error{"OmniSci prefix can not be used for new name of server."};
607  }
608  auto& cat = session_ptr_->getCatalog();
609  // check for a conflicting server
610  if (cat.getForeignServer(new_server_name)) {
611  throw std::runtime_error("Foreign server with name \"" + server_name +
612  "\" can not be renamed to \"" + new_server_name + "\"." +
613  "Foreign server with name \"" + new_server_name +
614  "\" exists.");
615  }
616  // update catalog
617  cat.renameForeignServer(server_name, new_server_name);
618  try {
619  // migrate object privileges
620  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
621  sys_cat.renameDBObject(server_name,
622  new_server_name,
624  cat.getForeignServer(new_server_name)->id,
625  cat);
626  } catch (const std::runtime_error& e) {
627  // permission migration failed, revert catalog update
628  cat.renameForeignServer(new_server_name, server_name);
629  throw;
630  }
631 }
632 
634  auto& ddl_payload = extractPayload(ddl_data_);
635  std::string server_name = ddl_payload["serverName"].GetString();
636  auto& cat = session_ptr_->getCatalog();
637  // update catalog
638  const auto foreign_server = cat.getForeignServer(server_name);
640  opt.populateOptionsMap(foreign_server->getOptionsAsJsonString());
641  opt.populateOptionsMap(ddl_payload["options"]);
642  cat.setForeignServerOptions(server_name, opt.getOptionsAsJsonString());
643 }
644 
646  auto& ddl_payload = extractPayload(ddl_data_);
647  std::string server_name = ddl_payload["serverName"].GetString();
648  std::string data_wrapper = ddl_payload["dataWrapper"].GetString();
649  auto& cat = session_ptr_->getCatalog();
650  // update catalog
651  cat.setForeignServerDataWrapper(server_name, data_wrapper);
652 }
653 
655  // TODO: implement `GRANT/REVOKE ALTER_SERVER` DDL commands
656  auto& ddl_payload = extractPayload(ddl_data_);
657  std::string server_name = ddl_payload["serverName"].GetString();
658  return session_ptr_->checkDBAccessPrivileges(
660 }
661 
663  const DdlCommandData& ddl_data,
664  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
665  : DdlCommand(ddl_data, session_ptr) {
666  auto& ddl_payload = extractPayload(ddl_data_);
667  CHECK(ddl_payload.HasMember("serverName"));
668  CHECK(ddl_payload["serverName"].IsString());
669  CHECK(ddl_payload.HasMember("ifExists"));
670  CHECK(ddl_payload["ifExists"].IsBool());
671 }
672 
674  auto& ddl_payload = extractPayload(ddl_data_);
675  std::string server_name = ddl_payload["serverName"].GetString();
676  if (isDefaultServer(server_name)) {
677  throw std::runtime_error{"OmniSci default servers cannot be dropped."};
678  }
679  bool if_exists = ddl_payload["ifExists"].GetBool();
680  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
681  if (if_exists) {
682  return ExecutionResult();
683  } else {
684  throw std::runtime_error{"Foreign server with name \"" + server_name +
685  "\" can not be dropped. Server does not exist."};
686  }
687  }
688  // check access privileges
689  if (!session_ptr_->checkDBAccessPrivileges(
691  throw std::runtime_error("Server " + server_name +
692  " will not be dropped. User has no DROP SERVER privileges.");
693  }
695  DBObject(server_name, ServerDBObjectType), session_ptr_->get_catalog_ptr().get());
696  session_ptr_->getCatalog().dropForeignServer(ddl_payload["serverName"].GetString());
697 
698  return ExecutionResult();
699 }
700 
701 SQLTypes JsonColumnSqlType::getSqlType(const rapidjson::Value& data_type) {
702  CHECK(data_type.IsObject());
703  CHECK(data_type.HasMember("type"));
704  CHECK(data_type["type"].IsString());
705 
706  std::string type = data_type["type"].GetString();
707  if (boost::iequals(type, "ARRAY")) {
708  CHECK(data_type.HasMember("array"));
709  CHECK(data_type["array"].IsObject());
710 
711  const auto& array = data_type["array"].GetObject();
712  CHECK(array.HasMember("elementType"));
713  CHECK(array["elementType"].IsString());
714  type = array["elementType"].GetString();
715  }
716  return getSqlType(type);
717 }
718 
719 SQLTypes JsonColumnSqlType::getSqlType(const std::string& type) {
720  if (boost::iequals(type, "BIGINT")) {
721  return kBIGINT;
722  }
723  if (boost::iequals(type, "BOOLEAN")) {
724  return kBOOLEAN;
725  }
726  if (boost::iequals(type, "DATE")) {
727  return kDATE;
728  }
729  if (boost::iequals(type, "DECIMAL")) {
730  return kDECIMAL;
731  }
732  if (boost::iequals(type, "DOUBLE")) {
733  return kDOUBLE;
734  }
735  if (boost::iequals(type, "FLOAT")) {
736  return kFLOAT;
737  }
738  if (boost::iequals(type, "INTEGER")) {
739  return kINT;
740  }
741  if (boost::iequals(type, "LINESTRING")) {
742  return kLINESTRING;
743  }
744  if (boost::iequals(type, "MULTIPOLYGON")) {
745  return kMULTIPOLYGON;
746  }
747  if (boost::iequals(type, "POINT")) {
748  return kPOINT;
749  }
750  if (boost::iequals(type, "POLYGON")) {
751  return kPOLYGON;
752  }
753  if (boost::iequals(type, "SMALLINT")) {
754  return kSMALLINT;
755  }
756  if (boost::iequals(type, "TEXT")) {
757  return kTEXT;
758  }
759  if (boost::iequals(type, "TIME")) {
760  return kTIME;
761  }
762  if (boost::iequals(type, "TIMESTAMP")) {
763  return kTIMESTAMP;
764  }
765  if (boost::iequals(type, "TINYINT")) {
766  return kTINYINT;
767  }
768 
769  throw std::runtime_error{"Unsupported type \"" + type + "\" specified."};
770 }
771 
772 int JsonColumnSqlType::getParam1(const rapidjson::Value& data_type) {
773  int param1 = -1;
774  CHECK(data_type.IsObject());
775  if (data_type.HasMember("precision") && !data_type["precision"].IsNull()) {
776  CHECK(data_type["precision"].IsInt());
777  param1 = data_type["precision"].GetInt();
778  } else if (auto type = getSqlType(data_type); IS_GEO(type)) {
779  param1 = static_cast<int>(kGEOMETRY);
780  }
781  return param1;
782 }
783 
784 int JsonColumnSqlType::getParam2(const rapidjson::Value& data_type) {
785  int param2 = 0;
786  CHECK(data_type.IsObject());
787  if (data_type.HasMember("scale") && !data_type["scale"].IsNull()) {
788  CHECK(data_type["scale"].IsInt());
789  param2 = data_type["scale"].GetInt();
790  } else if (auto type = getSqlType(data_type); IS_GEO(type) &&
791  data_type.HasMember("coordinateSystem") &&
792  !data_type["coordinateSystem"].IsNull()) {
793  CHECK(data_type["coordinateSystem"].IsInt());
794  param2 = data_type["coordinateSystem"].GetInt();
795  }
796  return param2;
797 }
798 
799 bool JsonColumnSqlType::isArray(const rapidjson::Value& data_type) {
800  CHECK(data_type.IsObject());
801  CHECK(data_type.HasMember("type"));
802  CHECK(data_type["type"].IsString());
803  return boost::iequals(data_type["type"].GetString(), "ARRAY");
804 }
805 
806 int JsonColumnSqlType::getArraySize(const rapidjson::Value& data_type) {
807  int size = -1;
808  if (isArray(data_type)) {
809  CHECK(data_type.HasMember("array"));
810  CHECK(data_type["array"].IsObject());
811 
812  const auto& array = data_type["array"].GetObject();
813  if (array.HasMember("size") && !array["size"].IsNull()) {
814  CHECK(array["size"].IsInt());
815  size = array["size"].GetInt();
816  }
817  }
818  return size;
819 }
820 
821 std::string* JsonColumnEncoding::getEncodingName(const rapidjson::Value& data_type) {
822  CHECK(data_type.IsObject());
823  CHECK(data_type.HasMember("encoding"));
824  CHECK(data_type["encoding"].IsObject());
825 
826  const auto& encoding = data_type["encoding"].GetObject();
827  CHECK(encoding.HasMember("type"));
828  CHECK(encoding["type"].IsString());
829  return new std::string(encoding["type"].GetString());
830 }
831 
832 int JsonColumnEncoding::getEncodingParam(const rapidjson::Value& data_type) {
833  CHECK(data_type.IsObject());
834  CHECK(data_type.HasMember("encoding"));
835  CHECK(data_type["encoding"].IsObject());
836 
837  int encoding_size = 0;
838  const auto& encoding = data_type["encoding"].GetObject();
839  if (encoding.HasMember("size") && !encoding["size"].IsNull()) {
840  CHECK(encoding["size"].IsInt());
841  encoding_size = encoding["size"].GetInt();
842  }
843  return encoding_size;
844 }
845 
847  const DdlCommandData& ddl_data,
848  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
849  : DdlCommand(ddl_data, session_ptr) {
850  auto& ddl_payload = extractPayload(ddl_data);
851  CHECK(ddl_payload.HasMember("serverName"));
852  CHECK(ddl_payload["serverName"].IsString());
853  CHECK(ddl_payload.HasMember("tableName"));
854  CHECK(ddl_payload["tableName"].IsString());
855  CHECK(ddl_payload.HasMember("ifNotExists"));
856  CHECK(ddl_payload["ifNotExists"].IsBool());
857  CHECK(ddl_payload.HasMember("columns"));
858  CHECK(ddl_payload["columns"].IsArray());
859 }
860 
862  auto& catalog = session_ptr_->getCatalog();
863  auto& ddl_payload = extractPayload(ddl_data_);
864 
865  const std::string& table_name = ddl_payload["tableName"].GetString();
866  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::TableDBObjectType,
868  throw std::runtime_error(
869  "Foreign table \"" + table_name +
870  "\" will not be created. User has no CREATE TABLE privileges.");
871  }
872 
873  bool if_not_exists = ddl_payload["ifNotExists"].GetBool();
874  if (!catalog.validateNonExistentTableOrView(table_name, if_not_exists)) {
875  return ExecutionResult();
876  }
877 
878  foreign_storage::ForeignTable foreign_table{};
879  std::list<ColumnDescriptor> columns{};
880  setColumnDetails(columns);
881  setTableDetails(table_name, foreign_table, columns.size());
882  catalog.createTable(foreign_table, columns, {}, true);
883 
884  // TODO (max): It's transactionally unsafe, should be fixed: we may create object w/o
885  // privileges
887  session_ptr_->get_currentUser(),
888  foreign_table.tableName,
890  catalog);
891 
892  return ExecutionResult();
893 }
894 
895 void CreateForeignTableCommand::setTableDetails(const std::string& table_name,
896  TableDescriptor& td,
897  const size_t column_count) {
898  ddl_utils::set_default_table_attributes(table_name, td, column_count);
899  td.userId = session_ptr_->get_currentUser().userId;
901  td.hasDeletedCol = false;
902  td.keyMetainfo = "[]";
903  td.fragments = "";
904  td.partitions = "";
905 
906  auto& ddl_payload = extractPayload(ddl_data_);
907  auto& foreign_table = dynamic_cast<foreign_storage::ForeignTable&>(td);
908  const std::string server_name = ddl_payload["serverName"].GetString();
909  foreign_table.foreign_server = session_ptr_->getCatalog().getForeignServer(server_name);
910  if (!foreign_table.foreign_server) {
911  throw std::runtime_error{
912  "Foreign Table with name \"" + table_name +
913  "\" can not be created. Associated foreign server with name \"" + server_name +
914  "\" does not exist."};
915  }
916 
917  if (ddl_payload.HasMember("options") && !ddl_payload["options"].IsNull()) {
918  CHECK(ddl_payload["options"].IsObject());
919  foreign_table.initializeOptions(ddl_payload["options"]);
920  } else {
921  // Initialize options even if none were provided to verify a legal state.
922  // This is necessary because some options (like "file_path") are optional only if a
923  // paired option ("base_path") exists in the server.
924  foreign_table.initializeOptions();
925  }
926 
927  if (const auto it = foreign_table.options.find("FRAGMENT_SIZE");
928  it != foreign_table.options.end()) {
929  foreign_table.maxFragRows = std::stoi(it->second);
930  }
931 }
932 
933 void CreateForeignTableCommand::setColumnDetails(std::list<ColumnDescriptor>& columns) {
934  auto& ddl_payload = extractPayload(ddl_data_);
935  std::unordered_set<std::string> column_names{};
936  for (auto& column_def : ddl_payload["columns"].GetArray()) {
937  CHECK(column_def.IsObject());
938  CHECK(column_def.HasMember("name"));
939  CHECK(column_def["name"].IsString());
940  const std::string& column_name = column_def["name"].GetString();
941 
942  CHECK(column_def.HasMember("dataType"));
943  CHECK(column_def["dataType"].IsObject());
944 
945  JsonColumnSqlType sql_type{column_def["dataType"]};
946  const auto& data_type = column_def["dataType"].GetObject();
947  CHECK(data_type.HasMember("notNull"));
948  CHECK(data_type["notNull"].IsBool());
949 
950  std::unique_ptr<JsonColumnEncoding> encoding;
951  if (data_type.HasMember("encoding") && !data_type["encoding"].IsNull()) {
952  CHECK(data_type["encoding"].IsObject());
953  encoding = std::make_unique<JsonColumnEncoding>(column_def["dataType"]);
954  }
955 
956  ColumnDescriptor cd;
957  ddl_utils::validate_non_duplicate_column(column_name, column_names);
960  column_name, cd, &sql_type, data_type["notNull"].GetBool(), encoding.get());
961  columns.emplace_back(cd);
962  }
963 }
964 
966  const DdlCommandData& ddl_data,
967  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
968  : DdlCommand(ddl_data, session_ptr) {
969  auto& ddl_payload = extractPayload(ddl_data_);
970  CHECK(ddl_payload.HasMember("tableName"));
971  CHECK(ddl_payload["tableName"].IsString());
972  CHECK(ddl_payload.HasMember("ifExists"));
973  CHECK(ddl_payload["ifExists"].IsBool());
974 }
975 
977  auto& catalog = session_ptr_->getCatalog();
978  auto& ddl_payload = extractPayload(ddl_data_);
979 
980  const std::string& table_name = ddl_payload["tableName"].GetString();
981  const TableDescriptor* td{nullptr};
982  std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>> td_with_lock;
983 
984  try {
985  td_with_lock =
986  std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>>(
988  catalog, table_name, false));
989  CHECK(td_with_lock);
990  td = (*td_with_lock)();
991  } catch (const std::runtime_error& e) {
992  // TODO(Misiu): This should not just swallow any exception, it should only catch
993  // exceptions that stem from the table not existing.
994  if (ddl_payload["ifExists"].GetBool()) {
995  return ExecutionResult();
996  } else {
997  throw e;
998  }
999  }
1000 
1001  CHECK(td);
1002 
1003  if (!session_ptr_->checkDBAccessPrivileges(
1005  throw std::runtime_error(
1006  "Foreign table \"" + table_name +
1007  "\" will not be dropped. User has no DROP TABLE privileges.");
1008  }
1009 
1011  auto table_data_write_lock =
1013  catalog.dropTable(td);
1014 
1015  return ExecutionResult();
1016 }
1017 
1019  const DdlCommandData& ddl_data,
1020  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1021  : DdlCommand(ddl_data, session_ptr) {}
1022 
1024  // Get all table names in the same way as OmniSql \t command
1025 
1026  // label_infos -> column labels
1027  std::vector<std::string> labels{"table_name"};
1028  std::vector<TargetMetaInfo> label_infos;
1029  for (const auto& label : labels) {
1030  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1031  }
1032 
1033  // Get all table names
1034  auto cat_ptr = session_ptr_->get_catalog_ptr();
1035  auto cur_user = session_ptr_->get_currentUser();
1036  auto table_names = cat_ptr->getTableNamesForUser(cur_user, GET_PHYSICAL_TABLES);
1037 
1038  // logical_values -> table data
1039  std::vector<RelLogicalValues::RowValues> logical_values;
1040  for (auto table_name : table_names) {
1041  logical_values.emplace_back(RelLogicalValues::RowValues{});
1042  logical_values.back().emplace_back(genLiteralStr(table_name));
1043  }
1044 
1045  // Create ResultSet
1046  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1047  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1048 
1049  return ExecutionResult(rSet, label_infos);
1050 }
1051 
1053  const DdlCommandData& ddl_data,
1054  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1055  : DdlCommand(ddl_data, session_ptr) {
1056  auto& ddl_payload = extractPayload(ddl_data_);
1057  if (ddl_payload.HasMember("tableNames")) {
1058  CHECK(ddl_payload["tableNames"].IsArray());
1059  for (const auto& table_name : ddl_payload["tableNames"].GetArray()) {
1060  CHECK(table_name.IsString());
1061  }
1062  }
1063 }
1064 
1066  const auto catalog = session_ptr_->get_catalog_ptr();
1067  std::vector<std::string> filtered_table_names = getFilteredTableNames();
1068 
1069  std::vector<TargetMetaInfo> label_infos;
1070  set_headers_with_type(label_infos,
1071  {// { label, type, notNull }
1072  {"table_id", kBIGINT, true},
1073  {"table_name", kTEXT, true},
1074  {"column_count", kBIGINT, true},
1075  {"is_sharded_table", kBOOLEAN, true},
1076  {"shard_count", kBIGINT, true},
1077  {"max_rows", kBIGINT, true},
1078  {"fragment_size", kBIGINT, true},
1079  {"max_rollback_epochs", kBIGINT, true},
1080  {"min_epoch", kBIGINT, true},
1081  {"max_epoch", kBIGINT, true},
1082  {"min_epoch_floor", kBIGINT, true},
1083  {"max_epoch_floor", kBIGINT, true},
1084  {"metadata_file_count", kBIGINT, true},
1085  {"total_metadata_file_size", kBIGINT, true},
1086  {"total_metadata_page_count", kBIGINT, true},
1087  {"total_free_metadata_page_count", kBIGINT, false},
1088  {"data_file_count", kBIGINT, true},
1089  {"total_data_file_size", kBIGINT, true},
1090  {"total_data_page_count", kBIGINT, true},
1091  {"total_free_data_page_count", kBIGINT, false}});
1092 
1093  std::vector<RelLogicalValues::RowValues> logical_values;
1094  for (const auto& table_name : filtered_table_names) {
1095  auto [td, td_with_lock] =
1096  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1097  auto agg_storage_stats = get_agg_storage_stats(td, catalog.get());
1098  add_table_details(logical_values, td, agg_storage_stats);
1099  }
1100 
1101  // Create ResultSet
1102  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1103  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1104 
1105  return ExecutionResult(rSet, label_infos);
1106 }
1107 
1109  const auto catalog = session_ptr_->get_catalog_ptr();
1110  auto& ddl_payload = extractPayload(ddl_data_);
1111  auto all_table_names =
1112  catalog->getTableNamesForUser(session_ptr_->get_currentUser(), GET_PHYSICAL_TABLES);
1113  std::vector<std::string> filtered_table_names;
1114  if (ddl_payload.HasMember("tableNames")) {
1115  std::set<std::string> all_table_names_set(all_table_names.begin(),
1116  all_table_names.end());
1117  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1118  std::string table_name = table_name_json.GetString();
1119  if (all_table_names_set.find(table_name) == all_table_names_set.end()) {
1120  throw std::runtime_error{"Unable to show table details for table: " + table_name +
1121  ". Table does not exist."};
1122  }
1123  auto [td, td_with_lock] =
1124  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1125  if (td->isForeignTable()) {
1126  throw std::runtime_error{
1127  "SHOW TABLE DETAILS is not supported for foreign tables. Table name: " +
1128  table_name + "."};
1129  }
1130  if (td->isTemporaryTable()) {
1131  throw std::runtime_error{
1132  "SHOW TABLE DETAILS is not supported for temporary tables. Table name: " +
1133  table_name + "."};
1134  }
1135  filtered_table_names.emplace_back(table_name);
1136  }
1137  } else {
1138  for (const auto& table_name : all_table_names) {
1139  auto [td, td_with_lock] =
1140  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1141  if (td->isForeignTable() || td->isTemporaryTable()) {
1142  continue;
1143  }
1144  filtered_table_names.emplace_back(table_name);
1145  }
1146  }
1147  return filtered_table_names;
1148 }
1149 
1151  const DdlCommandData& ddl_data,
1152  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1153  : DdlCommand(ddl_data, session_ptr) {}
1154 
1156  // label_infos -> column labels
1157  std::vector<std::string> labels{"Database", "Owner"};
1158  std::vector<TargetMetaInfo> label_infos;
1159  for (const auto& label : labels) {
1160  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1161  }
1162 
1163  // Get all table names
1164  auto cur_user = session_ptr_->get_currentUser();
1165  const Catalog_Namespace::DBSummaryList db_summaries =
1167 
1168  // logical_values -> table data
1169  std::vector<RelLogicalValues::RowValues> logical_values;
1170  for (const auto& db_summary : db_summaries) {
1171  logical_values.emplace_back(RelLogicalValues::RowValues{});
1172  logical_values.back().emplace_back(genLiteralStr(db_summary.dbName));
1173  logical_values.back().emplace_back(genLiteralStr(db_summary.dbOwnerName));
1174  }
1175 
1176  // Create ResultSet
1177  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1178  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1179 
1180  return ExecutionResult(rSet, label_infos);
1181 }
1182 
1184  const DdlCommandData& ddl_data,
1185  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1186  : DdlCommand(ddl_data, session_ptr) {
1187  if (!g_enable_fsi) {
1188  throw std::runtime_error("Unsupported command: SHOW FOREIGN SERVERS");
1189  }
1190  // Verify that members are valid
1191  auto& ddl_payload = extractPayload(ddl_data_);
1192  CHECK(ddl_payload.HasMember("command"));
1193  if (ddl_payload.HasMember("filters")) {
1194  CHECK(ddl_payload["filters"].IsArray());
1195  int num_filters = 0;
1196  for (auto const& filter_def : ddl_payload["filters"].GetArray()) {
1197  CHECK(filter_def.IsObject());
1198  CHECK(filter_def.HasMember("attribute"));
1199  CHECK(filter_def["attribute"].IsString());
1200  CHECK(filter_def.HasMember("value"));
1201  CHECK(filter_def["value"].IsString());
1202  CHECK(filter_def.HasMember("operation"));
1203  CHECK(filter_def["operation"].IsString());
1204  if (num_filters > 0) {
1205  CHECK(filter_def.HasMember("chain"));
1206  CHECK(filter_def["chain"].IsString());
1207  } else {
1208  CHECK(!filter_def.HasMember("chain"));
1209  }
1210  num_filters++;
1211  }
1212  }
1213 }
1214 
1216  std::vector<TargetMetaInfo> label_infos;
1217  auto& ddl_payload = extractPayload(ddl_data_);
1218 
1219  // label_infos -> column labels
1220  std::vector<std::string> labels{"server_name", "data_wrapper", "created_at", "options"};
1221  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
1222  label_infos.emplace_back(labels[1], SQLTypeInfo(kTEXT, true));
1223  // created_at is a TIMESTAMP
1224  label_infos.emplace_back(labels[2], SQLTypeInfo(kTIMESTAMP, true));
1225  label_infos.emplace_back(labels[3], SQLTypeInfo(kTEXT, true));
1226 
1227  const auto& user = session_ptr_->get_currentUser();
1228 
1229  std::vector<const foreign_storage::ForeignServer*> results;
1230 
1231  session_ptr_->getCatalog().getForeignServersForUser(
1232  extractFilters(ddl_payload), user, results);
1233 
1234  // logical_values -> table data
1235  std::vector<RelLogicalValues::RowValues> logical_values;
1236  for (auto const& server_ptr : results) {
1237  logical_values.emplace_back(RelLogicalValues::RowValues{});
1238  logical_values.back().emplace_back(genLiteralStr(server_ptr->name));
1239  logical_values.back().emplace_back(genLiteralStr(server_ptr->data_wrapper_type));
1240  logical_values.back().emplace_back(genLiteralTimestamp(server_ptr->creation_time));
1241  logical_values.back().emplace_back(
1242  genLiteralStr(server_ptr->getOptionsAsJsonString()));
1243  }
1244 
1245  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1246  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1247 
1248  return ExecutionResult(rSet, label_infos);
1249 }
1250 
1252  const DdlCommandData& ddl_data,
1253  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1254  : DdlCommand(ddl_data, session_ptr) {
1255  auto& ddl_payload = extractPayload(ddl_data_);
1256  CHECK(ddl_payload.HasMember("tableNames"));
1257  CHECK(ddl_payload["tableNames"].IsArray());
1258  for (auto const& tablename_def : ddl_payload["tableNames"].GetArray()) {
1259  CHECK(tablename_def.IsString());
1260  }
1261 }
1262 
1264  bool evict_cached_entries{false};
1266  auto& ddl_payload = extractPayload(ddl_data_);
1267  if (ddl_payload.HasMember("options") && !ddl_payload["options"].IsNull()) {
1268  opt.populateOptionsMap(ddl_payload["options"]);
1269  for (const auto& entry : opt.options) {
1270  if (entry.first != "EVICT") {
1271  throw std::runtime_error{
1272  "Invalid option \"" + entry.first +
1273  "\" provided for refresh command. Only \"EVICT\" option is supported."};
1274  }
1275  }
1276  CHECK(opt.options.find("EVICT") != opt.options.end());
1277 
1278  if (boost::iequals(opt.options["EVICT"], "true") ||
1279  boost::iequals(opt.options["EVICT"], "false")) {
1280  if (boost::iequals(opt.options["EVICT"], "true")) {
1281  evict_cached_entries = true;
1282  }
1283  } else {
1284  throw std::runtime_error{
1285  "Invalid value \"" + opt.options["EVICT"] +
1286  "\" provided for EVICT option. Value must be either \"true\" or \"false\"."};
1287  }
1288  }
1289 
1290  auto& cat = session_ptr_->getCatalog();
1291  const auto& current_user = session_ptr_->get_currentUser();
1292  /* verify object ownership if not suser */
1293  if (!current_user.isSuper) {
1294  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1295  std::string table_name = table_name_json.GetString();
1296  if (!Catalog_Namespace::SysCatalog::instance().verifyDBObjectOwnership(
1297  current_user, DBObject(table_name, TableDBObjectType), cat)) {
1298  throw std::runtime_error(
1299  std::string("REFRESH FOREIGN TABLES failed on table \"") + table_name +
1300  "\". It can only be executed by super user or "
1301  "owner of the "
1302  "object.");
1303  }
1304  }
1305  }
1306 
1307  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1308  std::string table_name = table_name_json.GetString();
1309  foreign_storage::refresh_foreign_table(cat, table_name, evict_cached_entries);
1310  }
1311 
1312  return ExecutionResult();
1313 }
1314 
1316  const DdlCommandData& ddl_data,
1317  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
1318  : DdlCommand(ddl_data, session_ptr) {
1319  auto& ddl_payload = extractPayload(ddl_data_);
1320  CHECK(ddl_payload.HasMember("tableName"));
1321  CHECK(ddl_payload["tableName"].IsString());
1322  CHECK(ddl_payload.HasMember("alterType"));
1323  CHECK(ddl_payload["alterType"].IsString());
1324  if (ddl_payload["alterType"] == "RENAME_TABLE") {
1325  CHECK(ddl_payload.HasMember("newTableName"));
1326  CHECK(ddl_payload["newTableName"].IsString());
1327  } else if (ddl_payload["alterType"] == "RENAME_COLUMN") {
1328  CHECK(ddl_payload.HasMember("oldColumnName"));
1329  CHECK(ddl_payload["oldColumnName"].IsString());
1330  CHECK(ddl_payload.HasMember("newColumnName"));
1331  CHECK(ddl_payload["newColumnName"].IsString());
1332  } else if (ddl_payload["alterType"] == "ALTER_OPTIONS") {
1333  CHECK(ddl_payload.HasMember("options"));
1334  CHECK(ddl_payload["options"].IsObject());
1335  } else {
1336  UNREACHABLE() << "Not a valid alter foreign table command: "
1337  << ddl_payload["alterType"].GetString();
1338  }
1339 }
1340 
1342  auto& ddl_payload = extractPayload(ddl_data_);
1343  auto& catalog = session_ptr_->getCatalog();
1344  const std::string& table_name = ddl_payload["tableName"].GetString();
1345  auto [td, td_with_lock] =
1346  get_table_descriptor_with_lock<lockmgr::WriteLock>(catalog, table_name, false);
1347 
1349 
1350  if (!session_ptr_->checkDBAccessPrivileges(
1352  throw std::runtime_error(
1353  "Current user does not have the privilege to alter foreign table: " + table_name);
1354  }
1355 
1356  auto table_data_write_lock =
1358  auto foreign_table = dynamic_cast<const foreign_storage::ForeignTable*>(td);
1359  CHECK(foreign_table);
1360 
1361  std::string alter_type = ddl_payload["alterType"].GetString();
1362  if (alter_type == "RENAME_TABLE") {
1363  renameTable(foreign_table);
1364  } else if (alter_type == "RENAME_COLUMN") {
1365  renameColumn(foreign_table);
1366  } else if (alter_type == "ALTER_OPTIONS") {
1367  alterOptions(foreign_table);
1368  }
1369 
1370  return ExecutionResult();
1371 }
1372 
1374  const foreign_storage::ForeignTable* foreign_table) {
1375  auto& ddl_payload = extractPayload(ddl_data_);
1376  auto& cat = session_ptr_->getCatalog();
1377  const std::string& table_name = ddl_payload["tableName"].GetString();
1378  const std::string& new_table_name = ddl_payload["newTableName"].GetString();
1379  if (cat.getForeignTable(new_table_name)) {
1380  throw std::runtime_error("Foreign table with name \"" + table_name +
1381  "\" can not be renamed to \"" + new_table_name + "\". " +
1382  "A different table with name \"" + new_table_name +
1383  "\" already exists.");
1384  }
1385  cat.renameTable(foreign_table, new_table_name);
1386 }
1387 
1389  const foreign_storage::ForeignTable* foreign_table) {
1390  auto& ddl_payload = extractPayload(ddl_data_);
1391  auto& cat = session_ptr_->getCatalog();
1392  const std::string& table_name = ddl_payload["tableName"].GetString();
1393  const std::string& old_column_name = ddl_payload["oldColumnName"].GetString();
1394  const std::string& new_column_name = ddl_payload["newColumnName"].GetString();
1395  auto column = cat.getMetadataForColumn(foreign_table->tableId, old_column_name);
1396  if (!column) {
1397  throw std::runtime_error("Column with name \"" + old_column_name +
1398  "\" can not be renamed to \"" + new_column_name + "\". " +
1399  "Column with name \"" + old_column_name +
1400  "\" does not exist.");
1401  }
1402  if (cat.getMetadataForColumn(foreign_table->tableId, new_column_name)) {
1403  throw std::runtime_error("Column with name \"" + old_column_name +
1404  "\" can not be renamed to \"" + new_column_name + "\". " +
1405  "A column with name \"" + new_column_name +
1406  "\" already exists.");
1407  }
1408  cat.renameColumn(foreign_table, column, new_column_name);
1409 }
1410 
1412  const foreign_storage::ForeignTable* foreign_table) {
1413  auto& ddl_payload = extractPayload(ddl_data_);
1414  const std::string& table_name = ddl_payload["tableName"].GetString();
1415  auto& cat = session_ptr_->getCatalog();
1416  auto new_options_map =
1417  foreign_storage::ForeignTable::create_options_map(ddl_payload["options"]);
1418  foreign_table->validateSupportedOptionKeys(new_options_map);
1420  cat.setForeignTableOptions(table_name, new_options_map, false);
1421 }
1422 
1424  const DdlCommandData& ddl_data,
1425  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1426  : DdlCommand(ddl_data, session_ptr) {
1427  auto& ddl_payload = extractPayload(ddl_data_);
1428  if (ddl_payload.HasMember("tableNames")) {
1429  CHECK(ddl_payload["tableNames"].IsArray());
1430  for (auto const& tablename_def : ddl_payload["tableNames"].GetArray()) {
1431  CHECK(tablename_def.IsString());
1432  }
1433  }
1434 }
1435 
1437  auto table_names = session_ptr_->get_catalog_ptr()->getTableNamesForUser(
1438  session_ptr_->get_currentUser(), GET_PHYSICAL_TABLES);
1439 
1440  auto& ddl_payload = extractPayload(ddl_data_);
1441  if (ddl_payload.HasMember("tableNames")) {
1442  std::vector<std::string> filtered_names;
1443  for (const auto& tablename_def : ddl_payload["tableNames"].GetArray()) {
1444  std::string filter_name = tablename_def.GetString();
1445  if (std::find(table_names.begin(), table_names.end(), filter_name) !=
1446  table_names.end()) {
1447  filtered_names.emplace_back(filter_name);
1448  } else {
1449  throw std::runtime_error("Can not show disk cache usage for table: " +
1450  filter_name + ". Table does not exist.");
1451  }
1452  }
1453  return filtered_names;
1454  } else {
1455  return table_names;
1456  }
1457 }
1458 
1460  auto cat_ptr = session_ptr_->get_catalog_ptr();
1461  auto table_names = getFilteredTableNames();
1462 
1463  const auto disk_cache = cat_ptr->getDataMgr().getPersistentStorageMgr()->getDiskCache();
1464  if (!disk_cache) {
1465  throw std::runtime_error{"Disk cache not enabled. Cannot show disk cache usage."};
1466  }
1467 
1468  // label_infos -> column labels
1469  std::vector<std::string> labels{"table name", "current cache size"};
1470  std::vector<TargetMetaInfo> label_infos;
1471  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
1472  label_infos.emplace_back(labels[1], SQLTypeInfo(kBIGINT, true));
1473 
1474  std::vector<RelLogicalValues::RowValues> logical_values;
1475 
1476  for (auto& table_name : table_names) {
1477  auto [td, td_with_lock] =
1478  get_table_descriptor_with_lock<lockmgr::ReadLock>(*cat_ptr, table_name, false);
1479 
1480  const auto mgr = dynamic_cast<File_Namespace::FileMgr*>(
1481  disk_cache->getGlobalFileMgr()->findFileMgr(cat_ptr->getDatabaseId(),
1482  td->tableId));
1483 
1484  // NOTE: This size does not include datawrapper metadata that is on disk.
1485  // If a mgr does not exist it means a cache is not enabled/created for the given
1486  // table.
1487  auto table_cache_size = mgr ? mgr->getTotalFileSize() : 0;
1488 
1489  // logical_values -> table data
1490  logical_values.emplace_back(RelLogicalValues::RowValues{});
1491  logical_values.back().emplace_back(genLiteralStr(table_name));
1492  logical_values.back().emplace_back(genLiteralBigInt(table_cache_size));
1493  }
1494 
1495  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1496  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1497 
1498  return ExecutionResult(rSet, label_infos);
1499 }
int32_t maxRollbackEpochs
ShowForeignServersCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
#define CHECK_EQ(x, y)
Definition: Logger.h:205
std::string partitions
ExecutionResult execute() override
AlterForeignServerCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
declare this class scoped local to avoid exposing rapidjson in the header file
static const AccessPrivileges DROP_SERVER
Definition: DBObject.h:190
std::string cat(Ts &&...args)
std::unique_ptr< DdlCommandData > ddl_data_
std::string getOptionsAsJsonString() const
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:101
Definition: sqltypes.h:48
SQLTypes
Definition: sqltypes.h:37
std::string tableName
static const AccessPrivileges ALTER_TABLE
Definition: DBObject.h:166
CreateForeignServerCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
Data_Namespace::DataMgr & getDataMgr() const
Definition: Catalog.h:222
#define NULL_BIGINT
#define LOG(tag)
Definition: Logger.h:188
static WriteLock getWriteLockForTable(const Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:155
ShowDatabasesCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
std::vector< const TableDescriptor * > getPhysicalTablesDescriptors(const TableDescriptor *logicalTableDesc) const
Definition: Catalog.cpp:3786
uint64_t getTotalFileSize() const
Definition: FileMgr.cpp:1186
std::string storageType
void revokeDBObjectPrivilegesFromAll(DBObject object, Catalog *catalog)
DropForeignTableCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
#define UNREACHABLE()
Definition: Logger.h:241
std::string fragments
CreateForeignTableCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
void validateSupportedOptionKeys(const OptionsMap &options_map) const
Verifies that the options_map contains the keys required by a foreign table; including those specifie...
void add_table_details(std::vector< RelLogicalValues::RowValues > &logical_values, const TableDescriptor *logical_table, const AggregratedStorageStats &agg_storage_stats)
void aggregate(const File_Namespace::StorageStats &storage_stats)
std::optional< uint64_t > total_free_data_page_count
Definition: FileMgr.h:103
void refresh_foreign_table(Catalog_Namespace::Catalog &catalog, const std::string &table_name, const bool evict_cached_entries)
ShowTablesCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
ShowDiskCacheUsageCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
void createDBObject(const UserMetadata &user, const std::string &objectName, DBObjectType type, const Catalog_Namespace::Catalog &catalog, int32_t objectId=-1)
std::string to_string(char const *&&v)
void set_headers_with_type(std::vector< TargetMetaInfo > &label_infos, const std::vector< std::tuple< std::string, SQLTypes, bool >> &headers)
std::tuple< const TableDescriptor *, std::unique_ptr< lockmgr::TableSchemaLockContainer< LockType > > > get_table_descriptor_with_lock(const Catalog_Namespace::Catalog &cat, const std::string &table_name, const bool populate_fragmenter)
void validate_non_duplicate_column(const std::string &column_name, std::unordered_set< std::string > &upper_column_names)
Definition: DdlUtils.cpp:521
static void validate_alter_options(const OptionsMap &options_map)
Verifies that the given options map only contains options that can be legally altered.
static const AccessPrivileges ALTER_SERVER
Definition: DBObject.h:191
std::unique_ptr< RexLiteral > genLiteralBigInt(int64_t val)
This file contains the class specification and related data structures for Catalog.
const std::string getTargetQuerySessionToKill()
const DdlCommandData & ddl_data_
const std::string commandStr()
static SysCatalog & instance()
Definition: SysCatalog.h:288
This file contains the class specification and related data structures for SysCatalog.
bool g_enable_s3_fsi
Classes representing a parse tree.
ShowTableDetailsCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
void setColumnDetails(std::list< ColumnDescriptor > &columns)
DropForeignServerCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static const AccessPrivileges DROP_TABLE
Definition: DBObject.h:160
ExecutionResult execute() override
std::optional< uint64_t > total_free_metadata_page_count
Definition: FileMgr.h:99
void populateOptionsMap(OptionsMap &&options_map, bool clear=false)
const rapidjson::Value & extractPayload(const DdlCommandData &ddl_data)
std::unique_ptr< RexLiteral > genLiteralTimestamp(time_t val)
ExecutionResult execute() override
ExecutionResult execute() override
DBSummaryList getDatabaseListForUser(const UserMetadata &user)
int getDatabaseId() const
Definition: Catalog.h:274
uint64_t total_metadata_page_count
Definition: FileMgr.h:98
static const AccessPrivileges CREATE_SERVER
Definition: DBObject.h:189
ExecutionResult execute() override
std::unique_ptr< RexLiteral > genLiteralBoolean(bool val)
void validate_non_reserved_keyword(const std::string &column_name)
Definition: DdlUtils.cpp:530
specifies the content in-memory of a row in the column metadata table
static const AccessPrivileges CREATE_TABLE
Definition: DBObject.h:159
ExecutionResult execute() override
std::string keyMetainfo
void set_default_table_attributes(const std::string &table_name, TableDescriptor &td, const int32_t column_count)
Definition: DdlUtils.cpp:507
File_Namespace::GlobalFileMgr * getGlobalFileMgr() const
Definition: DataMgr.cpp:528
std::string to_upper(const std::string &str)
static ResultSet * create(std::vector< TargetMetaInfo > &label_infos, std::vector< RelLogicalValues::RowValues > &logical_values)
ExecutionResult execute() override
void alterOptions(const foreign_storage::ForeignTable *foreign_table)
DistributedExecutionDetails getDistributedExecutionDetails()
void set_column_descriptor(const std::string &column_name, ColumnDescriptor &cd, SqlType *column_type, const bool not_null, const Encoding *encoding)
Definition: DdlUtils.cpp:493
ExecutionResult execute()
Definition: sqltypes.h:51
Definition: sqltypes.h:52
std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr_
std::vector< std::string > getFilteredTableNames()
DdlCommandExecutor(const std::string &ddl_statement, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
AggregratedStorageStats get_agg_storage_stats(const TableDescriptor *td, const Catalog_Namespace::Catalog *catalog)
uint64_t total_metadata_file_size
Definition: FileMgr.h:97
Basic constructors and methods of the row set interface.
static OptionsMap create_options_map(const rapidjson::Value &json_options)
Creates an options map from given options. Converts options that must be upper case appropriately...
void setTableDetails(const std::string &table_name, TableDescriptor &td, const size_t column_count)
std::vector< std::string > getFilteredTableNames()
ExecutionResult execute() override
static std::unique_ptr< RexLiteral > genLiteralStr(std::string val)
Definition: DBHandler.cpp:6399
ExecutionResult execute() override
static std::shared_ptr< MutexType > getMutex(const LockType lockType, const KeyType &key)
Definition: LegacyLockMgr.h:51
void validate_table_type(const TableDescriptor *td, const TableType expected_table_type, const std::string &command)
Definition: DdlUtils.cpp:538
const ForeignServer * foreign_server
Definition: ForeignTable.h:63
void renameTable(const foreign_storage::ForeignTable *foreign_table)
#define CHECK(condition)
Definition: Logger.h:197
bool isDefaultServer(const std::string &server_name)
std::list< DBSummary > DBSummaryList
Definition: SysCatalog.h:120
Definition: sqltypes.h:44
AggregratedStorageStats(const File_Namespace::StorageStats &storage_stats)
std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr_
std::vector< std::unique_ptr< const RexScalar >> RowValues
ExecutionLocation execution_location
const rapidjson::Value * extractFilters(const rapidjson::Value &payload)
AlterForeignTableCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
void renameColumn(const foreign_storage::ForeignTable *foreign_table)
static constexpr char const * FOREIGN_TABLE
bool g_enable_fsi
Definition: Catalog.cpp:91
ExecutionResult execute() override
ExecutionResult execute() override
ExecutionResult execute() override
#define IS_GEO(T)
Definition: sqltypes.h:242
#define VLOG(n)
Definition: Logger.h:291
RefreshForeignTablesCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)