mirror of
https://github.com/MariaDB/server.git
synced 2025-04-18 21:44:20 +03:00
MDEV-36216 TO_CHAR FM format not recognized in SQL_MODE=Oracle
Adding support for the "FM" format in function TO_CHAR(date_time, fmt). "FM" in the format string disables padding of all components following it. So now TO_CHAR() works as follows: - By default string format components DAY (weekday name) and MONTH (month name) are right-padded with spaces to the maximum possible DAY and MONTH name lengths respectively, according to the current locale specified in @@lc_time_names. So for example, with lc_time_names='en_US' all month names are right-padded with spaces up to 9 characters ('September' is the longest). SET lc_time_names='en_US'; SELECT TO_CHAR('0001-02-03', 'MONTH'); -> 'February ' (padded to 9 chars) NEW: When typed after FM, DAY and MONTH names are not right-padded with trailing spaces any more: SET lc_time_names='en_US'; SELECT TO_CHAR('0001-02-03', 'FMMONTH'); -> 'February' (not padded) - By default numeric components YYYY, YYY, YY, Y, DD, H12, H24, MI, SS are left-padded with leading digits '0' up to the maximum possible number of digits in the component (e.g. 4 for YYYY): SELECT TO_CHAR('0001-02-03', 'YYYY'); -> '0001' (padded to 4 chars) NEW: When typed after FM, these numeric components are not left-padded with leading zeros any more: SELECT TO_CHAR('0001-02-03', 'FMYYYY'); -> '1' (not padded) - If FM is specified multiple times in a format string, every FM negates the previous padding state: * an odd FM disables padding * an even FM enables padding Implementation details: - Adding a helper class Date_time_format_oracle. - Adding a helper method Date_time_format_oracle::append_lex_cstring() - Moving the function append_val() to Date_time_format_oracle as a method. - Moving the function make_date_time_oracle() to Date_time_format_oracle as a method format(). - Adding helper methods month_name() and day_name() in class MY_LOCALE, to return the corresponding components as LEX_CSTRINGs.
This commit is contained in:
parent
d3c9a2ee21
commit
2dc9b8b78e
@ -446,3 +446,239 @@ SELECT TO_CHAR((VALUES('2022-12-12','2020-10-10')));
|
||||
ERROR HY000: Illegal parameter data type row for operation 'to_char'
|
||||
SELECT TO_CHAR((STR_TO_DATE('2023-01-01', '%d-%m-%Y'), 'YYYY-MM-DD') );
|
||||
ERROR HY000: Illegal parameter data type row for operation 'to_char'
|
||||
#
|
||||
# MDEV-36216 TO_CHAR FM format not recognized in SQL_MODE=Oracle
|
||||
#
|
||||
SET NAMES utf8mb3;
|
||||
CREATE TABLE t1 (fmt VARCHAR(256));
|
||||
INSERT INTO t1 VALUES
|
||||
/* Add the slash character before FM to see the position of FM in the results */
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('/FMYYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-/FMMM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-/FMDD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD /FMHH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:/FMMI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:/FMSS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS /FMDAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY /FMMONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; /FMYYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-/FMMM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-/FMDD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD /FMHH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:/FMMI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:/FMSS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS /FMDAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY /FMMONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH/FM;'),
|
||||
/*Formats not covered above */
|
||||
('YYY YY Y HH12; /FMYYY YY Y HH12;'),
|
||||
/*FM specified multiple times*/
|
||||
('FMFMFMFMFMFMFMFMYYYY-MM-DD [DAY] [MONTH]'),
|
||||
('FMFMFMFMFMFMFMFMFMYYYY-MM-DD [DAY] [MONTH]'),
|
||||
(
|
||||
'YYYY-MM-DD [DAY] [MONTH]; FMYYYY-MM-DD [DAY] [MONTH]; '
|
||||
'FMYYYY-MM-DD [DAY] [MONTH]; FMYYYY-MM-DD [DAY] [MONTH]; '
|
||||
'FMYYYY-MM-DD [DAY] [MONTH];'
|
||||
),
|
||||
/*Corner cases*/
|
||||
('FX') /*Unknown format starting with 'F'*/,
|
||||
('F') /*Unexpected end of the format string*/;
|
||||
SET lc_time_names='en_US';
|
||||
SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
c1
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday February ;
|
||||
/1-2-3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-/2-3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-/3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 /4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:/5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:/6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 /Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday /February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; /1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-/2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-/3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 /4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:/5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:/6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 /Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday /February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday February /;
|
||||
001 01 1 04; /1 1 1 4;
|
||||
0001-02-03 [Saturday ] [February ]
|
||||
1-2-3 [Saturday] [February]
|
||||
0001-02-03 [Saturday ] [February ]; 1-2-3 [Saturday] [February]; 0001-02-03 [Saturday ] [February ]; 1-2-3 [Saturday] [February]; 0001-02-03 [Saturday ] [February ];
|
||||
NULL
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: date format not recognized at FX in function to_char.
|
||||
Warning 3047 Invalid argument error: date format not recognized at F in function to_char.
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v1 AS SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
SHOW CREATE VIEW v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE VIEW "v1" AS select to_char('0001-02-03 04:05:06',"t1"."fmt") AS "c1" from "t1" utf8mb3 utf8mb3_general_ci
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday February ;
|
||||
/1-2-3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-/2-3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-/3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 /4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:/5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:/6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 /Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday /February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; /1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-/2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-/3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 /4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:/5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:/6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 /Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday /February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday February /;
|
||||
001 01 1 04; /1 1 1 4;
|
||||
0001-02-03 [Saturday ] [February ]
|
||||
1-2-3 [Saturday] [February]
|
||||
0001-02-03 [Saturday ] [February ]; 1-2-3 [Saturday] [February]; 0001-02-03 [Saturday ] [February ]; 1-2-3 [Saturday] [February]; 0001-02-03 [Saturday ] [February ];
|
||||
NULL
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: date format not recognized at FX in function to_char.
|
||||
Warning 3047 Invalid argument error: date format not recognized at F in function to_char.
|
||||
SET sql_mode=DEFAULT;
|
||||
SHOW CREATE VIEW v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select to_char('0001-02-03 04:05:06',`t1`.`fmt`) AS `c1` from `t1` utf8mb3 utf8mb3_general_ci
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday February ;
|
||||
/1-2-3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-/2-3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-/3 4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 /4:5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:/5:6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:/6 Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 /Saturday February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday /February; 1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; /1-2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-/2-3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-/3 4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 /4:5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:/5:6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:/6 Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 /Saturday February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday /February;
|
||||
0001-02-03 04:05:06 Saturday February ; 0001-02-03 04:05:06 Saturday February /;
|
||||
001 01 1 04; /1 1 1 4;
|
||||
0001-02-03 [Saturday ] [February ]
|
||||
1-2-3 [Saturday] [February]
|
||||
0001-02-03 [Saturday ] [February ]; 1-2-3 [Saturday] [February]; 0001-02-03 [Saturday ] [February ]; 1-2-3 [Saturday] [February]; 0001-02-03 [Saturday ] [February ];
|
||||
NULL
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: date format not recognized at FX in function to_char.
|
||||
Warning 3047 Invalid argument error: date format not recognized at F in function to_char.
|
||||
DROP VIEW v1;
|
||||
SET lc_time_names='zh_CN';
|
||||
SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
c1
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 二月 ;
|
||||
/1-2-3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-/2-3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-/3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 /4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:/5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:/6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 /星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 /二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; /1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-/2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-/3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 /4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:/5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:/6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 /星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 /二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 二月 /;
|
||||
001 01 1 04; /1 1 1 4;
|
||||
0001-02-03 [星期六] [二月 ]
|
||||
1-2-3 [星期六] [二月]
|
||||
0001-02-03 [星期六] [二月 ]; 1-2-3 [星期六] [二月]; 0001-02-03 [星期六] [二月 ]; 1-2-3 [星期六] [二月]; 0001-02-03 [星期六] [二月 ];
|
||||
NULL
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: date format not recognized at FX in function to_char.
|
||||
Warning 3047 Invalid argument error: date format not recognized at F in function to_char.
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v1 AS SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
SHOW CREATE VIEW v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE VIEW "v1" AS select to_char('0001-02-03 04:05:06',"t1"."fmt") AS "c1" from "t1" utf8mb3 utf8mb3_general_ci
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 二月 ;
|
||||
/1-2-3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-/2-3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-/3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 /4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:/5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:/6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 /星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 /二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; /1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-/2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-/3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 /4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:/5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:/6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 /星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 /二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 二月 /;
|
||||
001 01 1 04; /1 1 1 4;
|
||||
0001-02-03 [星期六] [二月 ]
|
||||
1-2-3 [星期六] [二月]
|
||||
0001-02-03 [星期六] [二月 ]; 1-2-3 [星期六] [二月]; 0001-02-03 [星期六] [二月 ]; 1-2-3 [星期六] [二月]; 0001-02-03 [星期六] [二月 ];
|
||||
NULL
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: date format not recognized at FX in function to_char.
|
||||
Warning 3047 Invalid argument error: date format not recognized at F in function to_char.
|
||||
SET sql_mode=DEFAULT;
|
||||
SHOW CREATE VIEW v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select to_char('0001-02-03 04:05:06',`t1`.`fmt`) AS `c1` from `t1` utf8mb3 utf8mb3_general_ci
|
||||
SELECT * FROM v1;
|
||||
c1
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 二月 ;
|
||||
/1-2-3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-/2-3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-/3 4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 /4:5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:/5:6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:/6 星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 /星期六 二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 /二月; 1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; /1-2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-/2-3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-/3 4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 /4:5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:/5:6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:/6 星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 /星期六 二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 /二月;
|
||||
0001-02-03 04:05:06 星期六 二月 ; 0001-02-03 04:05:06 星期六 二月 /;
|
||||
001 01 1 04; /1 1 1 4;
|
||||
0001-02-03 [星期六] [二月 ]
|
||||
1-2-3 [星期六] [二月]
|
||||
0001-02-03 [星期六] [二月 ]; 1-2-3 [星期六] [二月]; 0001-02-03 [星期六] [二月 ]; 1-2-3 [星期六] [二月]; 0001-02-03 [星期六] [二月 ];
|
||||
NULL
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 3047 Invalid argument error: date format not recognized at FX in function to_char.
|
||||
Warning 3047 Invalid argument error: date format not recognized at F in function to_char.
|
||||
DROP VIEW v1;
|
||||
SET lc_time_names=DEFAULT;
|
||||
DROP TABLE t1;
|
||||
|
@ -234,3 +234,74 @@ SELECT TO_CHAR((VALUES('2022-12-12','2020-10-10')));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT TO_CHAR((STR_TO_DATE('2023-01-01', '%d-%m-%Y'), 'YYYY-MM-DD') );
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36216 TO_CHAR FM format not recognized in SQL_MODE=Oracle
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb3;
|
||||
CREATE TABLE t1 (fmt VARCHAR(256));
|
||||
INSERT INTO t1 VALUES
|
||||
|
||||
/* Add the slash character before FM to see the position of FM in the results */
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('/FMYYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-/FMMM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-/FMDD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD /FMHH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:/FMMI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:/FMSS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS /FMDAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY /FMMONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; /FMYYYY-MM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-/FMMM-DD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-/FMDD HH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD /FMHH24:MI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:/FMMI:SS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:/FMSS DAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS /FMDAY MONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY /FMMONTH;'),
|
||||
('YYYY-MM-DD HH24:MI:SS DAY MONTH; YYYY-MM-DD HH24:MI:SS DAY MONTH/FM;'),
|
||||
|
||||
/*Formats not covered above */
|
||||
('YYY YY Y HH12; /FMYYY YY Y HH12;'),
|
||||
|
||||
/*FM specified multiple times*/
|
||||
('FMFMFMFMFMFMFMFMYYYY-MM-DD [DAY] [MONTH]'),
|
||||
('FMFMFMFMFMFMFMFMFMYYYY-MM-DD [DAY] [MONTH]'),
|
||||
(
|
||||
'YYYY-MM-DD [DAY] [MONTH]; FMYYYY-MM-DD [DAY] [MONTH]; '
|
||||
'FMYYYY-MM-DD [DAY] [MONTH]; FMYYYY-MM-DD [DAY] [MONTH]; '
|
||||
'FMYYYY-MM-DD [DAY] [MONTH];'
|
||||
),
|
||||
|
||||
/*Corner cases*/
|
||||
('FX') /*Unknown format starting with 'F'*/,
|
||||
('F') /*Unexpected end of the format string*/;
|
||||
|
||||
SET lc_time_names='en_US';
|
||||
SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v1 AS SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
SHOW CREATE VIEW v1;
|
||||
SELECT * FROM v1;
|
||||
SET sql_mode=DEFAULT;
|
||||
SHOW CREATE VIEW v1;
|
||||
SELECT * FROM v1;
|
||||
DROP VIEW v1;
|
||||
|
||||
SET lc_time_names='zh_CN';
|
||||
SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v1 AS SELECT TO_CHAR('0001-02-03 04:05:06', fmt) AS c1 FROM t1;
|
||||
SHOW CREATE VIEW v1;
|
||||
SELECT * FROM v1;
|
||||
SET sql_mode=DEFAULT;
|
||||
SHOW CREATE VIEW v1;
|
||||
SELECT * FROM v1;
|
||||
DROP VIEW v1;
|
||||
|
||||
SET lc_time_names=DEFAULT;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
@ -1962,6 +1962,79 @@ null_date:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* A class to print TO_CHAR(date_time, format) */
|
||||
class Date_time_format_oracle
|
||||
{
|
||||
// m_fm is true if "FM" was found in the format string odd number of times
|
||||
bool m_fm;
|
||||
public:
|
||||
Date_time_format_oracle()
|
||||
:m_fm(false)
|
||||
{ }
|
||||
|
||||
/*
|
||||
Append a numeric value to a String.
|
||||
If m_fm is false, then left-pad the numeric value with '0'.
|
||||
|
||||
@param val - the numeric value to be appended to str
|
||||
@param size - the maximum number of digits possible in val
|
||||
@param [OUT] str - the result String (val will be appended to it)
|
||||
|
||||
@retval false - on success
|
||||
@retval true - on error (e.g. EOM)
|
||||
*/
|
||||
bool append_val(int val, uint size, String *str) const
|
||||
{
|
||||
if (m_fm)
|
||||
return str->append_longlong(val);
|
||||
return str->append_zerofill(val, size);
|
||||
}
|
||||
|
||||
/*
|
||||
Append a LEX_CSTRING value to a String.
|
||||
If m_fm is false, then right-pad the appended value with spaces.
|
||||
|
||||
@param ls - the LEX_CSTRING to be append to str
|
||||
@param max_char_length - the maximum possible length of ls, in characters
|
||||
@param [OUT] str - the result String (ls will be appended to it)
|
||||
|
||||
@retval false - on success
|
||||
@retval true - on error (e.g. EOM)
|
||||
*/
|
||||
bool append_lex_cstring(const LEX_CSTRING ls, uint max_char_length,
|
||||
String *str) const
|
||||
{
|
||||
// Locale data uses utf8mb3
|
||||
static constexpr CHARSET_INFO *cs= &my_charset_utf8mb3_general_ci;
|
||||
str->append(ls.str, ls.length, cs);
|
||||
if (!m_fm)
|
||||
{
|
||||
size_t char_length= cs->numchars(ls.str, ls.str + ls.length);
|
||||
if (char_length < max_char_length)
|
||||
return str->fill(str->length() + max_char_length - char_length, ' ');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Print a date/time value to a String according to the given format
|
||||
@param fmt_array - the format array
|
||||
@param l_time - the date/time value
|
||||
@param locale - the locale to use for textual components
|
||||
(MONTH and DAY)
|
||||
@param [OUT] str - the string to print into.
|
||||
|
||||
@retval false - on success
|
||||
@retval true - on error (e.g. EOM)
|
||||
*/
|
||||
bool format(const uint16 *fmt_array,
|
||||
const MYSQL_TIME *l_time,
|
||||
const MY_LOCALE *locale,
|
||||
String *str);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Oracle has many formatting models, we list all but only part of them
|
||||
are implemented, because some models depend on oracle functions
|
||||
@ -2138,7 +2211,8 @@ bool Item_func_tochar::parse_format_string(const String *format, uint *fmt_len)
|
||||
/*
|
||||
Oracle datetime format support text in double quotation marks like
|
||||
'YYYY"abc"MM"xyz"DD', When this happens, store the text and quotation
|
||||
marks, and use the text as a separator in make_date_time_oracle.
|
||||
marks, and use the text as a separator in
|
||||
Date_time_format_oracle::format().
|
||||
|
||||
NOTE: the quotation mark is not print in return value. for example:
|
||||
select TO_CHAR(sysdate, 'YYYY"abc"MM"xyzDD"') will return 2021abc01xyz11
|
||||
@ -2419,6 +2493,17 @@ bool Item_func_tochar::parse_format_string(const String *format, uint *fmt_len)
|
||||
tmp_fmt--;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
if (ptr + 1 == end)
|
||||
goto error;
|
||||
if (my_toupper(system_charset_info, ptr[1]) == 'M')
|
||||
{
|
||||
*tmp_fmt= FMT_FM;
|
||||
ptr+= 1;
|
||||
continue;
|
||||
}
|
||||
goto error;
|
||||
|
||||
default:
|
||||
offset= parse_special(cfmt, ptr, end, tmp_fmt);
|
||||
if (!offset)
|
||||
@ -2441,16 +2526,10 @@ error:
|
||||
}
|
||||
|
||||
|
||||
static inline bool append_val(int val, int size, String *str)
|
||||
{
|
||||
return str->append_zerofill(val, size);
|
||||
}
|
||||
|
||||
|
||||
static bool make_date_time_oracle(const uint16 *fmt_array,
|
||||
const MYSQL_TIME *l_time,
|
||||
const MY_LOCALE *locale,
|
||||
String *str)
|
||||
bool Date_time_format_oracle::format(const uint16 *fmt_array,
|
||||
const MYSQL_TIME *l_time,
|
||||
const MY_LOCALE *locale,
|
||||
String *str)
|
||||
{
|
||||
bool quotation_flag= false;
|
||||
const uint16 *ptr= fmt_array;
|
||||
@ -2558,16 +2637,8 @@ static bool make_date_time_oracle(const uint16 *fmt_array,
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *month_name= (locale->month_names->
|
||||
type_names[l_time->month-1]);
|
||||
size_t month_byte_len= strlen(month_name);
|
||||
size_t month_char_len;
|
||||
str->append(month_name, month_byte_len, system_charset_info);
|
||||
month_char_len= my_numchars_mb(&my_charset_utf8mb3_general_ci,
|
||||
month_name, month_name +
|
||||
month_byte_len);
|
||||
if (str->fill(str->length() + locale->max_month_name_length -
|
||||
month_char_len, ' '))
|
||||
if (append_lex_cstring(locale->month_name(l_time->month - 1),
|
||||
locale->max_month_name_length, str))
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
@ -2598,17 +2669,10 @@ static bool make_date_time_oracle(const uint16 *fmt_array,
|
||||
str->append("00", 2, system_charset_info);
|
||||
else
|
||||
{
|
||||
const char *day_name;
|
||||
size_t day_byte_len, day_char_len;
|
||||
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
|
||||
l_time->day), 0);
|
||||
day_name= locale->day_names->type_names[weekday];
|
||||
day_byte_len= strlen(day_name);
|
||||
str->append(day_name, day_byte_len, system_charset_info);
|
||||
day_char_len= my_numchars_mb(&my_charset_utf8mb3_general_ci,
|
||||
day_name, day_name + day_byte_len);
|
||||
if (str->fill(str->length() + locale->max_day_name_length -
|
||||
day_char_len, ' '))
|
||||
if (append_lex_cstring(locale->day_name(weekday),
|
||||
locale->max_day_name_length, str))
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
@ -2636,6 +2700,10 @@ static bool make_date_time_oracle(const uint16 *fmt_array,
|
||||
goto err_exit;
|
||||
break;
|
||||
|
||||
case FMT_FM:
|
||||
m_fm= !m_fm;
|
||||
break;
|
||||
|
||||
default:
|
||||
str->append((char) *ptr);
|
||||
}
|
||||
@ -2743,7 +2811,7 @@ String *Item_func_tochar::val_str(String* str)
|
||||
|
||||
/* Create the result string */
|
||||
str->set_charset(collation.collation);
|
||||
if (!make_date_time_oracle(fmt_array, &l_time, lc, str))
|
||||
if (!Date_time_format_oracle().format(fmt_array, &l_time, lc, str))
|
||||
return str;
|
||||
|
||||
null_date:
|
||||
|
@ -62,6 +62,26 @@ public:
|
||||
{}
|
||||
my_repertoire_t repertoire() const
|
||||
{ return is_ascii ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_EXTENDED; }
|
||||
/*
|
||||
Get a non-abbreviated month name by index
|
||||
@param month - the month index 0..11
|
||||
*/
|
||||
LEX_CSTRING month_name(uint month) const
|
||||
{
|
||||
if (month > 11)
|
||||
return Lex_cstring("##", 2);
|
||||
return Lex_cstring_strlen(month_names->type_names[month]);
|
||||
}
|
||||
/*
|
||||
Get a non-abbreviated weekday name by index
|
||||
@param weekday - the weekday index 0..6
|
||||
*/
|
||||
LEX_CSTRING day_name(uint weekday) const
|
||||
{
|
||||
if (weekday > 6)
|
||||
return Lex_cstring("##", 2);
|
||||
return Lex_cstring_strlen(day_names->type_names[weekday]);
|
||||
}
|
||||
};
|
||||
/* Exported variables */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user