35#include <rapidjson/document.h>
36#include <rapidjson/error/en.h>
37#include <rapidjson/rapidjson.h>
38#include <rapidjson/stringbuffer.h>
39#include <rapidjson/writer.h>
47#include <unordered_map>
48#include <unordered_set>
71 auto pos = s.find_first_not_of(
" \n\r\t");
78 const std::string &input_string,
const size_t &
n_files)
93 std::ostream &
print(std::ostream &out)
const;
110 out <<
"[Bulk_load_file_info: m_file_prefix=" <<
m_file_prefix <<
", "
111 <<
"m_file_suffix=" << suffix <<
", "
120 return obj.
print(out);
129 rapidjson::Document doc;
130 doc.Parse(file_name_arg.c_str());
131 return !doc.HasParseError() && doc.IsObject();
144 const rapidjson::Document &doc) {
145 constexpr char PREFIX_KEY[] =
"url-prefix";
146 constexpr char SUFFIX_KEY[] =
"url-suffix";
147 constexpr char APPENDTOLASTPREFIX_KEY[] =
"url-prefix-last-append";
148 constexpr char SEQUENCE_START_KEY[] =
"url-sequence-start";
149 constexpr char DRYRUN_KEY[] =
"is-dryrun";
150 static const std::unordered_set<std::string> all_keys = {
151 PREFIX_KEY, SUFFIX_KEY, APPENDTOLASTPREFIX_KEY, SEQUENCE_START_KEY,
154 if (!doc.IsObject()) {
155 error =
"Invalid JSON object used for filename argument!";
159 for (
const auto &child : doc.GetObject()) {
160 std::string
key = child.name.GetString();
161 if (all_keys.find(
key) == all_keys.end()) {
162 std::stringstream ss;
163 ss <<
"Unsupported JSON key: " <<
key;
169 if (!doc.HasMember(PREFIX_KEY)) {
170 error =
"Missing url-prefix in JSON filename argument!";
174 if (!doc[PREFIX_KEY].IsString()) {
175 std::stringstream ss;
176 ss <<
"The value of key " << PREFIX_KEY <<
" must be a string";
181 info.m_file_prefix = doc[PREFIX_KEY].GetString();
183 if (doc.HasMember(SUFFIX_KEY)) {
184 if (!
info.is_count_specified()) {
186 sout <<
"Cannot specify " << SUFFIX_KEY <<
" without COUNT clause";
191 if (!doc[SUFFIX_KEY].IsString()) {
192 std::stringstream ss;
193 ss <<
"The value of key " << SUFFIX_KEY <<
" must be a string";
197 info.m_file_suffix = doc[SUFFIX_KEY].GetString();
200 if (doc.HasMember(APPENDTOLASTPREFIX_KEY)) {
201 if (!
info.is_count_specified()) {
203 sout <<
"Cannot specify " << APPENDTOLASTPREFIX_KEY
204 <<
" without COUNT clause";
208 if (!doc[APPENDTOLASTPREFIX_KEY].IsString()) {
209 std::stringstream ss;
210 ss <<
"The value of key " << APPENDTOLASTPREFIX_KEY
211 <<
" must be a string";
215 info.m_appendtolastprefix = doc[APPENDTOLASTPREFIX_KEY].GetString();
218 if (doc.HasMember(SEQUENCE_START_KEY)) {
219 if (!
info.is_count_specified()) {
221 sout <<
"Cannot specify " << SEQUENCE_START_KEY
222 <<
" without COUNT clause";
226 if (doc[SEQUENCE_START_KEY].IsInt64()) {
228 const int64_t val = doc[SEQUENCE_START_KEY].GetInt64();
231 sout <<
"The value of key " << SEQUENCE_START_KEY
232 <<
" cannot be negative: (" << val <<
")";
237 if (doc[SEQUENCE_START_KEY].IsUint64()) {
238 info.m_start_index = doc[SEQUENCE_START_KEY].GetUint64();
239 }
else if (doc[SEQUENCE_START_KEY].IsString()) {
240 const std::string val = doc[SEQUENCE_START_KEY].GetString();
243 sout <<
"The value of key " << SEQUENCE_START_KEY <<
" cannot be empty";
246 }
else if ((val.length() == 7) &&
248 info.m_start_index = 1;
249 }
else if (std::all_of(val.begin(), val.end(),
250 [](
unsigned char c) { return std::isdigit(c); })) {
251 info.m_start_index = std::strtoull(val.c_str(),
nullptr, 10);
254 sout <<
"The value of key " << SEQUENCE_START_KEY <<
" is invalid ("
261 sout <<
"Invalid value for key " << SEQUENCE_START_KEY;
267 if (doc.HasMember(DRYRUN_KEY)) {
268 if (doc[DRYRUN_KEY].IsBool()) {
269 info.m_is_dryrun = doc[DRYRUN_KEY].GetBool();
270 }
else if (doc[DRYRUN_KEY].IsString()) {
271 const std::string val = doc[DRYRUN_KEY].GetString();
274 info.m_is_dryrun =
true;
275 }
else if (val ==
"0" ||
278 info.m_is_dryrun =
false;
281 sout <<
"Unsupported " << DRYRUN_KEY <<
" value: " << val;
285 }
else if (doc[DRYRUN_KEY].IsUint64()) {
286 const uint64_t val = doc[DRYRUN_KEY].GetUint64();
288 info.m_is_dryrun =
false;
289 }
else if (val == 1) {
290 info.m_is_dryrun =
true;
293 sout <<
"Unsupported " << DRYRUN_KEY <<
" value: " << val;
298 std::stringstream ss;
299 ss <<
"Invalid value for key " << DRYRUN_KEY;
304 info.m_is_dryrun =
false;
312 rapidjson::Document doc;
314 std::string parse_error;
317 parse_error = rapidjson::GetParseError_En(
ok.Code());
320 if (!doc.HasParseError()) {
329 [](
unsigned char c) { return std::tolower(c); });
330 if (protocol ==
"http" || protocol ==
"https") {
334 if (protocol.starts_with(
'{')) {
335 sout <<
"Could be malformed JSON (" << parse_error <<
") or ";
337 sout <<
"Unsupported protocol in URL";
Bulk_char
Bulk loader single byte attributes.
Definition: bulk_load_service.h:407
@ ENCLOSE_CHAR
Column enclosing character.
@ ESCAPE_CHAR
Escape character.
static bool parse_input_arg(std::string &error, Bulk_load_file_info &info, const rapidjson::Document &doc)
Validates whether the json argument matches the expected schema for bulk load, if it matches it fills...
Definition: bulk_load_service.h:142
Bulk_condition
Bulk loader boolean attributes.
Definition: bulk_load_service.h:377
@ OPTIONAL_ENCLOSE
If enclosing is optional.
@ ORDERED_DATA
The algorithm used is different based on whether the data is in sorted primary key order.
@ NON_EMPTY_TABLE
If true, we are loading data into a non-empty table.
@ DRYRUN
If true, the current execution is only a dry run.
Bulk_source
Bulk loader source.
Definition: bulk_load_service.h:61
@ LOCAL
Local file system.
Bulk_compression_algorithm
Bulk data compression algorithm.
Definition: bulk_load_service.h:354
std::ostream & operator<<(std::ostream &out, const Bulk_load_file_info &obj)
Definition: bulk_load_service.h:118
static bool is_json_object(const std::string &file_name_arg)
Check whether the specified argument is a valid JSON object.
Definition: bulk_load_service.h:128
std::string trim_left(const std::string &s)
Definition: bulk_load_service.h:70
void Bulk_loader
Definition: bulk_load_service.h:58
Bulk_string
Bulk loader string attributes.
Definition: bulk_load_service.h:357
@ COLUMN_TERM
Column terminator.
@ ROW_TERM
Row terminator.
@ APPENDTOLASTPREFIX
String to append to last file prefix.
@ SCHEMA_NAME
Schema name.
Bulk_size
Bulk loader size attributes.
Definition: bulk_load_service.h:391
@ COUNT_COLUMNS
Number of columns in the table.
@ MEMORY
Total memory size to use for LOAD in bytes.
@ START_INDEX
Index of the first file.
@ CONCURRENCY
Number of concurrent loaders to use,.
@ COUNT_ROW_SKIP
Number of rows to skip.
@ COUNT_FILES
Number of input files.
static Mysys_charset_loader * loader
Definition: charset.cc:197
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:36
static int native_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: m_string.h:216
Define rapidjson::SizeType to be std::uint64_t.
uint32 my_thread_id
Definition: my_thread_local.h:34
void error(const char *format,...)
void for_each(const Shards< COUNT > &shards, Function &&f) noexcept
Iterate over the shards.
Definition: ut0counter.h:323
const std::string charset("charset")
ulong n_files
Number of files to use for the double write buffer.
Definition: buf0dblwr.cc:83
bool load(THD *, const dd::String_type &fname, dd::String_type *buf)
Read an sdi file from disk and store in a buffer.
Definition: sdi_file.cc:308
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
std::basic_ostringstream< char, std::char_traits< char >, ut::allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut::allocator.
Definition: ut0new.h:2720
required string key
Definition: replication_asynchronous_connection_failover.proto:60
repeated Source source
Definition: replication_asynchronous_connection_failover.proto:42
required string type
Definition: replication_group_member_actions.proto:34
#define DECLARE_METHOD(retval, name, args)
Declares a method as a part of the Service definition.
Definition: service.h:103
#define END_SERVICE_DEFINITION(name)
A macro to end the last Service definition started with the BEGIN_SERVICE_DEFINITION macro.
Definition: service.h:91
#define BEGIN_SERVICE_DEFINITION(name)
Declares a new Service.
Definition: service.h:86
Definition: bulk_load_service.h:75
std::string m_input_string
Definition: bulk_load_service.h:101
size_t m_n_files
Definition: bulk_load_service.h:105
size_t m_start_index
Definition: bulk_load_service.h:86
std::string m_appendtolastprefix
Definition: bulk_load_service.h:85
Bulk_load_file_info()=default
std::ostream & print(std::ostream &out) const
Definition: bulk_load_service.h:108
std::string m_current_partition
Definition: bulk_load_service.h:88
std::string m_file_prefix
Definition: bulk_load_service.h:83
std::unordered_map< std::string, std::vector< int > > m_partitions
Definition: bulk_load_service.h:89
bool is_count_specified() const
Check if the COUNT clause has been explicitly specified.
Definition: bulk_load_service.h:97
bool m_is_dryrun
Definition: bulk_load_service.h:87
Bulk_source m_source
Definition: bulk_load_service.h:100
Bulk_load_file_info(const Bulk_source &source, const std::string &input_string, const size_t &n_files)
Definition: bulk_load_service.h:77
bool parse(std::string &error)
Definition: bulk_load_service.h:311
std::optional< std::string > m_file_suffix
Definition: bulk_load_service.h:84
Definition: m_ctype.h:421