Skip to content

Commit 42e9a08

Browse files
MDEV-38791 TO_DATE() allows duplicate format specifiers
The Oracle-mode TO_DATE() function incorrectly parsed strings containing conflicting format specifiers within the Day-name family (e.g., 'DAY DY') without throwing an ER_STD_INVALID_ARGUMENT error. This patch completes the existing validation framework for family-based conflict checks in item_timefunc.cc during format string parsing. Specifically, it adds formats_used() checks for FMT_DAY, ensuring that specifiers within the Day-name family strictly block each other. This aligns the Day-name handling with the already existing checks for the Year, Month, Hour, and Meridian families. Compatible specifiers, such as YYYY and DDD (Year and Day of Year), remain unaffected and parse successfully. A comprehensive MTR test suite has been added to func_to_date.test to cover standard and edge-case conflicts. Reported-by: Elena Stepanova <elenastepanova@github> Signed-off-by: Alexandru Diaconu <alexandrudiaconu93@gmail.com>
1 parent 768b6a2 commit 42e9a08

3 files changed

Lines changed: 176 additions & 0 deletions

File tree

mysql-test/suite/compat/oracle/r/func_to_date.result

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,3 +845,86 @@ x
845845
SELECT TO_DATE('20 серпня 2024','DD MONTH YYYY','NLS_DATE_LANGUAGE=UKRAINIAN') AS x FROM DUAL;
846846
x
847847
2024-08-20 00:00:00
848+
#
849+
# MDEV-38791: TO_DATE: Inconsistent treatment of duplicate or semantically similar format elements
850+
#
851+
SET sql_mode='ORACLE';
852+
# Year Family
853+
SELECT TO_DATE('2001 2001', 'YYYY YYYY') FROM DUAL;
854+
ERROR HY000: Invalid argument error: date format not recognized at YYYY in function to_date.
855+
SELECT TO_DATE('2001 001', 'YYYY YYY') FROM DUAL;
856+
ERROR HY000: Invalid argument error: date format not recognized at YYY in function to_date.
857+
SELECT TO_DATE('2025 2025', 'YYYY IYYY') FROM DUAL;
858+
ERROR HY000: Invalid argument error: date format not recognized at IYYY in function to_date.
859+
SELECT TO_DATE('2025 2025', 'YYYY RRRR') FROM DUAL;
860+
ERROR HY000: Invalid argument error: date format not recognized at RRRR in function to_date.
861+
SELECT TO_DATE('2025 25', 'YYYY YY') FROM DUAL;
862+
ERROR HY000: Invalid argument error: date format not recognized at YY in function to_date.
863+
SELECT TO_DATE('2025 25', 'IYYY YY') FROM DUAL;
864+
ERROR HY000: Invalid argument error: date format not recognized at IYYY YY in function to_date.
865+
SELECT TO_DATE('2025 25', 'RRRR RR') FROM DUAL;
866+
ERROR HY000: Invalid argument error: date format not recognized at RR in function to_date.
867+
SELECT TO_DATE('25 25', 'YY RR') FROM DUAL;
868+
ERROR HY000: Invalid argument error: date format not recognized at RR in function to_date.
869+
SELECT TO_DATE('025 025', 'YYY IYY') FROM DUAL;
870+
ERROR HY000: Invalid argument error: date format not recognized at IYY in function to_date.
871+
SELECT TO_DATE('5 5', 'Y I') FROM DUAL;
872+
ERROR HY000: Invalid argument error: date format not recognized at I in function to_date.
873+
# Month Family
874+
SELECT TO_DATE('February February', 'MONTH MONTH') FROM DUAL;
875+
ERROR HY000: Invalid argument error: date format not recognized at MONTH in function to_date.
876+
SELECT TO_DATE('12 12', 'MM MM') FROM DUAL;
877+
ERROR HY000: Invalid argument error: date format not recognized at MM in function to_date.
878+
SELECT TO_DATE('Feb February', 'MON MONTH') FROM DUAL;
879+
ERROR HY000: Invalid argument error: date format not recognized at MONTH in function to_date.
880+
SELECT TO_DATE('12 Dec', 'MM MON') FROM DUAL;
881+
ERROR HY000: Invalid argument error: date format not recognized at MON in function to_date.
882+
SELECT TO_DATE('12 December', 'MM MONTH') FROM DUAL;
883+
ERROR HY000: Invalid argument error: date format not recognized at MONTH in function to_date.
884+
SELECT TO_DATE('12 XII', 'MM RM') FROM DUAL;
885+
ERROR HY000: Invalid argument error: date format not recognized at RM in function to_date.
886+
SELECT TO_DATE('Dec XII', 'MON RM') FROM DUAL;
887+
ERROR HY000: Invalid argument error: date format not recognized at RM in function to_date.
888+
SELECT TO_DATE('December XII', 'MONTH RM') FROM DUAL;
889+
ERROR HY000: Invalid argument error: date format not recognized at RM in function to_date.
890+
# Day Family
891+
SELECT TO_DATE('Monday Mon', 'DAY DY') FROM DUAL;
892+
ERROR HY000: Invalid argument error: date format not recognized at DY in function to_date.
893+
SELECT TO_DATE('Mon Mon', 'DY DY') FROM DUAL;
894+
ERROR HY000: Invalid argument error: date format not recognized at DY in function to_date.
895+
SELECT TO_DATE('20 20', 'DD DD') FROM DUAL;
896+
ERROR HY000: Invalid argument error: date format not recognized at DD in function to_date.
897+
SELECT TO_DATE('Monday 2', 'DAY D') FROM DUAL;
898+
ERROR HY000: Invalid argument error: date format not recognized at D in function to_date.
899+
SELECT TO_DATE('Mon 2', 'DY D') FROM DUAL;
900+
ERROR HY000: Invalid argument error: date format not recognized at D in function to_date.
901+
SELECT TO_DATE('15 150', 'DD DDD') FROM DUAL;
902+
ERROR HY000: Invalid argument error: date format not recognized at DDD in function to_date.
903+
# Others
904+
SELECT TO_DATE('10 10', 'HH24 HH24') FROM DUAL;
905+
ERROR HY000: Invalid argument error: date format not recognized at HH24 in function to_date.
906+
SELECT TO_DATE('30 30', 'MI MI') FROM DUAL;
907+
ERROR HY000: Invalid argument error: date format not recognized at MI in function to_date.
908+
SELECT TO_DATE('45 45', 'SS SS') FROM DUAL;
909+
ERROR HY000: Invalid argument error: date format not recognized at SS in function to_date.
910+
SELECT TO_DATE('10 10', 'HH HH12') FROM DUAL;
911+
ERROR HY000: Invalid argument error: date format not recognized at HH12 in function to_date.
912+
SELECT TO_DATE('10 22', 'HH HH24') FROM DUAL;
913+
ERROR HY000: Invalid argument error: date format not recognized at HH24 in function to_date.
914+
SELECT TO_DATE('10 22', 'HH12 HH24') FROM DUAL;
915+
ERROR HY000: Invalid argument error: date format not recognized at HH24 in function to_date.
916+
SELECT TO_DATE('AM PM', 'AM PM') FROM DUAL;
917+
ERROR HY000: Invalid argument error: date format not recognized at PM in function to_date.
918+
SELECT TO_DATE('A.M. P.M.', 'A.M. P.M.') FROM DUAL;
919+
ERROR HY000: Invalid argument error: date format not recognized at P.M. in function to_date.
920+
SELECT TO_DATE('AM A.M.', 'AM A.M.') FROM DUAL;
921+
ERROR HY000: Invalid argument error: date format not recognized at A.M. in function to_date.
922+
SELECT TO_DATE('1 2', 'WW IW') FROM DUAL;
923+
ERROR HY000: Invalid argument error: date format not recognized at WW IW in function to_date.
924+
SELECT TO_DATE('123 456', 'FF FF') FROM DUAL;
925+
ERROR HY000: Invalid argument error: date format not recognized at FF in function to_date.
926+
# YYYY and DDD are compatible (Year + Day of Year)
927+
SELECT TO_DATE('2026 100', 'YYYY DDD') FROM DUAL;
928+
TO_DATE('2026 100', 'YYYY DDD')
929+
2026-04-10 00:00:00
930+
# End of 12.3 tests

mysql-test/suite/compat/oracle/t/func_to_date.test

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,92 @@ SELECT TO_DATE('15 ژوئن 2024','DD MONTH YYYY','NLS_DATE_LANGUAGE=PERSIAN') A
390390
SELECT TO_DATE('15 ਜੂਨ 2024','DD MONTH YYYY','NLS_DATE_LANGUAGE=PUNJABI') AS x FROM DUAL;
391391
SELECT TO_DATE('15 червень 2024','DD MONTH YYYY','NLS_DATE_LANGUAGE=UKRAINIAN') AS x FROM DUAL;
392392
SELECT TO_DATE('20 серпня 2024','DD MONTH YYYY','NLS_DATE_LANGUAGE=UKRAINIAN') AS x FROM DUAL;
393+
394+
--echo #
395+
--echo # MDEV-38791: TO_DATE: Inconsistent treatment of duplicate or semantically similar format elements
396+
--echo #
397+
398+
SET sql_mode='ORACLE';
399+
400+
--echo # Year Family
401+
--error ER_STD_INVALID_ARGUMENT
402+
SELECT TO_DATE('2001 2001', 'YYYY YYYY') FROM DUAL;
403+
--error ER_STD_INVALID_ARGUMENT
404+
SELECT TO_DATE('2001 001', 'YYYY YYY') FROM DUAL;
405+
--error ER_STD_INVALID_ARGUMENT
406+
SELECT TO_DATE('2025 2025', 'YYYY IYYY') FROM DUAL;
407+
--error ER_STD_INVALID_ARGUMENT
408+
SELECT TO_DATE('2025 2025', 'YYYY RRRR') FROM DUAL;
409+
--error ER_STD_INVALID_ARGUMENT
410+
SELECT TO_DATE('2025 25', 'YYYY YY') FROM DUAL;
411+
--error ER_STD_INVALID_ARGUMENT
412+
SELECT TO_DATE('2025 25', 'IYYY YY') FROM DUAL;
413+
--error ER_STD_INVALID_ARGUMENT
414+
SELECT TO_DATE('2025 25', 'RRRR RR') FROM DUAL;
415+
--error ER_STD_INVALID_ARGUMENT
416+
SELECT TO_DATE('25 25', 'YY RR') FROM DUAL;
417+
--error ER_STD_INVALID_ARGUMENT
418+
SELECT TO_DATE('025 025', 'YYY IYY') FROM DUAL;
419+
--error ER_STD_INVALID_ARGUMENT
420+
SELECT TO_DATE('5 5', 'Y I') FROM DUAL;
421+
422+
--echo # Month Family
423+
--error ER_STD_INVALID_ARGUMENT
424+
SELECT TO_DATE('February February', 'MONTH MONTH') FROM DUAL;
425+
--error ER_STD_INVALID_ARGUMENT
426+
SELECT TO_DATE('12 12', 'MM MM') FROM DUAL;
427+
--error ER_STD_INVALID_ARGUMENT
428+
SELECT TO_DATE('Feb February', 'MON MONTH') FROM DUAL;
429+
--error ER_STD_INVALID_ARGUMENT
430+
SELECT TO_DATE('12 Dec', 'MM MON') FROM DUAL;
431+
--error ER_STD_INVALID_ARGUMENT
432+
SELECT TO_DATE('12 December', 'MM MONTH') FROM DUAL;
433+
--error ER_STD_INVALID_ARGUMENT
434+
SELECT TO_DATE('12 XII', 'MM RM') FROM DUAL;
435+
--error ER_STD_INVALID_ARGUMENT
436+
SELECT TO_DATE('Dec XII', 'MON RM') FROM DUAL;
437+
--error ER_STD_INVALID_ARGUMENT
438+
SELECT TO_DATE('December XII', 'MONTH RM') FROM DUAL;
439+
440+
--echo # Day Family
441+
--error ER_STD_INVALID_ARGUMENT
442+
SELECT TO_DATE('Monday Mon', 'DAY DY') FROM DUAL;
443+
--error ER_STD_INVALID_ARGUMENT
444+
SELECT TO_DATE('Mon Mon', 'DY DY') FROM DUAL;
445+
--error ER_STD_INVALID_ARGUMENT
446+
SELECT TO_DATE('20 20', 'DD DD') FROM DUAL;
447+
--error ER_STD_INVALID_ARGUMENT
448+
SELECT TO_DATE('Monday 2', 'DAY D') FROM DUAL;
449+
--error ER_STD_INVALID_ARGUMENT
450+
SELECT TO_DATE('Mon 2', 'DY D') FROM DUAL;
451+
--error ER_STD_INVALID_ARGUMENT
452+
SELECT TO_DATE('15 150', 'DD DDD') FROM DUAL;
453+
454+
--echo # Others
455+
--error ER_STD_INVALID_ARGUMENT
456+
SELECT TO_DATE('10 10', 'HH24 HH24') FROM DUAL;
457+
--error ER_STD_INVALID_ARGUMENT
458+
SELECT TO_DATE('30 30', 'MI MI') FROM DUAL;
459+
--error ER_STD_INVALID_ARGUMENT
460+
SELECT TO_DATE('45 45', 'SS SS') FROM DUAL;
461+
--error ER_STD_INVALID_ARGUMENT
462+
SELECT TO_DATE('10 10', 'HH HH12') FROM DUAL;
463+
--error ER_STD_INVALID_ARGUMENT
464+
SELECT TO_DATE('10 22', 'HH HH24') FROM DUAL;
465+
--error ER_STD_INVALID_ARGUMENT
466+
SELECT TO_DATE('10 22', 'HH12 HH24') FROM DUAL;
467+
--error ER_STD_INVALID_ARGUMENT
468+
SELECT TO_DATE('AM PM', 'AM PM') FROM DUAL;
469+
--error ER_STD_INVALID_ARGUMENT
470+
SELECT TO_DATE('A.M. P.M.', 'A.M. P.M.') FROM DUAL;
471+
--error ER_STD_INVALID_ARGUMENT
472+
SELECT TO_DATE('AM A.M.', 'AM A.M.') FROM DUAL;
473+
--error ER_STD_INVALID_ARGUMENT
474+
SELECT TO_DATE('1 2', 'WW IW') FROM DUAL;
475+
--error ER_STD_INVALID_ARGUMENT
476+
SELECT TO_DATE('123 456', 'FF FF') FROM DUAL;
477+
478+
--echo # YYYY and DDD are compatible (Year + Day of Year)
479+
SELECT TO_DATE('2026 100', 'YYYY DDD') FROM DUAL;
480+
481+
--echo # End of 12.3 tests

sql/item_timefunc.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2982,6 +2982,8 @@ static bool parse_format_string(const String *format, uint16 *fmt_array,
29822982
}
29832983
else if (tmp1 == 'Y')
29842984
{
2985+
if (for_to_date && formats_used(&used, FMT_DAY))
2986+
goto error;
29852987
*tmp_fmt= FMT_DY; // Day name
29862988
tmp_len+= 3;
29872989
type_flags|= PARSE_TYPE_WEEKDAY | PARSE_TYPE_NON_DETERMINISTIC;
@@ -2990,6 +2992,8 @@ static bool parse_format_string(const String *format, uint16 *fmt_array,
29902992
{
29912993
if (ptr + 2 == end || my_toupper(system_charset_info, *(ptr+2)) != 'Y')
29922994
goto error;
2995+
if (for_to_date && formats_used(&used, FMT_DAY))
2996+
goto error;
29932997
*tmp_fmt= FMT_DAY; // Day name
29942998
tmp_len+= locale->max_day_name_length * my_charset_utf8mb3_bin.mbmaxlen;
29952999
type_flags|= PARSE_TYPE_WEEKDAY | PARSE_TYPE_NON_DETERMINISTIC;

0 commit comments

Comments
 (0)