Changeset: 32e04d46c28b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/32e04d46c28b
Added Files:
        sql/test/BugTracker-2025/Tests/7759-replace-wrong-error.test
Modified Files:
        monetdb5/modules/mal/pcre.c
        sql/test/BugTracker-2025/Tests/All
Branch: Mar2025
Log Message:

use the error message from pcre2 when the replace fails, solves issue #7759     
                                                                                
                              And added test.


diffs (131 lines):

diff --git a/monetdb5/modules/mal/pcre.c b/monetdb5/modules/mal/pcre.c
--- a/monetdb5/modules/mal/pcre.c
+++ b/monetdb5/modules/mal/pcre.c
@@ -322,7 +322,7 @@ single_replace(pcre2_code *pcre_code, pc
                           PCRE2_SPTR origin_str, PCRE2_SIZE len_origin_str,
                           uint32_t exec_options,
                           PCRE2_SPTR replacement, PCRE2_SIZE len_replacement,
-                          PCRE2_UCHAR *result, PCRE2_SIZE *max_result)
+                          PCRE2_UCHAR *result, PCRE2_SIZE *max_result, 
PCRE2_UCHAR *errbuf, size_t errlen)
 {
        int j = pcre2_substitute(pcre_code, origin_str, len_origin_str, 0, 
exec_options | PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, match_data, NULL, replacement, 
len_replacement, result, max_result);
        if (j == PCRE2_ERROR_NOMEMORY) {
@@ -334,6 +334,7 @@ single_replace(pcre2_code *pcre_code, pc
                j = pcre2_substitute(pcre_code, origin_str, len_origin_str, 0, 
exec_options, match_data, NULL, replacement, len_replacement, result, 
max_result);
        }
        if (j < 0) {
+               (void)pcre2_get_error_message(j, errbuf, errlen);
                GDKfree(result);
                return NULL;
        }
@@ -356,7 +357,9 @@ pcre_replace(str *res, const char *origi
        uint32_t exec_options = PCRE2_NOTEMPTY | PCRE2_NO_UTF_CHECK;
        PCRE2_SIZE len_origin_str = (PCRE2_SIZE) strlen(origin_str);
        PCRE2_SIZE len_replacement = (PCRE2_SIZE) strlen(replacement);
+       PCRE2_UCHAR errbuf[256];
 
+       errbuf[0] = 0;
        while (*flags) {
                switch (*flags) {
                case 'e':
@@ -387,7 +390,6 @@ pcre_replace(str *res, const char *origi
        pcre_code = pcre2_compile((PCRE2_SPTR) pattern, PCRE2_ZERO_TERMINATED,
                                                          compile_options, 
&err, &errpos, NULL);
        if (pcre_code == NULL) {
-               PCRE2_UCHAR errbuf[256];
                pcre2_get_error_message(err, errbuf, sizeof(errbuf));
                throw(MAL, global ? "pcre.replace" : "pcre.replace_first",
                          OPERATION_FAILED
@@ -412,13 +414,20 @@ pcre_replace(str *res, const char *origi
        tmpres = single_replace(pcre_code, match_data, (PCRE2_SPTR) origin_str,
                                                        len_origin_str, 
exec_options,
                                                        (PCRE2_SPTR) 
replacement, len_replacement,
-                                                       tmpres, &max_result);
+                                                       tmpres, &max_result, 
errbuf, sizeof(errbuf));
        pcre2_match_data_free(match_data);
        pcre2_code_free(pcre_code);
-       if (tmpres == NULL)
-               throw(MAL, global ? "pcre.replace" : "pcre.replace_first",
-                         SQLSTATE(HY013) MAL_MALLOC_FAIL);
-
+       if (tmpres == NULL) {
+               if (errbuf[0]) {
+                       throw(MAL, global ? "pcre.replace" : 
"pcre.replace_first",
+                               OPERATION_FAILED
+                               ": pcre replace of pattern (%s) failed with 
'%s'.",
+                               pattern, (char *) errbuf);
+               } else {
+                       throw(MAL, global ? "pcre.replace" : 
"pcre.replace_first",
+                               SQLSTATE(HY013) MAL_MALLOC_FAIL);
+               }
+       }
        *res = (char *) tmpres;
        return MAL_SUCCEED;
 #else
@@ -450,7 +459,9 @@ pcre_replace_bat(BAT **res, BAT *origin_
        PCRE2_SIZE len_replacement = (PCRE2_SIZE) strlen(replacement);
        PCRE2_SPTR origin_str;
        PCRE2_SIZE max_dest_size = 0;
+       PCRE2_UCHAR errbuf[256];
 
+       errbuf[0] = 0;
        while (*flags) {
                switch (*flags) {
                case 'e':
@@ -481,7 +492,6 @@ pcre_replace_bat(BAT **res, BAT *origin_
        pcre_code = pcre2_compile((PCRE2_SPTR) pattern, PCRE2_ZERO_TERMINATED,
                                                          compile_options, 
&err, &errpos, NULL);
        if (pcre_code == NULL) {
-               PCRE2_UCHAR errbuf[256];
                pcre2_get_error_message(err, errbuf, sizeof(errbuf));
                throw(MAL, global ? "pcre.replace" : "pcre.replace_first",
                          OPERATION_FAILED
@@ -515,15 +525,22 @@ pcre_replace_bat(BAT **res, BAT *origin_
                tmpres = single_replace(pcre_code, match_data, origin_str,
                                                                (PCRE2_SIZE) 
strlen((char *) origin_str), exec_options,
                                                                (PCRE2_SPTR) 
replacement, len_replacement,
-                                                               tmpres, 
&max_dest_size);
+                                                               tmpres, 
&max_dest_size, errbuf, sizeof(errbuf));
                if (tmpres == NULL || BUNappend(tmpbat, tmpres, false) != 
GDK_SUCCEED) {
                        bat_iterator_end(&origin_strsi);
                        pcre2_match_data_free(match_data);
                        pcre2_code_free(pcre_code);
                        GDKfree(tmpres);
                        BBPreclaim(tmpbat);
-                       throw(MAL, global ? "batpcre.replace" : 
"batpcre.replace_first",
-                                 SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       if (errbuf[0]) {
+                               throw(MAL, global ? "batpcre.replace" : 
"batpcre.replace_first",
+                                       OPERATION_FAILED
+                                       ": pcre replace of pattern (%s) failed 
with '%s'.",
+                                       pattern, (char *) errbuf);
+                       } else {
+                               throw(MAL, global ? "batpcre.replace" : 
"batpcre.replace_first",
+                                       SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       }
                }
        }
        bat_iterator_end(&origin_strsi);
diff --git a/sql/test/BugTracker-2025/Tests/7759-replace-wrong-error.test 
b/sql/test/BugTracker-2025/Tests/7759-replace-wrong-error.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2025/Tests/7759-replace-wrong-error.test
@@ -0,0 +1,10 @@
+statement ok
+CREATE OR REPLACE FUNCTION pcre_replace(s string, pattern string, repl string, 
flags string) RETURNS string EXTERNAL NAME pcre."replace"
+
+query T
+select pcre_replace('abcd','(bc)','$1','')
+----
+abcd
+
+statement error: operation failed: pcre replace of pattern (bc) failed with 
'unknown substring'.
+select pcre_replace('abcd','bc','$1','')
diff --git a/sql/test/BugTracker-2025/Tests/All 
b/sql/test/BugTracker-2025/Tests/All
--- a/sql/test/BugTracker-2025/Tests/All
+++ b/sql/test/BugTracker-2025/Tests/All
@@ -51,3 +51,4 @@ 7748-update-returning-subquery-crash
 7753-like-in-projection
 7725-crash-find-rel-ref
 7745-antijoin-bad-mal-gen
+7759-replace-wrong-error
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to