OmniSciDB  c0231cc57d
 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_ == "CREATE_USER") {
397  auto create_user_stmt = Parser::CreateUserStmt(extractPayload(*ddl_data_));
398  create_user_stmt.execute(*session_ptr_, read_only_mode);
399  return result;
400  } else if (ddl_command_ == "DROP_USER") {
401  auto drop_user_stmt = Parser::DropUserStmt(extractPayload(*ddl_data_));
402  drop_user_stmt.execute(*session_ptr_, read_only_mode);
403  return result;
404  } else if (ddl_command_ == "ALTER_USER") {
405  auto alter_user_stmt = Parser::AlterUserStmt(extractPayload(*ddl_data_));
406  alter_user_stmt.execute(*session_ptr_, read_only_mode);
407  return result;
408  } else if (ddl_command_ == "RENAME_USER") {
409  auto rename_user_stmt = Parser::RenameUserStmt(extractPayload(*ddl_data_));
410  rename_user_stmt.execute(*session_ptr_, read_only_mode);
411  return result;
412  } else if (ddl_command_ == "CREATE_ROLE") {
413  auto create_role_stmt = Parser::CreateRoleStmt(extractPayload(*ddl_data_));
414  create_role_stmt.execute(*session_ptr_, read_only_mode);
415  return result;
416  } else if (ddl_command_ == "DROP_ROLE") {
417  auto drop_role_stmt = Parser::DropRoleStmt(extractPayload(*ddl_data_));
418  drop_role_stmt.execute(*session_ptr_, read_only_mode);
419  return result;
420  } else if (ddl_command_ == "GRANT_ROLE") {
421  auto grant_role_stmt = Parser::GrantRoleStmt(extractPayload(*ddl_data_));
422  grant_role_stmt.execute(*session_ptr_, read_only_mode);
423  return result;
424  } else if (ddl_command_ == "REVOKE_ROLE") {
425  auto revoke_role_stmt = Parser::RevokeRoleStmt(extractPayload(*ddl_data_));
426  revoke_role_stmt.execute(*session_ptr_, read_only_mode);
427  return result;
428  } else if (ddl_command_ == "GRANT_PRIVILEGE") {
429  auto grant_privilege_stmt = Parser::GrantPrivilegesStmt(extractPayload(*ddl_data_));
430  grant_privilege_stmt.execute(*session_ptr_, read_only_mode);
431  return result;
432  } else if (ddl_command_ == "REVOKE_PRIVILEGE") {
433  auto revoke_privileges_stmt =
435  revoke_privileges_stmt.execute(*session_ptr_, read_only_mode);
436  return result;
437  } else if (ddl_command_ == "CREATE_DATAFRAME") {
438  auto create_dataframe_stmt = Parser::CreateDataframeStmt(extractPayload(*ddl_data_));
439  create_dataframe_stmt.execute(*session_ptr_, read_only_mode);
440  return result;
441  } else if (ddl_command_ == "VALIDATE_SYSTEM") {
442  // VALIDATE should have been excuted in outer context before it reaches here
443  UNREACHABLE();
444  } else if (ddl_command_ == "REFRESH_FOREIGN_TABLES") {
445  result =
446  RefreshForeignTablesCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
447  return result;
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_DATABASE") {
491  result = AlterDatabaseCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
492  } else if (ddl_command_ == "ALTER_FOREIGN_TABLE") {
493  result = AlterForeignTableCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
494  } else if (ddl_command_ == "SHOW_DISK_CACHE_USAGE") {
495  result = ShowDiskCacheUsageCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
496  } else if (ddl_command_ == "SHOW_USER_DETAILS") {
497  result = ShowUserDetailsCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
498  } else if (ddl_command_ == "SHOW_ROLES") {
499  result = ShowRolesCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
500  } else if (ddl_command_ == "REASSIGN_OWNED") {
501  result = ReassignOwnedCommand{*ddl_data_, session_ptr_}.execute(read_only_mode);
502  } else {
503  throw std::runtime_error("Unsupported DDL command");
504  }
505 
506  return result;
507 }
508 
510  return (ddl_command_ == "SHOW_USER_SESSIONS");
511 }
512 
514  return (ddl_command_ == "SHOW_QUERIES");
515 }
516 
518  return (ddl_command_ == "KILL_QUERY");
519 }
520 
522  return (ddl_command_ == "ALTER_SYSTEM_CLEAR");
523 }
524 
526  return (ddl_command_ == "ALTER_SESSION_SET");
527 }
528 
529 std::pair<std::string, std::string> DdlCommandExecutor::getSessionParameter() const {
530  enum SetParameterType { String_t, Numeric_t };
531  static const std::unordered_map<std::string, SetParameterType>
532  session_set_parameters_map = {{"EXECUTOR_DEVICE", SetParameterType::String_t},
533  {"CURRENT_DATABASE", SetParameterType::String_t}};
534 
535  auto& ddl_payload = extractPayload(*ddl_data_);
536  CHECK(ddl_payload.HasMember("sessionParameter"));
537  CHECK(ddl_payload["sessionParameter"].IsString());
538  CHECK(ddl_payload.HasMember("parameterValue"));
539  CHECK(ddl_payload["parameterValue"].IsString());
540  std::string parameter_name = to_upper(ddl_payload["sessionParameter"].GetString());
541  std::string parameter_value = ddl_payload["parameterValue"].GetString();
542 
543  const auto param_it = session_set_parameters_map.find(parameter_name);
544  if (param_it == session_set_parameters_map.end()) {
545  throw std::runtime_error(parameter_name + " is not a settable session parameter.");
546  }
547  if (param_it->second == SetParameterType::Numeric_t) {
548  if (!std::regex_match(parameter_value, std::regex("[(-|+)|][0-9]+"))) {
549  throw std::runtime_error("The value of session parameter " + param_it->first +
550  " should be a numeric.");
551  }
552  }
553  return {parameter_name, parameter_value};
554 }
555 
557  CHECK(ddl_command_ == "ALTER_SYSTEM_CLEAR");
558  auto& ddl_payload = extractPayload(*ddl_data_);
559  CHECK(ddl_payload.HasMember("cacheType"));
560  CHECK(ddl_payload["cacheType"].IsString());
561  return ddl_payload["cacheType"].GetString();
562 }
563 
565  DistributedExecutionDetails execution_details;
566  if (ddl_command_ == "CREATE_DATAFRAME" || ddl_command_ == "RENAME_TABLE" ||
567  ddl_command_ == "ALTER_TABLE" || ddl_command_ == "CREATE_TABLE" ||
568  ddl_command_ == "DROP_TABLE" || ddl_command_ == "TRUNCATE_TABLE" ||
569  ddl_command_ == "DUMP_TABLE" || ddl_command_ == "RESTORE_TABLE" ||
570  ddl_command_ == "OPTIMIZE_TABLE" || ddl_command_ == "CREATE_VIEW" ||
571  ddl_command_ == "DROP_VIEW" || ddl_command_ == "CREATE_DB" ||
572  ddl_command_ == "DROP_DB" || ddl_command_ == "ALTER_DATABASE" ||
573  ddl_command_ == "CREATE_USER" || ddl_command_ == "DROP_USER" ||
574  ddl_command_ == "ALTER_USER" || ddl_command_ == "RENAME_USER" ||
575  ddl_command_ == "CREATE_ROLE" || ddl_command_ == "DROP_ROLE" ||
576  ddl_command_ == "GRANT_ROLE" || ddl_command_ == "REVOKE_ROLE" ||
577  ddl_command_ == "REASSIGN_OWNED" || ddl_command_ == "CREATE_POLICY" ||
578  ddl_command_ == "DROP_POLICY" || ddl_command_ == "CREATE_SERVER" ||
579  ddl_command_ == "DROP_SERVER" || ddl_command_ == "CREATE_FOREIGN_TABLE" ||
580  ddl_command_ == "DROP_FOREIGN_TABLE" || ddl_command_ == "CREATE_USER_MAPPING" ||
581  ddl_command_ == "DROP_USER_MAPPING" || ddl_command_ == "ALTER_FOREIGN_TABLE" ||
582  ddl_command_ == "ALTER_SERVER" || ddl_command_ == "REFRESH_FOREIGN_TABLES" ||
583  ddl_command_ == "ALTER_SYSTEM_CLEAR") {
584  // group user/role/db commands
586  execution_details.aggregation_type = AggregationType::NONE;
587  } else if (ddl_command_ == "GRANT_PRIVILEGE" || ddl_command_ == "REVOKE_PRIVILEGE") {
588  auto& ddl_payload = extractPayload(*ddl_data_);
589  CHECK(ddl_payload.HasMember("type"));
590  const std::string& targetType = ddl_payload["type"].GetString();
591  if (targetType == "DASHBOARD") {
592  // dashboard commands should run on Aggregator alone
594  execution_details.aggregation_type = AggregationType::NONE;
595  } else {
597  execution_details.aggregation_type = AggregationType::NONE;
598  }
599 
600  } else if (ddl_command_ == "SHOW_TABLE_DETAILS" ||
601  ddl_command_ == "SHOW_DISK_CACHE_USAGE") {
603  execution_details.aggregation_type = AggregationType::UNION;
604  } else {
605  // Commands that fall here : COPY_TABLE, EXPORT_QUERY, etc.
607  execution_details.aggregation_type = AggregationType::NONE;
608  }
609  return execution_details;
610 }
611 
613  // caller should check whether DDL indicates KillQuery request
614  // i.e., use isKillQuery() before calling this function
615  auto& ddl_payload = extractPayload(*ddl_data_);
616  CHECK(isKillQuery());
617  CHECK(ddl_payload.HasMember("querySession"));
618  const std::string& query_session = ddl_payload["querySession"].GetString();
619  // regex matcher for public_session: start_time{3}-session_id{4} (Example:819-4RDo)
620  boost::regex session_id_regex{R"([0-9]{3}-[a-zA-Z0-9]{4})",
621  boost::regex::extended | boost::regex::icase};
622  if (!boost::regex_match(query_session, session_id_regex)) {
623  throw std::runtime_error(
624  "Please provide the correct session ID of the query that you want to interrupt.");
625  }
626  return query_session;
627 }
628 
629 const std::string DdlCommandExecutor::commandStr() const {
630  return ddl_command_;
631 }
632 
633 namespace {
634 const std::array<std::string, 3> kReservedServerPrefixes{"default", "system", "internal"};
635 
636 bool is_default_server(const std::string& server_name) {
637  return std::any_of(kReservedServerPrefixes.begin(),
639  [&server_name](const std::string& reserved_prefix) {
640  return boost::istarts_with(server_name, reserved_prefix);
641  });
642 }
643 
645  std::string error_message{"Foreign server names cannot start with "};
646  for (size_t i = 0; i < kReservedServerPrefixes.size(); i++) {
647  if (i > 0) {
648  error_message += ", ";
649  }
650  if (i == kReservedServerPrefixes.size() - 1) {
651  error_message += "or ";
652  }
653  error_message += "\"" + kReservedServerPrefixes[i] + "\"";
654  }
655  error_message += ".";
656  throw std::runtime_error{error_message};
657 }
658 } // namespace
659 
661  const DdlCommandData& ddl_data,
662  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
663  : DdlCommand(ddl_data, session_ptr) {
664  if (!g_enable_fsi) {
665  throw std::runtime_error("Unsupported command: CREATE FOREIGN SERVER");
666  }
667  auto& ddl_payload = extractPayload(ddl_data_);
668  CHECK(ddl_payload.HasMember("serverName"));
669  CHECK(ddl_payload["serverName"].IsString());
670  CHECK(ddl_payload.HasMember("dataWrapper"));
671  CHECK(ddl_payload["dataWrapper"].IsString());
672  if (ddl_payload.HasMember("options")) {
673  CHECK(ddl_payload["options"].IsObject());
674  }
675  CHECK(ddl_payload.HasMember("ifNotExists"));
676  CHECK(ddl_payload["ifNotExists"].IsBool());
677 }
678 
681 
682  if (read_only_mode) {
683  throw std::runtime_error("CREATE FOREIGN SERVER invalid in read only mode.");
684  }
685  auto& ddl_payload = extractPayload(ddl_data_);
686  std::string server_name = ddl_payload["serverName"].GetString();
687  if (is_default_server(server_name)) {
689  }
690  bool if_not_exists = ddl_payload["ifNotExists"].GetBool();
691  if (session_ptr_->getCatalog().getForeignServer(server_name)) {
692  if (if_not_exists) {
693  return result;
694  } else {
695  throw std::runtime_error{"A foreign server with name \"" + server_name +
696  "\" already exists."};
697  }
698  }
699  // check access privileges
700  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::ServerDBObjectType,
702  throw std::runtime_error("Server " + std::string(server_name) +
703  " will not be created. User has no create privileges.");
704  }
705 
706  auto& current_user = session_ptr_->get_currentUser();
707  auto foreign_server = std::make_unique<foreign_storage::ForeignServer>();
708  foreign_server->data_wrapper_type = to_upper(ddl_payload["dataWrapper"].GetString());
709  foreign_server->name = server_name;
710  foreign_server->user_id = current_user.userId;
711  if (ddl_payload.HasMember("options")) {
712  foreign_server->populateOptionsMap(ddl_payload["options"]);
713  }
714  foreign_server->validate();
715 
716  auto& catalog = session_ptr_->getCatalog();
717  catalog.createForeignServer(std::move(foreign_server),
718  ddl_payload["ifNotExists"].GetBool());
720  current_user, server_name, ServerDBObjectType, catalog);
721 
722  return result;
723 }
724 
726  const DdlCommandData& ddl_data,
727  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
728  : DdlCommand(ddl_data, session_ptr) {
729  auto& ddl_payload = extractPayload(ddl_data_);
730  CHECK(ddl_payload.HasMember("databaseName"));
731  CHECK(ddl_payload["databaseName"].IsString());
732  CHECK(ddl_payload.HasMember("alterType"));
733  CHECK(ddl_payload["alterType"].IsString());
734  if (ddl_payload["alterType"] == "RENAME_DATABASE") {
735  CHECK(ddl_payload.HasMember("newDatabaseName"));
736  CHECK(ddl_payload["newDatabaseName"].IsString());
737  } else if (ddl_payload["alterType"] == "CHANGE_OWNER") {
738  CHECK(ddl_payload.HasMember("newOwner"));
739  CHECK(ddl_payload["newOwner"].IsString());
740  } else {
741  UNREACHABLE(); // not-implemented alterType
742  }
743 }
744 
746  if (read_only_mode) {
747  throw std::runtime_error("ALTER DATABASE invalid in read only mode.");
748  }
749  auto& ddl_payload = extractPayload(ddl_data_);
750  std::string databaseName = ddl_payload["databaseName"].GetString();
751 
752  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
754  if (!sys_cat.getMetadataForDB(databaseName, db)) {
755  throw std::runtime_error("Database " + databaseName + " does not exists.");
756  }
757 
758  std::string alter_type = ddl_payload["alterType"].GetString();
759  if (alter_type == "CHANGE_OWNER") {
760  changeOwner();
761  } else if (alter_type == "RENAME_DATABASE") {
762  rename();
763  }
764 
765  return ExecutionResult();
766 }
767 
769  auto& ddl_payload = extractPayload(ddl_data_);
770  std::string database_name = ddl_payload["databaseName"].GetString();
771  std::string new_database_name = ddl_payload["newDatabaseName"].GetString();
772 
774  CHECK(Catalog_Namespace::SysCatalog::instance().getMetadataForDB(database_name, db));
775 
776  if (!session_ptr_->get_currentUser().isSuper &&
777  session_ptr_->get_currentUser().userId != db.dbOwner) {
778  throw std::runtime_error("Only a super user or the owner can rename the database.");
779  }
780 
782  new_database_name);
783 }
784 
786  auto& ddl_payload = extractPayload(ddl_data_);
787  std::string database_name = ddl_payload["databaseName"].GetString();
788  std::string new_owner = ddl_payload["newOwner"].GetString();
789  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
790  if (!session_ptr_->get_currentUser().isSuper) {
791  throw std::runtime_error(
792  "Only a super user can change a database's owner. "
793  "Current user is not a super-user. "
794  "Database with name \"" +
795  database_name + "\" will not have owner changed.");
796  }
797 
798  sys_cat.changeDatabaseOwner(database_name, new_owner);
799 }
800 
802  const DdlCommandData& ddl_data,
803  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
804  : DdlCommand(ddl_data, session_ptr) {
805  if (!g_enable_fsi) {
806  throw std::runtime_error("Unsupported command: ALTER FOREIGN SERVER");
807  }
808  auto& ddl_payload = extractPayload(ddl_data_);
809  CHECK(ddl_payload.HasMember("serverName"));
810  CHECK(ddl_payload["serverName"].IsString());
811  CHECK(ddl_payload.HasMember("alterType"));
812  CHECK(ddl_payload["alterType"].IsString());
813  if (ddl_payload["alterType"] == "SET_OPTIONS") {
814  CHECK(ddl_payload.HasMember("options"));
815  CHECK(ddl_payload["options"].IsObject());
816  } else if (ddl_payload["alterType"] == "SET_DATA_WRAPPER") {
817  CHECK(ddl_payload.HasMember("dataWrapper"));
818  CHECK(ddl_payload["dataWrapper"].IsString());
819  } else if (ddl_payload["alterType"] == "RENAME_SERVER") {
820  CHECK(ddl_payload.HasMember("newServerName"));
821  CHECK(ddl_payload["newServerName"].IsString());
822  } else if (ddl_payload["alterType"] == "CHANGE_OWNER") {
823  CHECK(ddl_payload.HasMember("newOwner"));
824  CHECK(ddl_payload["newOwner"].IsString());
825  } else {
826  UNREACHABLE(); // not-implemented alterType
827  }
828 }
829 
831  if (read_only_mode) {
832  throw std::runtime_error("ALTER FOREIGN SERVER invalid in read only mode.");
833  }
834  auto& ddl_payload = extractPayload(ddl_data_);
835  std::string server_name = ddl_payload["serverName"].GetString();
836  if (is_default_server(server_name)) {
837  throw std::runtime_error{"Default servers cannot be altered."};
838  }
839  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
840  throw std::runtime_error{"Foreign server with name \"" + server_name +
841  "\" does not exist and can not be altered."};
842  }
843  if (!hasAlterServerPrivileges()) {
844  throw std::runtime_error("Server " + server_name +
845  " can not be altered. User has no ALTER SERVER privileges.");
846  }
847  std::string alter_type = ddl_payload["alterType"].GetString();
848  if (alter_type == "CHANGE_OWNER") {
850  } else if (alter_type == "SET_DATA_WRAPPER") {
852  } else if (alter_type == "SET_OPTIONS") {
854  } else if (alter_type == "RENAME_SERVER") {
856  }
857 
858  return ExecutionResult();
859 }
860 
862  auto& ddl_payload = extractPayload(ddl_data_);
863  std::string server_name = ddl_payload["serverName"].GetString();
864  std::string new_owner = ddl_payload["newOwner"].GetString();
865  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
866  if (!session_ptr_->get_currentUser().isSuper) {
867  throw std::runtime_error(
868  "Only a super user can change a foreign server's owner. "
869  "Current user is not a super-user. "
870  "Foreign server with name \"" +
871  server_name + "\" will not have owner changed.");
872  }
873  Catalog_Namespace::UserMetadata user, original_owner;
874  if (!sys_cat.getMetadataForUser(new_owner, user)) {
875  throw std::runtime_error("User with username \"" + new_owner + "\" does not exist. " +
876  "Foreign server with name \"" + server_name +
877  "\" can not have owner changed.");
878  }
879  auto& cat = session_ptr_->getCatalog();
880  // get original owner metadata
881  bool original_owner_exists = sys_cat.getMetadataForUserById(
882  cat.getForeignServer(server_name)->user_id, original_owner);
883  // update catalog
884  cat.changeForeignServerOwner(server_name, user.userId);
885  try {
886  // update permissions
887  DBObject db_object(server_name, DBObjectType::ServerDBObjectType);
888  sys_cat.changeDBObjectOwnership(
889  user, original_owner, db_object, cat, original_owner_exists);
890  } catch (const std::runtime_error& e) {
891  // update permissions failed, revert catalog update
892  cat.changeForeignServerOwner(server_name, original_owner.userId);
893  throw;
894  }
895 }
896 
898  auto& ddl_payload = extractPayload(ddl_data_);
899  std::string server_name = ddl_payload["serverName"].GetString();
900  std::string new_server_name = ddl_payload["newServerName"].GetString();
901  if (is_default_server(new_server_name)) {
903  }
904  auto& cat = session_ptr_->getCatalog();
905  // check for a conflicting server
906  if (cat.getForeignServer(new_server_name)) {
907  throw std::runtime_error("Foreign server with name \"" + server_name +
908  "\" can not be renamed to \"" + new_server_name + "\"." +
909  "Foreign server with name \"" + new_server_name +
910  "\" exists.");
911  }
912  // update catalog
913  cat.renameForeignServer(server_name, new_server_name);
914  try {
915  // migrate object privileges
916  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
917  sys_cat.renameDBObject(server_name,
918  new_server_name,
920  cat.getForeignServer(new_server_name)->id,
921  cat);
922  } catch (const std::runtime_error& e) {
923  // permission migration failed, revert catalog update
924  cat.renameForeignServer(new_server_name, server_name);
925  throw;
926  }
927 }
928 
930  auto& ddl_payload = extractPayload(ddl_data_);
931  std::string server_name = ddl_payload["serverName"].GetString();
932  auto& cat = session_ptr_->getCatalog();
933  // update catalog
934  const auto foreign_server = cat.getForeignServer(server_name);
936  opt.populateOptionsMap(foreign_server->getOptionsAsJsonString());
937  opt.populateOptionsMap(ddl_payload["options"]);
938  cat.setForeignServerOptions(server_name, opt.getOptionsAsJsonString());
939 }
940 
942  auto& ddl_payload = extractPayload(ddl_data_);
943  std::string server_name = ddl_payload["serverName"].GetString();
944  std::string data_wrapper = ddl_payload["dataWrapper"].GetString();
945  auto& cat = session_ptr_->getCatalog();
946  // update catalog
947  cat.setForeignServerDataWrapper(server_name, data_wrapper);
948 }
949 
951  // TODO: implement `GRANT/REVOKE ALTER_SERVER` DDL commands
952  auto& ddl_payload = extractPayload(ddl_data_);
953  std::string server_name = ddl_payload["serverName"].GetString();
954  return session_ptr_->checkDBAccessPrivileges(
956 }
957 
959  const DdlCommandData& ddl_data,
960  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
961  : DdlCommand(ddl_data, session_ptr) {
962  if (!g_enable_fsi) {
963  throw std::runtime_error("Unsupported command: DROP FOREIGN SERVER");
964  }
965  auto& ddl_payload = extractPayload(ddl_data_);
966  CHECK(ddl_payload.HasMember("serverName"));
967  CHECK(ddl_payload["serverName"].IsString());
968  CHECK(ddl_payload.HasMember("ifExists"));
969  CHECK(ddl_payload["ifExists"].IsBool());
970 }
971 
973  if (read_only_mode) {
974  throw std::runtime_error("DROP FOREIGN SERVER invalid in read only mode.");
975  }
976  auto& ddl_payload = extractPayload(ddl_data_);
977  std::string server_name = ddl_payload["serverName"].GetString();
978  if (is_default_server(server_name)) {
979  throw std::runtime_error{"Default servers cannot be dropped."};
980  }
981  bool if_exists = ddl_payload["ifExists"].GetBool();
982  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
983  if (if_exists) {
984  return ExecutionResult();
985  } else {
986  throw std::runtime_error{"Foreign server with name \"" + server_name +
987  "\" can not be dropped. Server does not exist."};
988  }
989  }
990  // check access privileges
991  if (!session_ptr_->checkDBAccessPrivileges(
993  throw std::runtime_error("Server " + server_name +
994  " will not be dropped. User has no DROP SERVER privileges.");
995  }
997  DBObject(server_name, ServerDBObjectType), session_ptr_->get_catalog_ptr().get());
998  session_ptr_->getCatalog().dropForeignServer(ddl_payload["serverName"].GetString());
999 
1000  return ExecutionResult();
1001 }
1002 
1003 SQLTypes JsonColumnSqlType::getSqlType(const rapidjson::Value& data_type) {
1004  CHECK(data_type.IsObject());
1005  CHECK(data_type.HasMember("type"));
1006  CHECK(data_type["type"].IsString());
1007 
1008  std::string type = data_type["type"].GetString();
1009  if (boost::iequals(type, "ARRAY")) {
1010  CHECK(data_type.HasMember("array"));
1011  CHECK(data_type["array"].IsObject());
1012 
1013  const auto& array = data_type["array"].GetObject();
1014  CHECK(array.HasMember("elementType"));
1015  CHECK(array["elementType"].IsString());
1016  type = array["elementType"].GetString();
1017  }
1018  return getSqlType(type);
1019 }
1020 
1021 SQLTypes JsonColumnSqlType::getSqlType(const std::string& type) {
1022  if (boost::iequals(type, "BIGINT")) {
1023  return kBIGINT;
1024  }
1025  if (boost::iequals(type, "BOOLEAN")) {
1026  return kBOOLEAN;
1027  }
1028  if (boost::iequals(type, "DATE")) {
1029  return kDATE;
1030  }
1031  if (boost::iequals(type, "DECIMAL")) {
1032  return kDECIMAL;
1033  }
1034  if (boost::iequals(type, "DOUBLE")) {
1035  return kDOUBLE;
1036  }
1037  if (boost::iequals(type, "FLOAT")) {
1038  return kFLOAT;
1039  }
1040  if (boost::iequals(type, "INTEGER")) {
1041  return kINT;
1042  }
1043  if (boost::iequals(type, "LINESTRING")) {
1044  return kLINESTRING;
1045  }
1046  if (boost::iequals(type, "MULTILINESTRING")) {
1047  return kMULTILINESTRING;
1048  }
1049  if (boost::iequals(type, "MULTIPOLYGON")) {
1050  return kMULTIPOLYGON;
1051  }
1052  if (boost::iequals(type, "POINT")) {
1053  return kPOINT;
1054  }
1055  if (boost::iequals(type, "MULTIPOINT")) {
1056  return kMULTIPOINT;
1057  }
1058  if (boost::iequals(type, "POLYGON")) {
1059  return kPOLYGON;
1060  }
1061  if (boost::iequals(type, "SMALLINT")) {
1062  return kSMALLINT;
1063  }
1064  if (boost::iequals(type, "TEXT")) {
1065  return kTEXT;
1066  }
1067  if (boost::iequals(type, "TIME")) {
1068  return kTIME;
1069  }
1070  if (boost::iequals(type, "TIMESTAMP")) {
1071  return kTIMESTAMP;
1072  }
1073  if (boost::iequals(type, "TINYINT")) {
1074  return kTINYINT;
1075  }
1076 
1077  throw std::runtime_error{"Unsupported type \"" + type + "\" specified."};
1078 }
1079 
1080 int JsonColumnSqlType::getParam1(const rapidjson::Value& data_type) {
1081  int param1 = -1;
1082  CHECK(data_type.IsObject());
1083  if (data_type.HasMember("precision") && !data_type["precision"].IsNull()) {
1084  CHECK(data_type["precision"].IsInt());
1085  param1 = data_type["precision"].GetInt();
1086  } else if (auto type = getSqlType(data_type); IS_GEO(type)) {
1087  param1 = static_cast<int>(kGEOMETRY);
1088  }
1089  return param1;
1090 }
1091 
1092 int JsonColumnSqlType::getParam2(const rapidjson::Value& data_type) {
1093  int param2 = 0;
1094  CHECK(data_type.IsObject());
1095  if (data_type.HasMember("scale") && !data_type["scale"].IsNull()) {
1096  CHECK(data_type["scale"].IsInt());
1097  param2 = data_type["scale"].GetInt();
1098  } else if (auto type = getSqlType(data_type); IS_GEO(type) &&
1099  data_type.HasMember("coordinateSystem") &&
1100  !data_type["coordinateSystem"].IsNull()) {
1101  CHECK(data_type["coordinateSystem"].IsInt());
1102  param2 = data_type["coordinateSystem"].GetInt();
1103  }
1104  return param2;
1105 }
1106 
1107 bool JsonColumnSqlType::isArray(const rapidjson::Value& data_type) {
1108  CHECK(data_type.IsObject());
1109  CHECK(data_type.HasMember("type"));
1110  CHECK(data_type["type"].IsString());
1111  return boost::iequals(data_type["type"].GetString(), "ARRAY");
1112 }
1113 
1114 int JsonColumnSqlType::getArraySize(const rapidjson::Value& data_type) {
1115  int size = -1;
1116  if (isArray(data_type)) {
1117  CHECK(data_type.HasMember("array"));
1118  CHECK(data_type["array"].IsObject());
1119 
1120  const auto& array = data_type["array"].GetObject();
1121  if (array.HasMember("size") && !array["size"].IsNull()) {
1122  CHECK(array["size"].IsInt());
1123  size = array["size"].GetInt();
1124  }
1125  }
1126  return size;
1127 }
1128 
1129 std::string* JsonColumnEncoding::getEncodingName(const rapidjson::Value& data_type) {
1130  CHECK(data_type.IsObject());
1131  CHECK(data_type.HasMember("encoding"));
1132  CHECK(data_type["encoding"].IsObject());
1133 
1134  const auto& encoding = data_type["encoding"].GetObject();
1135  CHECK(encoding.HasMember("type"));
1136  CHECK(encoding["type"].IsString());
1137  return new std::string(encoding["type"].GetString());
1138 }
1139 
1140 int JsonColumnEncoding::getEncodingParam(const rapidjson::Value& data_type) {
1141  CHECK(data_type.IsObject());
1142  CHECK(data_type.HasMember("encoding"));
1143  CHECK(data_type["encoding"].IsObject());
1144 
1145  int encoding_size = 0;
1146  const auto& encoding = data_type["encoding"].GetObject();
1147  if (encoding.HasMember("size") && !encoding["size"].IsNull()) {
1148  CHECK(encoding["size"].IsInt());
1149  encoding_size = encoding["size"].GetInt();
1150  }
1151  return encoding_size;
1152 }
1153 
1155  const DdlCommandData& ddl_data,
1156  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1157  : DdlCommand(ddl_data, session_ptr) {
1158  if (!g_enable_fsi) {
1159  throw std::runtime_error("Unsupported command: CREATE FOREIGN TABLE");
1160  }
1161  auto& ddl_payload = extractPayload(ddl_data);
1162  CHECK(ddl_payload.HasMember("serverName"));
1163  CHECK(ddl_payload["serverName"].IsString());
1164  CHECK(ddl_payload.HasMember("tableName"));
1165  CHECK(ddl_payload["tableName"].IsString());
1166  CHECK(ddl_payload.HasMember("ifNotExists"));
1167  CHECK(ddl_payload["ifNotExists"].IsBool());
1168  CHECK(ddl_payload.HasMember("columns"));
1169  CHECK(ddl_payload["columns"].IsArray());
1170 }
1171 
1173  auto& catalog = session_ptr_->getCatalog();
1174  auto& ddl_payload = extractPayload(ddl_data_);
1175 
1176  if (read_only_mode) {
1177  throw std::runtime_error("CREATE FOREIGN TABLE invalid in read only mode.");
1178  }
1179  const std::string& table_name = ddl_payload["tableName"].GetString();
1180  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::TableDBObjectType,
1182  throw std::runtime_error(
1183  "Foreign table \"" + table_name +
1184  "\" will not be created. User has no CREATE TABLE privileges.");
1185  }
1186 
1187  bool if_not_exists = ddl_payload["ifNotExists"].GetBool();
1188  if (!catalog.validateNonExistentTableOrView(table_name, if_not_exists)) {
1189  return ExecutionResult();
1190  }
1191 
1192  foreign_storage::ForeignTable foreign_table{};
1193  std::list<ColumnDescriptor> columns{};
1194  setColumnDetails(columns);
1195  setTableDetails(table_name, foreign_table, columns);
1196  catalog.createTable(foreign_table, columns, {}, true);
1197 
1198  // TODO (max): It's transactionally unsafe, should be fixed: we may create object w/o
1199  // privileges
1201  session_ptr_->get_currentUser(),
1202  foreign_table.tableName,
1204  catalog);
1205 
1206  return ExecutionResult();
1207 }
1208 
1210  const std::string& table_name,
1211  TableDescriptor& td,
1212  const std::list<ColumnDescriptor>& columns) {
1213  ddl_utils::set_default_table_attributes(table_name, td, columns.size());
1214  td.userId = session_ptr_->get_currentUser().userId;
1216  td.hasDeletedCol = false;
1217  td.keyMetainfo = "[]";
1218  td.fragments = "";
1219  td.partitions = "";
1220 
1221  auto& ddl_payload = extractPayload(ddl_data_);
1222  auto& foreign_table = dynamic_cast<foreign_storage::ForeignTable&>(td);
1223  const std::string server_name = ddl_payload["serverName"].GetString();
1224  foreign_table.foreign_server = session_ptr_->getCatalog().getForeignServer(server_name);
1225  if (!foreign_table.foreign_server) {
1226  throw std::runtime_error{
1227  "Foreign Table with name \"" + table_name +
1228  "\" can not be created. Associated foreign server with name \"" + server_name +
1229  "\" does not exist."};
1230  }
1231 
1232  // check server usage privileges
1233  if (!is_default_server(server_name) &&
1234  !session_ptr_->checkDBAccessPrivileges(DBObjectType::ServerDBObjectType,
1236  server_name)) {
1237  throw std::runtime_error(
1238  "Current user does not have USAGE privilege on foreign server: " + server_name);
1239  }
1240 
1241  if (ddl_payload.HasMember("options") && !ddl_payload["options"].IsNull()) {
1242  CHECK(ddl_payload["options"].IsObject());
1243  foreign_table.initializeOptions(ddl_payload["options"]);
1244  } else {
1245  // Initialize options even if none were provided to verify a legal state.
1246  // This is necessary because some options (like "file_path") are optional only if a
1247  // paired option ("base_path") exists in the server.
1248  foreign_table.initializeOptions();
1249  }
1250  foreign_table.validateSchema(columns);
1251 
1252  if (const auto it = foreign_table.options.find("FRAGMENT_SIZE");
1253  it != foreign_table.options.end()) {
1254  foreign_table.maxFragRows = std::stoi(it->second);
1255  }
1256 
1257  if (const auto it = foreign_table.options.find("MAX_CHUNK_SIZE");
1258  it != foreign_table.options.end()) {
1259  foreign_table.maxChunkSize = std::stol(it->second);
1260  }
1261 
1262  if (const auto it = foreign_table.options.find("PARTITIONS");
1263  it != foreign_table.options.end()) {
1264  foreign_table.partitions = it->second;
1265  }
1266 }
1267 
1268 void CreateForeignTableCommand::setColumnDetails(std::list<ColumnDescriptor>& columns) {
1269  auto& ddl_payload = extractPayload(ddl_data_);
1270  std::unordered_set<std::string> column_names{};
1271  for (auto& column_def : ddl_payload["columns"].GetArray()) {
1272  CHECK(column_def.IsObject());
1273  CHECK(column_def.HasMember("name"));
1274  CHECK(column_def["name"].IsString());
1275  const std::string& column_name = column_def["name"].GetString();
1276 
1277  CHECK(column_def.HasMember("dataType"));
1278  CHECK(column_def["dataType"].IsObject());
1279 
1280  JsonColumnSqlType sql_type{column_def["dataType"]};
1281  const auto& data_type = column_def["dataType"].GetObject();
1282  CHECK(data_type.HasMember("notNull"));
1283  CHECK(data_type["notNull"].IsBool());
1284 
1285  std::unique_ptr<JsonColumnEncoding> encoding;
1286  if (data_type.HasMember("encoding") && !data_type["encoding"].IsNull()) {
1287  CHECK(data_type["encoding"].IsObject());
1288  encoding = std::make_unique<JsonColumnEncoding>(column_def["dataType"]);
1289  }
1290 
1291  ColumnDescriptor cd;
1292  ddl_utils::validate_non_duplicate_column(column_name, column_names);
1295  cd,
1296  &sql_type,
1297  data_type["notNull"].GetBool(),
1298  encoding.get(),
1299  nullptr);
1300  columns.emplace_back(cd);
1301  }
1302 }
1303 
1305  const DdlCommandData& ddl_data,
1306  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1307  : DdlCommand(ddl_data, session_ptr) {
1308  if (!g_enable_fsi) {
1309  throw std::runtime_error("Unsupported command: DROP FOREIGN TABLE");
1310  }
1311  auto& ddl_payload = extractPayload(ddl_data_);
1312  CHECK(ddl_payload.HasMember("tableName"));
1313  CHECK(ddl_payload["tableName"].IsString());
1314  CHECK(ddl_payload.HasMember("ifExists"));
1315  CHECK(ddl_payload["ifExists"].IsBool());
1316 }
1317 
1319  auto& catalog = session_ptr_->getCatalog();
1320  auto& ddl_payload = extractPayload(ddl_data_);
1321 
1322  if (read_only_mode) {
1323  throw std::runtime_error("DROP FOREIGN TABLE invalid in read only mode.");
1324  }
1325  const std::string& table_name = ddl_payload["tableName"].GetString();
1326  const TableDescriptor* td{nullptr};
1327  std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>> td_with_lock;
1328 
1329  try {
1330  td_with_lock =
1331  std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>>(
1333  catalog, table_name, false));
1334  CHECK(td_with_lock);
1335  td = (*td_with_lock)();
1336  } catch (const std::runtime_error& e) {
1337  // TODO(Misiu): This should not just swallow any exception, it should only catch
1338  // exceptions that stem from the table not existing.
1339  if (ddl_payload["ifExists"].GetBool()) {
1340  return ExecutionResult();
1341  } else {
1342  throw e;
1343  }
1344  }
1345 
1346  CHECK(td);
1347 
1348  if (!session_ptr_->checkDBAccessPrivileges(
1350  throw std::runtime_error(
1351  "Foreign table \"" + table_name +
1352  "\" will not be dropped. User has no DROP TABLE privileges.");
1353  }
1354 
1356  auto table_data_write_lock =
1358  catalog.dropTable(td);
1359 
1360  // TODO(Misiu): Implement per-table cache invalidation.
1362 
1363  return ExecutionResult();
1364 }
1365 
1367  const DdlCommandData& ddl_data,
1368  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1369  : DdlCommand(ddl_data, session_ptr) {}
1370 
1372  // Get all table names in the same way as OmniSql \t command
1373 
1374  // valid in read_only_mode
1375 
1376  // label_infos -> column labels
1377  std::vector<std::string> labels{"table_name"};
1378  std::vector<TargetMetaInfo> label_infos;
1379  for (const auto& label : labels) {
1380  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1381  }
1382 
1383  // Get all table names
1384  auto cat_ptr = session_ptr_->get_catalog_ptr();
1385  auto cur_user = session_ptr_->get_currentUser();
1386  auto table_names = cat_ptr->getTableNamesForUser(cur_user, GET_PHYSICAL_TABLES);
1387 
1388  // logical_values -> table data
1389  std::vector<RelLogicalValues::RowValues> logical_values;
1390  for (auto table_name : table_names) {
1391  logical_values.emplace_back(RelLogicalValues::RowValues{});
1392  logical_values.back().emplace_back(genLiteralStr(table_name));
1393  }
1394 
1395  // Create ResultSet
1396  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1397  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1398 
1399  return ExecutionResult(rSet, label_infos);
1400 }
1401 
1403  const DdlCommandData& ddl_data,
1404  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1405  : DdlCommand(ddl_data, session_ptr) {
1406  auto& ddl_payload = extractPayload(ddl_data_);
1407  if (ddl_payload.HasMember("tableNames")) {
1408  CHECK(ddl_payload["tableNames"].IsArray());
1409  for (const auto& table_name : ddl_payload["tableNames"].GetArray()) {
1410  CHECK(table_name.IsString());
1411  }
1412  }
1413 }
1414 
1416  const auto catalog = session_ptr_->get_catalog_ptr();
1417  std::vector<std::string> filtered_table_names = getFilteredTableNames();
1418 
1419  // valid in read_only_mode
1420 
1421  std::vector<TargetMetaInfo> label_infos;
1422  set_headers_with_type(label_infos,
1423  {// { label, type, notNull }
1424  {"table_id", kBIGINT, true},
1425  {"table_name", kTEXT, true},
1426  {"column_count", kBIGINT, true},
1427  {"is_sharded_table", kBOOLEAN, true},
1428  {"shard_count", kBIGINT, true},
1429  {"max_rows", kBIGINT, true},
1430  {"fragment_size", kBIGINT, true},
1431  {"max_rollback_epochs", kBIGINT, true},
1432  {"min_epoch", kBIGINT, true},
1433  {"max_epoch", kBIGINT, true},
1434  {"min_epoch_floor", kBIGINT, true},
1435  {"max_epoch_floor", kBIGINT, true},
1436  {"metadata_file_count", kBIGINT, true},
1437  {"total_metadata_file_size", kBIGINT, true},
1438  {"total_metadata_page_count", kBIGINT, true},
1439  {"total_free_metadata_page_count", kBIGINT, false},
1440  {"data_file_count", kBIGINT, true},
1441  {"total_data_file_size", kBIGINT, true},
1442  {"total_data_page_count", kBIGINT, true},
1443  {"total_free_data_page_count", kBIGINT, false}});
1444 
1445  std::vector<RelLogicalValues::RowValues> logical_values;
1446  for (const auto& table_name : filtered_table_names) {
1447  auto [td, td_with_lock] =
1448  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1449  auto agg_storage_stats = get_agg_storage_stats(td, catalog.get());
1450  add_table_details(logical_values, td, agg_storage_stats);
1451  }
1452 
1453  // Create ResultSet
1454  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1455  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1456 
1457  return ExecutionResult(rSet, label_infos);
1458 }
1459 
1461  const auto catalog = session_ptr_->get_catalog_ptr();
1462  auto& ddl_payload = extractPayload(ddl_data_);
1463  auto all_table_names =
1464  catalog->getTableNamesForUser(session_ptr_->get_currentUser(), GET_PHYSICAL_TABLES);
1465  std::transform(all_table_names.begin(),
1466  all_table_names.end(),
1467  all_table_names.begin(),
1468  [](const std::string& s) { return to_upper(s); });
1469  std::vector<std::string> filtered_table_names;
1470  if (ddl_payload.HasMember("tableNames")) {
1471  std::set<std::string> all_table_names_set(all_table_names.begin(),
1472  all_table_names.end());
1473  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1474  std::string table_name = table_name_json.GetString();
1475  if (all_table_names_set.find(to_upper(table_name)) == all_table_names_set.end()) {
1476  throw std::runtime_error{"Unable to show table details for table: " + table_name +
1477  ". Table does not exist."};
1478  }
1479  auto [td, td_with_lock] =
1480  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1481  if (td->isForeignTable()) {
1482  throw std::runtime_error{
1483  "SHOW TABLE DETAILS is not supported for foreign tables. Table name: " +
1484  table_name + "."};
1485  }
1486  if (td->isTemporaryTable()) {
1487  throw std::runtime_error{
1488  "SHOW TABLE DETAILS is not supported for temporary tables. Table name: " +
1489  table_name + "."};
1490  }
1491  filtered_table_names.emplace_back(table_name);
1492  }
1493  } else {
1494  for (const auto& table_name : all_table_names) {
1495  auto [td, td_with_lock] =
1496  get_table_descriptor_with_lock<lockmgr::ReadLock>(*catalog, table_name, false);
1497  if (td->isForeignTable() || td->isTemporaryTable()) {
1498  continue;
1499  }
1500  filtered_table_names.emplace_back(table_name);
1501  }
1502  }
1503  return filtered_table_names;
1504 }
1505 
1507  const DdlCommandData& ddl_data,
1508  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1509  : DdlCommand(ddl_data, session_ptr) {}
1510 
1512  // valid in read_only_mode
1513 
1514  auto& ddl_payload = extractPayload(ddl_data_);
1515  CHECK(ddl_payload.HasMember("tableName"));
1516  CHECK(ddl_payload["tableName"].IsString());
1517  const std::string& table_name = ddl_payload["tableName"].GetString();
1518 
1519  auto& catalog = session_ptr_->getCatalog();
1520  auto table_read_lock =
1522 
1523  const TableDescriptor* td = catalog.getMetadataForTable(table_name, false);
1524  if (!td) {
1525  throw std::runtime_error("Table/View " + table_name + " does not exist.");
1526  }
1527 
1529  dbObject.loadKey(catalog);
1530  std::vector<DBObject> privObjects = {dbObject};
1531 
1532  if (!Catalog_Namespace::SysCatalog::instance().hasAnyPrivileges(
1533  session_ptr_->get_currentUser(), privObjects)) {
1534  throw std::runtime_error("Table/View " + table_name + " does not exist.");
1535  }
1536  if (td->isView && !session_ptr_->get_currentUser().isSuper) {
1537  auto query_state = query_state::QueryState::create(session_ptr_, td->viewSQL);
1538  auto query_state_proxy = query_state->createQueryStateProxy();
1539  auto calcite_mgr = catalog.getCalciteMgr();
1540  const auto calciteQueryParsingOption =
1541  calcite_mgr->getCalciteQueryParsingOption(true, false, false);
1542  const auto calciteOptimizationOption = calcite_mgr->getCalciteOptimizationOption(
1543  false,
1545  {},
1547  auto result = calcite_mgr->process(query_state_proxy,
1548  td->viewSQL,
1549  calciteQueryParsingOption,
1550  calciteOptimizationOption);
1551  try {
1552  calcite_mgr->checkAccessedObjectsPrivileges(query_state_proxy, result);
1553  } catch (const std::runtime_error&) {
1554  throw std::runtime_error("Not enough privileges to show the view SQL");
1555  }
1556  }
1557  // Construct
1558  auto create_table_sql = catalog.dumpCreateTable(td);
1561  return result;
1562 }
1563 
1565  const DdlCommandData& ddl_data,
1566  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1567  : DdlCommand(ddl_data, session_ptr) {}
1568 
1570  // valid in read_only_mode
1571 
1572  // label_infos -> column labels
1573  std::vector<std::string> labels{"Database", "Owner"};
1574  std::vector<TargetMetaInfo> label_infos;
1575  for (const auto& label : labels) {
1576  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1577  }
1578 
1579  // Get all table names
1580  auto cur_user = session_ptr_->get_currentUser();
1581  const Catalog_Namespace::DBSummaryList db_summaries =
1583 
1584  // logical_values -> table data
1585  std::vector<RelLogicalValues::RowValues> logical_values;
1586  for (const auto& db_summary : db_summaries) {
1587  logical_values.emplace_back(RelLogicalValues::RowValues{});
1588  logical_values.back().emplace_back(genLiteralStr(db_summary.dbName));
1589  logical_values.back().emplace_back(genLiteralStr(db_summary.dbOwnerName));
1590  }
1591 
1592  // Create ResultSet
1593  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1594  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1595 
1596  return ExecutionResult(rSet, label_infos);
1597 }
1598 
1600  const DdlCommandData& ddl_data,
1601  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1602  : DdlCommand(ddl_data, session_ptr) {}
1603 
1605  // Get all row-wise functions
1606  auto& ddl_payload = extractPayload(ddl_data_);
1607  std::vector<TargetMetaInfo> label_infos;
1608  std::vector<RelLogicalValues::RowValues> logical_values;
1609 
1610  if (ddl_payload.HasMember("ScalarFnNames")) {
1611  // label_infos -> column labels
1612  label_infos.emplace_back("name", SQLTypeInfo(kTEXT, true));
1613  label_infos.emplace_back("signature", SQLTypeInfo(kTEXT, true));
1614  label_infos.emplace_back("CPU", SQLTypeInfo(kBOOLEAN, true));
1615  label_infos.emplace_back("GPU", SQLTypeInfo(kBOOLEAN, true));
1616  label_infos.emplace_back("Runtime", SQLTypeInfo(kBOOLEAN, true));
1617  for (const auto& udf_name_json : ddl_payload["ScalarFnNames"].GetArray()) {
1618  std::string udf_name = udf_name_json.GetString();
1619  std::vector<ExtensionFunction> ext_funcs =
1621 
1622  for (ExtensionFunction& fn : ext_funcs) {
1623  logical_values.emplace_back(RelLogicalValues::RowValues{});
1624  // Name
1625  logical_values.back().emplace_back(genLiteralStr(udf_name));
1626  // Signature
1627  logical_values.back().emplace_back(genLiteralStr(fn.toSignature()));
1628  // CPU?
1629  logical_values.back().emplace_back(genLiteralBoolean(fn.isCPU()));
1630  // GPU?
1631  logical_values.back().emplace_back(genLiteralBoolean(fn.isGPU()));
1632  // Runtime?
1633  logical_values.back().emplace_back(genLiteralBoolean(fn.isRuntime()));
1634  }
1635  }
1636 
1637  } else {
1638  // label_infos -> column labels
1639  for (const auto& label : {"Scalar UDF"}) {
1640  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1641  }
1642 
1643  // logical_values -> table data
1644  for (auto name : ExtensionFunctionsWhitelist::get_udfs_name(/* is_runtime */ false)) {
1645  logical_values.emplace_back(RelLogicalValues::RowValues{});
1646  logical_values.back().emplace_back(genLiteralStr(name));
1647  }
1648  }
1649 
1650  // Create ResultSet
1651  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1652  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1653 
1654  return ExecutionResult(rSet, label_infos);
1655 }
1656 
1658  const DdlCommandData& ddl_data,
1659  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1660  : DdlCommand(ddl_data, session_ptr) {}
1661 
1663  // Get all runtime row-wise functions
1664  std::vector<TargetMetaInfo> label_infos;
1665  std::vector<RelLogicalValues::RowValues> logical_values;
1666 
1667  // label_infos -> column labels
1668  for (const auto& label : {"Runtime Scalar UDF"}) {
1669  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1670  }
1671 
1672  // logical_values -> table data
1673  for (auto name : ExtensionFunctionsWhitelist::get_udfs_name(/* is_runtime */ true)) {
1674  logical_values.emplace_back(RelLogicalValues::RowValues{});
1675  logical_values.back().emplace_back(genLiteralStr(name));
1676  }
1677 
1678  // Create ResultSet
1679  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1680  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1681 
1682  return ExecutionResult(rSet, label_infos);
1683 }
1684 
1686  const DdlCommandData& ddl_data,
1687  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1688  : DdlCommand(ddl_data, session_ptr) {}
1689 
1691  // valid in read_only_mode
1692 
1693  // Get all table functions
1694  auto& ddl_payload = extractPayload(ddl_data_);
1695  std::vector<TargetMetaInfo> label_infos;
1696  std::vector<RelLogicalValues::RowValues> logical_values;
1697 
1698  if (ddl_payload.HasMember("tfNames")) {
1699  // label_infos -> column labels
1700  label_infos.emplace_back("name", SQLTypeInfo(kTEXT, true));
1701  label_infos.emplace_back("signature", SQLTypeInfo(kTEXT, true));
1702  label_infos.emplace_back("input_names", SQLTypeInfo(kTEXT, true));
1703  label_infos.emplace_back("input_types", SQLTypeInfo(kTEXT, true));
1704  label_infos.emplace_back("output_names", SQLTypeInfo(kTEXT, true));
1705  label_infos.emplace_back("output_types", SQLTypeInfo(kTEXT, true));
1706  label_infos.emplace_back("CPU", SQLTypeInfo(kBOOLEAN, true));
1707  label_infos.emplace_back("GPU", SQLTypeInfo(kBOOLEAN, true));
1708  label_infos.emplace_back("Runtime", SQLTypeInfo(kBOOLEAN, true));
1709  label_infos.emplace_back("filter_table_transpose", SQLTypeInfo(kBOOLEAN, true));
1710  // logical_values -> table data
1711  for (const auto& tf_name_json : ddl_payload["tfNames"].GetArray()) {
1712  std::string tf_name = tf_name_json.GetString();
1714  for (table_functions::TableFunction& tf : tfs) {
1715  logical_values.emplace_back(RelLogicalValues::RowValues{});
1716  // Name
1717  logical_values.back().emplace_back(genLiteralStr(tf.getName(true, false)));
1718  // Signature
1719  logical_values.back().emplace_back(genLiteralStr(
1720  tf.getSignature(/*include_name*/ false, /*include_output*/ true)));
1721  // Input argument names
1722  logical_values.back().emplace_back(
1723  genLiteralStr(tf.getArgNames(/* use_input_args */ true)));
1724  // Input argument types
1725  logical_values.back().emplace_back(
1726  genLiteralStr(tf.getArgTypes(/* use_input_args */ true)));
1727  // Output argument names
1728  logical_values.back().emplace_back(
1729  genLiteralStr(tf.getArgNames(/* use_input_args */ false)));
1730  // Output argument types
1731  logical_values.back().emplace_back(
1732  genLiteralStr(tf.getArgTypes(/* use_input_args */ false)));
1733  // CPU?
1734  logical_values.back().emplace_back(genLiteralBoolean(tf.isCPU()));
1735  // GPU?
1736  logical_values.back().emplace_back(genLiteralBoolean(tf.isGPU()));
1737  // Runtime?
1738  logical_values.back().emplace_back(genLiteralBoolean(tf.isRuntime()));
1739  // Implements filter_table_transpose?
1740  logical_values.back().emplace_back(genLiteralBoolean(
1741  !tf.getFunctionAnnotation("filter_table_function_transpose", "").empty()));
1742  }
1743  }
1744  } else {
1745  // label_infos -> column labels
1746  for (const auto& label : {"Table UDF"}) {
1747  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1748  }
1749 
1750  // logical_values -> table data
1751  std::unordered_set<std::string> unique_names;
1753  /* is_runtime */ false)) {
1754  std::string name = tf.getName(true, true);
1755  if (unique_names.find(name) == unique_names.end()) {
1756  unique_names.emplace(name);
1757  logical_values.emplace_back(RelLogicalValues::RowValues{});
1758  logical_values.back().emplace_back(genLiteralStr(name));
1759  }
1760  }
1761  }
1762 
1763  // Create ResultSet
1764  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1765  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1766 
1767  return ExecutionResult(rSet, label_infos);
1768 }
1769 
1771  const DdlCommandData& ddl_data,
1772  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1773  : DdlCommand(ddl_data, session_ptr) {}
1774 
1776  // valid in read_only_mode
1777 
1778  // Get all runtime table functions
1779  std::vector<TargetMetaInfo> label_infos;
1780  std::vector<RelLogicalValues::RowValues> logical_values;
1781 
1782  // label_infos -> column labels
1783  for (const auto& label : {"Runtime Table UDF"}) {
1784  label_infos.emplace_back(label, SQLTypeInfo(kTEXT, true));
1785  }
1786 
1787  // logical_values -> table data
1788  std::unordered_set<std::string> unique_names;
1789  for (auto tf :
1791  std::string name = tf.getName(true, true);
1792  if (unique_names.find(name) == unique_names.end()) {
1793  unique_names.emplace(name);
1794  logical_values.emplace_back(RelLogicalValues::RowValues{});
1795  logical_values.back().emplace_back(genLiteralStr(name));
1796  }
1797  }
1798 
1799  // Create ResultSet
1800  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1801  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1802 
1803  return ExecutionResult(rSet, label_infos);
1804 }
1805 
1807  const DdlCommandData& ddl_data,
1808  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1809  : DdlCommand(ddl_data, session_ptr) {
1810  if (!g_enable_fsi) {
1811  throw std::runtime_error("Unsupported command: SHOW FOREIGN SERVERS");
1812  }
1813  // Verify that members are valid
1814  auto& ddl_payload = extractPayload(ddl_data_);
1815  CHECK(ddl_payload.HasMember("command"));
1816  if (ddl_payload.HasMember("filters")) {
1817  CHECK(ddl_payload["filters"].IsArray());
1818  int num_filters = 0;
1819  for (auto const& filter_def : ddl_payload["filters"].GetArray()) {
1820  CHECK(filter_def.IsObject());
1821  CHECK(filter_def.HasMember("attribute"));
1822  CHECK(filter_def["attribute"].IsString());
1823  CHECK(filter_def.HasMember("value"));
1824  CHECK(filter_def["value"].IsString());
1825  CHECK(filter_def.HasMember("operation"));
1826  CHECK(filter_def["operation"].IsString());
1827  if (num_filters > 0) {
1828  CHECK(filter_def.HasMember("chain"));
1829  CHECK(filter_def["chain"].IsString());
1830  } else {
1831  CHECK(!filter_def.HasMember("chain"));
1832  }
1833  num_filters++;
1834  }
1835  }
1836 }
1837 
1839  // valid in read_only_mode
1840 
1841  std::vector<TargetMetaInfo> label_infos;
1842  auto& ddl_payload = extractPayload(ddl_data_);
1843 
1844  // label_infos -> column labels
1845  std::vector<std::string> labels{"server_name", "data_wrapper", "created_at", "options"};
1846  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
1847  label_infos.emplace_back(labels[1], SQLTypeInfo(kTEXT, true));
1848  // created_at is a TIMESTAMP
1849  label_infos.emplace_back(labels[2], SQLTypeInfo(kTIMESTAMP, true));
1850  label_infos.emplace_back(labels[3], SQLTypeInfo(kTEXT, true));
1851 
1852  const auto& user = session_ptr_->get_currentUser();
1853 
1854  std::vector<const foreign_storage::ForeignServer*> results;
1855 
1856  session_ptr_->getCatalog().getForeignServersForUser(
1857  extractFilters(ddl_payload), user, results);
1858 
1859  // logical_values -> table data
1860  std::vector<RelLogicalValues::RowValues> logical_values;
1861  for (auto const& server_ptr : results) {
1862  logical_values.emplace_back(RelLogicalValues::RowValues{});
1863  logical_values.back().emplace_back(genLiteralStr(server_ptr->name));
1864  logical_values.back().emplace_back(genLiteralStr(server_ptr->data_wrapper_type));
1865  logical_values.back().emplace_back(genLiteralTimestamp(server_ptr->creation_time));
1866  logical_values.back().emplace_back(
1867  genLiteralStr(server_ptr->getOptionsAsJsonString()));
1868  }
1869 
1870  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1871  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1872 
1873  return ExecutionResult(rSet, label_infos);
1874 }
1875 
1877  const DdlCommandData& ddl_data,
1878  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1879  : DdlCommand(ddl_data, session_ptr) {
1880  if (!g_enable_fsi) {
1881  throw std::runtime_error("Unsupported command: SHOW CREATE SERVER");
1882  }
1883  // Verify that members are valid
1884  auto& payload = extractPayload(ddl_data_);
1885  CHECK(payload.HasMember("serverName"));
1886  CHECK(payload["serverName"].IsString());
1887  server_ = (payload["serverName"].GetString());
1888 }
1889 
1891  // valid in read_only_mode
1892 
1893  using namespace Catalog_Namespace;
1894  auto& catalog = session_ptr_->getCatalog();
1895  const auto server = catalog.getForeignServer(server_);
1896  if (!server) {
1897  throw std::runtime_error("Foreign server " + server_ + " does not exist.");
1898  }
1899  DBObject dbObject(server_, ServerDBObjectType);
1900  dbObject.loadKey(catalog);
1901  std::vector<DBObject> privObjects = {dbObject};
1902  if (!SysCatalog::instance().hasAnyPrivileges(session_ptr_->get_currentUser(),
1903  privObjects)) {
1904  throw std::runtime_error("Foreign server " + server_ + " does not exist.");
1905  }
1906  auto create_stmt = catalog.dumpCreateServer(server_);
1907 
1908  std::vector<std::string> labels{"create_server_sql"};
1909  std::vector<TargetMetaInfo> label_infos;
1910  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
1911 
1912  std::vector<RelLogicalValues::RowValues> logical_values;
1913  logical_values.emplace_back(RelLogicalValues::RowValues{});
1914  logical_values.back().emplace_back(genLiteralStr(create_stmt));
1915 
1916  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
1917  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
1918 
1919  return ExecutionResult(rSet, label_infos);
1920 }
1921 
1923  const DdlCommandData& ddl_data,
1924  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
1925  : DdlCommand(ddl_data, session_ptr) {
1926  if (!g_enable_fsi) {
1927  throw std::runtime_error("Unsupported command: REFRESH FOREIGN TABLE");
1928  }
1929  auto& ddl_payload = extractPayload(ddl_data_);
1930  CHECK(ddl_payload.HasMember("tableNames"));
1931  CHECK(ddl_payload["tableNames"].IsArray());
1932  for (auto const& tablename_def : ddl_payload["tableNames"].GetArray()) {
1933  CHECK(tablename_def.IsString());
1934  }
1935 }
1936 
1938  if (read_only_mode) {
1939  throw std::runtime_error("REFRESH FOREIGN TABLE invalid in read only mode.");
1940  }
1941 
1942  const auto execute_read_lock =
1946 
1947  bool evict_cached_entries{false};
1949  auto& ddl_payload = extractPayload(ddl_data_);
1950  if (ddl_payload.HasMember("options") && !ddl_payload["options"].IsNull()) {
1951  opt.populateOptionsMap(ddl_payload["options"]);
1952  for (const auto& entry : opt.options) {
1953  if (entry.first != "EVICT") {
1954  throw std::runtime_error{
1955  "Invalid option \"" + entry.first +
1956  "\" provided for refresh command. Only \"EVICT\" option is supported."};
1957  }
1958  }
1959  CHECK(opt.options.find("EVICT") != opt.options.end());
1960 
1961  if (boost::iequals(opt.options["EVICT"], "true") ||
1962  boost::iequals(opt.options["EVICT"], "false")) {
1963  if (boost::iequals(opt.options["EVICT"], "true")) {
1964  evict_cached_entries = true;
1965  }
1966  } else {
1967  throw std::runtime_error{
1968  "Invalid value \"" + opt.options["EVICT"] +
1969  "\" provided for EVICT option. Value must be either \"true\" or \"false\"."};
1970  }
1971  }
1972 
1973  auto& cat = session_ptr_->getCatalog();
1974  const auto& current_user = session_ptr_->get_currentUser();
1975  /* verify object ownership if not suser */
1976  if (!current_user.isSuper) {
1977  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1978  std::string table_name = table_name_json.GetString();
1979  if (!Catalog_Namespace::SysCatalog::instance().verifyDBObjectOwnership(
1980  current_user, DBObject(table_name, TableDBObjectType), cat)) {
1981  throw std::runtime_error(
1982  std::string("REFRESH FOREIGN TABLES failed on table \"") + table_name +
1983  "\". It can only be executed by super user or "
1984  "owner of the "
1985  "object.");
1986  }
1987  }
1988  }
1989 
1990  for (const auto& table_name_json : ddl_payload["tableNames"].GetArray()) {
1991  std::string table_name = table_name_json.GetString();
1992  static const std::array<std::string, 4> log_system_tables{
1997  if (cat.isInfoSchemaDb() && !shared::contains(log_system_tables, table_name)) {
1998  throw std::runtime_error(
1999  "REFRESH FOREIGN TABLE can only be executed for the following tables: " +
2000  join(log_system_tables, ","));
2001  }
2002  foreign_storage::refresh_foreign_table(cat, table_name, evict_cached_entries);
2003  }
2004 
2005  // todo(yoonmin) : allow per-table cache invalidation for the foreign table
2007 
2008  return ExecutionResult();
2009 }
2010 
2012  const DdlCommandData& ddl_data,
2013  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
2014  : DdlCommand(ddl_data, session_ptr) {
2015  if (!g_enable_fsi) {
2016  throw std::runtime_error("Unsupported command: ALTER FOREIGN TABLE");
2017  }
2018  auto& ddl_payload = extractPayload(ddl_data_);
2019  CHECK(ddl_payload.HasMember("tableName"));
2020  CHECK(ddl_payload["tableName"].IsString());
2021  CHECK(ddl_payload.HasMember("alterType"));
2022  CHECK(ddl_payload["alterType"].IsString());
2023  if (ddl_payload["alterType"] == "RENAME_TABLE") {
2024  CHECK(ddl_payload.HasMember("newTableName"));
2025  CHECK(ddl_payload["newTableName"].IsString());
2026  } else if (ddl_payload["alterType"] == "RENAME_COLUMN") {
2027  CHECK(ddl_payload.HasMember("oldColumnName"));
2028  CHECK(ddl_payload["oldColumnName"].IsString());
2029  CHECK(ddl_payload.HasMember("newColumnName"));
2030  CHECK(ddl_payload["newColumnName"].IsString());
2031  } else if (ddl_payload["alterType"] == "ALTER_OPTIONS") {
2032  CHECK(ddl_payload.HasMember("options"));
2033  CHECK(ddl_payload["options"].IsObject());
2034  } else {
2035  UNREACHABLE() << "Not a valid alter foreign table command: "
2036  << ddl_payload["alterType"].GetString();
2037  }
2038 }
2039 
2041  if (read_only_mode) {
2042  throw std::runtime_error("ALTER FOREIGN TABLE invalid in read only mode.");
2043  }
2044 
2045  auto& ddl_payload = extractPayload(ddl_data_);
2046  auto& catalog = session_ptr_->getCatalog();
2047  const std::string& table_name = ddl_payload["tableName"].GetString();
2048  auto [td, td_with_lock] =
2049  get_table_descriptor_with_lock<lockmgr::WriteLock>(catalog, table_name, false);
2050 
2052 
2053  if (!session_ptr_->checkDBAccessPrivileges(
2055  throw std::runtime_error(
2056  "Current user does not have the privilege to alter foreign table: " + table_name);
2057  }
2058 
2059  auto table_data_write_lock =
2061  auto foreign_table = dynamic_cast<const foreign_storage::ForeignTable*>(td);
2062  CHECK(foreign_table);
2063 
2064  std::string alter_type = ddl_payload["alterType"].GetString();
2065  if (alter_type == "RENAME_TABLE") {
2066  renameTable(foreign_table);
2067  } else if (alter_type == "RENAME_COLUMN") {
2068  renameColumn(foreign_table);
2069  } else if (alter_type == "ALTER_OPTIONS") {
2070  alterOptions(*foreign_table);
2071  }
2072 
2073  return ExecutionResult();
2074 }
2075 
2077  const foreign_storage::ForeignTable* foreign_table) {
2078  auto& ddl_payload = extractPayload(ddl_data_);
2079  auto& cat = session_ptr_->getCatalog();
2080  const std::string& table_name = ddl_payload["tableName"].GetString();
2081  const std::string& new_table_name = ddl_payload["newTableName"].GetString();
2082  if (cat.getForeignTable(new_table_name)) {
2083  throw std::runtime_error("Foreign table with name \"" + table_name +
2084  "\" can not be renamed to \"" + new_table_name + "\". " +
2085  "A different table with name \"" + new_table_name +
2086  "\" already exists.");
2087  }
2088  cat.renameTable(foreign_table, new_table_name);
2089 }
2090 
2092  const foreign_storage::ForeignTable* foreign_table) {
2093  auto& ddl_payload = extractPayload(ddl_data_);
2094  auto& cat = session_ptr_->getCatalog();
2095  const std::string& old_column_name = ddl_payload["oldColumnName"].GetString();
2096  const std::string& new_column_name = ddl_payload["newColumnName"].GetString();
2097  auto column = cat.getMetadataForColumn(foreign_table->tableId, old_column_name);
2098  if (!column) {
2099  throw std::runtime_error("Column with name \"" + old_column_name +
2100  "\" can not be renamed to \"" + new_column_name + "\". " +
2101  "Column with name \"" + old_column_name +
2102  "\" does not exist.");
2103  }
2104  if (cat.getMetadataForColumn(foreign_table->tableId, new_column_name)) {
2105  throw std::runtime_error("Column with name \"" + old_column_name +
2106  "\" can not be renamed to \"" + new_column_name + "\". " +
2107  "A column with name \"" + new_column_name +
2108  "\" already exists.");
2109  }
2110  cat.renameColumn(foreign_table, column, new_column_name);
2111 }
2112 
2114  const foreign_storage::ForeignTable& foreign_table) {
2115  auto& ddl_payload = extractPayload(ddl_data_);
2116  const std::string& table_name = ddl_payload["tableName"].GetString();
2117  auto& cat = session_ptr_->getCatalog();
2118  auto new_options_map =
2119  foreign_storage::ForeignTable::createOptionsMap(ddl_payload["options"]);
2120  foreign_table.validateSupportedOptionKeys(new_options_map);
2121  foreign_table.validateAlterOptions(new_options_map);
2122  cat.setForeignTableOptions(table_name, new_options_map, false);
2123 }
2124 
2126  const DdlCommandData& ddl_data,
2127  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2128  : DdlCommand(ddl_data, session_ptr) {
2129  auto& ddl_payload = extractPayload(ddl_data_);
2130  if (ddl_payload.HasMember("tableNames")) {
2131  CHECK(ddl_payload["tableNames"].IsArray());
2132  for (auto const& tablename_def : ddl_payload["tableNames"].GetArray()) {
2133  CHECK(tablename_def.IsString());
2134  }
2135  }
2136 }
2137 
2139  auto table_names = session_ptr_->get_catalog_ptr()->getTableNamesForUser(
2140  session_ptr_->get_currentUser(), GET_PHYSICAL_TABLES);
2141 
2142  auto& ddl_payload = extractPayload(ddl_data_);
2143  if (ddl_payload.HasMember("tableNames")) {
2144  std::vector<std::string> filtered_names;
2145  for (const auto& tablename_def : ddl_payload["tableNames"].GetArray()) {
2146  std::string filter_name = tablename_def.GetString();
2147  if (std::find(table_names.begin(), table_names.end(), filter_name) !=
2148  table_names.end()) {
2149  filtered_names.emplace_back(filter_name);
2150  } else {
2151  throw std::runtime_error("Can not show disk cache usage for table: " +
2152  filter_name + ". Table does not exist.");
2153  }
2154  }
2155  return filtered_names;
2156  } else {
2157  return table_names;
2158  }
2159 }
2160 
2162  // valid in read_only_mode
2163 
2164  auto cat_ptr = session_ptr_->get_catalog_ptr();
2165  auto table_names = getFilteredTableNames();
2166 
2167  const auto disk_cache = cat_ptr->getDataMgr().getPersistentStorageMgr()->getDiskCache();
2168  if (!disk_cache) {
2169  throw std::runtime_error{"Disk cache not enabled. Cannot show disk cache usage."};
2170  }
2171 
2172  // label_infos -> column labels
2173  std::vector<std::string> labels{"table name", "current cache size"};
2174  std::vector<TargetMetaInfo> label_infos;
2175  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
2176  label_infos.emplace_back(labels[1], SQLTypeInfo(kBIGINT, true));
2177 
2178  std::vector<RelLogicalValues::RowValues> logical_values;
2179 
2180  for (auto& table_name : table_names) {
2181  auto [td, td_with_lock] =
2182  get_table_descriptor_with_lock<lockmgr::ReadLock>(*cat_ptr, table_name, false);
2183 
2184  auto table_cache_size =
2185  disk_cache->getSpaceReservedByTable(cat_ptr->getDatabaseId(), td->tableId);
2186 
2187  // logical_values -> table data
2188  logical_values.emplace_back(RelLogicalValues::RowValues{});
2189  logical_values.back().emplace_back(genLiteralStr(table_name));
2190  logical_values.back().emplace_back(genLiteralBigInt(table_cache_size));
2191  }
2192 
2193  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
2194  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
2195 
2196  return ExecutionResult(rSet, label_infos);
2197 }
2198 
2200  const DdlCommandData& ddl_data,
2201  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2202  : DdlCommand(ddl_data, session_ptr) {
2203  auto& ddl_payload = extractPayload(ddl_data);
2204  if (ddl_payload.HasMember("userNames")) {
2205  CHECK(ddl_payload["userNames"].IsArray());
2206  for (const auto& user_name : ddl_payload["userNames"].GetArray()) {
2207  CHECK(user_name.IsString());
2208  }
2209  }
2210  CHECK(ddl_payload.HasMember("all"));
2211  CHECK(ddl_payload["all"].IsBool());
2212 }
2213 
2215  // valid in read_only_mode
2216 
2217  auto& ddl_payload = extractPayload(ddl_data_);
2218  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
2219 
2220  Catalog_Namespace::UserMetadata self = session_ptr_->get_currentUser();
2221  bool all = ddl_payload.HasMember("all") ? ddl_payload["all"].GetBool() : false;
2222  if (all && !self.isSuper) {
2223  throw std::runtime_error(
2224  "SHOW ALL USER DETAILS is only available to superusers. (Try SHOW USER "
2225  "DETAILS instead?)");
2226  }
2227 
2228  // label_infos -> column labels
2229  std::vector<TargetMetaInfo> label_infos;
2230  label_infos.emplace_back("NAME", SQLTypeInfo(kTEXT, true));
2231  label_infos.emplace_back("ID", SQLTypeInfo(kBIGINT, true));
2232  if (all) {
2233  label_infos.emplace_back("IS_SUPER", SQLTypeInfo(kBOOLEAN, true));
2234  }
2235  label_infos.emplace_back("DEFAULT_DB", SQLTypeInfo(kTEXT, true));
2236  if (self.isSuper) {
2237  label_infos.emplace_back("CAN_LOGIN", SQLTypeInfo(kBOOLEAN, true));
2238  }
2239  std::vector<RelLogicalValues::RowValues> logical_values;
2240 
2241  auto cat = session_ptr_->get_catalog_ptr();
2242  DBObject dbObject(cat->name(), DatabaseDBObjectType);
2243  dbObject.loadKey();
2244  dbObject.setPrivileges(AccessPrivileges::ACCESS);
2245 
2246  std::map<std::string, Catalog_Namespace::UserMetadata> user_map;
2247  auto user_list = !all ? sys_cat.getAllUserMetadata(cat->getDatabaseId())
2248  : sys_cat.getAllUserMetadata();
2249  for (auto& user : user_list) {
2250  if (user.can_login || self.isSuper) { // hide users who have disabled accounts
2251  user_map[user.userName] = user;
2252  }
2253  }
2254 
2255  if (ddl_payload.HasMember("userNames")) {
2256  std::map<std::string, Catalog_Namespace::UserMetadata> user_map2;
2257  for (const auto& user_name_json : ddl_payload["userNames"].GetArray()) {
2258  std::string user_name = user_name_json.GetString();
2259  auto uit = user_map.find(user_name);
2260  if (uit == user_map.end()) {
2261  throw std::runtime_error("User \"" + user_name + "\" not found. ");
2262  }
2263  user_map2[uit->first] = uit->second;
2264  }
2265  user_map = user_map2;
2266  }
2267 
2268  Catalog_Namespace::DBSummaryList dbsums = sys_cat.getDatabaseListForUser(self);
2269  std::unordered_set<std::string> visible_databases;
2270  if (!self.isSuper) {
2271  for (const auto& dbsum : dbsums) {
2272  visible_databases.insert(dbsum.dbName);
2273  }
2274  }
2275 
2276  for (const auto& [user_name, user] : user_map) {
2277  // database
2278  std::string dbname;
2280  if (sys_cat.getMetadataForDBById(user.defaultDbId, db)) {
2281  if (self.isSuper || visible_databases.count(db.dbName)) {
2282  dbname = db.dbName;
2283  }
2284  }
2285  if (self.isSuper) {
2286  dbname += "(" + std::to_string(user.defaultDbId) + ")";
2287  }
2288 
2289  // logical_values -> table data
2290  logical_values.emplace_back(RelLogicalValues::RowValues{});
2291  logical_values.back().emplace_back(genLiteralStr(user.userName));
2292  logical_values.back().emplace_back(genLiteralBigInt(user.userId));
2293  if (all) {
2294  logical_values.back().emplace_back(genLiteralBoolean(user.isSuper));
2295  }
2296  logical_values.back().emplace_back(genLiteralStr(dbname));
2297  if (self.isSuper) {
2298  logical_values.back().emplace_back(genLiteralBoolean(user.can_login));
2299  }
2300  }
2301 
2302  // Create ResultSet
2303  CHECK_EQ(logical_values.size(), user_map.size());
2304  if (logical_values.size() >= 1U) {
2305  CHECK_EQ(logical_values[0].size(), label_infos.size());
2306  }
2307  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
2308  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
2309 
2310  return ExecutionResult(rSet, label_infos);
2311 }
2312 
2314  const DdlCommandData& ddl_data,
2315  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2316  : DdlCommand(ddl_data, session_ptr) {
2317  auto& ddl_payload = extractPayload(ddl_data);
2318  CHECK(ddl_payload["userName"].IsString());
2319  CHECK(ddl_payload["effective"].IsBool());
2320 }
2321 
2323  // valid in read_only_mode
2324 
2325  auto& ddl_payload = extractPayload(ddl_data_);
2326  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
2327 
2328  // label_infos -> column labels
2329  std::vector<TargetMetaInfo> label_infos;
2330  std::vector<std::string> labels{"ROLES"};
2331  label_infos.emplace_back(labels[0], SQLTypeInfo(kTEXT, true));
2332 
2333  // logical_values -> table data
2334  std::vector<RelLogicalValues::RowValues> logical_values;
2335  std::vector<std::string> roles_list;
2336  Catalog_Namespace::UserMetadata self = session_ptr_->get_currentUser();
2337  std::string user_name = ddl_payload["userName"].GetString();
2338  bool effective = ddl_payload["effective"].GetBool();
2339  if (user_name.empty()) {
2340  user_name = self.userName;
2341  }
2343  bool is_user = sys_cat.getMetadataForUser(user_name, user);
2344  if (!self.isSuper) {
2345  if (is_user) {
2346  if (self.userId != user.userId) {
2347  throw std::runtime_error(
2348  "Only a superuser is authorized to request list of roles granted to another "
2349  "user.");
2350  }
2351  } else {
2352  if (!sys_cat.isRoleGrantedToGrantee(
2353  self.userName, user_name, /*only_direct=*/false)) {
2354  throw std::runtime_error(
2355  "Only a superuser is authorized to request list of roles granted to a role "
2356  "they don't have.");
2357  }
2358  }
2359  }
2360  if (user.isSuper) {
2361  auto s = sys_cat.getCreatedRoles();
2362  roles_list.insert(roles_list.end(), s.begin(), s.end());
2363  } else {
2364  roles_list = sys_cat.getRoles(user_name, effective);
2365  }
2366  for (const std::string& role_name : roles_list) {
2367  logical_values.emplace_back(RelLogicalValues::RowValues{});
2368  logical_values.back().emplace_back(genLiteralStr(role_name));
2369  }
2370 
2371  // Create ResultSet
2372  std::shared_ptr<ResultSet> rSet = std::shared_ptr<ResultSet>(
2373  ResultSetLogicalValuesBuilder::create(label_infos, logical_values));
2374 
2375  return ExecutionResult(rSet, label_infos);
2376 }
2377 
2379  const DdlCommandData& ddl_data,
2380  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
2381  : DdlCommand(ddl_data, session_ptr) {
2382  auto& ddl_payload = extractPayload(ddl_data_);
2383  CHECK(ddl_payload.HasMember("oldOwners"));
2384  CHECK(ddl_payload["oldOwners"].IsArray());
2385  for (const auto& old_owner : ddl_payload["oldOwners"].GetArray()) {
2386  CHECK(old_owner.IsString());
2387  old_owners_.emplace(old_owner.GetString());
2388  }
2389  CHECK(ddl_payload.HasMember("newOwner"));
2390  CHECK(ddl_payload["newOwner"].IsString());
2391  new_owner_ = ddl_payload["newOwner"].GetString();
2392 }
2393 
2395  if (read_only_mode) {
2396  throw std::runtime_error("REASSIGN OWNER invalid in read only mode.");
2397  }
2398  if (!session_ptr_->get_currentUser().isSuper) {
2399  throw std::runtime_error{
2400  "Only super users can reassign ownership of database objects."};
2401  }
2402  const auto catalog = session_ptr_->get_catalog_ptr();
2403  catalog->reassignOwners(old_owners_, new_owner_);
2404  return ExecutionResult();
2405 }
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:63
SQLTypes
Definition: sqltypes.h:52
const std::string commandStr() const
std::string tableName
ExecutionResult execute(bool read_only_mode) override
static const AccessPrivileges ALTER_TABLE
Definition: DBObject.h:165
ExecutionResult execute(bool read_only_mode) override
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:691
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
std::shared_lock< T > shared_lock
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:661
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:341
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)
AlterDatabaseCommand(const DdlCommandData &ddl_data, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
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:700
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:4630
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:677
File_Namespace::GlobalFileMgr * getGlobalFileMgr() const
Definition: DataMgr.cpp:606
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:66
Definition: sqltypes.h:67
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:238
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)
void renameDatabase(std::string const &old_name, std::string const &new_name)
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:7263
std::string returnCacheType() const
void validate_table_type(const TableDescriptor *td, const TableType expected_table_type, const std::string &command)
Definition: DdlUtils.cpp:708
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:59
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:2226
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:323
#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)