OmniSciDB  0b528656ed
DdlCommandExecutor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "DdlCommandExecutor.h"
18 
19 #include <boost/algorithm/string/predicate.hpp>
20 
21 #include "Catalog/Catalog.h"
22 #include "Catalog/SysCatalog.h"
25 #include "LockMgr/LockMgr.h"
26 #include "Parser/ParserNode.h"
27 #include "Shared/StringTransform.h"
28 
29 extern bool g_enable_fsi;
30 
31 bool DdlCommand::isDefaultServer(const std::string& server_name) {
32  return boost::iequals(server_name.substr(0, 7), "omnisci");
33 }
34 
35 namespace {
36 void set_headers(TQueryResult& _return, const std::vector<std::string>& headers) {
37  TRowDescriptor row_descriptor;
38  for (const auto& header : headers) {
39  TColumnType column_type{};
40  column_type.col_name = header;
41  column_type.col_type.type = TDatumType::type::STR;
42  row_descriptor.push_back(column_type);
43 
44  _return.row_set.columns.emplace_back();
45  }
46  _return.row_set.row_desc = row_descriptor;
47  _return.row_set.is_columnar = true;
48 }
49 
50 void add_row(TQueryResult& _return, const std::vector<std::string>& row) {
51  for (size_t i = 0; i < row.size(); i++) {
52  _return.row_set.columns[i].data.str_col.emplace_back(row[i]);
53  _return.row_set.columns[i].nulls.emplace_back(false);
54  }
55 }
56 } // namespace
57 
59  const std::string& ddl_statement,
60  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
61  : session_ptr_(session_ptr) {
62  CHECK(!ddl_statement.empty());
63  ddl_query_.Parse(ddl_statement);
64  CHECK(ddl_query_.IsObject());
65  CHECK(ddl_query_.HasMember("payload"));
66  CHECK(ddl_query_["payload"].IsObject());
67  const auto& payload = ddl_query_["payload"].GetObject();
68  CHECK(payload.HasMember("command"));
69  CHECK(payload["command"].IsString());
70 }
71 
72 void DdlCommandExecutor::execute(TQueryResult& _return) {
73  const auto& payload = ddl_query_["payload"].GetObject();
74  const auto& ddl_command = std::string_view(payload["command"].GetString());
75  if (ddl_command == "CREATE_SERVER") {
76  CreateForeignServerCommand{payload, session_ptr_}.execute(_return);
77  } else if (ddl_command == "DROP_SERVER") {
78  DropForeignServerCommand{payload, session_ptr_}.execute(_return);
79  } else if (ddl_command == "CREATE_FOREIGN_TABLE") {
80  CreateForeignTableCommand{payload, session_ptr_}.execute(_return);
81  } else if (ddl_command == "DROP_FOREIGN_TABLE") {
82  DropForeignTableCommand{payload, session_ptr_}.execute(_return);
83  } else if (ddl_command == "SHOW_TABLES") {
84  ShowTablesCommand{payload, session_ptr_}.execute(_return);
85  } else if (ddl_command == "SHOW_DATABASES") {
86  ShowDatabasesCommand{payload, session_ptr_}.execute(_return);
87  } else if (ddl_command == "SHOW_SERVERS") {
88  ShowForeignServersCommand{payload, session_ptr_}.execute(_return);
89  } else if (ddl_command == "ALTER_SERVER") {
90  AlterForeignServerCommand{payload, session_ptr_}.execute(_return);
91  } else if (ddl_command == "REFRESH_FOREIGN_TABLES") {
92  RefreshForeignTablesCommand{payload, session_ptr_}.execute(_return);
93  } else {
94  throw std::runtime_error("Unsupported DDL command");
95  }
96 }
97 
99  const auto& payload = ddl_query_["payload"].GetObject();
100  const auto& ddl_command = std::string_view(payload["command"].GetString());
101  return (ddl_command == "SHOW_USER_SESSIONS");
102 }
103 
105  const rapidjson::Value& ddl_payload,
106  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
107  : DdlCommand(ddl_payload, session_ptr) {
108  CHECK(ddl_payload.HasMember("serverName"));
109  CHECK(ddl_payload["serverName"].IsString());
110  CHECK(ddl_payload.HasMember("dataWrapper"));
111  CHECK(ddl_payload["dataWrapper"].IsString());
112  CHECK(ddl_payload.HasMember("options"));
113  CHECK(ddl_payload["options"].IsObject());
114  CHECK(ddl_payload.HasMember("ifNotExists"));
115  CHECK(ddl_payload["ifNotExists"].IsBool());
116 }
117 
118 void CreateForeignServerCommand::execute(TQueryResult& _return) {
119  std::string server_name = ddl_payload_["serverName"].GetString();
120  if (isDefaultServer(server_name)) {
121  throw std::runtime_error{"Server names cannot start with \"omnisci\"."};
122  }
123  bool if_not_exists = ddl_payload_["ifNotExists"].GetBool();
124  if (session_ptr_->getCatalog().getForeignServer(server_name)) {
125  if (if_not_exists) {
126  return;
127  } else {
128  throw std::runtime_error{"A foreign server with name \"" + server_name +
129  "\" already exists."};
130  }
131  }
132  // check access privileges
133  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::ServerDBObjectType,
135  throw std::runtime_error("Server " + std::string(server_name) +
136  " will not be created. User has no create privileges.");
137  }
138 
139  auto& current_user = session_ptr_->get_currentUser();
140  auto foreign_server = std::make_unique<foreign_storage::ForeignServer>();
141  foreign_server->data_wrapper_type = to_upper(ddl_payload_["dataWrapper"].GetString());
142  foreign_server->name = server_name;
143  foreign_server->user_id = current_user.userId;
144  foreign_server->populateOptionsMap(ddl_payload_["options"]);
145  foreign_server->validate();
146 
147  auto& catalog = session_ptr_->getCatalog();
148  catalog.createForeignServer(std::move(foreign_server),
149  ddl_payload_["ifNotExists"].GetBool());
151  current_user, server_name, ServerDBObjectType, catalog);
152 }
153 
155  const rapidjson::Value& ddl_payload,
156  std::shared_ptr<const Catalog_Namespace::SessionInfo> session_ptr)
157  : DdlCommand(ddl_payload, session_ptr) {
158  CHECK(ddl_payload.HasMember("serverName"));
159  CHECK(ddl_payload["serverName"].IsString());
160  CHECK(ddl_payload.HasMember("alterType"));
161  CHECK(ddl_payload["alterType"].IsString());
162  if (ddl_payload["alterType"] == "SET_OPTIONS") {
163  CHECK(ddl_payload.HasMember("options"));
164  CHECK(ddl_payload["options"].IsObject());
165  } else if (ddl_payload["alterType"] == "SET_DATA_WRAPPER") {
166  CHECK(ddl_payload.HasMember("dataWrapper"));
167  CHECK(ddl_payload["dataWrapper"].IsString());
168  } else if (ddl_payload["alterType"] == "RENAME_SERVER") {
169  CHECK(ddl_payload.HasMember("newServerName"));
170  CHECK(ddl_payload["newServerName"].IsString());
171  } else if (ddl_payload["alterType"] == "CHANGE_OWNER") {
172  CHECK(ddl_payload.HasMember("newOwner"));
173  CHECK(ddl_payload["newOwner"].IsString());
174  } else {
175  UNREACHABLE(); // not-implemented alterType
176  }
177 }
178 
179 void AlterForeignServerCommand::execute(TQueryResult& _return) {
180  std::string server_name = ddl_payload_["serverName"].GetString();
181  if (isDefaultServer(server_name)) {
182  throw std::runtime_error{"OmniSci default servers cannot be altered."};
183  }
184  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
185  throw std::runtime_error{"Foreign server with name \"" + server_name +
186  "\" does not exist and can not be altered."};
187  }
188  if (!hasAlterServerPrivileges()) {
189  throw std::runtime_error("Server " + server_name +
190  " can not be altered. User has no ALTER SERVER privileges.");
191  }
192  std::string alter_type = ddl_payload_["alterType"].GetString();
193  if (alter_type == "CHANGE_OWNER") {
195  } else if (alter_type == "SET_DATA_WRAPPER") {
197  } else if (alter_type == "SET_OPTIONS") {
199  } else if (alter_type == "RENAME_SERVER") {
201  }
202 }
203 
205  std::string server_name = ddl_payload_["serverName"].GetString();
206  std::string new_owner = ddl_payload_["newOwner"].GetString();
207  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
208  if (!session_ptr_->get_currentUser().isSuper) {
209  throw std::runtime_error(
210  "Only a super user can change a foreign server's owner. "
211  "Current user is not a super-user. "
212  "Foreign server with name \"" +
213  server_name + "\" will not have owner changed.");
214  }
215  Catalog_Namespace::UserMetadata user, original_owner;
216  if (!sys_cat.getMetadataForUser(new_owner, user)) {
217  throw std::runtime_error("User with username \"" + new_owner + "\" does not exist. " +
218  "Foreign server with name \"" + server_name +
219  "\" can not have owner changed.");
220  }
221  auto& cat = session_ptr_->getCatalog();
222  // get original owner metadata
223  bool original_owner_exists = sys_cat.getMetadataForUserById(
224  cat.getForeignServer(server_name)->user_id, original_owner);
225  // update catalog
226  cat.changeForeignServerOwner(server_name, user.userId);
227  try {
228  // update permissions
229  DBObject db_object(server_name, DBObjectType::ServerDBObjectType);
230  sys_cat.changeDBObjectOwnership(
231  user, original_owner, db_object, cat, original_owner_exists);
232  } catch (const std::runtime_error& e) {
233  // update permissions failed, revert catalog update
234  cat.changeForeignServerOwner(server_name, original_owner.userId);
235  throw;
236  }
237 }
238 
240  std::string server_name = ddl_payload_["serverName"].GetString();
241  std::string new_server_name = ddl_payload_["newServerName"].GetString();
242  if (isDefaultServer(new_server_name)) {
243  throw std::runtime_error{"OmniSci prefix can not be used for new name of server."};
244  }
245  auto& cat = session_ptr_->getCatalog();
246  // check for a conflicting server
247  if (cat.getForeignServer(new_server_name)) {
248  throw std::runtime_error("Foreign server with name \"" + server_name +
249  "\" can not be renamed to \"" + new_server_name + "\"." +
250  "Foreign server with name \"" + new_server_name +
251  "\" exists.");
252  }
253  // update catalog
254  cat.renameForeignServer(server_name, new_server_name);
255  try {
256  // migrate object privileges
257  auto& sys_cat = Catalog_Namespace::SysCatalog::instance();
258  sys_cat.renameDBObject(server_name,
259  new_server_name,
261  cat.getForeignServer(new_server_name)->id,
262  cat);
263  } catch (const std::runtime_error& e) {
264  // permission migration failed, revert catalog update
265  cat.renameForeignServer(new_server_name, server_name);
266  throw;
267  }
268 }
269 
271  std::string server_name = ddl_payload_["serverName"].GetString();
272  auto& cat = session_ptr_->getCatalog();
273  // update catalog
274  const auto foreign_server = cat.getForeignServer(server_name);
276  opt.populateOptionsMap(foreign_server->getOptionsAsJsonString());
277  opt.populateOptionsMap(ddl_payload_["options"]);
278  cat.setForeignServerOptions(server_name, opt.getOptionsAsJsonString());
279 }
280 
282  std::string server_name = ddl_payload_["serverName"].GetString();
283  std::string data_wrapper = ddl_payload_["dataWrapper"].GetString();
284  auto& cat = session_ptr_->getCatalog();
285  // update catalog
286  cat.setForeignServerDataWrapper(server_name, data_wrapper);
287 }
288 
290  // TODO: implement `GRANT/REVOKE ALTER_SERVER` DDL commands
291  std::string server_name = ddl_payload_["serverName"].GetString();
292  return session_ptr_->checkDBAccessPrivileges(
294 }
295 
297  const rapidjson::Value& ddl_payload,
298  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
299  : DdlCommand(ddl_payload, session_ptr) {
300  CHECK(ddl_payload.HasMember("serverName"));
301  CHECK(ddl_payload["serverName"].IsString());
302  CHECK(ddl_payload.HasMember("ifExists"));
303  CHECK(ddl_payload["ifExists"].IsBool());
304 }
305 
306 void DropForeignServerCommand::execute(TQueryResult& _return) {
307  std::string server_name = ddl_payload_["serverName"].GetString();
308  if (isDefaultServer(server_name)) {
309  throw std::runtime_error{"OmniSci default servers cannot be dropped."};
310  }
311  bool if_exists = ddl_payload_["ifExists"].GetBool();
312  if (!session_ptr_->getCatalog().getForeignServer(server_name)) {
313  if (if_exists) {
314  return;
315  } else {
316  throw std::runtime_error{"Foreign server with name \"" + server_name +
317  "\" does not exist."};
318  }
319  }
320  // check access privileges
321  if (!session_ptr_->checkDBAccessPrivileges(
323  throw std::runtime_error("Server " + server_name +
324  " will not be dropped. User has no DROP SERVER privileges.");
325  }
327  DBObject(server_name, ServerDBObjectType), session_ptr_->get_catalog_ptr().get());
328  session_ptr_->getCatalog().dropForeignServer(ddl_payload_["serverName"].GetString());
329 }
330 
331 SQLTypes JsonColumnSqlType::getSqlType(const rapidjson::Value& data_type) {
332  CHECK(data_type.IsObject());
333  CHECK(data_type.HasMember("type"));
334  CHECK(data_type["type"].IsString());
335 
336  std::string type = data_type["type"].GetString();
337  if (boost::iequals(type, "ARRAY")) {
338  CHECK(data_type.HasMember("array"));
339  CHECK(data_type["array"].IsObject());
340 
341  const auto& array = data_type["array"].GetObject();
342  CHECK(array.HasMember("elementType"));
343  CHECK(array["elementType"].IsString());
344  type = array["elementType"].GetString();
345  }
346  return getSqlType(type);
347 }
348 
350  if (boost::iequals(type, "BIGINT")) {
351  return kBIGINT;
352  }
353  if (boost::iequals(type, "BOOLEAN")) {
354  return kBOOLEAN;
355  }
356  if (boost::iequals(type, "DATE")) {
357  return kDATE;
358  }
359  if (boost::iequals(type, "DECIMAL")) {
360  return kDECIMAL;
361  }
362  if (boost::iequals(type, "DOUBLE")) {
363  return kDOUBLE;
364  }
365  if (boost::iequals(type, "FLOAT")) {
366  return kFLOAT;
367  }
368  if (boost::iequals(type, "INTEGER")) {
369  return kINT;
370  }
371  if (boost::iequals(type, "LINESTRING")) {
372  return kLINESTRING;
373  }
374  if (boost::iequals(type, "MULTIPOLYGON")) {
375  return kMULTIPOLYGON;
376  }
377  if (boost::iequals(type, "POINT")) {
378  return kPOINT;
379  }
380  if (boost::iequals(type, "POLYGON")) {
381  return kPOLYGON;
382  }
383  if (boost::iequals(type, "SMALLINT")) {
384  return kSMALLINT;
385  }
386  if (boost::iequals(type, "TEXT")) {
387  return kTEXT;
388  }
389  if (boost::iequals(type, "TIME")) {
390  return kTIME;
391  }
392  if (boost::iequals(type, "TIMESTAMP")) {
393  return kTIMESTAMP;
394  }
395  if (boost::iequals(type, "TINYINT")) {
396  return kTINYINT;
397  }
398 
399  throw std::runtime_error{"Unsupported type \"" + type + "\" specified."};
400 }
401 
402 int JsonColumnSqlType::getParam1(const rapidjson::Value& data_type) {
403  int param1 = -1;
404  CHECK(data_type.IsObject());
405  if (data_type.HasMember("precision") && !data_type["precision"].IsNull()) {
406  CHECK(data_type["precision"].IsInt());
407  param1 = data_type["precision"].GetInt();
408  } else if (auto type = getSqlType(data_type); IS_GEO(type)) {
409  param1 = static_cast<int>(kGEOMETRY);
410  }
411  return param1;
412 }
413 
414 int JsonColumnSqlType::getParam2(const rapidjson::Value& data_type) {
415  int param2 = 0;
416  CHECK(data_type.IsObject());
417  if (data_type.HasMember("scale") && !data_type["scale"].IsNull()) {
418  CHECK(data_type["scale"].IsInt());
419  param2 = data_type["scale"].GetInt();
420  } else if (auto type = getSqlType(data_type); IS_GEO(type) &&
421  data_type.HasMember("coordinateSystem") &&
422  !data_type["coordinateSystem"].IsNull()) {
423  CHECK(data_type["coordinateSystem"].IsInt());
424  param2 = data_type["coordinateSystem"].GetInt();
425  }
426  return param2;
427 }
428 
429 bool JsonColumnSqlType::isArray(const rapidjson::Value& data_type) {
430  CHECK(data_type.IsObject());
431  CHECK(data_type.HasMember("type"));
432  CHECK(data_type["type"].IsString());
433  return boost::iequals(data_type["type"].GetString(), "ARRAY");
434 }
435 
436 int JsonColumnSqlType::getArraySize(const rapidjson::Value& data_type) {
437  int size = -1;
438  if (isArray(data_type)) {
439  CHECK(data_type.HasMember("array"));
440  CHECK(data_type["array"].IsObject());
441 
442  const auto& array = data_type["array"].GetObject();
443  if (array.HasMember("size") && !array["size"].IsNull()) {
444  CHECK(array["size"].IsInt());
445  size = array["size"].GetInt();
446  }
447  }
448  return size;
449 }
450 
451 std::string* JsonColumnEncoding::getEncodingName(const rapidjson::Value& data_type) {
452  CHECK(data_type.IsObject());
453  CHECK(data_type.HasMember("encoding"));
454  CHECK(data_type["encoding"].IsObject());
455 
456  const auto& encoding = data_type["encoding"].GetObject();
457  CHECK(encoding.HasMember("type"));
458  CHECK(encoding["type"].IsString());
459  return new std::string(encoding["type"].GetString());
460 }
461 
462 int JsonColumnEncoding::getEncodingParam(const rapidjson::Value& data_type) {
463  CHECK(data_type.IsObject());
464  CHECK(data_type.HasMember("encoding"));
465  CHECK(data_type["encoding"].IsObject());
466 
467  int encoding_size = 0;
468  const auto& encoding = data_type["encoding"].GetObject();
469  if (encoding.HasMember("size") && !encoding["size"].IsNull()) {
470  CHECK(encoding["size"].IsInt());
471  encoding_size = encoding["size"].GetInt();
472  }
473  return encoding_size;
474 }
475 
477  const rapidjson::Value& ddl_payload,
478  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
479  : DdlCommand(ddl_payload, session_ptr) {
480  CHECK(ddl_payload.HasMember("serverName"));
481  CHECK(ddl_payload["serverName"].IsString());
482  CHECK(ddl_payload.HasMember("tableName"));
483  CHECK(ddl_payload["tableName"].IsString());
484  CHECK(ddl_payload.HasMember("ifNotExists"));
485  CHECK(ddl_payload["ifNotExists"].IsBool());
486  CHECK(ddl_payload.HasMember("columns"));
487  CHECK(ddl_payload["columns"].IsArray());
488 }
489 
490 void CreateForeignTableCommand::execute(TQueryResult& _return) {
491  auto& catalog = session_ptr_->getCatalog();
492 
493  const std::string& table_name = ddl_payload_["tableName"].GetString();
494  if (!session_ptr_->checkDBAccessPrivileges(DBObjectType::TableDBObjectType,
496  throw std::runtime_error(
497  "Foreign table \"" + table_name +
498  "\" will not be created. User has no CREATE TABLE privileges.");
499  }
500 
501  bool if_not_exists = ddl_payload_["ifNotExists"].GetBool();
502  if (!catalog.validateNonExistentTableOrView(table_name, if_not_exists)) {
503  return;
504  }
505 
506  foreign_storage::ForeignTable foreign_table{};
507  std::list<ColumnDescriptor> columns{};
508  setColumnDetails(columns);
509  setTableDetails(table_name, foreign_table, columns.size());
510  catalog.createTable(foreign_table, columns, {}, true);
511 
512  // TODO (max): It's transactionally unsafe, should be fixed: we may create object w/o
513  // privileges
515  session_ptr_->get_currentUser(),
516  foreign_table.tableName,
518  catalog);
519 }
520 
521 void CreateForeignTableCommand::setTableDetails(const std::string& table_name,
522  TableDescriptor& td,
523  const size_t column_count) {
524  ddl_utils::set_default_table_attributes(table_name, td, column_count);
525  td.userId = session_ptr_->get_currentUser().userId;
527  td.hasDeletedCol = false;
528  td.keyMetainfo = "[]";
529  td.fragments = "";
530  td.partitions = "";
531 
532  auto& foreign_table = dynamic_cast<foreign_storage::ForeignTable&>(td);
533  const std::string server_name = ddl_payload_["serverName"].GetString();
534  foreign_table.foreign_server = session_ptr_->getCatalog().getForeignServer(server_name);
535  if (!foreign_table.foreign_server) {
536  throw std::runtime_error{"Foreign server with name \"" + server_name +
537  "\" does not exist."};
538  }
539 
540  if (ddl_payload_.HasMember("options") && !ddl_payload_["options"].IsNull()) {
541  CHECK(ddl_payload_["options"].IsObject());
542  foreign_table.populateOptionsMap(ddl_payload_["options"]);
543 
544  if (foreign_table.foreign_server->data_wrapper_type ==
547  } else if (foreign_table.foreign_server->data_wrapper_type ==
550  }
551  }
552 
553  if (const auto it = foreign_table.options.find("FRAGMENT_SIZE");
554  it != foreign_table.options.end()) {
555  foreign_table.maxFragRows = std::stoi(it->second);
556  }
557 }
558 
559 void CreateForeignTableCommand::setColumnDetails(std::list<ColumnDescriptor>& columns) {
560  std::unordered_set<std::string> column_names{};
561  for (auto& column_def : ddl_payload_["columns"].GetArray()) {
562  CHECK(column_def.IsObject());
563  CHECK(column_def.HasMember("name"));
564  CHECK(column_def["name"].IsString());
565  const std::string& column_name = column_def["name"].GetString();
566 
567  CHECK(column_def.HasMember("dataType"));
568  CHECK(column_def["dataType"].IsObject());
569 
570  JsonColumnSqlType sql_type{column_def["dataType"]};
571  const auto& data_type = column_def["dataType"].GetObject();
572  CHECK(data_type.HasMember("notNull"));
573  CHECK(data_type["notNull"].IsBool());
574 
575  std::unique_ptr<JsonColumnEncoding> encoding;
576  if (data_type.HasMember("encoding") && !data_type["encoding"].IsNull()) {
577  CHECK(data_type["encoding"].IsObject());
578  encoding = std::make_unique<JsonColumnEncoding>(column_def["dataType"]);
579  }
580 
581  ColumnDescriptor cd;
582  ddl_utils::validate_non_duplicate_column(column_name, column_names);
585  column_name, cd, &sql_type, data_type["notNull"].GetBool(), encoding.get());
586  columns.emplace_back(cd);
587  }
588 }
589 
591  const rapidjson::Value& ddl_payload,
592  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
593  : DdlCommand(ddl_payload, session_ptr) {
594  CHECK(ddl_payload.HasMember("tableName"));
595  CHECK(ddl_payload["tableName"].IsString());
596  CHECK(ddl_payload.HasMember("ifExists"));
597  CHECK(ddl_payload["ifExists"].IsBool());
598 }
599 
600 void DropForeignTableCommand::execute(TQueryResult& _return) {
601  auto& catalog = session_ptr_->getCatalog();
602  const std::string& table_name = ddl_payload_["tableName"].GetString();
603  const TableDescriptor* td{nullptr};
604  std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>> td_with_lock;
605 
606  try {
607  td_with_lock =
608  std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>>(
610  catalog, table_name, false));
611  td = (*td_with_lock)();
612  } catch (const std::runtime_error& e) {
613  if (ddl_payload_["ifExists"].GetBool()) {
614  return;
615  } else {
616  throw e;
617  }
618  }
619 
620  CHECK(td);
621  CHECK(td_with_lock);
622 
623  if (!session_ptr_->checkDBAccessPrivileges(
625  throw std::runtime_error(
626  "Foreign table \"" + table_name +
627  "\" will not be dropped. User has no DROP TABLE privileges.");
628  }
629 
631  auto table_data_write_lock =
633  catalog.dropTable(td);
634 }
635 
637  const rapidjson::Value& ddl_payload,
638  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
639  : DdlCommand(ddl_payload, session_ptr) {}
640 
641 void ShowTablesCommand::execute(TQueryResult& _return) {
642  // Get all table names in the same way as OmniSql \t command
643  auto cat_ptr = session_ptr_->get_catalog_ptr();
644  auto table_names =
645  cat_ptr->getTableNamesForUser(session_ptr_->get_currentUser(), GET_PHYSICAL_TABLES);
646  set_headers(_return, std::vector<std::string>{"table_name"});
647  // Place table names in query result
648  for (auto& table_name : table_names) {
649  add_row(_return, std::vector<std::string>{table_name});
650  }
651 }
652 
654  const rapidjson::Value& ddl_payload,
655  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
656  : DdlCommand(ddl_payload, session_ptr) {}
657 
658 void ShowDatabasesCommand::execute(TQueryResult& _return) {
659  const auto& user = session_ptr_->get_currentUser();
660  const Catalog_Namespace::DBSummaryList db_summaries =
662  set_headers(_return, {"Database", "Owner"});
663  for (const auto& db_summary : db_summaries) {
664  add_row(_return, {db_summary.dbName, db_summary.dbOwnerName});
665  }
666 }
667 
669  const rapidjson::Value& ddl_payload,
670  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
671  : DdlCommand(ddl_payload, session_ptr) {
672  if (!g_enable_fsi) {
673  throw std::runtime_error("Unsupported command: SHOW FOREIGN SERVERS");
674  }
675  // Verify that members are valid
676  CHECK(ddl_payload.HasMember("command"));
677  if (ddl_payload.HasMember("filters")) {
678  CHECK(ddl_payload["filters"].IsArray());
679  int num_filters = 0;
680  for (auto const& filter_def : ddl_payload["filters"].GetArray()) {
681  CHECK(filter_def.IsObject());
682  CHECK(filter_def.HasMember("attribute"));
683  CHECK(filter_def["attribute"].IsString());
684  CHECK(filter_def.HasMember("value"));
685  CHECK(filter_def["value"].IsString());
686  CHECK(filter_def.HasMember("operation"));
687  CHECK(filter_def["operation"].IsString());
688  if (num_filters > 0) {
689  CHECK(filter_def.HasMember("chain"));
690  CHECK(filter_def["chain"].IsString());
691  } else {
692  CHECK(!filter_def.HasMember("chain"));
693  }
694  num_filters++;
695  }
696  }
697 }
698 
699 void ShowForeignServersCommand::execute(TQueryResult& _return) {
700  const std::vector<std::string> col_names{
701  "server_name", "data_wrapper", "created_at", "options"};
702 
703  std::vector<const foreign_storage::ForeignServer*> results;
704  const auto& user = session_ptr_->get_currentUser();
705  if (ddl_payload_.HasMember("filters")) {
706  session_ptr_->getCatalog().getForeignServersForUser(
707  &ddl_payload_["filters"], user, results);
708  } else {
709  session_ptr_->getCatalog().getForeignServersForUser(nullptr, user, results);
710  }
711  set_headers(_return, col_names);
712 
713  _return.row_set.row_desc[2].col_type.type = TDatumType::type::TIMESTAMP;
714 
715  for (auto const& server_ptr : results) {
716  _return.row_set.columns[0].data.str_col.emplace_back(server_ptr->name);
717 
718  _return.row_set.columns[1].data.str_col.emplace_back(server_ptr->data_wrapper_type);
719 
720  _return.row_set.columns[2].data.int_col.push_back(server_ptr->creation_time);
721 
722  _return.row_set.columns[3].data.str_col.emplace_back(
723  server_ptr->getOptionsAsJsonString());
724 
725  for (size_t i = 0; i < _return.row_set.columns.size(); i++)
726  _return.row_set.columns[i].nulls.emplace_back(false);
727  }
728 }
729 
731  const rapidjson::Value& ddl_payload,
732  std::shared_ptr<Catalog_Namespace::SessionInfo const> session_ptr)
733  : DdlCommand(ddl_payload, session_ptr) {
734  CHECK(ddl_payload.HasMember("tableNames"));
735  CHECK(ddl_payload["tableNames"].IsArray());
736  for (auto const& tableName_def : ddl_payload["tableNames"].GetArray()) {
737  CHECK(tableName_def.IsString());
738  }
739 }
740 
741 void RefreshForeignTablesCommand::execute(TQueryResult& _return) {
743  if (ddl_payload_.HasMember("options") && !ddl_payload_["options"].IsNull()) {
744  opt.populateOptionsMap(ddl_payload_["options"]);
745  CHECK(opt.options.find("EVICT") != opt.options.end());
746  CHECK(boost::iequals(opt.options["EVICT"], "true") ||
747  boost::iequals(opt.options["EVICT"], "false"));
748  }
749  throw std::runtime_error("REFRESH FOREIGN TABLES is not yet implemented");
750 }
std::string partitions
static int getParam2(const rapidjson::Value &data_type)
std::map< std::string, std::string, std::less<> > options
static const AccessPrivileges DROP_SERVER
Definition: DBObject.h:190
static bool isArray(const rapidjson::Value &data_type)
void execute(TQueryResult &_return) override
Definition: sqltypes.h:50
SQLTypes
Definition: sqltypes.h:39
std::string getOptionsAsJsonString() const
void execute(TQueryResult &_return) override
static void validateOptions(const ForeignTable *foreign_table)
static WriteLock getWriteLockForTable(const Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:155
ShowDatabasesCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
std::string storageType
void revokeDBObjectPrivilegesFromAll(DBObject object, Catalog *catalog)
void execute(TQueryResult &_return) override
AlterForeignServerCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
#define UNREACHABLE()
Definition: Logger.h:241
void populateOptionsMap(const rapidjson::Value &ddl_options)
std::string fragments
DropForeignServerCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static int getEncodingParam(const rapidjson::Value &data_type)
DropForeignTableCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static int getArraySize(const rapidjson::Value &data_type)
void createDBObject(const UserMetadata &user, const std::string &objectName, DBObjectType type, const Catalog_Namespace::Catalog &catalog, int32_t objectId=-1)
void validate_non_duplicate_column(const std::string &column_name, std::unordered_set< std::string > &upper_column_names)
Definition: DdlUtils.cpp:520
ShowTablesCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
static const AccessPrivileges ALTER_SERVER
Definition: DBObject.h:191
This file contains the class specification and related data structures for Catalog.
void execute(TQueryResult &_return) override
static SysCatalog & instance()
Definition: SysCatalog.h:284
This file contains the class specification and related data structures for SysCatalog.
std::string cat(Ts &&... args)
Classes representing a parse tree.
void execute(TQueryResult &_return) override
void setColumnDetails(std::list< ColumnDescriptor > &columns)
static const AccessPrivileges DROP_TABLE
Definition: DBObject.h:160
RefreshForeignTablesCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
CreateForeignTableCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
DBSummaryList getDatabaseListForUser(const UserMetadata &user)
void execute(TQueryResult &_return) override
bool g_enable_fsi
Definition: Catalog.cpp:90
static const AccessPrivileges CREATE_SERVER
Definition: DBObject.h:189
void validate_non_reserved_keyword(const std::string &column_name)
Definition: DdlUtils.cpp:529
specifies the content in-memory of a row in the column metadata table
CreateForeignServerCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
void set_headers(TQueryResult &_return, const std::vector< std::string > &headers)
static const AccessPrivileges CREATE_TABLE
Definition: DBObject.h:159
std::string keyMetainfo
void set_default_table_attributes(const std::string &table_name, TableDescriptor &td, const int32_t column_count)
Definition: DdlUtils.cpp:506
void add_row(TQueryResult &_return, const std::vector< std::string > &row)
std::string to_upper(const std::string &str)
void set_column_descriptor(const std::string &column_name, ColumnDescriptor &cd, SqlType *column_type, const bool not_null, const Encoding *encoding)
Definition: DdlUtils.cpp:492
void execute(TQueryResult &_return)
Definition: sqltypes.h:53
Definition: sqltypes.h:54
std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr_
void execute(TQueryResult &_return) override
void validate_drop_table_type(const TableDescriptor *td, const TableType expected_table_type)
Definition: DdlUtils.cpp:537
void setTableDetails(const std::string &table_name, TableDescriptor &td, const size_t column_count)
rapidjson::Document ddl_query_
#define CHECK(condition)
Definition: Logger.h:197
static constexpr char const * CSV
Definition: ForeignServer.h:35
static std::string * getEncodingName(const rapidjson::Value &data_type)
void execute(TQueryResult &_return) override
static SQLTypes getSqlType(const rapidjson::Value &data_type)
bool isDefaultServer(const std::string &server_name)
void execute(TQueryResult &_return) override
const rapidjson::Value & ddl_payload_
static void validateOptions(const ForeignTable *foreign_table)
std::list< DBSummary > DBSummaryList
Definition: SysCatalog.h:120
Definition: sqltypes.h:46
std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr_
DdlCommandExecutor(const std::string &ddl_statement, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)
specifies the content in-memory of a row in the table metadata table
static int getParam1(const rapidjson::Value &data_type)
static constexpr char const * FOREIGN_TABLE
#define IS_GEO(T)
Definition: sqltypes.h:172
static constexpr char const * PARQUET
Definition: ForeignServer.h:36
ShowForeignServersCommand(const rapidjson::Value &ddl_payload, std::shared_ptr< Catalog_Namespace::SessionInfo const > session_ptr)