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