Skip to content

Commit b79ef7e

Browse files
authored
Merge pull request #128 from Mytherin/bumpmysql
Apply patches and bump DuckDB
2 parents 59710ef + 3b697f4 commit b79ef7e

12 files changed

+138
-129
lines changed

.github/workflows/MainDistributionPipeline.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
uses: duckdb/extension-ci-tools/.github/workflows/[email protected]
1919
with:
2020
extension_name: mysql_scanner
21-
duckdb_version: v1.2.2
21+
duckdb_version: main
2222
ci_tools_version: v1.2.2
2323
exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;windows_amd64_rtools;windows_amd64_mingw;linux_amd64_musl'
2424
build_duckdb_shell: false
@@ -29,7 +29,7 @@ jobs:
2929
uses: duckdb/extension-ci-tools/.github/workflows/[email protected]
3030
secrets: inherit
3131
with:
32-
duckdb_version: v1.2.2
32+
duckdb_version: main
3333
ci_tools_version: v1.2.2
3434
extension_name: mysql_scanner
3535
exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;windows_amd64_rtools;windows_amd64_mingw;linux_amd64_musl'

duckdb

Submodule duckdb updated 2309 files

src/include/storage/mysql_catalog.hpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,18 @@ class MySQLCatalog : public Catalog {
3737

3838
void ScanSchemas(ClientContext &context, std::function<void(SchemaCatalogEntry &)> callback) override;
3939

40-
optional_ptr<SchemaCatalogEntry> GetSchema(CatalogTransaction transaction, const string &schema_name,
41-
OnEntryNotFound if_not_found,
42-
QueryErrorContext error_context = QueryErrorContext()) override;
43-
44-
unique_ptr<PhysicalOperator> PlanInsert(ClientContext &context, LogicalInsert &op,
45-
unique_ptr<PhysicalOperator> plan) override;
46-
unique_ptr<PhysicalOperator> PlanCreateTableAs(ClientContext &context, LogicalCreateTable &op,
47-
unique_ptr<PhysicalOperator> plan) override;
48-
unique_ptr<PhysicalOperator> PlanDelete(ClientContext &context, LogicalDelete &op,
49-
unique_ptr<PhysicalOperator> plan) override;
50-
unique_ptr<PhysicalOperator> PlanUpdate(ClientContext &context, LogicalUpdate &op,
51-
unique_ptr<PhysicalOperator> plan) override;
40+
optional_ptr<SchemaCatalogEntry> LookupSchema(CatalogTransaction transaction, const EntryLookupInfo &schema_lookup,
41+
OnEntryNotFound if_not_found) override;
42+
43+
PhysicalOperator &PlanCreateTableAs(ClientContext &context, PhysicalPlanGenerator &planner, LogicalCreateTable &op,
44+
PhysicalOperator &plan) override;
45+
PhysicalOperator &PlanInsert(ClientContext &context, PhysicalPlanGenerator &planner, LogicalInsert &op,
46+
optional_ptr<PhysicalOperator> plan) override;
47+
PhysicalOperator &PlanDelete(ClientContext &context, PhysicalPlanGenerator &planner, LogicalDelete &op,
48+
PhysicalOperator &plan) override;
49+
PhysicalOperator &PlanUpdate(ClientContext &context, PhysicalPlanGenerator &planner, LogicalUpdate &op,
50+
PhysicalOperator &plan) override;
51+
5252
unique_ptr<LogicalOperator> BindCreateIndex(Binder &binder, CreateStatement &stmt, TableCatalogEntry &table,
5353
unique_ptr<LogicalOperator> plan) override;
5454

src/include/storage/mysql_schema_entry.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class MySQLSchemaEntry : public SchemaCatalogEntry {
3838
void Scan(ClientContext &context, CatalogType type, const std::function<void(CatalogEntry &)> &callback) override;
3939
void Scan(CatalogType type, const std::function<void(CatalogEntry &)> &callback) override;
4040
void DropEntry(ClientContext &context, DropInfo &info) override;
41-
optional_ptr<CatalogEntry> GetEntry(CatalogTransaction transaction, CatalogType type, const string &name) override;
41+
optional_ptr<CatalogEntry> LookupEntry(CatalogTransaction transaction, const EntryLookupInfo &lookup_info) override;
4242

4343
private:
4444
void AlterTable(MySQLTransaction &transaction, RenameTableInfo &info);

src/mysql_filter_pushdown.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,11 @@ string MySQLFilterPushdown::TransformComparison(ExpressionType type) {
3232
}
3333
}
3434

35-
3635
static string TransformBlobToMySQL(const string &val) {
3736
char const HEX_DIGITS[] = "0123456789ABCDEF";
3837

3938
string result = "x'";
40-
for(idx_t i = 0; i < val.size(); i++) {
39+
for (idx_t i = 0; i < val.size(); i++) {
4140
uint8_t byte_val = static_cast<uint8_t>(val[i]);
4241
result += HEX_DIGITS[(byte_val >> 4) & 0xf];
4342
result += HEX_DIGITS[byte_val & 0xf];
@@ -89,7 +88,7 @@ string MySQLFilterPushdown::TransformFilter(string &column_name, TableFilter &fi
8988
case TableFilterType::IN_FILTER: {
9089
auto &in_filter = filter.Cast<InFilter>();
9190
string in_list;
92-
for(auto &val : in_filter.values) {
91+
for (auto &val : in_filter.values) {
9392
if (!in_list.empty()) {
9493
in_list += ", ";
9594
}

src/mysql_utils.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ std::tuple<MySQLConnectionParameters, unordered_set<string>> MySQLUtils::ParseCo
103103
key = StringUtil::Lower(key);
104104

105105
if (set_options.find(key) != set_options.end()) {
106-
throw InvalidInputException("Duplicate '%s' parameter in connection string. Each parameter should only be specified once.", key);
106+
throw InvalidInputException(
107+
"Duplicate '%s' parameter in connection string. Each parameter should only be specified once.", key);
107108
}
108109

109110
// Handle duplicate options (except for aliased options like passwd/password which map to the same option)
@@ -142,8 +143,8 @@ std::tuple<MySQLConnectionParameters, unordered_set<string>> MySQLUtils::ParseCo
142143
} else if (val == "preferred") {
143144
// nop
144145
} else {
145-
throw InvalidInputException("Invalid dsn - compression mode must be either disabled/required/preferred - got %s",
146-
value);
146+
throw InvalidInputException(
147+
"Invalid dsn - compression mode must be either disabled/required/preferred - got %s", value);
147148
}
148149
} else if (key == "ssl_mode") {
149150
set_options.insert("ssl_mode");
@@ -269,18 +270,20 @@ MYSQL *MySQLUtils::Connect(const string &dsn) {
269270
if (!result) {
270271
string original_error = mysql_error(mysql);
271272
string attempted_host = host ? host : "nullptr (default)";
272-
273+
273274
if (config.host.empty() || config.host == "localhost") {
274-
result = mysql_real_connect(mysql, "127.0.0.1", user, passwd, db, config.port, unix_socket, config.client_flag);
275-
275+
result =
276+
mysql_real_connect(mysql, "127.0.0.1", user, passwd, db, config.port, unix_socket, config.client_flag);
277+
276278
if (!result) {
277-
throw IOException("Failed to connect to MySQL database with parameters \"%s\": %s. First attempted host: %s. "
278-
"Retry with 127.0.0.1 also failed.",
279-
dsn, mysql_error(mysql), attempted_host.c_str());
279+
throw IOException(
280+
"Failed to connect to MySQL database with parameters \"%s\": %s. First attempted host: %s. "
281+
"Retry with 127.0.0.1 also failed.",
282+
dsn, mysql_error(mysql), attempted_host.c_str());
280283
}
281284
} else {
282-
throw IOException("Failed to connect to MySQL database with parameters \"%s\": %s. Attempted host: %s",
283-
dsn, original_error.c_str(), attempted_host.c_str());
285+
throw IOException("Failed to connect to MySQL database with parameters \"%s\": %s. Attempted host: %s", dsn,
286+
original_error.c_str(), attempted_host.c_str());
284287
}
285288
}
286289
if (mysql_set_character_set(mysql, "utf8mb4") != 0) {

src/storage/mysql_catalog.cpp

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ string EscapeConnectionString(const string &input) {
3939
return result;
4040
}
4141

42-
string AddConnectionOption(const KeyValueSecret &kv_secret, const string &name, const unordered_set<string> &existing_params) {
42+
string AddConnectionOption(const KeyValueSecret &kv_secret, const string &name,
43+
const unordered_set<string> &existing_params) {
4344
if (existing_params.find(name) != existing_params.end()) {
44-
// option already provided in connection string
45-
return string();
46-
}
45+
// option already provided in connection string
46+
return string();
47+
}
4748
Value input_val = kv_secret.TryGetValue(name);
4849
if (input_val.IsNull()) {
4950
// not provided
@@ -83,13 +84,13 @@ string UnescapePercentage(const string &input, idx_t start, idx_t end) {
8384
auto url_escapes = "20 3C<3E>23#25%2B+7B{7D}7C|5C\\5E^7E~5B[5D]60`3B;2F/3F?3A;40@3D=26&24$";
8485

8586
string result;
86-
for(idx_t i = start; i < end; i++) {
87+
for (idx_t i = start; i < end; i++) {
8788
if (i + 2 < end && input[i] == '%') {
8889
// find the escape code
8990
char first_char = StringUtil::CharacterToUpper(input[i + 1]);
9091
char second_char = StringUtil::CharacterToUpper(input[i + 2]);
9192
char escape_result = '\0';
92-
for(idx_t esc_pos = 0; url_escapes[esc_pos]; esc_pos += 3) {
93+
for (idx_t esc_pos = 0; url_escapes[esc_pos]; esc_pos += 3) {
9394
if (first_char == url_escapes[esc_pos] && second_char == url_escapes[esc_pos + 1]) {
9495
// found the correct escape
9596
escape_result = url_escapes[esc_pos + 2];
@@ -111,25 +112,25 @@ string UnescapePercentage(const string &input, idx_t start, idx_t end) {
111112

112113
vector<URIToken> ParseURITokens(const string &dsn, idx_t start) {
113114
vector<URIToken> result;
114-
for(idx_t pos = start; pos < dsn.size(); pos++) {
115-
switch(dsn[pos]) {
116-
case ':':
117-
case '@':
118-
case '/':
119-
case '?':
120-
case '=':
121-
case '&': {
122-
// found a delimiter
123-
URIToken token;
124-
token.value = UnescapePercentage(dsn, start, pos);
125-
token.delimiter = dsn[pos];
126-
start = pos + 1;
127-
result.push_back(std::move(token));
128-
break;
129-
}
130-
default:
131-
// include in token
132-
break;
115+
for (idx_t pos = start; pos < dsn.size(); pos++) {
116+
switch (dsn[pos]) {
117+
case ':':
118+
case '@':
119+
case '/':
120+
case '?':
121+
case '=':
122+
case '&': {
123+
// found a delimiter
124+
URIToken token;
125+
token.value = UnescapePercentage(dsn, start, pos);
126+
token.delimiter = dsn[pos];
127+
start = pos + 1;
128+
result.push_back(std::move(token));
129+
break;
130+
}
131+
default:
132+
// include in token
133+
break;
133134
}
134135
}
135136
URIToken token;
@@ -140,7 +141,8 @@ vector<URIToken> ParseURITokens(const string &dsn, idx_t start) {
140141
}
141142

142143
struct URIValue {
143-
URIValue(string name_p, string value_p) : name(std::move(name_p)), value(std::move(value_p)) {}
144+
URIValue(string name_p, string value_p) : name(std::move(name_p)), value(std::move(value_p)) {
145+
}
144146

145147
string name;
146148
string value;
@@ -207,13 +209,14 @@ vector<string> GetAttributeNames(const vector<URIToken> &tokens, idx_t token_cou
207209
return result;
208210
}
209211

210-
void ParseMainAttributes(const vector<URIToken> &tokens, idx_t token_count, vector<URIValue> &result, ErrorData &error) {
212+
void ParseMainAttributes(const vector<URIToken> &tokens, idx_t token_count, vector<URIValue> &result,
213+
ErrorData &error) {
211214
auto attribute_names = GetAttributeNames(tokens, token_count, error);
212215
if (error.HasError()) {
213216
return;
214217
}
215218
D_ASSERT(attribute_names.size() == token_count);
216-
for(idx_t i = 0; i < token_count; i++) {
219+
for (idx_t i = 0; i < token_count; i++) {
217220
result.emplace_back(attribute_names[i], tokens[i].value);
218221
}
219222
}
@@ -232,7 +235,7 @@ void ParseAttributes(const vector<URIToken> &tokens, idx_t attribute_start, vect
232235
uri_attribute_map["ssl-key"] = "ssl_key";
233236

234237
// parse key=value attributes
235-
for(idx_t i = attribute_start; i < tokens.size(); i += 2) {
238+
for (idx_t i = attribute_start; i < tokens.size(); i += 2) {
236239
// check if the format is correct
237240
if (i + 1 >= tokens.size() || tokens[i].delimiter != '=') {
238241
throw ParserException("Invalid URI string - expected attribute=value pairs after ?");
@@ -243,13 +246,14 @@ void ParseAttributes(const vector<URIToken> &tokens, idx_t attribute_start, vect
243246
auto entry = uri_attribute_map.find(tokens[i].value);
244247
if (entry == uri_attribute_map.end()) {
245248
string supported_options;
246-
for(auto &entry : uri_attribute_map) {
249+
for (auto &entry : uri_attribute_map) {
247250
if (!supported_options.empty()) {
248251
supported_options += ", ";
249252
}
250253
supported_options += entry.first;
251254
}
252-
throw ParserException("Invalid URI string - unsupported attribute \"%s\"\nSupported options: %s", tokens[i].value, supported_options);
255+
throw ParserException("Invalid URI string - unsupported attribute \"%s\"\nSupported options: %s",
256+
tokens[i].value, supported_options);
253257
}
254258
result.emplace_back(entry->second, tokens[i + 1].value);
255259
}
@@ -262,15 +266,15 @@ vector<URIValue> ExtractURIValues(const vector<URIToken> &tokens, ErrorData &err
262266
if (tokens.empty()) {
263267
return result;
264268
}
265-
269+
266270
// If we only have one empty token with no delimiter, don't treat it as a host
267271
if (tokens.size() == 1 && tokens[0].value.empty() && tokens[0].delimiter == '\0') {
268272
return result;
269273
}
270-
274+
271275
// figure out how many "non-attribute" tokens we have
272276
idx_t attribute_start = tokens.size();
273-
for(idx_t i = 0; i < tokens.size(); i++) {
277+
for (idx_t i = 0; i < tokens.size(); i++) {
274278
if (tokens[i].delimiter == '?') {
275279
// found a question-mark - this is a token
276280
attribute_start = i + 1;
@@ -296,8 +300,8 @@ bool TryConvertURIInternal(const string &dsn, idx_t start_pos, string &connectio
296300
}
297301

298302
unordered_set<string> added_params;
299-
300-
for(auto &val : values) {
303+
304+
for (auto &val : values) {
301305
// Skip duplicate parameters
302306
if (added_params.find(val.name) != added_params.end()) {
303307
continue;
@@ -321,7 +325,7 @@ void TryConvertURI(string &dsn) {
321325
if (dsn.empty()) {
322326
return;
323327
}
324-
328+
325329
// [scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...
326330
idx_t start_pos = 0;
327331
// skip the past the scheme (either mysql:// or mysqlx://)
@@ -376,7 +380,7 @@ string MySQLCatalog::GetConnectionString(ClientContext &context, const string &a
376380
// Build a new connection string with parameters from the secret that don't
377381
// already exist in the original connection string
378382
string new_connection_info;
379-
383+
380384
new_connection_info += AddConnectionOption(kv_secret, "user", existing_params);
381385
new_connection_info += AddConnectionOption(kv_secret, "password", existing_params);
382386
new_connection_info += AddConnectionOption(kv_secret, "host", existing_params);
@@ -431,15 +435,16 @@ void MySQLCatalog::ScanSchemas(ClientContext &context, std::function<void(Schema
431435
schemas.Scan(context, [&](CatalogEntry &schema) { callback(schema.Cast<MySQLSchemaEntry>()); });
432436
}
433437

434-
optional_ptr<SchemaCatalogEntry> MySQLCatalog::GetSchema(CatalogTransaction transaction, const string &schema_name,
435-
OnEntryNotFound if_not_found,
436-
QueryErrorContext error_context) {
438+
optional_ptr<SchemaCatalogEntry> MySQLCatalog::LookupSchema(CatalogTransaction transaction,
439+
const EntryLookupInfo &schema_lookup,
440+
OnEntryNotFound if_not_found) {
441+
auto schema_name = schema_lookup.GetEntryName();
437442
if (schema_name == DEFAULT_SCHEMA) {
438443
if (default_schema.empty()) {
439444
throw InvalidInputException("Attempting to fetch the default schema - but no database was "
440445
"provided in the connection string");
441446
}
442-
return GetSchema(transaction, default_schema, if_not_found, error_context);
447+
schema_name = default_schema;
443448
}
444449
auto entry = schemas.GetEntry(transaction.GetContext(), schema_name);
445450
if (!entry && if_not_found != OnEntryNotFound::RETURN_NULL) {

0 commit comments

Comments
 (0)