From 2c1a292112e05082cc5e4f8eac29fa3a13e0fa6c Mon Sep 17 00:00:00 2001 From: Pali Date: Thu, 17 Jan 2019 09:47:06 +0100 Subject: [PATCH 1/2] Fix warning message in test t/55utf8.t for MariaDB 10.2.20+, 10.3.12+ and 10.4.1+ Bug: https://github.com/gooddata/DBD-MariaDB/issues/121 Bug-Debian: https://bugs.debian.org/919071 Gbp-Pq: Name mariadb-10.3.12-message.patch --- t/55utf8.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/55utf8.t b/t/55utf8.t index cbea705..bf12869 100644 --- a/t/55utf8.t +++ b/t/55utf8.t @@ -80,7 +80,7 @@ ok $sth->finish; cmp_ok($dbh->{mariadb_warning_count}, '==', 1, 'got warning for INSERT') or do { diag("SHOW WARNINGS:"); diag($_->[2]) foreach $dbh->selectall_array("SHOW WARNINGS", { mariadb_server_prepare => 0 }); }; my (undef, undef, $warning) = $dbh->selectrow_array("SHOW WARNINGS", { mariadb_server_prepare => 0 }); -like($warning, qr/^(?:Incorrect string value: '\\xC4\\x80dam'|Data truncated) for column 'ascii' at row 1$/, 'warning is correct'); +like($warning, qr/^(?:Incorrect string value: '\\xC4\\x80dam'|Data truncated) for column (?:'ascii'|`.*`\.`.*`\.`ascii`) at row 1$/, 'warning is correct'); # AsBinary() is deprecated as of MySQL 5.7.6, use ST_AsBinary() instead my $asbinary = $dbh->{mariadb_serverversion} >= 50706 ? 'ST_AsBinary' : 'AsBinary'; -- cgit v1.2.3 From bd21d036bd06d2bba0c90e036648c0f2df61a4e3 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Fri, 22 Jan 2021 13:26:21 +0100 Subject: Adjust test case expectation that works with either 8.0.22+ or prior mysql versions. Bug: https://github.com/gooddata/DBD-MariaDB/issues/160 Bug-Debian: https://bugs.debian.org/980640 Gbp-Pq: Name fix-mysql-8.0.22.patch --- t/rt122541-decimals.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/rt122541-decimals.t b/t/rt122541-decimals.t index 00292c0..1c0c787 100644 --- a/t/rt122541-decimals.t +++ b/t/rt122541-decimals.t @@ -14,6 +14,6 @@ plan tests => 2; for my $mariadb_server_prepare (0, 1) { $dbh->{mariadb_server_prepare} = $mariadb_server_prepare; - is $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], '1.70', + like $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], qr/1.70?$/, 'floats with fixed-length of decimals returns correct value for mariadb_server_prepare=' . $mariadb_server_prepare; } -- cgit v1.2.3 From 43ea334fa249967d33d2eb68a545fc26c3a10943 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Fri, 22 Jan 2021 15:53:48 +0100 Subject: Adjust test case expectation that works with either 8.0.22+ or prior mysql versions. Bug: https://github.com/gooddata/DBD-MariaDB/issues/160 Bug-Debian: https://bugs.debian.org/980640 Gbp-Pq: Name fix-mysql-8.0.22.patch --- t/rt122541-decimals.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/rt122541-decimals.t b/t/rt122541-decimals.t index 00292c0..1c0c787 100644 --- a/t/rt122541-decimals.t +++ b/t/rt122541-decimals.t @@ -14,6 +14,6 @@ plan tests => 2; for my $mariadb_server_prepare (0, 1) { $dbh->{mariadb_server_prepare} = $mariadb_server_prepare; - is $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], '1.70', + like $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], qr/1.70?$/, 'floats with fixed-length of decimals returns correct value for mariadb_server_prepare=' . $mariadb_server_prepare; } -- cgit v1.2.3 From 8bb4a4a3e15553c56cc4b13e0d6cdea4e17d83b8 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Tue, 2 Nov 2021 19:32:54 +0100 Subject: Adjust test case expectation that works with either 8.0.22+ or prior mysql versions. Bug: https://github.com/gooddata/DBD-MariaDB/issues/160 Bug-Debian: https://bugs.debian.org/980640 Gbp-Pq: Name fix-mysql-8.0.22.patch --- t/rt122541-decimals.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/rt122541-decimals.t b/t/rt122541-decimals.t index 00292c0..1c0c787 100644 --- a/t/rt122541-decimals.t +++ b/t/rt122541-decimals.t @@ -14,6 +14,6 @@ plan tests => 2; for my $mariadb_server_prepare (0, 1) { $dbh->{mariadb_server_prepare} = $mariadb_server_prepare; - is $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], '1.70', + like $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], qr/1.70?$/, 'floats with fixed-length of decimals returns correct value for mariadb_server_prepare=' . $mariadb_server_prepare; } -- cgit v1.2.3 From ed9fe4a6068e6419feede025093a3060444e9341 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Thu, 7 Apr 2022 21:38:42 +0200 Subject: Adjust test case expectation that works with either 8.0.22+ or prior mysql versions. Bug: https://github.com/gooddata/DBD-MariaDB/issues/160 Bug-Debian: https://bugs.debian.org/980640 Gbp-Pq: Name fix-mysql-8.0.22.patch --- t/rt122541-decimals.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/rt122541-decimals.t b/t/rt122541-decimals.t index 00292c0..1c0c787 100644 --- a/t/rt122541-decimals.t +++ b/t/rt122541-decimals.t @@ -14,6 +14,6 @@ plan tests => 2; for my $mariadb_server_prepare (0, 1) { $dbh->{mariadb_server_prepare} = $mariadb_server_prepare; - is $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], '1.70', + like $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], qr/1.70?$/, 'floats with fixed-length of decimals returns correct value for mariadb_server_prepare=' . $mariadb_server_prepare; } -- cgit v1.2.3 From e5144011bb4fb101e2a27d83689f002aa8f66860 Mon Sep 17 00:00:00 2001 From: Debian Perl Group Date: Thu, 7 Apr 2022 21:38:42 +0200 Subject: Fix test failures with MariaDB 10.6.x Origin: upstream GitHub issues Bug: https://github.com/perl5-dbi/DBD-MariaDB/issues/164 https://github.com/perl5-dbi/DBD-MariaDB/issues/167 Bug-Debian: https://bugs.debian.org/1002093 Reviewed-by: gregor herrmann Last-Update: 2022-04-07 Gbp-Pq: Name fix-mariadb-10.6.x.patch --- dbdimp.c | 25 +++++++++++++++++++++---- t/40server_prepare.t | 4 +++- t/45bind_no_backslash_escapes.t | 4 ---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 5618430..5b05c06 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -617,6 +617,25 @@ char **fill_out_embedded_options(char *options, return options_list; } +#if MYSQL_VERSION_ID < 50001 +/* MySQL client prior to version 5.0.1 does not implement mysql_real_escape_string() for SERVER_STATUS_NO_BACKSLASH_ESCAPES */ +static unsigned long string_escape_quotes(char *to, const char *from, unsigned long len) +{ + const char *to_start = to; + const char *end = from + len; + + while (from < end) + { + if (*from == '\'') + *to++ = '\''; + *to++ = *from++; + } + + *to = '\0'; + return to - to_start; +} +#endif + /* constructs an SQL statement previously prepared with actual values replacing placeholders @@ -828,9 +847,8 @@ static char *parse_params( #if MYSQL_VERSION_ID < 50001 if (sock->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) { - *ptr++ = 'X'; *ptr++ = '\''; - ptr += mysql_hex_string(ptr, ph->value, ph->len); + ptr += string_escape_quotes(ptr, ph->value, ph->len); *ptr++ = '\''; } else @@ -6406,9 +6424,8 @@ SV* mariadb_db_quote(SV *dbh, SV *str, SV *type) #if MYSQL_VERSION_ID < 50001 if (imp_dbh->pmysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) { - *sptr++ = 'X'; *sptr++ = '\''; - sptr += mysql_hex_string(sptr, ptr, len); + sptr += string_escape_quotes(sptr, ptr, len); *sptr++ = '\''; } else diff --git a/t/40server_prepare.t b/t/40server_prepare.t index 6eb2cf1..d4208cd 100644 --- a/t/40server_prepare.t +++ b/t/40server_prepare.t @@ -75,7 +75,9 @@ is_deeply($dbh->selectall_arrayref('SELECT id, mydata FROM t3'), [[1, 2]]); $dbh->{mariadb_server_prepare_disable_fallback} = 1; my $error_handler_called = 0; $dbh->{HandleError} = sub { $error_handler_called = 1; die $_[0]; }; -eval { $dbh->prepare("USE " . $dbh->quote_identifier($test_db)) }; +# MariaDB server since version 10.6.2 can prepare all statements except PREPARE, EXECUTE, and DEALLOCATE / DROP PREPARE. Previous MariaDB and Mysql versions cannot prepare USE statement +my $non_preparable_statement = ($dbh->{mariadb_serverversion} >= 100602) ? q(PREPARE stmt FROM "SELECT 1") : ("USE " . $dbh->quote_identifier($test_db)); +eval { $dbh->prepare($non_preparable_statement); }; $dbh->{HandleError} = undef; ok($error_handler_called, 'USE is not supported with mariadb_server_prepare_disable_fallback=1'); diff --git a/t/45bind_no_backslash_escapes.t b/t/45bind_no_backslash_escapes.t index 13dce12..eaf011b 100644 --- a/t/45bind_no_backslash_escapes.t +++ b/t/45bind_no_backslash_escapes.t @@ -18,10 +18,6 @@ if ($dbh->{mariadb_serverversion} < 50001) { plan skip_all => "Servers < 5.0.1 do not support sql_mode NO_BACKSLASH_ESCAPES"; } -if ($dbh->{mariadb_clientversion} < 50001) { - $id2_quoted_no_backslash = q(X'737472696E675C737472696E6722737472696E6727737472696E67'); -} - plan tests => 20; ok $dbh->do('CREATE TEMPORARY TABLE t(id VARCHAR(255), value TEXT)'); -- cgit v1.2.3 From 5b94c0f3b5b26191df78dd18f35aeee57180c569 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Fri, 8 Apr 2022 22:18:21 +0200 Subject: Adjust test case expectation that works with either 8.0.22+ or prior mysql versions. Bug: https://github.com/gooddata/DBD-MariaDB/issues/160 Bug-Debian: https://bugs.debian.org/980640 Gbp-Pq: Name fix-mysql-8.0.22.patch --- t/rt122541-decimals.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/rt122541-decimals.t b/t/rt122541-decimals.t index 00292c0..1c0c787 100644 --- a/t/rt122541-decimals.t +++ b/t/rt122541-decimals.t @@ -14,6 +14,6 @@ plan tests => 2; for my $mariadb_server_prepare (0, 1) { $dbh->{mariadb_server_prepare} = $mariadb_server_prepare; - is $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], '1.70', + like $dbh->selectrow_arrayref('SELECT round(degrees(0.00043) * 69, 2)')->[0], qr/1.70?$/, 'floats with fixed-length of decimals returns correct value for mariadb_server_prepare=' . $mariadb_server_prepare; } -- cgit v1.2.3 From ceded680356537045bd213ee68dd9603af37c6a0 Mon Sep 17 00:00:00 2001 From: Debian Perl Group Date: Fri, 8 Apr 2022 22:18:21 +0200 Subject: Fix compatibility with new MariaDB client and server versions Origin: https://github.com/perl5-dbi/DBD-MariaDB/pull/168 Bug-Debian: https://bugs.debian.org/1002093 Reviewed-by: gregor herrmann Last-Update: 2022-04-08 Gbp-Pq: Name Fix_compatibility_with_new_MariaDB_client_and_server_versions.patch --- Makefile.PL | 8 +++++++- dbdimp.c | 25 +++++++++++++++++++++---- dbdimp.h | 26 ++++++++++++++++++++++++++ t/40server_prepare.t | 4 +++- t/45bind_no_backslash_escapes.t | 4 ---- 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 6acce9d..969ec62 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -744,7 +744,13 @@ sub Configure { # https://jira.mariadb.org/browse/MDEV-16478 $function .= "\n#if defined(MARIADB_BASE_VERSION) || defined(MARIADB_PACKAGE_VERSION)\nif (mysql_get_client_version() >= 100301 && mysql_get_client_version() < 100308) return 1;\n#endif\n"; } - $function .= 'return (mysql_get_client_version() == MYSQL_VERSION_ID) ? 0 : 1;'; + # MariaDB Connector/C 3.1.10+ has broken mysql_get_client_version() function, so use mariadb_get_infov(MARIADB_CLIENT_VERSION_ID) instead + $function .= "size_t version;\n"; + $function .= "#if defined(MARIADB_PACKAGE_VERSION) && defined(MARIADB_PACKAGE_VERSION_ID) && MARIADB_PACKAGE_VERSION_ID >= 30000\n"; + $function .= "if (mariadb_get_infov((void *)0, MARIADB_CLIENT_VERSION_ID, &version) != 0)\n"; + $function .= "#endif\n"; + $function .= "version = mysql_get_client_version();\n"; + $function .= 'return (version == MYSQL_VERSION_ID) ? 0 : 1;'; # libmysqld is built using g++ rather than gcc and sometimes # we have to use libstdc++ to resolve linking problems foreach my $add_ldflags (undef, '-lstdc++') { diff --git a/dbdimp.c b/dbdimp.c index 5618430..5b05c06 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -617,6 +617,25 @@ char **fill_out_embedded_options(char *options, return options_list; } +#if MYSQL_VERSION_ID < 50001 +/* MySQL client prior to version 5.0.1 does not implement mysql_real_escape_string() for SERVER_STATUS_NO_BACKSLASH_ESCAPES */ +static unsigned long string_escape_quotes(char *to, const char *from, unsigned long len) +{ + const char *to_start = to; + const char *end = from + len; + + while (from < end) + { + if (*from == '\'') + *to++ = '\''; + *to++ = *from++; + } + + *to = '\0'; + return to - to_start; +} +#endif + /* constructs an SQL statement previously prepared with actual values replacing placeholders @@ -828,9 +847,8 @@ static char *parse_params( #if MYSQL_VERSION_ID < 50001 if (sock->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) { - *ptr++ = 'X'; *ptr++ = '\''; - ptr += mysql_hex_string(ptr, ph->value, ph->len); + ptr += string_escape_quotes(ptr, ph->value, ph->len); *ptr++ = '\''; } else @@ -6406,9 +6424,8 @@ SV* mariadb_db_quote(SV *dbh, SV *str, SV *type) #if MYSQL_VERSION_ID < 50001 if (imp_dbh->pmysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) { - *sptr++ = 'X'; *sptr++ = '\''; - sptr += mysql_hex_string(sptr, ptr, len); + sptr += string_escape_quotes(sptr, ptr, len); *sptr++ = '\''; } else diff --git a/dbdimp.h b/dbdimp.h index 41cc72a..aee608f 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -322,6 +322,32 @@ PERL_STATIC_INLINE UV SvUV_nomg(pTHX_ SV *sv) #define my_bool bool #endif +/* + * MariaDB Connector/C 3.1.10 changed API of mysql_get_client_version() + * function. Before that release it returned client version. With that release + * it started returning Connector/C package version. + * + * So when compiling with MariaDB Connector/C client library, redefine + * mysql_get_client_version() to always returns client version via function + * mariadb_get_infov(MARIADB_CLIENT_VERSION_ID) call. + * + * Driver code expects for a long time that mysql_get_client_version() call + * returns client version and not something different. + * + * Function mariadb_get_infov() is supported since MariaDB Connector/C 3.0+. + */ +#if defined(MARIADB_PACKAGE_VERSION) && defined(MARIADB_PACKAGE_VERSION_ID) && MARIADB_PACKAGE_VERSION_ID >= 30000 +PERL_STATIC_INLINE unsigned long mariadb_get_client_version(void) +{ + /* MARIADB_CLIENT_VERSION_ID really expects size_t type, documentation is wrong and says unsigned int. */ + size_t version; + if (mariadb_get_infov(NULL, MARIADB_CLIENT_VERSION_ID, &version) != 0) + version = mysql_get_client_version(); /* On error fallback to mysql_get_client_version() */ + return version; +} +#define mysql_get_client_version() mariadb_get_client_version() +#endif + /* MYSQL_SECURE_AUTH became a no-op from MySQL 5.7.5 and is removed from MySQL 8.0.3 */ #if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID <= 50704 #define HAVE_SECURE_AUTH diff --git a/t/40server_prepare.t b/t/40server_prepare.t index 6eb2cf1..d4208cd 100644 --- a/t/40server_prepare.t +++ b/t/40server_prepare.t @@ -75,7 +75,9 @@ is_deeply($dbh->selectall_arrayref('SELECT id, mydata FROM t3'), [[1, 2]]); $dbh->{mariadb_server_prepare_disable_fallback} = 1; my $error_handler_called = 0; $dbh->{HandleError} = sub { $error_handler_called = 1; die $_[0]; }; -eval { $dbh->prepare("USE " . $dbh->quote_identifier($test_db)) }; +# MariaDB server since version 10.6.2 can prepare all statements except PREPARE, EXECUTE, and DEALLOCATE / DROP PREPARE. Previous MariaDB and Mysql versions cannot prepare USE statement +my $non_preparable_statement = ($dbh->{mariadb_serverversion} >= 100602) ? q(PREPARE stmt FROM "SELECT 1") : ("USE " . $dbh->quote_identifier($test_db)); +eval { $dbh->prepare($non_preparable_statement); }; $dbh->{HandleError} = undef; ok($error_handler_called, 'USE is not supported with mariadb_server_prepare_disable_fallback=1'); diff --git a/t/45bind_no_backslash_escapes.t b/t/45bind_no_backslash_escapes.t index 13dce12..eaf011b 100644 --- a/t/45bind_no_backslash_escapes.t +++ b/t/45bind_no_backslash_escapes.t @@ -18,10 +18,6 @@ if ($dbh->{mariadb_serverversion} < 50001) { plan skip_all => "Servers < 5.0.1 do not support sql_mode NO_BACKSLASH_ESCAPES"; } -if ($dbh->{mariadb_clientversion} < 50001) { - $id2_quoted_no_backslash = q(X'737472696E675C737472696E6722737472696E6727737472696E67'); -} - plan tests => 20; ok $dbh->do('CREATE TEMPORARY TABLE t(id VARCHAR(255), value TEXT)'); -- cgit v1.2.3