OmniSciDB  cde582ebc3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DdlCommandExecutor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, 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 <algorithm>
20 
21 #include <boost/algorithm/string/predicate.hpp>
22 
23 #include "rapidjson/document.h"
24 
25 // Note: avoid adding #include(s) that require thrift
26 
27 #include "Catalog/Catalog.h"
28 #include "Catalog/SysCatalog.h"
30 #include "LockMgr/LockMgr.h"
31 #include "Parser/ParserNode.h"
32 #include "Shared/StringTransform.h"
33 #include "Shared/SysDefinitions.h"
34 
35 #include "QueryEngine/Execute.h" // Executor::getArenaBlockSize()
38 
39 extern bool g_enable_fsi;
40 
41 namespace {
42 template <class LockType>
43 std::tuple<const TableDescriptor*,
44  std::unique_ptr<lockmgr::TableSchemaLockContainer<LockType>>>
46  const std::string& table_name,
47  const bool populate_fragmenter) {
48  const TableDescriptor* td{nullptr};
49  std::unique_ptr<lockmgr::TableSchemaLockContainer<LockType>> td_with_lock =
50  std::make_unique<lockmgr::TableSchemaLockContainer<LockType>>(
52  cat, table_name, populate_fragmenter));
53  CHECK(td_with_lock);
54  td = (*td_with_lock)();
55  CHECK(td);
56  return std::make_tuple(td, std::move(td_with_lock));
57 }
58 
60  int32_t min_epoch;
61  int32_t max_epoch;
62  int32_t min_epoch_floor;
63  int32_t max_epoch_floor;
64 
66  : File_Namespace::StorageStats(storage_stats)
67  , min_epoch(storage_stats.epoch)
68  , max_epoch(storage_stats.epoch)
69  , min_epoch_floor(storage_stats.epoch_floor)
70  , max_epoch_floor(storage_stats.epoch_floor) {}
71 
72  void aggregate(const File_Namespace::StorageStats& storage_stats) {
73  metadata_file_count += storage_stats.metadata_file_count;
74  total_metadata_file_size += storage_stats.total_metadata_file_size;
75  total_metadata_page_count += storage_stats.total_metadata_page_count;
76  if (storage_stats.total_free_metadata_page_count) {
77  if (total_free_metadata_page_count) {
78  total_free_metadata_page_count.value() +=
79  storage_stats.total_free_metadata_page_count.value();
80  } else {
81  total_free_metadata_page_count = storage_stats.total_free_metadata_page_count;
82  }
83  }
84  data_file_count += storage_stats.data_file_count;
85  total_data_file_size += storage_stats.total_data_file_size;
86  total_data_page_count += storage_stats.total_data_page_count;
87  if (storage_stats.total_free_data_page_count) {
88  if (total_free_data_page_count) {
89  total_free_data_page_count.value() +=
90  storage_stats.total_free_data_page_count.value();
91  } else {
92  total_free_data_page_count = storage_stats.total_free_data_page_count;
93  }
94  }
95  min_epoch = std::min(min_epoch, storage_stats.epoch);
96  max_epoch = std::max(max_epoch, storage_stats.epoch);
97  min_epoch_floor = std::min(min_epoch_floor, storage_stats.epoch_floor);
98  max_epoch_floor = std::max(max_epoch_floor, storage_stats.epoch_floor);
99  }
100 };
101 
103  const Catalog_Namespace::Catalog* catalog) {
104  const auto global_file_mgr = catalog->getDataMgr().getGlobalFileMgr();
105  std::optional<AggregratedStorageStats> agg_storage_stats;
106  if (td->nShards > 0) {
107  const auto physical_tables = catalog->getPhysicalTablesDescriptors(td, false);
108  CHECK_EQ(static_cast<size_t>(td->nShards), physical_tables.size());
109 
110  for (const auto physical_table : physical_tables) {
111  auto storage_stats = global_file_mgr->getStorageStats(catalog->getDatabaseId(),
112  physical_table->tableId);
113  if (agg_storage_stats) {
114  agg_storage_stats.value().aggregate(storage_stats);
115  } else {
116  agg_storage_stats = storage_stats;
117  }
118  }
119  } else {
120  agg_storage_stats =
121  global_file_mgr->getStorageStats(catalog->getDatabaseId(), td->tableId);
122  }
123  CHECK(agg_storage_stats.has_value());
124  return agg_storage_stats.value();
125 }
126 
127 std::unique_ptr<RexLiteral> genLiteralStr(std::string val) {
128  return std::unique_ptr<RexLiteral>(
129  new RexLiteral(val, SQLTypes::kTEXT, SQLTypes::kTEXT, 0, 0, 0, 0));
130 }
131 
132 std::unique_ptr<RexLiteral> genLiteralTimestamp(time_t val) {
133  return std::unique_ptr<RexLiteral>(new RexLiteral(
134  (int64_t)val, SQLTypes::kTIMESTAMP, SQLTypes::kTIMESTAMP, 0, 8, 0, 8));
135 }
136 
137 std::unique_ptr<RexLiteral> genLiteralBigInt(int64_t val) {
138  return std::unique_ptr<RexLiteral>(
139  new RexLiteral(val, SQLTypes::kBIGINT, SQLTypes::kBIGINT, 0, 8, 0, 8));
140 }
141 
142 std::unique_ptr<RexLiteral> genLiteralBoolean(bool val) {
143  return std::unique_ptr<RexLiteral>(
144  // new RexLiteral(val, SQLTypes::kBOOLEAN, SQLTypes::kBOOLEAN, 0, 0, 0, 0));
145  new RexLiteral(
146  (int64_t)(val ? 1 : 0), SQLTypes::kBIGINT, SQLTypes::kBIGINT, 0, 8, 0, 8));
147 }
148 
150  std::vector<TargetMetaInfo>& label_infos,
151  const std::vector<std::tuple<std::string, SQLTypes, bool>>& headers) {
152  for (const auto& header : headers) {
153  auto [_val, _type, _notnull] = header;
154  if (_type == kBIGINT || _type == kTEXT || _type == kTIMESTAMP || _type == kBOOLEAN) {
155  label_infos.emplace_back(_val, SQLTypeInfo(_type, _notnull));
156  } else {
157  UNREACHABLE() << "Unsupported type provided for header. SQL type: "
158  << to_string(_type);
159  }
160  }
161 }
162 
163 void add_table_details(std::vector<RelLogicalValues::RowValues>& logical_values,
164  const TableDescriptor* logical_table,
165  const AggregratedStorageStats& agg_storage_stats) {
166  bool is_sharded_table = (logical_table->nShards > 0);
167  logical_values.emplace_back(RelLogicalValues::RowValues{});
168  logical_values.back().emplace_back(genLiteralBigInt(logical_table->tableId));
169  logical_values.back().emplace_back(genLiteralStr(logical_table->tableName));
170  logical_values.back().emplace_back(genLiteralBigInt(logical_table->nColumns));
171  logical_values.back().emplace_back(genLiteralBoolean(is_sharded_table));
172  logical_values.back().emplace_back(genLiteralBigInt(logical_table->nShards));
173  logical_values.back().emplace_back(genLiteralBigInt(logical_table->maxRows));
174  logical_values.back().emplace_back(genLiteralBigInt(logical_table->maxFragRows));
175  logical_values.back().emplace_back(genLiteralBigInt(logical_table->maxRollbackEpochs));
176  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.min_epoch));
177  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.max_epoch));
178  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.min_epoch_floor));
179  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.max_epoch_floor));
180  logical_values.back().emplace_back(
181  genLiteralBigInt(agg_storage_stats.metadata_file_count));
182  logical_values.back().emplace_back(
183  genLiteralBigInt(agg_storage_stats.total_metadata_file_size));
184  logical_values.back().emplace_back(
185  genLiteralBigInt(agg_storage_stats.total_metadata_page_count));
186 
187  if (agg_storage_stats.total_free_metadata_page_count) {
188  logical_values.back().emplace_back(
189  genLiteralBigInt(agg_storage_stats.total_free_metadata_page_count.value()));
190  } else {
191  logical_values.back().emplace_back(genLiteralBigInt(NULL_BIGINT));
192  }
193 
194  logical_values.back().emplace_back(genLiteralBigInt(agg_storage_stats.data_file_count));
195  logical_values.back().emplace_back(
196  genLiteralBigInt(agg_storage_stats.total_data_file_size));
197  logical_values.back().emplace_back(
198  genLiteralBigInt(agg_storage_stats.total_data_page_count));
199 
200  if (agg_storage_stats.total_free_data_page_count) {
201  logical_values.back().emplace_back(
202  genLiteralBigInt(agg_storage_stats.total_free_data_page_count.value()));
203  } else {
204  logical_values.back().emplace_back(genLiteralBigInt(NULL_BIGINT));
205  }
206 }
207 
208 // -----------------------------------------------------------------------
209 // class: JsonColumnSqlType
210 // Defined & Implemented here to avoid exposing rapidjson in the header file
211 // -----------------------------------------------------------------------
212 
215  public:
216  JsonColumnSqlType(const rapidjson::Value& data_type)
217  : ddl_utils::SqlType(getSqlType(data_type),
218  getParam1(data_type),
219  getParam2(data_type),
220  isArray(data_type),
221  getArraySize(data_type)) {}
222 
223  private:
224  static SQLTypes getSqlType(const rapidjson::Value& data_type);
225  static SQLTypes getSqlType(const std::string& type);
226  static int getParam1(const rapidjson::Value& data_type);
227  static int getParam2(const rapidjson::Value& data_type);
228  static bool isArray(const rapidjson::Value& data_type);
229  static int getArraySize(const rapidjson::Value& data_type);
230 };
231 
233  public:
234  JsonColumnEncoding(const rapidjson::Value& data_type)
235  : ddl_utils::Encoding(getEncodingName(data_type), getEncodingParam(data_type)) {}
236 
237  private:
238  static std::string* getEncodingName(const rapidjson::Value& data_type);
239  static int getEncodingParam(const rapidjson::Value& data_type);
240 };
241 
242 // -----------------------------------------------------------------------
243 // class DdlCommandDataImpl:
244 //
245 // Concrete class to cache parse data
246 // Defined & Implemented here to avoid exposing rapidjson in the header file
247 // Helper/access fns available to get useful pieces of cache data
248 // -----------------------------------------------------------------------
250  public:
251  DdlCommandDataImpl(const std::string& ddl_statement);
252  ~DdlCommandDataImpl() override;
253 
254  // The full query available for futher analysis
255  const rapidjson::Value& query() const;
256 
257  // payload as extracted from the query
258  const rapidjson::Value& payload() const;
259 
260  // commandStr extracted from the payload
261  std::string commandStr() override;
262 
263  rapidjson::Document ddl_query;
264 };
265 
266 DdlCommandDataImpl::DdlCommandDataImpl(const std::string& ddl_statement)
267  : DdlCommandData(ddl_statement) {
268  ddl_query.Parse(ddl_statement);
269 }
270 
272 
273 const rapidjson::Value& DdlCommandDataImpl::query() const {
274  return ddl_query;
275 }
276 
277 const rapidjson::Value& DdlCommandDataImpl::payload() const {
278  CHECK(ddl_query.HasMember("payload"));
279  CHECK(ddl_query["payload"].IsObject());
280  return ddl_query["payload"];
281 }
282 
284  if (ddl_query.IsObject() && ddl_query.HasMember("payload") &&
285  ddl_query["payload"].IsObject()) {
286  auto& payload = ddl_query["payload"];
287  if (payload.HasMember("command") && payload["command"].IsString()) {
288  return payload["command"].GetString();
289  }
290  }
291  return "";
292 }
293 
294 // Helper Fn to get the payload from the abstract base class
295 const rapidjson::Value& extractPayload(const DdlCommandData& ddl_data) {
296  const DdlCommandDataImpl* data = static_cast<const DdlCommandDataImpl*>(&ddl_data);
297  return data->payload();
298 }
299 
300 const rapidjson::Value* extractFilters(const rapidjson::Value& payload) {
301  const rapidjson::Value* filters = nullptr;
302  if (payload.HasMember("filters") && payload["filters"].IsArray()) {
303  filters = &payload["filters"];
304  }
305  return filters;
306 }
307 
308 } // namespace
309 
311  const std::string& ddl_statement,
312  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
313  : session_ptr_(session_ptr) {
314  CHECK(!ddl_statement.empty());
315  ddl_statement_ = ddl_statement;
316 
317  // parse the incoming query,
318  // cache the parsed rapidjson object inside a DdlCommandDataImpl
319  // store the "abstract/base class" reference in ddl_data_
320  DdlCommandDataImpl* ddl_query_data = new DdlCommandDataImpl(ddl_statement);
321  ddl_data_ = std::unique_ptr<DdlCommandData>(ddl_query_data);
322 
323  VLOG(2) << "Parsing JSON DDL from Calcite: " << ddl_statement;
324  auto& ddl_query = ddl_query_data->query();
325  CHECK(ddl_query.IsObject()) << ddl_statement;
326  CHECK(ddl_query.HasMember("payload"));
327  CHECK(ddl_query["payload"].IsObject());
328  const auto& payload = ddl_query["payload"].GetObject();
329  CHECK(payload.HasMember("command"));
330  CHECK(payload["command"].IsString());
331  ddl_command_ = payload["command"].GetString();
332 }
333 
336 
337  // the following commands use parser node locking to ensure safe concurrent access
338  if (ddl_command_ == "CREATE_TABLE") {
339  auto create_table_stmt = Parser::CreateTableStmt(extractPayload(*ddl_data_));
340  create_table_stmt.execute(*session_ptr_, read_only_mode);
341  return result;
342  } else if (ddl_command_ == "CREATE_VIEW") {
343  auto create_view_stmt = Parser::CreateViewStmt(extractPayload(*ddl_data_));
344  create_view_stmt.execute(*session_ptr_, read_only_mode);
345  return result;
346  } else if (ddl_command_ == "DROP_TABLE") {
347  auto drop_table_stmt = Parser::DropTableStmt(extractPayload(*ddl_data_));
348  drop_table_stmt.execute(*session_ptr_, read_only_mode);
349  return result;
350  } else if (ddl_command_ == "DROP_VIEW") {
351  auto drop_view_stmt = Parser::DropViewStmt(extractPayload(*ddl_data_));
352  drop_view_stmt.execute(*session_ptr_, read_only_mode);
353  return result;
354  } else if (ddl_command_ == "RENAME_TABLE") {
355  auto rename_table_stmt = Parser::RenameTableStmt(extractPayload(*ddl_data_));
356  rename_table_stmt.execute(*session_ptr_, read_only_mode);
357  return result;
358  } else if (ddl_command_ == "ALTER_TABLE") {
360  if (stmt != nullptr) {
361  stmt->execute(*session_ptr_, read_only_mode);
362  }
363  return result;
364  } else if (ddl_command_ == "TRUNCATE_TABLE") {
365  auto truncate_table_stmt = Parser::TruncateTableStmt(extractPayload(*ddl_data_));
366  truncate_table_stmt.execute(*session_ptr_, read_only_mode);
367  return result;
368  } else if (ddl_command_ == "DUMP_TABLE") {
369  auto dump_table_stmt = Parser::DumpTableStmt(extractPayload(*ddl_data_));
370  dump_table_stmt.execute(*session_ptr_, read_only_mode);
371  return result;
372  } else if (ddl_command_ == "RESTORE_TABLE") {
373  auto restore_table_stmt = Parser::RestoreTableStmt(extractPayload(*ddl_data_));
374  restore_table_stmt.execute(*session_ptr_, read_only_mode);
375  return result;
376  } else if (ddl_command_ == "OPTIMIZE_TABLE") {
377  auto optimize_table_stmt = Parser::OptimizeTableStmt(extractPayload(*ddl_data_));
378  optimize_table_stmt.execute(*session_ptr_, read_only_mode);
379  return result;
380  } else if (ddl_command_ == "COPY_TABLE") {
381  auto copy_table_stmt = Parser::CopyTableStmt(extractPayload(*ddl_data_));
382  copy_table_stmt.execute(*session_ptr_, read_only_mode);
383  return result;
384  } else if (ddl_command_ == "EXPORT_QUERY") {
385  auto export_query_stmt = Parser::ExportQueryStmt(extractPayload(*ddl_data_));
386  export_query_stmt.execute(*session_ptr_, read_only_mode);
387  return result;
388  } else if (ddl_command_ == "CREATE_DB") {
389  auto create_db_stmt = Parser::CreateDBStmt(extractPayload(*ddl_data_));
390  create_db_stmt.execute(*session_ptr_, read_only_mode);
391  return result;
392  } else if (ddl_command_ == "DROP_DB") {
393  auto drop_db_stmt = Parser::DropDBStmt(extractPayload(*ddl_data_));
394  drop_db_stmt.execute(*session_ptr_, read_only_mode);
395  return result;
396  } else if (ddl_command_ == "RENAME_DB") {
397  auto rename_db_stmt = Parser::RenameDBStmt(extractPayload(*ddl_data_));
398  rename_db_stmt.execute(*session_ptr_, read_only_mode);
399  return result;
400  } else if (ddl_command_ == "CREATE_USER") {
401  auto create_user_stmt = Parser::CreateUserStmt(extractPayload(*ddl_data_));
402  create_user_stmt.execute(*session_ptr_, read_only_mode);
403  return result;
404  } else if (ddl_command_ == "DROP_USER") {
405  auto drop_user_stmt = Parser::DropUserStmt(extractPayload(*ddl_data_));
406  drop_user_stmt.execute(*session_ptr_, read_only_mode);
407  return result;
408  } else if (ddl_command_ == "ALTER_USER") {
409  auto alter_user_stmt = Parser::AlterUserStmt(extractPayload(*ddl_data_));
410  alter_user_stmt.execute(*session_ptr_, read_only_mode);
411  return result;
412  } else if (ddl_command_ == "RENAME_USER") {
413  auto rename_user_stmt = Parser::RenameUserStmt(extractPayload(*ddl_data_));
414  rename_user_stmt.execute(*session_ptr_, read_only_mode);
415  return result;
416  } else if (ddl_command_ == "CREATE_ROLE") {
417  auto create_role_stmt = Parser::CreateRoleStmt(extractPayload(*ddl_data_));
418  create_role_stmt.execute(*session_ptr_, read_only_mode);
419  return result;
420  } else if (ddl_command_ == "DROP_ROLE") {
421  auto drop_role_stmt = Parser::DropRoleStmt(extractPayload(*ddl_data_));
422  drop_role_stmt.execute(*session_ptr_, read_only_mode);
423  return result;
424  } else if (ddl_command_ == "GRANT_ROLE") {
425  auto grant_role_stmt = Parser::GrantRoleStmt(extractPayload(*ddl_data_));
426  grant_role_stmt.execute(*session_ptr_, read_only_mode);
427  return result;
428  } else if (ddl_command_ == "REVOKE_ROLE") {
429  auto revoke_role_stmt = Parser::RevokeRoleStmt(extractPayload(*ddl_data_));
430  revoke_role_stmt.execute(*session_ptr_, read_only_mode);
431  return result;
432  } else if (ddl_command_ == "GRANT_PRIVILEGE") {
433  auto grant_privilege_stmt = Parser::GrantPrivilegesStmt(extractPayload(*ddl_data_));
434  grant_privilege_stmt.execute(*session_ptr_, read_only_mode);
435  return result;
436  } else if (ddl_command_ == "REVOKE_PRIVILEGE") {
437  auto revoke_privileges_stmt =
439  revoke_privileges_stmt.execute(*session_ptr_, read_only_mode);
440  return result;
441  } else if (ddl_command_ == "CREATE_DATAFRAME") {
442  auto create_dataframe_stmt = Parser::CreateDataframeStmt(extractPayload(*ddl_data_));
443  create_dataframe_stmt.execute(*session_ptr_, read_only_mode);
444  return result;
445  } else if (ddl_command_ == "VALIDATE_SYSTEM") {
446  // VALIDATE should have been excuted in outer context before it reaches here
447  UNREACHABLE();
448  }
449 
450  // the following commands require a global unique lock until proper table locking has
451  // been implemented and/or verified
452  auto execute_write_lock =
456  // TODO(vancouver): add appropriate table locking
457 
458  if (ddl_command_ == "CREATE_SERVER") {
459  result = CreateForeignServerCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
460  } else if (ddl_command_ == "DROP_SERVER") {
461  result = DropForeignServerCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
462  } else if (ddl_command_ == "CREATE_FOREIGN_TABLE") {
463  result = CreateForeignTableCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
464  } else if (ddl_command_ == "DROP_FOREIGN_TABLE") {
465  result = DropForeignTableCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
466  } else if (ddl_command_ == "SHOW_TABLES") {
467  result = ShowTablesCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
468  } else if (ddl_command_ == "SHOW_TABLE_DETAILS") {
469  result = ShowTableDetailsCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
470  } else if (ddl_command_ == "SHOW_CREATE_TABLE") {
471  result = ShowCreateTableCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
472  } else if (ddl_command_ == "SHOW_DATABASES") {
473  result = ShowDatabasesCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
474  } else if (ddl_command_ == "SHOW_SERVERS") {
475  result = ShowForeignServersCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
476  } else if (ddl_command_ == "SHOW_CREATE_SERVER") {
477  result = ShowCreateServerCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
478  } else if (ddl_command_ == "SHOW_FUNCTIONS") {
479  result = ShowFunctionsCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
480  } else if (ddl_command_ == "SHOW_RUNTIME_FUNCTIONS") {
481  result =
482  ShowRuntimeFunctionsCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
483  } else if (ddl_command_ == "SHOW_TABLE_FUNCTIONS") {
484  result = ShowTableFunctionsCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
485  } else if (ddl_command_ == "SHOW_RUNTIME_TABLE_FUNCTIONS") {
487  read_only_mode);
488  } else if (ddl_command_ == "ALTER_SERVER") {
489  result = AlterForeignServerCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
490  } else if (ddl_command_ == "ALTER_FOREIGN_TABLE") {
491  result = AlterForeignTableCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
492  } else if (ddl_command_ == "REFRESH_FOREIGN_TABLES") {
493  result =
494  RefreshForeignTablesCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
495  } else if (ddl_command_ == "SHOW_DISK_CACHE_USAGE") {
496  result = ShowDiskCacheUsageCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
497  } else if (ddl_command_ == "SHOW_USER_DETAILS") {
498  result = ShowUserDetailsCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
499  } else if (ddl_command_ == "SHOW_ROLES") {
500  result = ShowRolesCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
501  } else if (ddl_command_ == "REASSIGN_OWNED") {
502  result = ReassignOwnedCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
503  } else {
504  throw std::runtime_error("Unsupported DDL command");
505  }
506 
507  return result;
508 }
509 
511  return (ddl_command_ == "SHOW_USER_SESSIONS");
512 }
513 
515  return (ddl_command_ == "SHOW_QUERIES");
516 }
517 
519  return (ddl_command_ == "KILL_QUERY");
520 }
521 
523  return (ddl_command_ == "ALTER_SYSTEM_CLEAR");
524 }
525 
527  return (ddl_command_ == "ALTER_SESSION_SET");
528 }
529 
530 std::pair<std::string, std::string> DdlCommandExecutor::getSessionParameter() const {
531  enum SetParameterType { String_t, Numeric_t };
532  static const std::unordered_map<std::string, SetParameterType>
533  session_set_parameters_map = {{"EXECUTOR_DEVICE", SetParameterType::String_t},
534  {"CURRENT_DATABASE", SetParameterType::String_t}};
535 
536  auto& ddl_payload = extractPayload(*ddl_data_);
537  CHECK(ddl_payload.HasMember("sessionParameter"));
538  CHECK(ddl_payload["sessionParameter"].IsString());
539  CHECK(ddl_payload.HasMember("parameterValue"));
540  CHECK(ddl_payload["parameterValue"].IsString());
541  std::string parameter_name = to_upper(ddl_payload["sessionParameter"].GetString());
542  std::string parameter_value = ddl_payload["parameterValue"].GetString();
543 
544  const auto param_it = session_set_parameters_map.find(parameter_name);
545  if (param_it == session_set_parameters_map.end()) {
546  throw std::runtime_error(parameter_name + " is not a settable session parameter.");
547  }
548  if (param_it->second == SetParameterType::Numeric_t) {
549  if (!std::regex_match(parameter_value, std::regex("[(-|+)|][0-9]+"))) {
550  throw std::runtime_error("The value of session parameter " + param_it->first +
551  " should be a numeric.");
552  }
553  }
554  return {parameter_name, parameter_value};
555 }
556 
558  CHECK(ddl_command_ == "ALTER_SYSTEM_CLEAR");
559  auto& ddl_payload = extractPayload(*ddl_data_);
560  CHECK(ddl_payload.HasMember("cacheType"));
561  CHECK(ddl_payload["cacheType"].IsString());
562  return ddl_payload["cacheType"].GetString();
563 }
564 
566  DistributedExecutionDetails execution_details;
567  if (ddl_command_ == "CREATE_DATAFRAME" || ddl_command_ == "RENAME_TABLE" ||
568  ddl_command_ == "ALTER_TABLE" || ddl_command_ == "CREATE_TABLE" ||
569  ddl_command_ == "DROP_TABLE" || ddl_command_ == "TRUNCATE_TABLE" ||
570  ddl_command_ == "DUMP_TABLE" || ddl_command_ == "RESTORE_TABLE" ||
571  ddl_command_ == "OPTIMIZE_TABLE" || ddl_command_ == "CREATE_VIEW" ||
572  ddl_command_ == "DROP_VIEW" || ddl_command_ == "CREATE_DB" ||
573  ddl_command_ == "DROP_DB" || ddl_command_ == "RENAME_DB" ||
574  ddl_command_ == "CREATE_USER" || ddl_command_ == "DROP_USER" ||
575  ddl_command_ == "ALTER_USER" || ddl_command_ == "RENAME_USER" ||
576  ddl_command_ == "CREATE_ROLE" || ddl_command_ == "DROP_ROLE" ||
577  ddl_command_ == "GRANT_ROLE" || ddl_command_ == "REVOKE_ROLE" ||
578  ddl_command_ == "REASSIGN_OWNED" || ddl_command_ == "CREATE_POLICY" ||
579  ddl_command_ == "DROP_POLICY" || ddl_command_ == "CREATE_SERVER" ||
580  ddl_command_ == "DROP_SERVER" || ddl_command_ == "CREATE_FOREIGN_TABLE" ||
581  ddl_command_ == "DROP_FOREIGN_TABLE" || ddl_command_ == "CREATE_USER_MAPPING" ||
582  ddl_command_ == "DROP_USER_MAPPING" || ddl_command_ == "ALTER_FOREIGN_TABLE" ||
583  ddl_command_ == "ALTER_SERVER" || ddl_command_ == "REFRESH_FOREIGN_TABLES" ||
584  ddl_command_ == "ALTER_SYSTEM_CLEAR") {
585  // group user/role/db commands
587  execution_details.aggregation_type = AggregationType::NONE;
588  } else if (ddl_command_ == "GRANT_PRIVILEGE" || ddl_command_ == "REVOKE_PRIVILEGE") {
589  auto& ddl_payload = extractPayload(*ddl_data_);
590  CHECK(ddl_payload.HasMember("type"));
591  const std::string& targetType = ddl_payload["type"].GetString();
592  if (targetType == "DASHBOARD") {
593  // dashboard commands should run on Aggregator alone
595  execution_details.aggregation_type = AggregationType::NONE;
596  } else {
598  execution_details.aggregation_type = AggregationType::NONE;
599  }
600 
601  } else if (ddl_command_ == "SHOW_TABLE_DETAILS" ||
602  ddl_command_ == "SHOW_DISK_CACHE_USAGE") {
604  execution_details.aggregation_type = AggregationType::UNION;
605  } else {
606  // Commands that fall here : COPY_TABLE, EXPORT_QUERY, etc.
608  execution_details.aggregation_type = AggregationType::NONE;
609  }
610  return execution_details;
611 }
612 
614  // caller should check whether DDL indicates KillQuery request
615  // i.e., use isKillQuery() before calling this function
616  auto& ddl_payload = extractPayload(*ddl_data_);
617  CHECK(isKillQuery());
618  CHECK(ddl_payload.HasMember("querySession"));
619  const std::string& query_session = ddl_payload["querySession"].GetString();
620  // regex matcher for public_session: start_time{3}-session_id{4} (Example:819-4RDo)
621  boost::regex session_id_regex{R"([0-9]{3}-[a-zA-Z0-9]{4})",
622  boost::regex::extended | boost::regex::icase};
623  if (!boost::regex_match(query_session, session_id_regex)) {
624  throw std::runtime_error(
625  "Please provide the correct session ID of the query that you want to interrupt.");
626  }
627  return query_session;
628 }
629 
630 const std::string DdlCommandExecutor::commandStr() const {
631  return ddl_command_;
632 }
633 
634 namespace {
635 const std::array<std::string, 3> kReservedServerPrefixes{"default", "system", "internal"};
636 
637 bool is_default_server(const std::string& server_name) {
638  return std::any_of(kReservedServerPrefixes.begin(),
640  [&server_name](const std::string& reserved_prefix) {
641  return boost::istarts_with(server_name, reserved_prefix);
642  });
643 }
644 
646  std::string error_message{"Foreign server names cannot start with "};
647  for (size_t i = 0; i < kReservedServerPrefixes.size(); i++) {
648  if (i > 0) {
649  error_message += ", ";
650  }
651  if (i == kReservedServerPrefixes.size() - 1) {
652  error_message += "or ";
653  }
654  error_message += "\"" + kReservedServerPrefixes[i] + "\"";
655  }
656  error_message += ".";
657  throw std::runtime_error{error_message};
658 }
659 } // namespace
660 
662  const DdlCommandData& ddl_data,
663  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
664  : DdlCommand(ddl_data, session_ptr) {
665  if (!g_enable_fsi) {
666  throw std::runtime_error("Unsupported command: CREATE FOREIGN SERVER");
667  }
668  auto& ddl_payload = extractPayload(ddl_data_);
669  CHECK(ddl_payload.HasMember("serverName"));
670  CHECK(ddl_payload["serverName"].IsString());
671  CHECK(ddl_payload.HasMember("dataWrapper"));
672  CHECK(ddl_payload["dataWrapper"].IsString());
673  if (ddl_payload.HasMember("options")) {
674  CHECK(ddl_payload["options"].IsObject());
675  }
676  CHECK(ddl_payload.HasMember("ifNotExists"));
677  CHECK(ddl_payload["ifNotExists"].IsBool());
678 }
679 
682 
683  if (read_only_mode) {
684  throw std::runtime_error("CREATE FOREIGN SERVER invalid in read only mode.");
685  }
686  auto& ddl_payload = extractPayload(ddl_data_);
687  std::string server_name = ddl_payload["serverName"].GetString();
688  if (is_default_server(server_name)) {
690  }
691  bool if_not_exists = ddl_payload["ifNotExists"].GetBool();
692  if (session_ptr_->getCatalog().getForeignServer(server_name)) {
693  if (if_not_exists) {
694  return result;
695  } else {
696  throw std::runtime_error{"A foreign server with name \"" + server_name +
697  "\" already exists."};
698  }
699  }
700  // check access privileges
701  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::ServerDBObjectType,
703  throw std::runtime_error("Server " + std::string(server_name) +
704  " will not be created. User has no create privileges.");
705  }
706 
707  auto& current_user = session_ptr_->get_currentUser();
708  auto foreign_server = std::make_unique<foreign_storage::ForeignServer>();
709  foreign_server->data_wrapper_type = to_upper(ddl_payload["dataWrapper"].GetString());
710  foreign_server->name = server_name;
711  foreign_server->user_id = current_user.userId;
712  if (ddl_payload.HasMember("options")) {
713  foreign_server->populateOptionsMap(ddl_payload["options"]);
714  }
715  foreign_server->validate();
716 
717  auto& catalog = session_ptr_->getCatalog();
718  catalog.createForeignServer(std::move(foreign_server),
719  ddl_payload["ifNotExists"].GetBool());
721  current_user, server_name, ServerDBObjectType, catalog);
722 
723  return result;
724 }
725 
727  const DdlCommandData& ddl_data,
728  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
729  : DdlCommand(ddl_data, session_ptr) {
730  if (!g_enable_fsi) {
731  throw std::runtime_error("Unsupported command: ALTER FOREIGN SERVER");
732  }
733  auto& ddl_payload = extractPayload(ddl_data_);
734  CHECK(ddl_payload.HasMember("serverName"));
735  CHECK(ddl_payload["serverName"].IsString());
736  CHECK(ddl_payload.HasMember("alterType"));
737  CHECK(ddl_payload["alterType"].IsString());
738  if (ddl_payload["alterType"] == "SET_OPTIONS") {
739  CHECK(ddl_payload.HasMember("options"));
740  CHECK(ddl_payload["options"].IsObject());
741  } else if (ddl_payload["alterType"] == "SET_DATA_WRAPPER") {
742  CHECK(ddl_payload.HasMember("dataWrapper"));
743  CHECK(ddl_payload["dataWrapper"].IsString());
744  } else if (ddl_payload["alterType"] == "RENAME_SERVER") {
745  CHECK(ddl_payload.HasMember("newServerName"));
746  CHECK(ddl_payload["newServerName"].IsString());
747  } else if (ddl_payload["alterType"] == "CHANGE_OWNER") {
748  CHECK(ddl_payload.HasMember("newOwner"));
749  CHECK(ddl_payload["newOwner"].IsString());
750  } else {
751  UNREACHABLE(); // not-implemented alterType
752  }
753 }
754 
756  if (read_only_mode) {
757  throw std::runtime_error("ALTER FOREIGN SERVER invalid in read only mode.");
758  }
759  auto& ddl_payload = extractPayload(ddl_data_);
760  std::string server_name = ddl_payload["serverName"].GetString();
761  if (is_default_server(server_name)) {
762  throw std::runtime_error{"Default servers cannot be altered."};
763  }
764  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
765  throw std::runtime_error{"Foreign server with name \"" + server_name +
766  "\" does not exist and can not be altered."};
767  }
768  if (!hasAlterServerPrivileges()) {
769  throw std::runtime_error("Server " + server_name +
770  " can not be altered. User has no ALTER SERVER privileges.");
771  }
772  std::string alter_type = ddl_payload["alterType"].GetString();
773  if (alter_type == "CHANGE_OWNER") {
775  } else if (alter_type == "SET_DATA_WRAPPER") {
777  } else if (alter_type == "SET_OPTIONS") {
779  } else if (alter_type == "RENAME_SERVER") {
781  }
782 
783  return ExecutionResult();
784 }
785 
787  auto& ddl_payload = extractPayload(ddl_data_);
788  std::string server_name = ddl_payload["serverName"].GetString();
789  std::string new_owner = ddl_payload["newOwner"].GetString();
790  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
791  if (!session_ptr_->get_currentUser().isSuper) {
792  throw std::runtime_error(
793  "Only a super user can change a foreign server's owner. "
794  "Current user is not a super-user. "
795  "Foreign server with name \"" +
796  server_name + "\" will not have owner changed.");
797  }
798  Catalog_Namespace::UserMetadata user, original_owner;
799  if (!sys_cat.getMetadataForUser(new_owner, user)) {
800  throw std::runtime_error("User with username \"" + new_owner + "\" does not exist. " +
801  "Foreign server with name \"" + server_name +
802  "\" can not have owner changed.");
803  }
804  auto& cat = session_ptr_->getCatalog();
805  // get original owner metadata
806  bool original_owner_exists = sys_cat.getMetadataForUserById(
807  cat.getForeignServer(server_name)->user_id, original_owner);
808  // update catalog
809  cat.changeForeignServerOwner(server_name, user.userId);
810  try {
811  // update permissions
812  DBObject db_object(server_name, DBObjectType::ServerDBObjectType);
813  sys_cat.changeDBObjectOwnership(
814  user, original_owner, db_object, cat, original_owner_exists);
815  } catch (const std::runtime_error& e) {
816  // update permissions failed, revert catalog update
817  cat.changeForeignServerOwner(server_name, original_owner.userId);
818  throw;
819  }
820 }
821 
823  auto& ddl_payload = extractPayload(ddl_data_);
824  std::string server_name = ddl_payload["serverName"].GetString();
825  std::string new_server_name = ddl_payload["newServerName"].GetString();
826  if (is_default_server(new_server_name)) {
828  }
829  auto& cat = session_ptr_->getCatalog();
830  // check for a conflicting server
831  if (cat.getForeignServer(new_server_name)) {
832  throw std::runtime_error("Foreign server with name \"" + server_name +
833  "\" can not be renamed to \"" + new_server_name + "\"." +
834  "Foreign server with name \"" + new_server_name +
835  "\" exists.");
836  }
837  // update catalog
838  cat.renameForeignServer(server_name, new_server_name);
839  try {
840  // migrate object privileges
841  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
842  sys_cat.renameDBObject(server_name,
843  new_server_name,
845  cat.getForeignServer(new_server_name)->id,
846  cat);
847  } catch (const std::runtime_error& e) {
848  // permission migration failed, revert catalog update
849  cat.renameForeignServer(new_server_name, server_name);
850  throw;
851  }
852 }
853 
855  auto& ddl_payload = extractPayload(ddl_data_);
856  std::string server_name = ddl_payload["serverName"].GetString();
857  auto& cat = session_ptr_->getCatalog();
858  // update catalog
859  const auto foreign_server = cat.getForeignServer(server_name);
861  opt.populateOptionsMap(foreign_server->getOptionsAsJsonString());
862  opt.populateOptionsMap(ddl_payload["options"]);
863  cat.setForeignServerOptions(server_name, opt.getOptionsAsJsonString());
864 }
865 
867  auto& ddl_payload = extractPayload(ddl_data_);
868  std::string server_name = ddl_payload["serverName"].GetString();
869  std::string data_wrapper = ddl_payload["dataWrapper"].GetString();
870  auto& cat = session_ptr_->getCatalog();
871  // update catalog
872  cat.setForeignServerDataWrapper(server_name, data_wrapper);
873 }
874 
876  // TODO: implement `GRANT/REVOKE ALTER_SERVER` DDL commands
877  auto& ddl_payload = extractPayload(ddl_data_);
878  std::string server_name = ddl_payload["serverName"].GetString();
879  return session_ptr_->checkDBAccessPrivileges(
881 }
882 
884  const DdlCommandData& ddl_data,
885  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
886  : DdlCommand(ddl_data, session_ptr) {
887  if (!g_enable_fsi) {
888  throw std::runtime_error("Unsupported command: DROP FOREIGN SERVER");
889  }
890  auto& ddl_payload = extractPayload(ddl_data_);
891  CHECK(ddl_payload.HasMember("serverName"));
892  CHECK(ddl_payload["serverName"].IsString());
893  CHECK(ddl_payload.HasMember("ifExists"));
894  CHECK(ddl_payload["ifExists"].IsBool());
895 }
896 
898  if (read_only_mode) {
899  throw std::runtime_error("DROP FOREIGN SERVER invalid in read only mode.");
900  }
901  auto& ddl_payload = extractPayload(ddl_data_);
902  std::string server_name = ddl_payload["serverName"].GetString();
903  if (is_default_server(server_name)) {
904  throw std::runtime_error{"Default servers cannot be dropped."};
905  }
906  bool if_exists = ddl_payload["ifExists"].GetBool();
907  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
908  if (if_exists) {
909  return ExecutionResult();
910  } else {
911  throw std::runtime_error{"Foreign server with name \"" + server_name +
912  "\" can not be dropped. Server does not exist."};
913  }
914  }
915  // check access privileges
916  if (!session_ptr_->checkDBAccessPrivileges(
918  throw std::runtime_error("Server " + server_name +
919  " will not be dropped. User has no DROP SERVER privileges.");
920  }
922  DBObject(server_name, ServerDBObjectType), session_ptr_->get_catalog_ptr().get());
923  session_ptr_->getCatalog().dropForeignServer(ddl_payload["serverName"].GetString());
924 
925  return ExecutionResult();
926 }
927 
928 SQLTypes JsonColumnSqlType::getSqlType(const rapidjson::Value& data_type) {
929  CHECK(data_type.IsObject());
930  CHECK(data_type.HasMember("type"));
931  CHECK(data_type["type"].IsString());
932 
933  std::string type = data_type["type"].GetString();
934  if (boost::iequals(type, "ARRAY")) {
935  CHECK(data_type.HasMember("array"));
936  CHECK(data_type["array"].IsObject());
937 
938  const auto& array = data_type["array"].GetObject();
939  CHECK(array.HasMember("elementType"));
940  CHECK(array["elementType"].IsString());
941  type = array["elementType"].GetString();
942  }
943  return getSqlType(type);
944 }
945 
946 SQLTypes JsonColumnSqlType::getSqlType(const std::string& type) {
947  if (boost::iequals(type, "BIGINT")) {
948  return kBIGINT;
949  }
950  if (boost::iequals(type, "BOOLEAN")) {
951  return kBOOLEAN;
952  }
953  if (boost::iequals(type, "DATE")) {
954  return kDATE;
955  }
956  if (boost::iequals(type, "DECIMAL")) {
957  return kDECIMAL;
958  }
959  if (boost::iequals(type, "DOUBLE")) {
960  return kDOUBLE;
961  }
962  if (boost::iequals(type, "FLOAT")) {
963  return kFLOAT;
964  }
965  if (boost::iequals(type, "INTEGER")) {
966  return kINT;
967  }
968  if (boost::iequals(type, "LINESTRING")) {
969  return kLINESTRING;
970  }
971  if (boost::iequals(type, "MULTIPOLYGON")) {
972  return kMULTIPOLYGON;
973  }
974  if (boost::iequals(type, "POINT")) {
975  return kPOINT;
976  }
977  if (boost::iequals(type, "POLYGON")) {
978  return kPOLYGON;
979  }
980  if (boost::iequals(type, "SMALLINT")) {
981  return kSMALLINT;
982  }
983  if (boost::iequals(type, "TEXT")) {
984  return kTEXT;
985  }
986  if (boost::iequals(type, "TIME")) {
987  return kTIME;
988  }
989  if (boost::iequals(type, "TIMESTAMP")) {
990  return kTIMESTAMP;
991  }
992  if (boost::iequals(type, "TINYINT")) {
993  return kTINYINT;
994  }
995 
996  throw std::runtime_error{"Unsupported type \"" + type + "\" specified."};
997 }
998 
999 int JsonColumnSqlType::getParam1(const rapidjson::Value& data_type) {
1000  int param1 = -1;
1001  CHECK(data_type.IsObject());
1002  if (data_type.HasMember("precision") && !data_type["precision"].IsNull()) {
1003  CHECK(data_type["precision"].IsInt());
1004  param1 = data_type["precision"].GetInt();
1005  } else if (auto type = getSqlType(data_type); IS_GEO(type)) {
1006  param1 = static_cast<int>(kGEOMETRY);
1007  }
1008  return param1;
1009 }
1010 
1011 int JsonColumnSqlType::getParam2(const rapidjson::Value& data_type) {
1012  int param2 = 0;
1013  CHECK(data_type.IsObject());
1014  if (data_type.HasMember("scale") && !data_type["scale"].IsNull()) {
1015  CHECK(data_type["scale"].IsInt());
1016  param2 = data_type["scale"].GetInt();
1017  } else if (auto type = getSqlType(data_type); IS_GEO(type) &&
1018  data_type.HasMember("coordinateSystem") &&
1019  !data_type["coordinateSystem"].IsNull()) {
1020  CHECK(data_type["coordinateSystem"].IsInt());
1021  param2 = data_type["coordinateSystem"].GetInt();
1022  }
1023  return param2;
1024 }
1025 
1026 bool JsonColumnSqlType::isArray(const rapidjson::Value& data_type) {
1027  CHECK(data_type.IsObject());
1028  CHECK(data_type.HasMember("type"));
1029  CHECK(data_type["type"].IsString());
1030  return boost::iequals(data_type["type"].GetString(), "ARRAY");
1031 }
1032 
1033 int JsonColumnSqlType::getArraySize(const rapidjson::Value& data_type) {
1034  int size = -1;
1035  if (isArray(data_type)) {
1036  CHECK(data_type.HasMember("array"));
1037  CHECK(data_type["array"].IsObject());
1038 
1039  const auto& array = data_type["array"].GetObject();
1040  if (array.HasMember("size") && !array["size"].IsNull()) {
1041  CHECK(array["size"].IsInt());
1042  size = array["size"].GetInt();
1043  }
1044  }
1045  return size;
1046 }
1047 
1048 std::string* JsonColumnEncoding::getEncodingName(const rapidjson::Value& data_type) {
1049  CHECK(data_type.IsObject());
1050  CHECK(data_type.HasMember("encoding"));
1051  CHECK(data_type["encoding"].IsObject());
1052 
1053  const auto& encoding = data_type["encoding"].GetObject();
1054  CHECK(encoding.HasMember("type"));
1055  CHECK(encoding["type"].IsString());
1056  return new std::string(encoding["type"].GetString());
1057 }
1058 
1059 int JsonColumnEncoding::getEncodingParam(const rapidjson::Value& data_type) {
1060  CHECK(data_type.IsObject());
1061  CHECK(data_type.HasMember("encoding"));
1062  CHECK(data_type["encoding"].IsObject());
1063 
1064  int encoding_size = 0;
1065  const auto& encoding = data_type["encoding"].GetObject();
1066  if (encoding.HasMember("size") && !encoding["size"].IsNull()) {
1067  CHECK(encoding["size"].IsInt());
1068  encoding_size = encoding["size"].GetInt();
1069  }
1070  return encoding_size;
1071 }
1072 
1074  const DdlCommandData& ddl_data,
1075  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1076  : DdlCommand(ddl_data, session_ptr) {
1077  if (!g_enable_fsi) {
1078  throw std::runtime_error("Unsupported command: CREATE FOREIGN TABLE");
1079  }
1080  auto& ddl_payload = extractPayload(ddl_data);
1081  CHECK(ddl_payload.HasMember("serverName"));
1082  CHECK(ddl_payload["serverName"].IsString());
1083  CHECK(ddl_payload.HasMember("tableName"));
1084  CHECK(ddl_payload["tableName"].IsString());
1085  CHECK(ddl_payload.HasMember("ifNotExists"));
1086  CHECK(ddl_payload["ifNotExists"].IsBool());
1087  CHECK(ddl_payload.HasMember("columns"));
1088  CHECK(ddl_payload["columns"].IsArray());
1089 }
1090 
1092  auto& catalog = session_ptr_->getCatalog();
1093  auto& ddl_payload = extractPayload(ddl_data_);
1094 
1095  if (read_only_mode) {
1096  throw std::runtime_error("CREATE FOREIGN TABLE invalid in read only mode.");
1097  }
1098  const std::string& table_name = ddl_payload["tableName"].GetString();
1099  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::TableDBObjectType,
1101  throw std::runtime_error(
1102  "Foreign table \"" + table_name +
1103  "\" will not be created. User has no CREATE TABLE privileges.");
1104  }
1105 
1106  bool if_not_exists = ddl_payload["ifNotExists"].GetBool();
1107  if (!catalog.validateNonExistentTableOrView(table_name, if_not_exists)) {
1108  return ExecutionResult();
1109  }
1110 
1111  foreign_storage::ForeignTable foreign_table{};
1112  std::list<ColumnDescriptor> columns{};
1113  setColumnDetails(columns);
1114  setTableDetails(table_name, foreign_table, columns);
1115  catalog.createTable(foreign_table, columns, {}, true);
1116 
1117  // TODO (max): It's transactionally unsafe, should be fixed: we may create object w/o
1118  // privileges
1120  session_ptr_->get_currentUser(),
1121  foreign_table.tableName,
1123  catalog);
1124 
1125  return ExecutionResult();
1126 }
1127 
1129  const std::string& table_name,
1130  TableDescriptor& td,
1131  const std::list<ColumnDescriptor>& columns) {
1132  ddl_utils::set_default_table_attributes(table_name, td, columns.size());
1133  td.userId = session_ptr_->get_currentUser().userId;
1135  td.hasDeletedCol = false;
1136  td.keyMetainfo = "[]";
1137  td.fragments = "";
1138  td.partitions = "";
1139 
1140  auto& ddl_payload = extractPayload(ddl_data_);
1141  auto& foreign_table = dynamic_cast<foreign_storage::ForeignTable&>(td);
1142  const std::string server_name = ddl_payload["serverName"].GetString();
1143  foreign_table.foreign_server = session_ptr_->getCatalog().getForeignServer(server_name);
1144  if (!foreign_table.foreign_server) {
1145  throw std::runtime_error{
1146  "Foreign Table with name \"" + table_name +
1147  "\" can not be created. Associated foreign server with name \"" + server_name +
1148  "\" does not exist."};
1149  }
1150 
1151  // check server usage privileges
1152  if (!is_default_server(server_name) &&
1153  !session_ptr_->checkDBAccessPrivileges(DBObjectType::ServerDBObjectType,
1155  server_name)) {
1156  throw std::runtime_error(
1157  "Current user does not have USAGE privilege on foreign server: " + server_name);
1158  }
1159 
1160  if (ddl_payload.HasMember("options") && !ddl_payload["options"].IsNull()) {
1161  CHECK(ddl_payload["options"].IsObject());
1162  foreign_table.initializeOptions(ddl_payload["options"]);
1163  } else {
1164  // Initialize options even if none were provided to verify a legal state.
1165  // This is necessary because some options (like "file_path") are optional only if a
1166  // paired option ("base_path") exists in the server.
1167  foreign_table.initializeOptions();
1168  }
1169  foreign_table.validateSchema(columns);
1170 
1171  if (const auto it = foreign_table.options.find("FRAGMENT_SIZE");
1172  it != foreign_table.options.end()) {
1173  foreign_table.maxFragRows = std::stoi(it->second);
1174  }
1175 
1176  if (const auto it = foreign_table.options.find("MAX_CHUNK_SIZE");
1177  it != foreign_table.options.end()) {
1178  foreign_table.maxChunkSize = std::stol(it->second);
1179  }
1180 
1181  if (const auto it = foreign_table.options.find("PARTITIONS");
1182  it != foreign_table.options.end()) {
1183  foreign_table.partitions = it->second;
1184  }
1185 }
1186 
1187 void CreateForeignTableCommand::setColumnDetails(std::list<ColumnDescriptor>& columns) {
1188  auto& ddl_payload = extractPayload(ddl_data_);
1189  std::unordered_set<std::string> column_names{};
1190  for (auto& column_def : ddl_payload["columns"].GetArray()) {
1191  CHECK(column_def.IsObject());
1192  CHECK(column_def.HasMember("name"));
1193  CHECK(column_def["name"].IsString());
1194  const std::string& column_name = column_def["name"].GetString();
1195 
1196  CHECK(column_def.HasMember("dataType"));
1197  CHECK(column_def["dataType"].IsObject());
1198 
1199  JsonColumnSqlType sql_type{column_def["dataType"]};
1200  const auto& data_type = column_def["dataType"].GetObject();
1201  CHECK(data_type.HasMember("notNull"));
1202  CHECK(data_type["notNull"].IsBool());
1203 
1204  std::unique_ptr<JsonColumnEncoding> encoding;
1205  if (data_type.HasMember("encoding") && !data_type["encoding"].IsNull()) {
1206  CHECK(data_type["encoding"].IsObject());
1207  encoding = std::make_unique<JsonColumnEncoding>(column_def["dataType"]);
1208  }
1209 
1210  ColumnDescriptor cd;
1211  ddl_utils::validate_non_duplicate_column(column_name, column_names);
1214  cd,
1215  &sql_type,
1216  data_type["notNull"].GetBool(),
1217  encoding.get(),
1218  nullptr);
1219  columns.emplace_back(cd);
1220  }
1221 }
1222 
1224  const DdlCommandData& ddl_data,
1225  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1226  : DdlCommand(ddl_data, session_ptr) {
1227  if (!g_enable_fsi) {
1228  throw std::runtime_error("Unsupported command: DROP FOREIGN TABLE");
1229  }
1230  auto& ddl_payload = extractPayload(ddl_data_);
1231  CHECK(ddl_payload.HasMember("tableName"));
1232  CHECK(ddl_payload["tableName"].IsString());
1233  CHECK(ddl_payload.HasMember("ifExists"));
1234  CHECK(ddl_payload["ifExists"].IsBool());
1235 }
1236 
1238  auto& catalog = session_ptr_->getCatalog();
1239  auto& ddl_payload = extractPayload(ddl_data_);
1240 
1241  if (read_only_mode) {
1242  throw std::runtime_error("DROP FOREIGN TABLE invalid in read only mode.");
1243  }
1244  const std::string& table_name = ddl_payload["tableName"].GetString();
1245  const TableDescriptor* td{nullptr};
1246  std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>> td_with_lock;
1247 
1248  try {
1249  td_with_lock =
1250  std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>>(
1252  catalog, table_name, false));
1253  CHECK(td_with_lock);
1254  td = (*td_with_lock)();
1255  } catch (const std::runtime_error& e) {
1256  // TODO(Misiu): This should not just swallow any exception, it should only catch
1257  // exceptions that stem from the table not existing.
1258  if (ddl_payload["ifExists"].GetBool()) {
1259  return ExecutionResult();
1260  } else {
1261  throw e;
1262  }
1263  }
1264 
1265  CHECK(td);
1266 
1267  if (!session_ptr_->checkDBAccessPrivileges(
1269  throw std::runtime_error(
1270  "Foreign table \"" + table_name +
1271  "\" will not be dropped. User has no DROP TABLE privileges.");
1272  }
1273 
1275  auto table_data_write_lock =
1277  catalog.dropTable(td);
1278 
1279  // TODO(Misiu): Implement per-table cache invalidation.
1281 
1282  return ExecutionResult();
1283 }
1284 
1286  const DdlCommandData& ddl_data,
1287  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1288  : DdlCommand(ddl_data, session_ptr) {}
1289 
1291  // Get all table names in the same way as OmniSql \t command
1292 
1293  // valid in read_only_mode
1294 
1295  // label_infos -> column labels
1296  std::vector<std::string> labels{"table_name"};
1297  std::vector<TargetMetaInfo> label_infos;
1298  for (const auto& label : labels) {
1299  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1300  }
1301 
1302  // Get all table names
1303  auto cat_ptr = session_ptr_->get_catalog_ptr();
1304  auto cur_user = session_ptr_->get_currentUser();
1305  auto table_names = cat_ptr->getTableNamesForUser(cur_user, GET_PHYSICAL_TABLES);
1306 
1307  // logical_values -> table data
1308  std::vector<RelLogicalValues::RowValues> logical_values;
1309  for (auto table_name : table_names) {
1310  logical_values.emplace_back(RelLogicalValues::RowValues{});
1311  logical_values.back().emplace_back(genLiteralStr(table_name));
1312  }
1313 
1314  // Create ResultSet
1315  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1316  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1317 
1318  return ExecutionResult(rSet, label_infos);
1319 }
1320 
1322  const DdlCommandData& ddl_data,
1323  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1324  : DdlCommand(ddl_data, session_ptr) {
1325  auto& ddl_payload = extractPayload(ddl_data_);
1326  if (ddl_payload.HasMember("tableNames")) {
1327  CHECK(ddl_payload["tableNames"].IsArray());
1328  for (const auto& table_name : ddl_payload["tableNames"].GetArray()) {
1329  CHECK(table_name.IsString());
1330  }
1331  }
1332 }
1333 
1335  const auto catalog = session_ptr_->get_catalog_ptr();
1336  std::vector<std::string> filtered_table_names = getFilteredTableNames();
1337 
1338  // valid in read_only_mode
1339 
1340  std::vector<TargetMetaInfo> label_infos;
1341  set_headers_with_type(label_infos,
1342  {// { label, type, notNull }
1343  {"table_id", kBIGINT, true},
1344  {"table_name", kTEXT, true},
1345  {"column_count", kBIGINT, true},
1346  {"is_sharded_table", kBOOLEAN, true},
1347  {"shard_count", kBIGINT, true},
1348  {"max_rows", kBIGINT, true},
1349  {"fragment_size", kBIGINT, true},
1350  {"max_rollback_epochs", kBIGINT, true},
1351  {"min_epoch", kBIGINT, true},
1352  {"max_epoch", kBIGINT, true},
1353  {"min_epoch_floor", kBIGINT, true},
1354  {"max_epoch_floor", kBIGINT, true},
1355  {"metadata_file_count", kBIGINT, true},
1356  {"total_metadata_file_size", kBIGINT, true},
1357  {"total_metadata_page_count", kBIGINT, true},
1358  {"total_free_metadata_page_count", kBIGINT, false},
1359  {"data_file_count", kBIGINT, true},
1360  {"total_data_file_size", kBIGINT, true},
1361  {"total_data_page_count", kBIGINT, true},
1362  {"total_free_data_page_count", kBIGINT, false}});
1363 
1364  std::vector<RelLogicalValues::RowValues> logical_values;
1365  for (const auto& table_name : filtered_table_names) {
1366  auto [td, td_with_lock] =
1367  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1368  auto agg_storage_stats = get_agg_storage_stats(td, catalog.get());
1369  add_table_details(logical_values, td, agg_storage_stats);
1370  }
1371 
1372  // Create ResultSet
1373  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1374  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1375 
1376  return ExecutionResult(rSet, label_infos);
1377 }
1378 
1380  const auto catalog = session_ptr_->get_catalog_ptr();
1381  auto& ddl_payload = extractPayload(ddl_data_);
1382  auto all_table_names =
1383  catalog->getTableNamesForUser(session_ptr_->get_currentUser(), GET_PHYSICAL_TABLES);
1384  std::transform(all_table_names.begin(),
1385  all_table_names.end(),
1386  all_table_names.begin(),
1387  [](const std::string& s) { return to_upper(s); });
1388  std::vector<std::string> filtered_table_names;
1389  if (ddl_payload.HasMember("tableNames")) {
1390  std::set<std::string> all_table_names_set(all_table_names.begin(),
1391  all_table_names.end());
1392  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1393  std::string table_name = table_name_json.GetString();
1394  if (all_table_names_set.find(to_upper(table_name)) == all_table_names_set.end()) {
1395  throw std::runtime_error{"Unable to show table details for table: " + table_name +
1396  ". Table does not exist."};
1397  }
1398  auto [td, td_with_lock] =
1399  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1400  if (td->isForeignTable()) {
1401  throw std::runtime_error{
1402  "SHOW TABLE DETAILS is not supported for foreign tables. Table name: " +
1403  table_name + "."};
1404  }
1405  if (td->isTemporaryTable()) {
1406  throw std::runtime_error{
1407  "SHOW TABLE DETAILS is not supported for temporary tables. Table name: " +
1408  table_name + "."};
1409  }
1410  filtered_table_names.emplace_back(table_name);
1411  }
1412  } else {
1413  for (const auto& table_name : all_table_names) {
1414  auto [td, td_with_lock] =
1415  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1416  if (td->isForeignTable() || td->isTemporaryTable()) {
1417  continue;
1418  }
1419  filtered_table_names.emplace_back(table_name);
1420  }
1421  }
1422  return filtered_table_names;
1423 }
1424 
1426  const DdlCommandData& ddl_data,
1427  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1428  : DdlCommand(ddl_data, session_ptr) {}
1429 
1431  // valid in read_only_mode
1432 
1433  auto& ddl_payload = extractPayload(ddl_data_);
1434  CHECK(ddl_payload.HasMember("tableName"));
1435  CHECK(ddl_payload["tableName"].IsString());
1436  const std::string& table_name = ddl_payload["tableName"].GetString();
1437 
1438  auto& catalog = session_ptr_->getCatalog();
1439  auto table_read_lock =
1441 
1442  const TableDescriptor* td = catalog.getMetadataForTable(table_name, false);
1443  if (!td) {
1444  throw std::runtime_error("Table/View " + table_name + " does not exist.");
1445  }
1446 
1448  dbObject.loadKey(catalog);
1449  std::vector<DBObject> privObjects = {dbObject};
1450 
1451  if (!Catalog_Namespace::SysCatalog::instance().hasAnyPrivileges(
1452  session_ptr_->get_currentUser(), privObjects)) {
1453  throw std::runtime_error("Table/View " + table_name + " does not exist.");
1454  }
1455  if (td->isView && !session_ptr_->get_currentUser().isSuper) {
1456  auto query_state = query_state::QueryState::create(session_ptr_, td->viewSQL);
1457  auto query_state_proxy = query_state->createQueryStateProxy();
1458  auto calcite_mgr = catalog.getCalciteMgr();
1459  const auto calciteQueryParsingOption =
1460  calcite_mgr->getCalciteQueryParsingOption(true, false, false);
1461  const auto calciteOptimizationOption =
1462  calcite_mgr->getCalciteOptimizationOption(false, g_enable_watchdog, {});
1463  auto result = calcite_mgr->process(query_state_proxy,
1464  td->viewSQL,
1465  calciteQueryParsingOption,
1466  calciteOptimizationOption);
1467  try {
1468  calcite_mgr->checkAccessedObjectsPrivileges(query_state_proxy, result);
1469  } catch (const std::runtime_error&) {
1470  throw std::runtime_error("Not enough privileges to show the view SQL");
1471  }
1472  }
1473  // Construct
1474  auto create_table_sql = catalog.dumpCreateTable(td);
1477  return result;
1478 }
1479 
1481  const DdlCommandData& ddl_data,
1482  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1483  : DdlCommand(ddl_data, session_ptr) {}
1484 
1486  // valid in read_only_mode
1487 
1488  // label_infos -> column labels
1489  std::vector<std::string> labels{"Database", "Owner"};
1490  std::vector<TargetMetaInfo> label_infos;
1491  for (const auto& label : labels) {
1492  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1493  }
1494 
1495  // Get all table names
1496  auto cur_user = session_ptr_->get_currentUser();
1497  const Catalog_Namespace::DBSummaryList db_summaries =
1499 
1500  // logical_values -> table data
1501  std::vector<RelLogicalValues::RowValues> logical_values;
1502  for (const auto& db_summary : db_summaries) {
1503  logical_values.emplace_back(RelLogicalValues::RowValues{});
1504  logical_values.back().emplace_back(genLiteralStr(db_summary.dbName));
1505  logical_values.back().emplace_back(genLiteralStr(db_summary.dbOwnerName));
1506  }
1507 
1508  // Create ResultSet
1509  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1510  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1511 
1512  return ExecutionResult(rSet, label_infos);
1513 }
1514 
1516  const DdlCommandData& ddl_data,
1517  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1518  : DdlCommand(ddl_data, session_ptr) {}
1519 
1521  // Get all row-wise functions
1522  auto& ddl_payload = extractPayload(ddl_data_);
1523  std::vector<TargetMetaInfo> label_infos;
1524  std::vector<RelLogicalValues::RowValues> logical_values;
1525 
1526  if (ddl_payload.HasMember("ScalarFnNames")) {
1527  // label_infos -> column labels
1528  label_infos.emplace_back("name", SQLTypeInfo(kTEXT, true));
1529  label_infos.emplace_back("signature", SQLTypeInfo(kTEXT, true));
1530  label_infos.emplace_back("CPU", SQLTypeInfo(kBOOLEAN, true));
1531  label_infos.emplace_back("GPU", SQLTypeInfo(kBOOLEAN, true));
1532  label_infos.emplace_back("Runtime", SQLTypeInfo(kBOOLEAN, true));
1533  for (const auto& udf_name_json : ddl_payload["ScalarFnNames"].GetArray()) {
1534  std::string udf_name = udf_name_json.GetString();
1535  std::vector<ExtensionFunction> ext_funcs =
1537 
1538  for (ExtensionFunction& fn : ext_funcs) {
1539  logical_values.emplace_back(RelLogicalValues::RowValues{});
1540  // Name
1541  logical_values.back().emplace_back(genLiteralStr(udf_name));
1542  // Signature
1543  logical_values.back().emplace_back(genLiteralStr(fn.toSignature()));
1544  // CPU?
1545  logical_values.back().emplace_back(genLiteralBoolean(fn.isCPU()));
1546  // GPU?
1547  logical_values.back().emplace_back(genLiteralBoolean(fn.isGPU()));
1548  // Runtime?
1549  logical_values.back().emplace_back(genLiteralBoolean(fn.isRuntime()));
1550  }
1551  }
1552 
1553  } else {
1554  // label_infos -> column labels
1555  for (const auto& label : {"Scalar UDF"}) {
1556  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1557  }
1558 
1559  // logical_values -> table data
1560  for (auto name : ExtensionFunctionsWhitelist::get_udfs_name(/* is_runtime */ false)) {
1561  logical_values.emplace_back(RelLogicalValues::RowValues{});
1562  logical_values.back().emplace_back(genLiteralStr(name));
1563  }
1564  }
1565 
1566  // Create ResultSet
1567  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1568  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1569 
1570  return ExecutionResult(rSet, label_infos);
1571 }
1572 
1574  const DdlCommandData& ddl_data,
1575  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1576  : DdlCommand(ddl_data, session_ptr) {}
1577 
1579  // Get all runtime row-wise functions
1580  std::vector<TargetMetaInfo> label_infos;
1581  std::vector<RelLogicalValues::RowValues> logical_values;
1582 
1583  // label_infos -> column labels
1584  for (const auto& label : {"Runtime Scalar UDF"}) {
1585  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1586  }
1587 
1588  // logical_values -> table data
1589  for (auto name : ExtensionFunctionsWhitelist::get_udfs_name(/* is_runtime */ true)) {
1590  logical_values.emplace_back(RelLogicalValues::RowValues{});
1591  logical_values.back().emplace_back(genLiteralStr(name));
1592  }
1593 
1594  // Create ResultSet
1595  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1596  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1597 
1598  return ExecutionResult(rSet, label_infos);
1599 }
1600 
1602  const DdlCommandData& ddl_data,
1603  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1604  : DdlCommand(ddl_data, session_ptr) {}
1605 
1607  // valid in read_only_mode
1608 
1609  // Get all table functions
1610  auto& ddl_payload = extractPayload(ddl_data_);
1611  std::vector<TargetMetaInfo> label_infos;
1612  std::vector<RelLogicalValues::RowValues> logical_values;
1613 
1614  if (ddl_payload.HasMember("tfNames")) {
1615  // label_infos -> column labels
1616  label_infos.emplace_back("name", SQLTypeInfo(kTEXT, true));
1617  label_infos.emplace_back("signature", SQLTypeInfo(kTEXT, true));
1618  label_infos.emplace_back("input_names", SQLTypeInfo(kTEXT, true));
1619  label_infos.emplace_back("input_types", SQLTypeInfo(kTEXT, true));
1620  label_infos.emplace_back("output_names", SQLTypeInfo(kTEXT, true));
1621  label_infos.emplace_back("output_types", SQLTypeInfo(kTEXT, true));
1622  label_infos.emplace_back("CPU", SQLTypeInfo(kBOOLEAN, true));
1623  label_infos.emplace_back("GPU", SQLTypeInfo(kBOOLEAN, true));
1624  label_infos.emplace_back("Runtime", SQLTypeInfo(kBOOLEAN, true));
1625  label_infos.emplace_back("filter_table_transpose", SQLTypeInfo(kBOOLEAN, true));
1626  // logical_values -> table data
1627  for (const auto& tf_name_json : ddl_payload["tfNames"].GetArray()) {
1628  std::string tf_name = tf_name_json.GetString();
1630  for (table_functions::TableFunction& tf : tfs) {
1631  logical_values.emplace_back(RelLogicalValues::RowValues{});
1632  // Name
1633  logical_values.back().emplace_back(genLiteralStr(tf.getName(true, false)));
1634  // Signature
1635  logical_values.back().emplace_back(genLiteralStr(
1636  tf.getSignature(/*include_name*/ false, /*include_output*/ true)));
1637  // Input argument names
1638  logical_values.back().emplace_back(
1639  genLiteralStr(tf.getArgNames(/* use_input_args */ true)));
1640  // Input argument types
1641  logical_values.back().emplace_back(
1642  genLiteralStr(tf.getArgTypes(/* use_input_args */ true)));
1643  // Output argument names
1644  logical_values.back().emplace_back(
1645  genLiteralStr(tf.getArgNames(/* use_input_args */ false)));
1646  // Output argument types
1647  logical_values.back().emplace_back(
1648  genLiteralStr(tf.getArgTypes(/* use_input_args */ false)));
1649  // CPU?
1650  logical_values.back().emplace_back(genLiteralBoolean(tf.isCPU()));
1651  // GPU?
1652  logical_values.back().emplace_back(genLiteralBoolean(tf.isGPU()));
1653  // Runtime?
1654  logical_values.back().emplace_back(genLiteralBoolean(tf.isRuntime()));
1655  // Implements filter_table_transpose?
1656  logical_values.back().emplace_back(genLiteralBoolean(
1657  !tf.getFunctionAnnotation("filter_table_function_transpose", "").empty()));
1658  }
1659  }
1660  } else {
1661  // label_infos -> column labels
1662  for (const auto& label : {"Tabel UDF"}) {
1663  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1664  }
1665 
1666  // logical_values -> table data
1667  std::unordered_set<std::string> unique_names;
1669  /* is_runtime */ false)) {
1670  std::string name = tf.getName(true, true);
1671  if (unique_names.find(name) == unique_names.end()) {
1672  unique_names.emplace(name);
1673  logical_values.emplace_back(RelLogicalValues::RowValues{});
1674  logical_values.back().emplace_back(genLiteralStr(name));
1675  }
1676  }
1677  }
1678 
1679  // Create ResultSet
1680  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1681  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1682 
1683  return ExecutionResult(rSet, label_infos);
1684 }
1685 
1687  const DdlCommandData& ddl_data,
1688  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1689  : DdlCommand(ddl_data, session_ptr) {}
1690 
1692  // valid in read_only_mode
1693 
1694  // Get all runtime table functions
1695  std::vector<TargetMetaInfo> label_infos;
1696  std::vector<RelLogicalValues::RowValues> logical_values;
1697 
1698  // label_infos -> column labels
1699  for (const auto& label : {"Runtime Table UDF"}) {
1700  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1701  }
1702 
1703  // logical_values -> table data
1704  std::unordered_set<std::string> unique_names;
1705  for (auto tf :
1707  std::string name = tf.getName(true, true);
1708  if (unique_names.find(name) == unique_names.end()) {
1709  unique_names.emplace(name);
1710  logical_values.emplace_back(RelLogicalValues::RowValues{});
1711  logical_values.back().emplace_back(genLiteralStr(name));
1712  }
1713  }
1714 
1715  // Create ResultSet
1716  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1717  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1718 
1719  return ExecutionResult(rSet, label_infos);
1720 }
1721 
1723  const DdlCommandData& ddl_data,
1724  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1725  : DdlCommand(ddl_data, session_ptr) {
1726  if (!g_enable_fsi) {
1727  throw std::runtime_error("Unsupported command: SHOW FOREIGN SERVERS");
1728  }
1729  // Verify that members are valid
1730  auto& ddl_payload = extractPayload(ddl_data_);
1731  CHECK(ddl_payload.HasMember("command"));
1732  if (ddl_payload.HasMember("filters")) {
1733  CHECK(ddl_payload["filters"].IsArray());
1734  int num_filters = 0;
1735  for (auto const& filter_def : ddl_payload["filters"].GetArray()) {
1736  CHECK(filter_def.IsObject());
1737  CHECK(filter_def.HasMember("attribute"));
1738  CHECK(filter_def["attribute"].IsString());
1739  CHECK(filter_def.HasMember("value"));
1740  CHECK(filter_def["value"].IsString());
1741  CHECK(filter_def.HasMember("operation"));
1742  CHECK(filter_def["operation"].IsString());
1743  if (num_filters > 0) {
1744  CHECK(filter_def.HasMember("chain"));
1745  CHECK(filter_def["chain"].IsString());
1746  } else {
1747  CHECK(!filter_def.HasMember("chain"));
1748  }
1749  num_filters++;
1750  }
1751  }
1752 }
1753 
1755  // valid in read_only_mode
1756 
1757  std::vector<TargetMetaInfo> label_infos;
1758  auto& ddl_payload = extractPayload(ddl_data_);
1759 
1760  // label_infos -> column labels
1761  std::vector<std::string> labels{"server_name", "data_wrapper", "created_at", "options"};
1762  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
1763  label_infos.emplace_back(labels[1], SQLTypeInfo(kTEXT, true));
1764  // created_at is a TIMESTAMP
1765  label_infos.emplace_back(labels[2], SQLTypeInfo(kTIMESTAMP, true));
1766  label_infos.emplace_back(labels[3], SQLTypeInfo(kTEXT, true));
1767 
1768  const auto& user = session_ptr_->get_currentUser();
1769 
1770  std::vector<const foreign_storage::ForeignServer*> results;
1771 
1772  session_ptr_->getCatalog().getForeignServersForUser(
1773  extractFilters(ddl_payload), user, results);
1774 
1775  // logical_values -> table data
1776  std::vector<RelLogicalValues::RowValues> logical_values;
1777  for (auto const& server_ptr : results) {
1778  logical_values.emplace_back(RelLogicalValues::RowValues{});
1779  logical_values.back().emplace_back(genLiteralStr(server_ptr->name));
1780  logical_values.back().emplace_back(genLiteralStr(server_ptr->data_wrapper_type));
1781  logical_values.back().emplace_back(genLiteralTimestamp(server_ptr->creation_time));
1782  logical_values.back().emplace_back(
1783  genLiteralStr(server_ptr->getOptionsAsJsonString()));
1784  }
1785 
1786  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1787  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1788 
1789  return ExecutionResult(rSet, label_infos);
1790 }
1791 
1793  const DdlCommandData& ddl_data,
1794  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1795  : DdlCommand(ddl_data, session_ptr) {
1796  if (!g_enable_fsi) {
1797  throw std::runtime_error("Unsupported command: SHOW CREATE SERVER");
1798  }
1799  // Verify that members are valid
1800  auto& payload = extractPayload(ddl_data_);
1801  CHECK(payload.HasMember("serverName"));
1802  CHECK(payload["serverName"].IsString());
1803  server_ = (payload["serverName"].GetString());
1804 }
1805 
1807  // valid in read_only_mode
1808 
1809  using namespace Catalog_Namespace;
1810  auto& catalog = session_ptr_->getCatalog();
1811  const auto server = catalog.getForeignServer(server_);
1812  if (!server) {
1813  throw std::runtime_error("Foreign server " + server_ + " does not exist.");
1814  }
1815  DBObject dbObject(server_, ServerDBObjectType);
1816  dbObject.loadKey(catalog);
1817  std::vector<DBObject> privObjects = {dbObject};
1818  if (!SysCatalog::instance().hasAnyPrivileges(session_ptr_->get_currentUser(),
1819  privObjects)) {
1820  throw std::runtime_error("Foreign server " + server_ + " does not exist.");
1821  }
1822  auto create_stmt = catalog.dumpCreateServer(server_);
1823 
1824  std::vector<std::string> labels{"create_server_sql"};
1825  std::vector<TargetMetaInfo> label_infos;
1826  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
1827 
1828  std::vector<RelLogicalValues::RowValues> logical_values;
1829  logical_values.emplace_back(RelLogicalValues::RowValues{});
1830  logical_values.back().emplace_back(genLiteralStr(create_stmt));
1831 
1832  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1833  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1834 
1835  return ExecutionResult(rSet, label_infos);
1836 }
1837 
1839  const DdlCommandData& ddl_data,
1840  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1841  : DdlCommand(ddl_data, session_ptr) {
1842  if (!g_enable_fsi) {
1843  throw std::runtime_error("Unsupported command: REFRESH FOREIGN TABLE");
1844  }
1845  auto& ddl_payload = extractPayload(ddl_data_);
1846  CHECK(ddl_payload.HasMember("tableNames"));
1847  CHECK(ddl_payload["tableNames"].IsArray());
1848  for (auto const& tablename_def : ddl_payload["tableNames"].GetArray()) {
1849  CHECK(tablename_def.IsString());
1850  }
1851 }
1852 
1854  if (read_only_mode) {
1855  throw std::runtime_error("REFRESH FOREIGN TABLE invalid in read only mode.");
1856  }
1857 
1858  bool evict_cached_entries{false};
1860  auto& ddl_payload = extractPayload(ddl_data_);
1861  if (ddl_payload.HasMember("options") && !ddl_payload["options"].IsNull()) {
1862  opt.populateOptionsMap(ddl_payload["options"]);
1863  for (const auto& entry : opt.options) {
1864  if (entry.first != "EVICT") {
1865  throw std::runtime_error{
1866  "Invalid option \"" + entry.first +
1867  "\" provided for refresh command. Only \"EVICT\" option is supported."};
1868  }
1869  }
1870  CHECK(opt.options.find("EVICT") != opt.options.end());
1871 
1872  if (boost::iequals(opt.options["EVICT"], "true") ||
1873  boost::iequals(opt.options["EVICT"], "false")) {
1874  if (boost::iequals(opt.options["EVICT"], "true")) {
1875  evict_cached_entries = true;
1876  }
1877  } else {
1878  throw std::runtime_error{
1879  "Invalid value \"" + opt.options["EVICT"] +
1880  "\" provided for EVICT option. Value must be either \"true\" or \"false\"."};
1881  }
1882  }
1883 
1884  auto& cat = session_ptr_->getCatalog();
1885  const auto& current_user = session_ptr_->get_currentUser();
1886  /* verify object ownership if not suser */
1887  if (!current_user.isSuper) {
1888  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1889  std::string table_name = table_name_json.GetString();
1890  if (!Catalog_Namespace::SysCatalog::instance().verifyDBObjectOwnership(
1891  current_user, DBObject(table_name, TableDBObjectType), cat)) {
1892  throw std::runtime_error(
1893  std::string("REFRESH FOREIGN TABLES failed on table \"") + table_name +
1894  "\". It can only be executed by super user or "
1895  "owner of the "
1896  "object.");
1897  }
1898  }
1899  }
1900 
1901  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1902  std::string table_name = table_name_json.GetString();
1903  static const std::array<std::string, 4> log_system_tables{
1908  if (cat.isInfoSchemaDb() && !shared::contains(log_system_tables, table_name)) {
1909  throw std::runtime_error(
1910  "REFRESH FOREIGN TABLE can only be executed for the following tables: " +
1911  join(log_system_tables, ","));
1912  }
1913  foreign_storage::refresh_foreign_table(cat, table_name, evict_cached_entries);
1914  }
1915 
1916  // todo(yoonmin) : allow per-table cache invalidation for the foreign table
1918 
1919  return ExecutionResult();
1920 }
1921 
1923  const DdlCommandData& ddl_data,
1924  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
1925  : DdlCommand(ddl_data, session_ptr) {
1926  if (!g_enable_fsi) {
1927  throw std::runtime_error("Unsupported command: ALTER FOREIGN TABLE");
1928  }
1929  auto& ddl_payload = extractPayload(ddl_data_);
1930  CHECK(ddl_payload.HasMember("tableName"));
1931  CHECK(ddl_payload["tableName"].IsString());
1932  CHECK(ddl_payload.HasMember("alterType"));
1933  CHECK(ddl_payload["alterType"].IsString());
1934  if (ddl_payload["alterType"] == "RENAME_TABLE") {
1935  CHECK(ddl_payload.HasMember("newTableName"));
1936  CHECK(ddl_payload["newTableName"].IsString());
1937  } else if (ddl_payload["alterType"] == "RENAME_COLUMN") {
1938  CHECK(ddl_payload.HasMember("oldColumnName"));
1939  CHECK(ddl_payload["oldColumnName"].IsString());
1940  CHECK(ddl_payload.HasMember("newColumnName"));
1941  CHECK(ddl_payload["newColumnName"].IsString());
1942  } else if (ddl_payload["alterType"] == "ALTER_OPTIONS") {
1943  CHECK(ddl_payload.HasMember("options"));
1944  CHECK(ddl_payload["options"].IsObject());
1945  } else {
1946  UNREACHABLE() << "Not a valid alter foreign table command: "
1947  << ddl_payload["alterType"].GetString();
1948  }
1949 }
1950 
1952  if (read_only_mode) {
1953  throw std::runtime_error("ALTER FOREIGN TABLE invalid in read only mode.");
1954  }
1955 
1956  auto& ddl_payload = extractPayload(ddl_data_);
1957  auto& catalog = session_ptr_->getCatalog();
1958  const std::string& table_name = ddl_payload["tableName"].GetString();
1959  auto [td, td_with_lock] =
1960  get_table_descriptor_with_lock<lockmgr::WriteLock>(catalog, table_name, false);
1961 
1963 
1964  if (!session_ptr_->checkDBAccessPrivileges(
1966  throw std::runtime_error(
1967  "Current user does not have the privilege to alter foreign table: " + table_name);
1968  }
1969 
1970  auto table_data_write_lock =
1972  auto foreign_table = dynamic_cast<const foreign_storage::ForeignTable*>(td);
1973  CHECK(foreign_table);
1974 
1975  std::string alter_type = ddl_payload["alterType"].GetString();
1976  if (alter_type == "RENAME_TABLE") {
1977  renameTable(foreign_table);
1978  } else if (alter_type == "RENAME_COLUMN") {
1979  renameColumn(foreign_table);
1980  } else if (alter_type == "ALTER_OPTIONS") {
1981  alterOptions(*foreign_table);
1982  }
1983 
1984  return ExecutionResult();
1985 }
1986 
1988  const foreign_storage::ForeignTable* foreign_table) {
1989  auto& ddl_payload = extractPayload(ddl_data_);
1990  auto& cat = session_ptr_->getCatalog();
1991  const std::string& table_name = ddl_payload["tableName"].GetString();
1992  const std::string& new_table_name = ddl_payload["newTableName"].GetString();
1993  if (cat.getForeignTable(new_table_name)) {
1994  throw std::runtime_error("Foreign table with name \"" + table_name +
1995  "\" can not be renamed to \"" + new_table_name + "\". " +
1996  "A different table with name \"" + new_table_name +
1997  "\" already exists.");
1998  }
1999  cat.renameTable(foreign_table, new_table_name);
2000 }
2001 
2003  const foreign_storage::ForeignTable* foreign_table) {
2004  auto& ddl_payload = extractPayload(ddl_data_);
2005  auto& cat = session_ptr_->getCatalog();
2006  const std::string& old_column_name = ddl_payload["oldColumnName"].GetString();
2007  const std::string& new_column_name = ddl_payload["newColumnName"].GetString();
2008  auto column = cat.getMetadataForColumn(foreign_table->tableId, old_column_name);
2009  if (!column) {
2010  throw std::runtime_error("Column with name \"" + old_column_name +
2011  "\" can not be renamed to \"" + new_column_name + "\". " +
2012  "Column with name \"" + old_column_name +
2013  "\" does not exist.");
2014  }
2015  if (cat.getMetadataForColumn(foreign_table->tableId, new_column_name)) {
2016  throw std::runtime_error("Column with name \"" + old_column_name +
2017  "\" can not be renamed to \"" + new_column_name + "\". " +
2018  "A column with name \"" + new_column_name +
2019  "\" already exists.");
2020  }
2021  cat.renameColumn(foreign_table, column, new_column_name);
2022 }
2023 
2025  const foreign_storage::ForeignTable& foreign_table) {
2026  auto& ddl_payload = extractPayload(ddl_data_);
2027  const std::string& table_name = ddl_payload["tableName"].GetString();
2028  auto& cat = session_ptr_->getCatalog();
2029  auto new_options_map =
2030  foreign_storage::ForeignTable::createOptionsMap(ddl_payload["options"]);
2031  foreign_table.validateSupportedOptionKeys(new_options_map);
2032  foreign_table.validateAlterOptions(new_options_map);
2033  cat.setForeignTableOptions(table_name, new_options_map, false);
2034 }
2035 
2037  const DdlCommandData& ddl_data,
2038  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2039  : DdlCommand(ddl_data, session_ptr) {
2040  auto& ddl_payload = extractPayload(ddl_data_);
2041  if (ddl_payload.HasMember("tableNames")) {
2042  CHECK(ddl_payload["tableNames"].IsArray());
2043  for (auto const& tablename_def : ddl_payload["tableNames"].GetArray()) {
2044  CHECK(tablename_def.IsString());
2045  }
2046  }
2047 }
2048 
2050  auto table_names = session_ptr_->get_catalog_ptr()->getTableNamesForUser(
2051  session_ptr_->get_currentUser(), GET_PHYSICAL_TABLES);
2052 
2053  auto& ddl_payload = extractPayload(ddl_data_);
2054  if (ddl_payload.HasMember("tableNames")) {
2055  std::vector<std::string> filtered_names;
2056  for (const auto& tablename_def : ddl_payload["tableNames"].GetArray()) {
2057  std::string filter_name = tablename_def.GetString();
2058  if (std::find(table_names.begin(), table_names.end(), filter_name) !=
2059  table_names.end()) {
2060  filtered_names.emplace_back(filter_name);
2061  } else {
2062  throw std::runtime_error("Can not show disk cache usage for table: " +
2063  filter_name + ". Table does not exist.");
2064  }
2065  }
2066  return filtered_names;
2067  } else {
2068  return table_names;
2069  }
2070 }
2071 
2073  // valid in read_only_mode
2074 
2075  auto cat_ptr = session_ptr_->get_catalog_ptr();
2076  auto table_names = getFilteredTableNames();
2077 
2078  const auto disk_cache = cat_ptr->getDataMgr().getPersistentStorageMgr()->getDiskCache();
2079  if (!disk_cache) {
2080  throw std::runtime_error{"Disk cache not enabled. Cannot show disk cache usage."};
2081  }
2082 
2083  // label_infos -> column labels
2084  std::vector<std::string> labels{"table name", "current cache size"};
2085  std::vector<TargetMetaInfo> label_infos;
2086  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
2087  label_infos.emplace_back(labels[1], SQLTypeInfo(kBIGINT, true));
2088 
2089  std::vector<RelLogicalValues::RowValues> logical_values;
2090 
2091  for (auto& table_name : table_names) {
2092  auto [td, td_with_lock] =
2093  get_table_descriptor_with_lock<lockmgr::ReadLock>(*cat_ptr, table_name, false);
2094 
2095  auto table_cache_size =
2096  disk_cache->getSpaceReservedByTable(cat_ptr->getDatabaseId(), td->tableId);
2097 
2098  // logical_values -> table data
2099  logical_values.emplace_back(RelLogicalValues::RowValues{});
2100  logical_values.back().emplace_back(genLiteralStr(table_name));
2101  logical_values.back().emplace_back(genLiteralBigInt(table_cache_size));
2102  }
2103 
2104  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
2105  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
2106 
2107  return ExecutionResult(rSet, label_infos);
2108 }
2109 
2111  const DdlCommandData& ddl_data,
2112  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2113  : DdlCommand(ddl_data, session_ptr) {
2114  auto& ddl_payload = extractPayload(ddl_data);
2115  if (ddl_payload.HasMember("userNames")) {
2116  CHECK(ddl_payload["userNames"].IsArray());
2117  for (const auto& user_name : ddl_payload["userNames"].GetArray()) {
2118  CHECK(user_name.IsString());
2119  }
2120  }
2121  CHECK(ddl_payload.HasMember("all"));
2122  CHECK(ddl_payload["all"].IsBool());
2123 }
2124 
2126  // valid in read_only_mode
2127 
2128  auto& ddl_payload = extractPayload(ddl_data_);
2129  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
2130 
2131  Catalog_Namespace::UserMetadata self = session_ptr_->get_currentUser();
2132  bool all = ddl_payload.HasMember("all") ? ddl_payload["all"].GetBool() : false;
2133  if (all && !self.isSuper) {
2134  throw std::runtime_error(
2135  "SHOW ALL USER DETAILS is only available to superusers. (Try SHOW USER "
2136  "DETAILS instead?)");
2137  }
2138 
2139  // label_infos -> column labels
2140  std::vector<TargetMetaInfo> label_infos;
2141  label_infos.emplace_back("NAME", SQLTypeInfo(kTEXT, true));
2142  label_infos.emplace_back("ID", SQLTypeInfo(kBIGINT, true));
2143  if (all) {
2144  label_infos.emplace_back("IS_SUPER", SQLTypeInfo(kBOOLEAN, true));
2145  }
2146  label_infos.emplace_back("DEFAULT_DB", SQLTypeInfo(kTEXT, true));
2147  if (self.isSuper) {
2148  label_infos.emplace_back("CAN_LOGIN", SQLTypeInfo(kBOOLEAN, true));
2149  }
2150  std::vector<RelLogicalValues::RowValues> logical_values;
2151 
2152  auto cat = session_ptr_->get_catalog_ptr();
2153  DBObject dbObject(cat->name(), DatabaseDBObjectType);
2154  dbObject.loadKey();
2155  dbObject.setPrivileges(AccessPrivileges::ACCESS);
2156 
2157  std::map<std::string, Catalog_Namespace::UserMetadata> user_map;
2158  auto user_list = !all ? sys_cat.getAllUserMetadata(cat->getDatabaseId())
2159  : sys_cat.getAllUserMetadata();
2160  for (auto& user : user_list) {
2161  if (user.can_login || self.isSuper) { // hide users who have disabled accounts
2162  user_map[user.userName] = user;
2163  }
2164  }
2165 
2166  if (ddl_payload.HasMember("userNames")) {
2167  std::map<std::string, Catalog_Namespace::UserMetadata> user_map2;
2168  for (const auto& user_name_json : ddl_payload["userNames"].GetArray()) {
2169  std::string user_name = user_name_json.GetString();
2170  auto uit = user_map.find(user_name);
2171  if (uit == user_map.end()) {
2172  throw std::runtime_error("User \"" + user_name + "\" not found. ");
2173  }
2174  user_map2[uit->first] = uit->second;
2175  }
2176  user_map = user_map2;
2177  }
2178 
2179  Catalog_Namespace::DBSummaryList dbsums = sys_cat.getDatabaseListForUser(self);
2180  std::unordered_set<std::string> visible_databases;
2181  if (!self.isSuper) {
2182  for (const auto& dbsum : dbsums) {
2183  visible_databases.insert(dbsum.dbName);
2184  }
2185  }
2186 
2187  for (const auto& [user_name, user] : user_map) {
2188  // database
2189  std::string dbname;
2191  if (sys_cat.getMetadataForDBById(user.defaultDbId, db)) {
2192  if (self.isSuper || visible_databases.count(db.dbName)) {
2193  dbname = db.dbName;
2194  }
2195  }
2196  if (self.isSuper) {
2197  dbname += "(" + std::to_string(user.defaultDbId) + ")";
2198  }
2199 
2200  // logical_values -> table data
2201  logical_values.emplace_back(RelLogicalValues::RowValues{});
2202  logical_values.back().emplace_back(genLiteralStr(user.userName));
2203  logical_values.back().emplace_back(genLiteralBigInt(user.userId));
2204  if (all) {
2205  logical_values.back().emplace_back(genLiteralBoolean(user.isSuper));
2206  }
2207  logical_values.back().emplace_back(genLiteralStr(dbname));
2208  if (self.isSuper) {
2209  logical_values.back().emplace_back(genLiteralBoolean(user.can_login));
2210  }
2211  }
2212 
2213  // Create ResultSet
2214  CHECK_EQ(logical_values.size(), user_map.size());
2215  if (logical_values.size() >= 1U) {
2216  CHECK_EQ(logical_values[0].size(), label_infos.size());
2217  }
2218  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
2219  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
2220 
2221  return ExecutionResult(rSet, label_infos);
2222 }
2223 
2225  const DdlCommandData& ddl_data,
2226  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2227  : DdlCommand(ddl_data, session_ptr) {
2228  auto& ddl_payload = extractPayload(ddl_data);
2229  CHECK(ddl_payload["userName"].IsString());
2230  CHECK(ddl_payload["effective"].IsBool());
2231 }
2232 
2234  // valid in read_only_mode
2235 
2236  auto& ddl_payload = extractPayload(ddl_data_);
2237  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
2238 
2239  // label_infos -> column labels
2240  std::vector<TargetMetaInfo> label_infos;
2241  std::vector<std::string> labels{"ROLES"};
2242  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
2243 
2244  // logical_values -> table data
2245  std::vector<RelLogicalValues::RowValues> logical_values;
2246  std::vector<std::string> roles_list;
2247  Catalog_Namespace::UserMetadata self = session_ptr_->get_currentUser();
2248  std::string user_name = ddl_payload["userName"].GetString();
2249  bool effective = ddl_payload["effective"].GetBool();
2250  if (user_name.empty()) {
2251  user_name = self.userName;
2252  }
2254  bool is_user = sys_cat.getMetadataForUser(user_name, user);
2255  if (!self.isSuper) {
2256  if (is_user) {
2257  if (self.userId != user.userId) {
2258  throw std::runtime_error(
2259  "Only a superuser is authorized to request list of roles granted to another "
2260  "user.");
2261  }
2262  } else {
2263  if (!sys_cat.isRoleGrantedToGrantee(
2264  self.userName, user_name, /*only_direct=*/false)) {
2265  throw std::runtime_error(
2266  "Only a superuser is authorized to request list of roles granted to a role "
2267  "they don't have.");
2268  }
2269  }
2270  }
2271  if (user.isSuper) {
2272  auto s = sys_cat.getCreatedRoles();
2273  roles_list.insert(roles_list.end(), s.begin(), s.end());
2274  } else {
2275  roles_list = sys_cat.getRoles(user_name, effective);
2276  }
2277  for (const std::string& role_name : roles_list) {
2278  logical_values.emplace_back(RelLogicalValues::RowValues{});
2279  logical_values.back().emplace_back(genLiteralStr(role_name));
2280  }
2281 
2282  // Create ResultSet
2283  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
2284  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
2285 
2286  return ExecutionResult(rSet, label_infos);
2287 }
2288 
2290  const DdlCommandData& ddl_data,
2291  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2292  : DdlCommand(ddl_data, session_ptr) {
2293  auto& ddl_payload = extractPayload(ddl_data_);
2294  CHECK(ddl_payload.HasMember("oldOwners"));
2295  CHECK(ddl_payload["oldOwners"].IsArray());
2296  for (const auto& old_owner : ddl_payload["oldOwners"].GetArray()) {
2297  CHECK(old_owner.IsString());
2298  old_owners_.emplace(old_owner.GetString());
2299  }
2300  CHECK(ddl_payload.HasMember("newOwner"));
2301  CHECK(ddl_payload["newOwner"].IsString());
2302  new_owner_ = ddl_payload["newOwner"].GetString();
2303 }
2304 
2306  if (read_only_mode) {
2307  throw std::runtime_error("REASSIGN OWNER invalid in read only mode.");
2308  }
2309  if (!session_ptr_->get_currentUser().isSuper) {
2310  throw std::runtime_error{
2311  "Only super users can reassign ownership of database objects."};
2312  }
2313  const auto catalog = session_ptr_->get_catalog_ptr();
2314  catalog->reassignOwners(old_owners_, new_owner_);
2315  return ExecutionResult();
2316 }
static std::shared_ptr< WrapperType< MutexType > > getMutex(const LockType lockType, const KeyType &key)
bool contains(const T &container, const U &element)
Definition: misc.h:195
int32_t maxRollbackEpochs
ShowForeignServersCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static constexpr const char * WS_SERVER_ACCESS_LOGS_SYS_TABLE_NAME
Definition: Catalog.h:117
ExecutionResult execute(bool read_only_mode) override
#define CHECK_EQ(x, y)
Definition: Logger.h:230
std::string partitions
ShowRolesCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static constexpr const char * SERVER_LOGS_SYS_TABLE_NAME
Definition: Catalog.h:114
ExecutionResult execute(bool read_only_mode) override
AlterForeignServerCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static std::vector< TableFunction > get_table_funcs()
void alterOptions(const foreign_storage::ForeignTable &foreign_table)
const std::string getTargetQuerySessionToKill() const
declare this class scoped local to avoid exposing rapidjson in the header file
static WriteLock getWriteLockForTable(Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:225
ShowCreateTableCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static const AccessPrivileges DROP_SERVER
Definition: DBObject.h:189
std::string cat(Ts &&...args)
ShowCreateServerCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
std::unique_ptr< DdlCommandData > ddl_data_
std::string getOptionsAsJsonString() const
static std::vector< ExtensionFunction > get_ext_funcs(const std::string &name)
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:132
Definition: sqltypes.h:49
SQLTypes
Definition: sqltypes.h:38
const std::string commandStr() const
std::string tableName
ExecutionResult execute(bool read_only_mode) override
static const AccessPrivileges ALTER_TABLE
Definition: DBObject.h:165
CreateForeignServerCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
Data_Namespace::DataMgr & getDataMgr() const
Definition: Catalog.h:243
void validateAlterOptions(const OptionsMap &options_map) const
Verifies that the given options map only contains options that can be legally altered.
ExecutionResult execute(bool read_only_mode) override
#define NULL_BIGINT
ShowDatabasesCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
ExecutionResult execute(bool read_only_mode) override
ExecutionResult execute(bool read_only_mode) override
std::string storageType
void revokeDBObjectPrivilegesFromAll(DBObject object, Catalog *catalog)
static const AccessPrivileges SERVER_USAGE
Definition: DBObject.h:191
static std::shared_ptr< QueryState > create(ARGS &&...args)
Definition: QueryState.h:145
std::string join(T const &container, std::string const &delim)
DropForeignTableCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
#define UNREACHABLE()
Definition: Logger.h:266
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:112
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)
ExecutionResult execute(bool read_only_mode) override
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)
DistributedExecutionDetails getDistributedExecutionDetails() const
std::pair< std::string, std::string > getSessionParameter() const
ExecutionResult execute(bool read_only_mode) override
void validate_non_duplicate_column(const std::string &column_name, std::unordered_set< std::string > &upper_column_names)
Definition: DdlUtils.cpp:676
ExecutionResult execute(bool read_only_mode) override
std::set< std::string > old_owners_
static constexpr const char * REQUEST_LOGS_SYS_TABLE_NAME
Definition: Catalog.h:115
void set_column_descriptor(const std::string &column_name, ColumnDescriptor &cd, SqlType *column_type, const bool not_null, const Encoding *encoding, const std::string *default_value)
Definition: DdlUtils.cpp:646
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:190
std::unique_ptr< RexLiteral > genLiteralBigInt(int64_t val)
This file contains the class specification and related data structures for Catalog.
ExecutionResult execute(bool read_only_mode) override
void setTableDetails(const std::string &table_name, TableDescriptor &td, const std::list< ColumnDescriptor > &columns)
bool isAlterSystemClear() const
ExecutionResult execute(bool read_only_mode) override
const DdlCommandData & ddl_data_
bool is_default_server(const std::string &server_name)
static SysCatalog & instance()
Definition: SysCatalog.h:337
This file contains the class specification and related data structures for SysCatalog.
Classes representing a parse tree.
ExecutionResult execute(bool read_only_mode) override
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:159
std::optional< uint64_t > total_free_metadata_page_count
Definition: FileMgr.h:108
ExecutionResult execute(bool read_only_mode) override
void populateOptionsMap(OptionsMap &&options_map, bool clear=false)
const rapidjson::Value & extractPayload(const DdlCommandData &ddl_data)
static std::unordered_set< std::string > get_udfs_name(const bool is_runtime)
std::unique_ptr< RexLiteral > genLiteralTimestamp(time_t val)
bool isShowUserSessions() const
std::unique_lock< T > unique_lock
ExecutionResult execute(bool read_only_mode) override
DBSummaryList getDatabaseListForUser(const UserMetadata &user)
bool g_enable_watchdog
int getDatabaseId() const
Definition: Catalog.h:298
uint64_t total_metadata_page_count
Definition: FileMgr.h:107
static const AccessPrivileges CREATE_SERVER
Definition: DBObject.h:188
void updateResultSet(const std::string &query_ra, RType type, bool success=true)
std::unique_ptr< RexLiteral > genLiteralBoolean(bool val)
void validate_non_reserved_keyword(const std::string &column_name)
Definition: DdlUtils.cpp:685
specifies the content in-memory of a row in the column metadata table
OUTPUT transform(INPUT const &input, FUNC const &func)
Definition: misc.h:296
static const AccessPrivileges CREATE_TABLE
Definition: DBObject.h:158
std::vector< const TableDescriptor * > getPhysicalTablesDescriptors(const TableDescriptor *logical_table_desc, bool populate_fragmenter=true) const
Definition: Catalog.cpp:4601
std::string keyMetainfo
ExecutionResult execute(bool read_only_mode) override
void set_default_table_attributes(const std::string &table_name, TableDescriptor &td, const int32_t column_count)
Definition: DdlUtils.cpp:662
File_Namespace::GlobalFileMgr * getGlobalFileMgr() const
Definition: DataMgr.cpp:609
std::string to_upper(const std::string &str)
static ResultSet * create(std::vector< TargetMetaInfo > &label_infos, std::vector< RelLogicalValues::RowValues > &logical_values)
void loadKey()
Definition: DBObject.cpp:190
bool isAlterSessionSet() const
Definition: sqltypes.h:52
Definition: sqltypes.h:53
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)
ExecutionResult execute(bool read_only_mode)
AggregratedStorageStats get_agg_storage_stats(const TableDescriptor *td, const Catalog_Namespace::Catalog *catalog)
ExecutionResult execute(bool read_only_mode) override
uint64_t total_metadata_file_size
Definition: FileMgr.h:106
static ReadLock getReadLockForTable(Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:243
ExecutionResult execute(bool read_only_mode) override
Basic constructors and methods of the row set interface.
std::tuple< const TableDescriptor *, std::unique_ptr< lockmgr::TableSchemaLockContainer< LockType > > > get_table_descriptor_with_lock(Catalog_Namespace::Catalog &cat, const std::string &table_name, const bool populate_fragmenter)
static const AccessPrivileges ACCESS
Definition: DBObject.h:153
ReassignOwnedCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
std::vector< std::string > getFilteredTableNames()
static std::unique_ptr< RexLiteral > genLiteralStr(std::string val)
Definition: DBHandler.cpp:7522
std::string returnCacheType() const
void validate_table_type(const TableDescriptor *td, const TableType expected_table_type, const std::string &command)
Definition: DdlUtils.cpp:693
const ForeignServer * foreign_server
Definition: ForeignTable.h:56
void renameTable(const foreign_storage::ForeignTable *foreign_table)
ShowFunctionsCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
#define CHECK(condition)
Definition: Logger.h:222
ExecutionResult execute(bool read_only_mode) override
ExecutionResult execute(bool read_only_mode) override
std::list< DBSummary > DBSummaryList
Definition: SysCatalog.h:145
std::string viewSQL
Definition: sqltypes.h:45
AggregratedStorageStats(const File_Namespace::StorageStats &storage_stats)
std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr_
std::vector< std::unique_ptr< const RexScalar >> RowValues
Definition: RelAlgDag.h:2176
ExecutionResult execute(bool read_only_mode) override
ExecutionLocation execution_location
string name
Definition: setup.in.py:72
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)
const std::array< std::string, 3 > kReservedServerPrefixes
static constexpr char const * FOREIGN_TABLE
bool g_enable_fsi
Definition: Catalog.cpp:96
ShowRuntimeFunctionsCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static constexpr const char * WS_SERVER_LOGS_SYS_TABLE_NAME
Definition: Catalog.h:116
ShowUserDetailsCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
#define IS_GEO(T)
Definition: sqltypes.h:251
#define VLOG(n)
Definition: Logger.h:316
std::atomic< bool > isSuper
Definition: SysCatalog.h:107
static std::unique_ptr< Parser::DDLStmt > delegate(const rapidjson::Value &payload)
ShowRuntimeTableFunctionsCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
RefreshForeignTablesCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
ExecutionResult execute(bool read_only_mode) override
ShowTableFunctionsCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)