OmniSciDB  fe05a0c208
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ForeignTable.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 "ForeignTable.h"
18 
19 #include <regex>
20 
22 #include "Shared/DateTimeParser.h"
23 #include "Shared/misc.h"
24 
26 
27 namespace foreign_storage {
33 
37 }
38 
39 bool ForeignTable::isAppendMode() const {
40  auto update_mode = options.find(REFRESH_UPDATE_TYPE_KEY);
41  return (update_mode != options.end() &&
42  update_mode->second == APPEND_REFRESH_UPDATE_TYPE);
43 }
44 
46  OptionsMap options_map;
47  populateOptionsMap(std::move(options_map));
49 }
50 
51 void ForeignTable::initializeOptions(const rapidjson::Value& options) {
52  // Create the options map first because the json version is not guaranteed to be
53  // upper-case, which we need to compare reliably with alterable_options.
54  auto options_map = createOptionsMap(options);
55  validateSupportedOptionKeys(options_map);
56  populateOptionsMap(std::move(options_map));
58 }
59 
60 // This function can't be static because it needs to know the data wrapper type.
61 void ForeignTable::validateSupportedOptionKeys(const OptionsMap& options_map) const {
62  const auto& data_wrapper_options =
66  for (const auto& [key, value] : options_map) {
68  !shared::contains(data_wrapper_options, key)) {
69  throw std::runtime_error{"Invalid foreign table option \"" + key + "\"."};
70  }
71  }
72 }
73 
75  auto update_type_entry =
77  CHECK(update_type_entry != options.end());
78  auto update_type_value = update_type_entry->second;
79  if (update_type_value != ALL_REFRESH_UPDATE_TYPE &&
80  update_type_value != APPEND_REFRESH_UPDATE_TYPE) {
81  std::string error_message =
82  "Invalid value \"" + update_type_value + "\" for " + REFRESH_UPDATE_TYPE_KEY +
83  " option." + " Value must be \"" + std::string{APPEND_REFRESH_UPDATE_TYPE} +
84  "\" or \"" + std::string{ALL_REFRESH_UPDATE_TYPE} + "\".";
85  throw std::runtime_error{error_message};
86  }
87 
88  auto refresh_timing_entry =
90  CHECK(refresh_timing_entry != options.end());
91  if (auto refresh_timing_value = refresh_timing_entry->second;
92  refresh_timing_value == SCHEDULE_REFRESH_TIMING_TYPE) {
93  auto start_date_entry = options.find(REFRESH_START_DATE_TIME_KEY);
94  if (start_date_entry == options.end()) {
95  throw std::runtime_error{std::string{REFRESH_START_DATE_TIME_KEY} +
96  " option must be provided for scheduled refreshes."};
97  }
98  auto start_date_time = dateTimeParse<kTIMESTAMP>(start_date_entry->second, 0);
99  int64_t current_time = std::chrono::duration_cast<std::chrono::seconds>(
100  std::chrono::system_clock::now().time_since_epoch())
101  .count();
102  if (start_date_time < current_time) {
103  throw std::runtime_error{std::string{REFRESH_START_DATE_TIME_KEY} +
104  " cannot be a past date time."};
105  }
106 
107  auto interval_entry = options.find(REFRESH_INTERVAL_KEY);
108  if (interval_entry != options.end()) {
109  std::string interval_types{"HD"};
111  interval_types += "S";
112  }
113  boost::regex interval_regex{"^\\d{1,}[" + interval_types + "]$",
114  boost::regex::extended | boost::regex::icase};
115  if (!boost::regex_match(interval_entry->second, interval_regex)) {
116  throw std::runtime_error{"Invalid value provided for the " +
117  std::string{REFRESH_INTERVAL_KEY} + " option."};
118  }
119  }
120  } else if (refresh_timing_value != MANUAL_REFRESH_TIMING_TYPE) {
121  throw std::runtime_error{"Invalid value provided for the " +
122  std::string{REFRESH_TIMING_TYPE_KEY} +
123  " option. Value must be \"" + MANUAL_REFRESH_TIMING_TYPE +
124  "\" or \"" + SCHEDULE_REFRESH_TIMING_TYPE + "\"."};
125  }
126 }
127 
131  .validateTableOptions(this);
132 }
133 
134 OptionsMap ForeignTable::createOptionsMap(const rapidjson::Value& json_options) {
135  OptionsMap options_map;
136  CHECK(json_options.IsObject());
137  for (const auto& member : json_options.GetObject()) {
138  auto key = to_upper(member.name.GetString());
139  if (std::find(upper_case_options.begin(), upper_case_options.end(), key) !=
140  upper_case_options.end()) {
141  options_map[key] = to_upper(member.value.GetString());
142  } else {
143  options_map[key] = member.value.GetString();
144  }
145  }
146  return options_map;
147 }
148 
149 void ForeignTable::validateAlterOptions(const OptionsMap& options_map) {
150  for (const auto& [key, value] : options_map) {
151  if (!shared::contains(alterable_options, key)) {
152  throw std::runtime_error{std::string("Altering foreign table option \"") + key +
153  "\" is not currently supported."};
154  }
155  }
156 }
157 
158 void ForeignTable::validateSchema(const std::list<ColumnDescriptor>& columns) const {
161  .validateSchema(columns);
162 }
163 
164 } // namespace foreign_storage
bool contains(const T &container, const U &element)
Definition: misc.h:163
static const ForeignDataWrapper & createForValidation(const std::string &data_wrapper_type, const ForeignTable *foreign_table=nullptr)
static void validateAlterOptions(const OptionsMap &options_map)
Verifies that the given options map only contains options that can be legally altered.
void validateDataWrapperOptions() const
static const std::set< const char * > supported_options
Definition: ForeignTable.h:56
void initializeOptions()
Creates an empty option map for the table. Verifies that the required option keys are present and tha...
void validateOptionValues() const
Verifies the values for mapped options are valid.
virtual const std::set< std::string_view > & getSupportedTableOptions() const =0
void validateSupportedOptionKeys(const OptionsMap &options_map) const
Verifies that the options_map contains the keys required by a foreign table; including those specifie...
static constexpr const char * MANUAL_REFRESH_TIMING_TYPE
Definition: ForeignTable.h:50
virtual void validateTableOptions(const ForeignTable *foreign_table) const =0
static OptionsMap createOptionsMap(const rapidjson::Value &json_options)
Creates an options map from given options. Converts options that must be upper case appropriately...
static constexpr const char * REFRESH_START_DATE_TIME_KEY
Definition: ForeignTable.h:43
static constexpr const char * REFRESH_UPDATE_TYPE_KEY
Definition: ForeignTable.h:45
int count
void populateOptionsMap(OptionsMap &&options_map, bool clear=false)
static constexpr const char * REFRESH_INTERVAL_KEY
Definition: ForeignTable.h:44
void validateRefreshOptionValues() const
bool isAppendMode() const
Checks if the table is in append mode.
std::string to_upper(const std::string &str)
void validateSchema(const std::list< ColumnDescriptor > &columns) const
Verifies the schema is supported by this foreign table.
static const std::set< const char * > alterable_options
Definition: ForeignTable.h:69
bool g_enable_seconds_refresh
static constexpr const char * ALL_REFRESH_UPDATE_TYPE
Definition: ForeignTable.h:47
static constexpr const char * APPEND_REFRESH_UPDATE_TYPE
Definition: ForeignTable.h:48
const ForeignServer * foreign_server
Definition: ForeignTable.h:53
static constexpr const char * REFRESH_TIMING_TYPE_KEY
Definition: ForeignTable.h:42
#define CHECK(condition)
Definition: Logger.h:203
std::map< std::string, std::string, std::less<>> OptionsMap
static constexpr const char * SCHEDULE_REFRESH_TIMING_TYPE
Definition: ForeignTable.h:49
virtual void validateSchema(const std::list< ColumnDescriptor > &columns) const
static const std::set< const char * > upper_case_options
Definition: ForeignTable.h:62