OmniSciDB  91042dcc5b
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 "RefreshTimeCalculator.h"
23 #include "Shared/DateTimeParser.h"
24 #include "Shared/misc.h"
25 
27 
28 namespace foreign_storage {
34 
38 }
39 
40 bool ForeignTable::isAppendMode() const {
41  auto update_mode = options.find(REFRESH_UPDATE_TYPE_KEY);
42  return (update_mode != options.end() &&
43  update_mode->second == APPEND_REFRESH_UPDATE_TYPE);
44 }
45 
47  OptionsMap options_map;
48  populateOptionsMap(std::move(options_map));
50 }
51 
52 void ForeignTable::initializeOptions(const rapidjson::Value& options) {
53  // Create the options map first because the json version is not guaranteed to be
54  // upper-case, which we need to compare reliably with alterable_options.
55  auto options_map = createOptionsMap(options);
56  validateSupportedOptionKeys(options_map);
57  populateOptionsMap(std::move(options_map));
59 }
60 
61 // This function can't be static because it needs to know the data wrapper type.
62 void ForeignTable::validateSupportedOptionKeys(const OptionsMap& options_map) const {
63  const auto& data_wrapper_options =
67  for (const auto& [key, value] : options_map) {
69  !shared::contains(data_wrapper_options, key)) {
70  throw std::runtime_error{"Invalid foreign table option \"" + key + "\"."};
71  }
72  }
73 }
74 
76  auto update_type_entry =
78  CHECK(update_type_entry != options.end());
79  auto update_type_value = update_type_entry->second;
80  if (update_type_value != ALL_REFRESH_UPDATE_TYPE &&
81  update_type_value != APPEND_REFRESH_UPDATE_TYPE) {
82  std::string error_message =
83  "Invalid value \"" + update_type_value + "\" for " + REFRESH_UPDATE_TYPE_KEY +
84  " option." + " Value must be \"" + std::string{APPEND_REFRESH_UPDATE_TYPE} +
85  "\" or \"" + std::string{ALL_REFRESH_UPDATE_TYPE} + "\".";
86  throw std::runtime_error{error_message};
87  }
88 
89  auto refresh_timing_entry =
91  CHECK(refresh_timing_entry != options.end());
92  if (auto refresh_timing_value = refresh_timing_entry->second;
93  refresh_timing_value == SCHEDULE_REFRESH_TIMING_TYPE) {
94  auto start_date_entry = options.find(REFRESH_START_DATE_TIME_KEY);
95  if (start_date_entry == options.end()) {
96  throw std::runtime_error{std::string{REFRESH_START_DATE_TIME_KEY} +
97  " option must be provided for scheduled refreshes."};
98  }
99  auto start_date_time = dateTimeParse<kTIMESTAMP>(start_date_entry->second, 0);
100  int64_t current_time = RefreshTimeCalculator::getCurrentTime();
101  if (start_date_time < current_time) {
102  throw std::runtime_error{std::string{REFRESH_START_DATE_TIME_KEY} +
103  " cannot be a past date time."};
104  }
105 
106  auto interval_entry = options.find(REFRESH_INTERVAL_KEY);
107  if (interval_entry != options.end()) {
108  std::string interval_types{"HD"};
110  interval_types += "S";
111  }
112  boost::regex interval_regex{"^\\d{1,}[" + interval_types + "]$",
113  boost::regex::extended | boost::regex::icase};
114  if (!boost::regex_match(interval_entry->second, interval_regex)) {
115  throw std::runtime_error{"Invalid value provided for the " +
116  std::string{REFRESH_INTERVAL_KEY} + " option."};
117  }
118  }
119  } else if (refresh_timing_value != MANUAL_REFRESH_TIMING_TYPE) {
120  throw std::runtime_error{"Invalid value provided for the " +
121  std::string{REFRESH_TIMING_TYPE_KEY} +
122  " option. Value must be \"" + MANUAL_REFRESH_TIMING_TYPE +
123  "\" or \"" + SCHEDULE_REFRESH_TIMING_TYPE + "\"."};
124  }
125 }
126 
130  .validateTableOptions(this);
131 }
132 
133 OptionsMap ForeignTable::createOptionsMap(const rapidjson::Value& json_options) {
134  OptionsMap options_map;
135  CHECK(json_options.IsObject());
136  for (const auto& member : json_options.GetObject()) {
137  auto key = to_upper(member.name.GetString());
138  if (std::find(upper_case_options.begin(), upper_case_options.end(), key) !=
139  upper_case_options.end()) {
140  options_map[key] = to_upper(member.value.GetString());
141  } else {
142  options_map[key] = member.value.GetString();
143  }
144  }
145  return options_map;
146 }
147 
148 void ForeignTable::validateAlterOptions(const OptionsMap& options_map) {
149  for (const auto& [key, value] : options_map) {
150  if (!shared::contains(alterable_options, key)) {
151  throw std::runtime_error{std::string("Altering foreign table option \"") + key +
152  "\" is not currently supported."};
153  }
154  }
155 }
156 
157 void ForeignTable::validateSchema(const std::list<ColumnDescriptor>& columns) const {
160  .validateSchema(columns);
161 }
162 
163 } // namespace foreign_storage
bool contains(const T &container, const U &element)
Definition: misc.h:189
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:58
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:52
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:44
static constexpr const char * REFRESH_UPDATE_TYPE_KEY
Definition: ForeignTable.h:46
void populateOptionsMap(OptionsMap &&options_map, bool clear=false)
static constexpr const char * REFRESH_INTERVAL_KEY
Definition: ForeignTable.h:45
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:72
bool g_enable_seconds_refresh
static constexpr const char * ALL_REFRESH_UPDATE_TYPE
Definition: ForeignTable.h:49
static constexpr const char * APPEND_REFRESH_UPDATE_TYPE
Definition: ForeignTable.h:50
const ForeignServer * foreign_server
Definition: ForeignTable.h:55
static constexpr const char * REFRESH_TIMING_TYPE_KEY
Definition: ForeignTable.h:43
#define CHECK(condition)
Definition: Logger.h:211
std::map< std::string, std::string, std::less<>> OptionsMap
static constexpr const char * SCHEDULE_REFRESH_TIMING_TYPE
Definition: ForeignTable.h:51
virtual void validateSchema(const std::list< ColumnDescriptor > &columns) const
static const std::set< const char * > upper_case_options
Definition: ForeignTable.h:65