diff --git a/mysql-test/main/mdev_38792.result b/mysql-test/main/mdev_38792.result new file mode 100644 index 0000000000000..e956f80d208d6 --- /dev/null +++ b/mysql-test/main/mdev_38792.result @@ -0,0 +1,15 @@ +SET sql_mode='ORACLE'; +SELECT TO_DATE('2002 - AD', 'YYYY AD'); +TO_DATE('2002 - AD', 'YYYY AD') +2002-03-17 00:00:00 +SELECT TO_DATE('2024---01---01', 'YYYYMMDD'); +TO_DATE('2024---01---01', 'YYYYMMDD') +NULL +Warnings: +Warning 1411 Incorrect datetime value: '2024---01---01' for function to_date +SELECT TO_DATE('2024 . 05 . 10', 'YYYYMMDD'); +TO_DATE('2024 . 05 . 10', 'YYYYMMDD') +2024-05-10 00:00:00 +SELECT TO_DATE('2002 - February - 10', 'YYYY MONTH DD'); +TO_DATE('2002 - February - 10', 'YYYY MONTH DD') +2002-02-10 00:00:00 diff --git a/mysql-test/main/mdev_38792.test b/mysql-test/main/mdev_38792.test new file mode 100644 index 0000000000000..6d683d6ffd552 --- /dev/null +++ b/mysql-test/main/mdev_38792.test @@ -0,0 +1,6 @@ +SET sql_mode='ORACLE'; + +SELECT TO_DATE('2002 - AD', 'YYYY AD'); +SELECT TO_DATE('2024---01---01', 'YYYYMMDD'); +SELECT TO_DATE('2024 . 05 . 10', 'YYYYMMDD'); +SELECT TO_DATE('2002 - February - 10', 'YYYY MONTH DD'); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index c008c2089ba29..872a523a39811 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -721,6 +721,35 @@ extract_oracle_date_time(THD *thd, uint16 *format_ptr, continue; } + /* + MDEV-38792: TO_DATE: Inconsistent treatment of different separators in the date and format strings. + Skip punctuation and spaces in the input string before matching the next + format token, but avoid skipping a '-' sign if it's followed by a digit + (as it might be part of a negative year in SYYYY). + */ + // while (val < val_end && !my_isalnum(val_cs, *val)) + // { + // if (*val == '-' && (val + 1 < val_end) && my_isdigit(val_cs, *(val + 1))) + // { + // break; + // } + // val++; + // } + bool skipped_punct= false; + while (val < val_end && !my_isalnum(val_cs, *val)) + { + /* Only preserve the minus sign if the current format token supports negative values */ + if (*val == '-' && format == FMT_SYYYY && + (val + 1 < val_end) && my_isdigit(val_cs, *(val + 1))) + { + break; + } + val++; + skipped_punct= true; + } + + if (skipped_punct) part_of_digits = 0; + error= 0; if (!(val_len= (uint) (val_end - val))) goto error;