MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
- Adding optional qualifiers to data types: CREATE TABLE t1 (a schema.DATE); Qualifiers now work only for three pre-defined schemas: mariadb_schema oracle_schema maxdb_schema These schemas are virtual (hard-coded) for now, but may turn into real databases on disk in the future. - mariadb_schema.TYPE now always resolves to a true MariaDB data type TYPE without sql_mode specific translations. - oracle_schema.DATE translates to MariaDB DATETIME. - maxdb_schema.TIMESTAMP translates to MariaDB DATETIME. - Fixing SHOW CREATE TABLE to use a qualifier for a data type TYPE if the current sql_mode translates TYPE to something else. The above changes fix the reported problem, so this script: SET sql_mode=ORACLE; CREATE TABLE t2 AS SELECT mariadb_date_column FROM t1; is now replicated as: SET sql_mode=ORACLE; CREATE TABLE t2 (mariadb_date_column mariadb_schema.DATE); and the slave can unambiguously treat DATE as the true MariaDB DATE without ORACLE specific translation to DATETIME. Similar, SET sql_mode=MAXDB; CREATE TABLE t2 AS SELECT mariadb_timestamp_column FROM t1; is now replicated as: SET sql_mode=MAXDB; CREATE TABLE t2 (mariadb_timestamp_column mariadb_schema.TIMESTAMP); so the slave treats TIMESTAMP as the true MariaDB TIMESTAMP without MAXDB specific translation to DATETIME.
This commit is contained in:
parent
a8458a2345
commit
d63631c3fa
@ -108,6 +108,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
|||||||
../sql/sql_explain.cc ../sql/sql_explain.h
|
../sql/sql_explain.cc ../sql/sql_explain.h
|
||||||
../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h
|
../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h
|
||||||
../sql/compat56.cc
|
../sql/compat56.cc
|
||||||
|
../sql/sql_schema.cc
|
||||||
../sql/sql_type.cc ../sql/sql_type.h
|
../sql/sql_type.cc ../sql/sql_type.h
|
||||||
../sql/sql_mode.cc
|
../sql/sql_mode.cc
|
||||||
../sql/table_cache.cc ../sql/mf_iocache_encr.cc
|
../sql/table_cache.cc ../sql/mf_iocache_encr.cc
|
||||||
|
@ -158,3 +158,13 @@ show triggers like '%T1%';
|
|||||||
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
|
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
|
||||||
drop table t1;
|
drop table t1;
|
||||||
set GLOBAL sql_mode=default;
|
set GLOBAL sql_mode=default;
|
||||||
|
#
|
||||||
|
# MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
#
|
||||||
|
# Compatibility schema names respect the filesystem case sensitivity
|
||||||
|
CREATE TABLE t1 (a MARIADB_SCHEMA.date);
|
||||||
|
ERROR HY000: Unknown data type: 'MARIADB_SCHEMA.date'
|
||||||
|
CREATE TABLE t1 (a Mariadb_schema.date);
|
||||||
|
ERROR HY000: Unknown data type: 'Mariadb_schema.date'
|
||||||
|
CREATE TABLE t1 (a mariadb_schema.date);
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -129,3 +129,18 @@ let $datadir= `select @@datadir`;
|
|||||||
remove_file $datadir/mysql_upgrade_info;
|
remove_file $datadir/mysql_upgrade_info;
|
||||||
|
|
||||||
set GLOBAL sql_mode=default;
|
set GLOBAL sql_mode=default;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo # Compatibility schema names respect the filesystem case sensitivity
|
||||||
|
|
||||||
|
--error ER_UNKNOWN_ERROR
|
||||||
|
CREATE TABLE t1 (a MARIADB_SCHEMA.date);
|
||||||
|
--error ER_UNKNOWN_ERROR
|
||||||
|
CREATE TABLE t1 (a Mariadb_schema.date);
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a mariadb_schema.date);
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -179,6 +179,7 @@ my @DEFAULT_SUITES= qw(
|
|||||||
binlog_encryption-
|
binlog_encryption-
|
||||||
csv-
|
csv-
|
||||||
compat/oracle-
|
compat/oracle-
|
||||||
|
compat/maxdb-
|
||||||
encryption-
|
encryption-
|
||||||
federated-
|
federated-
|
||||||
funcs_1-
|
funcs_1-
|
||||||
|
65
mysql-test/suite/compat/maxdb/rpl_mariadb_timestamp.result
Normal file
65
mysql-test/suite/compat/maxdb/rpl_mariadb_timestamp.result
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
#
|
||||||
|
# MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
#
|
||||||
|
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:00:00');
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01 10:20:30');
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
CREATE TABLE t2 SELECT * FROM t1;
|
||||||
|
SET timestamp=DEFAULT;
|
||||||
|
include/show_binlog_events.inc
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a TIMESTAMP)
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES (NULL)
|
||||||
|
master-bin.000001 # Table_map # # table_id: # (test.t1)
|
||||||
|
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES ('2001-01-01 10:20:30')
|
||||||
|
master-bin.000001 # Table_map # # table_id: # (test.t1)
|
||||||
|
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; CREATE TABLE "t2" (
|
||||||
|
"a" mariadb_schema.timestamp NOT NULL DEFAULT current_timestamp()
|
||||||
|
)
|
||||||
|
master-bin.000001 # Annotate_rows # # CREATE TABLE t2 SELECT * FROM t1
|
||||||
|
master-bin.000001 # Table_map # # table_id: # (test.t2)
|
||||||
|
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
connection slave;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
2001-01-01 10:00:00
|
||||||
|
2001-01-01 10:20:30
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`a` timestamp NOT NULL DEFAULT current_timestamp()
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" mariadb_schema.timestamp NOT NULL DEFAULT current_timestamp()
|
||||||
|
)
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE "t2" (
|
||||||
|
"a" mariadb_schema.timestamp NOT NULL DEFAULT current_timestamp()
|
||||||
|
)
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
include/rpl_end.inc
|
34
mysql-test/suite/compat/maxdb/rpl_mariadb_timestamp.test
Normal file
34
mysql-test/suite/compat/maxdb/rpl_mariadb_timestamp.test
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
--source include/have_binlog_format_row.inc
|
||||||
|
--source include/master-slave.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:00:00');
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (a TIMESTAMP);
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01 10:20:30');
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
CREATE TABLE t2 SELECT * FROM t1;
|
||||||
|
SET timestamp=DEFAULT;
|
||||||
|
|
||||||
|
--let $binlog_file = LAST
|
||||||
|
source include/show_binlog_events.inc;
|
||||||
|
|
||||||
|
|
||||||
|
--sync_slave_with_master
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
|
||||||
|
--connection master
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--source include/rpl_end.inc
|
53
mysql-test/suite/compat/maxdb/type_timestamp.result
Normal file
53
mysql-test/suite/compat/maxdb/type_timestamp.result
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#
|
||||||
|
# MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
#
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_timestamp TIMESTAMP,
|
||||||
|
mdb_timestamp mariadb_schema.TIMESTAMP,
|
||||||
|
ora_timestamp oracle_schema.TIMESTAMP,
|
||||||
|
max_timestamp maxdb_schema.TIMESTAMP
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`def_timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||||
|
`mdb_timestamp` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`ora_timestamp` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`max_timestamp` datetime DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"def_timestamp" mariadb_schema.timestamp NOT NULL DEFAULT current_timestamp(),
|
||||||
|
"mdb_timestamp" mariadb_schema.timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
"ora_timestamp" mariadb_schema.timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
"max_timestamp" datetime DEFAULT NULL
|
||||||
|
)
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_timestamp TIMESTAMP,
|
||||||
|
mdb_timestamp mariadb_schema.TIMESTAMP,
|
||||||
|
ora_timestamp oracle_schema.TIMESTAMP,
|
||||||
|
max_timestamp maxdb_schema.TIMESTAMP
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"def_timestamp" datetime DEFAULT NULL,
|
||||||
|
"mdb_timestamp" mariadb_schema.timestamp NOT NULL DEFAULT current_timestamp(),
|
||||||
|
"ora_timestamp" mariadb_schema.timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
"max_timestamp" datetime DEFAULT NULL
|
||||||
|
)
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`def_timestamp` datetime DEFAULT NULL,
|
||||||
|
`mdb_timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||||
|
`ora_timestamp` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`max_timestamp` datetime DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
29
mysql-test/suite/compat/maxdb/type_timestamp.test
Normal file
29
mysql-test/suite/compat/maxdb/type_timestamp.test
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
--echo #
|
||||||
|
--echo # MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_timestamp TIMESTAMP,
|
||||||
|
mdb_timestamp mariadb_schema.TIMESTAMP,
|
||||||
|
ora_timestamp oracle_schema.TIMESTAMP,
|
||||||
|
max_timestamp maxdb_schema.TIMESTAMP
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
SET sql_mode=MAXDB;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_timestamp TIMESTAMP,
|
||||||
|
mdb_timestamp mariadb_schema.TIMESTAMP,
|
||||||
|
ora_timestamp oracle_schema.TIMESTAMP,
|
||||||
|
max_timestamp maxdb_schema.TIMESTAMP
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
86
mysql-test/suite/compat/oracle/r/rpl_mariadb_date.result
Normal file
86
mysql-test/suite/compat/oracle/r/rpl_mariadb_date.result
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
SET SQL_MODE=DEFAULT;
|
||||||
|
CREATE TABLE t1 (a DATE);
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01');
|
||||||
|
SET SQL_MODE= ORACLE;
|
||||||
|
CREATE TABLE t2 SELECT * FROM t1;
|
||||||
|
include/show_binlog_events.inc
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a DATE)
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES (NULL)
|
||||||
|
master-bin.000001 # Table_map # # table_id: # (test.t1)
|
||||||
|
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES ('2001-01-01')
|
||||||
|
master-bin.000001 # Table_map # # table_id: # (test.t1)
|
||||||
|
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; CREATE TABLE "t2" (
|
||||||
|
"a" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
master-bin.000001 # Annotate_rows # # CREATE TABLE t2 SELECT * FROM t1
|
||||||
|
master-bin.000001 # Table_map # # table_id: # (test.t2)
|
||||||
|
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
SET SQL_MODE= DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` date DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`a` date DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SET SQL_MODE= ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE "t2" (
|
||||||
|
"a" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
connection slave;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
NULL
|
||||||
|
2001-01-01
|
||||||
|
SELECT * FROM t2;
|
||||||
|
a
|
||||||
|
NULL
|
||||||
|
2001-01-01
|
||||||
|
SET SQL_MODE= DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` date DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`a` date DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SET SQL_MODE= ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE "t2" (
|
||||||
|
"a" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
connection master;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
include/rpl_end.inc
|
@ -6,3 +6,153 @@ t1 CREATE TABLE "t1" (
|
|||||||
"a" datetime DEFAULT NULL
|
"a" datetime DEFAULT NULL
|
||||||
)
|
)
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
#
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (a unknown.DATE);
|
||||||
|
ERROR HY000: Unknown data type: 'unknown.date'
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_date DATE,
|
||||||
|
mdb_date mariadb_schema.DATE,
|
||||||
|
ora_date oracle_schema.DATE,
|
||||||
|
max_date maxdb_schema.DATE
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`def_date` date DEFAULT NULL,
|
||||||
|
`mdb_date` date DEFAULT NULL,
|
||||||
|
`ora_date` datetime DEFAULT NULL,
|
||||||
|
`max_date` date DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"def_date" mariadb_schema.date DEFAULT NULL,
|
||||||
|
"mdb_date" mariadb_schema.date DEFAULT NULL,
|
||||||
|
"ora_date" datetime DEFAULT NULL,
|
||||||
|
"max_date" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_date DATE,
|
||||||
|
mdb_date mariadb_schema.DATE,
|
||||||
|
ora_date oracle_schema.DATE,
|
||||||
|
max_date maxdb_schema.DATE
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"def_date" datetime DEFAULT NULL,
|
||||||
|
"mdb_date" mariadb_schema.date DEFAULT NULL,
|
||||||
|
"ora_date" datetime DEFAULT NULL,
|
||||||
|
"max_date" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`def_date` datetime DEFAULT NULL,
|
||||||
|
`mdb_date` date DEFAULT NULL,
|
||||||
|
`ora_date` datetime DEFAULT NULL,
|
||||||
|
`max_date` date DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# ALTER..MODIFY and ALTER..CHANGE understand qualifiers
|
||||||
|
#
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (a DATE);
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01');
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
2001-01-01
|
||||||
|
ALTER TABLE t1 MODIFY a DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" datetime DEFAULT NULL
|
||||||
|
)
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
2001-01-01 00:00:00
|
||||||
|
ALTER TABLE t1 MODIFY a mariadb_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
2001-01-01
|
||||||
|
ALTER TABLE t1 MODIFY a oracle_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" datetime DEFAULT NULL
|
||||||
|
)
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
2001-01-01 00:00:00
|
||||||
|
ALTER TABLE t1 CHANGE a b mariadb_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"b" mariadb_schema.date DEFAULT NULL
|
||||||
|
)
|
||||||
|
SELECT * FROM t1;
|
||||||
|
b
|
||||||
|
2001-01-01
|
||||||
|
ALTER TABLE t1 CHANGE b a oracle_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE "t1" (
|
||||||
|
"a" datetime DEFAULT NULL
|
||||||
|
)
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
2001-01-01 00:00:00
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Qualified syntax is not supported yet in SP
|
||||||
|
# See MDEV-23353 Qualified data types in SP
|
||||||
|
#
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
CREATE FUNCTION f1() RETURN mariadb_schema.DATE AS
|
||||||
|
BEGIN
|
||||||
|
RETURN CURRENT_DATE;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'mariadb_schema.DATE AS
|
||||||
|
BEGIN
|
||||||
|
RETURN CURRENT_DATE;
|
||||||
|
END' at line 1
|
||||||
|
CREATE PROCEDURE p1(a mariadb_schema.DATE) AS
|
||||||
|
BEGIN
|
||||||
|
NULL;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') AS
|
||||||
|
BEGIN
|
||||||
|
NULL;
|
||||||
|
END' at line 1
|
||||||
|
CREATE PROCEDURE p1() AS
|
||||||
|
a mariadb_schema.DATE;
|
||||||
|
BEGIN
|
||||||
|
NULL;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ';
|
||||||
|
BEGIN
|
||||||
|
NULL;
|
||||||
|
END' at line 2
|
||||||
|
38
mysql-test/suite/compat/oracle/t/rpl_mariadb_date.test
Normal file
38
mysql-test/suite/compat/oracle/t/rpl_mariadb_date.test
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
--source include/have_binlog_format_row.inc
|
||||||
|
--source include/master-slave.inc
|
||||||
|
|
||||||
|
SET SQL_MODE=DEFAULT;
|
||||||
|
CREATE TABLE t1 (a DATE);
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01');
|
||||||
|
|
||||||
|
SET SQL_MODE= ORACLE;
|
||||||
|
CREATE TABLE t2 SELECT * FROM t1;
|
||||||
|
|
||||||
|
--let $binlog_file = LAST
|
||||||
|
source include/show_binlog_events.inc;
|
||||||
|
|
||||||
|
SET SQL_MODE= DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
|
||||||
|
SET SQL_MODE= ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
|
||||||
|
--sync_slave_with_master
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
SET SQL_MODE= DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
|
||||||
|
SET SQL_MODE= ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
--connection master
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
--source include/rpl_end.inc
|
@ -2,3 +2,102 @@ SET sql_mode=ORACLE;
|
|||||||
CREATE TABLE t1 (a DATE);
|
CREATE TABLE t1 (a DATE);
|
||||||
SHOW CREATE TABLE t1;
|
SHOW CREATE TABLE t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
--error ER_UNKNOWN_ERROR
|
||||||
|
CREATE TABLE t1 (a unknown.DATE);
|
||||||
|
|
||||||
|
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_date DATE,
|
||||||
|
mdb_date mariadb_schema.DATE,
|
||||||
|
ora_date oracle_schema.DATE,
|
||||||
|
max_date maxdb_schema.DATE
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
def_date DATE,
|
||||||
|
mdb_date mariadb_schema.DATE,
|
||||||
|
ora_date oracle_schema.DATE,
|
||||||
|
max_date maxdb_schema.DATE
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # ALTER..MODIFY and ALTER..CHANGE understand qualifiers
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET sql_mode=DEFAULT;
|
||||||
|
CREATE TABLE t1 (a DATE);
|
||||||
|
INSERT INTO t1 VALUES ('2001-01-01');
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
ALTER TABLE t1 MODIFY a DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
ALTER TABLE t1 MODIFY a mariadb_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
ALTER TABLE t1 MODIFY a oracle_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
ALTER TABLE t1 CHANGE a b mariadb_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
ALTER TABLE t1 CHANGE b a oracle_schema.DATE;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Qualified syntax is not supported yet in SP
|
||||||
|
--echo # See MDEV-23353 Qualified data types in SP
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET sql_mode=ORACLE;
|
||||||
|
DELIMITER $$;
|
||||||
|
# Change to this when merging to 10.5:
|
||||||
|
#--error ER_UNKNOWN_DATA_TYPE
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
CREATE FUNCTION f1() RETURN mariadb_schema.DATE AS
|
||||||
|
BEGIN
|
||||||
|
RETURN CURRENT_DATE;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
CREATE PROCEDURE p1(a mariadb_schema.DATE) AS
|
||||||
|
BEGIN
|
||||||
|
NULL;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
CREATE PROCEDURE p1() AS
|
||||||
|
a mariadb_schema.DATE;
|
||||||
|
BEGIN
|
||||||
|
NULL;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
@ -127,6 +127,7 @@ SET (SQL_SOURCE
|
|||||||
rpl_gtid.cc rpl_parallel.cc
|
rpl_gtid.cc rpl_parallel.cc
|
||||||
semisync.cc semisync_master.cc semisync_slave.cc
|
semisync.cc semisync_master.cc semisync_slave.cc
|
||||||
semisync_master_ack_receiver.cc
|
semisync_master_ack_receiver.cc
|
||||||
|
sql_schema.cc
|
||||||
sql_type.cc sql_mode.cc
|
sql_type.cc sql_mode.cc
|
||||||
item_windowfunc.cc sql_window.cc
|
item_windowfunc.cc sql_window.cc
|
||||||
sql_cte.cc
|
sql_cte.cc
|
||||||
|
13
sql/field.cc
13
sql/field.cc
@ -10407,6 +10407,19 @@ void Column_definition::set_attributes(const Lex_field_type_st &type,
|
|||||||
set_handler(type.type_handler());
|
set_handler(type.type_handler());
|
||||||
charset= cs;
|
charset= cs;
|
||||||
|
|
||||||
|
#if MYSQL_VERSION_ID > 100500
|
||||||
|
#error When merging to 10.5, please move the code below to
|
||||||
|
#error Type_handler_timestamp_common::Column_definition_set_attributes()
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
Unlike other types TIMESTAMP fields are NOT NULL by default.
|
||||||
|
Unless --explicit-defaults-for-timestamp is given.
|
||||||
|
*/
|
||||||
|
if (!opt_explicit_defaults_for_timestamp &&
|
||||||
|
type.type_handler()->field_type() == MYSQL_TYPE_TIMESTAMP)
|
||||||
|
flags|= NOT_NULL_FLAG;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (type.length())
|
if (type.length())
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -1157,10 +1157,8 @@ extern "C" my_thread_id next_thread_id_noinline()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
const Type_handler *THD::type_handler_for_date() const
|
const Type_handler *THD::type_handler_for_datetime() const
|
||||||
{
|
{
|
||||||
if (!(variables.sql_mode & MODE_ORACLE))
|
|
||||||
return &type_handler_newdate;
|
|
||||||
if (opt_mysql56_temporal_format)
|
if (opt_mysql56_temporal_format)
|
||||||
return &type_handler_datetime2;
|
return &type_handler_datetime2;
|
||||||
return &type_handler_datetime;
|
return &type_handler_datetime;
|
||||||
|
@ -3422,7 +3422,7 @@ public:
|
|||||||
{
|
{
|
||||||
return !MY_TEST(variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES);
|
return !MY_TEST(variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES);
|
||||||
}
|
}
|
||||||
const Type_handler *type_handler_for_date() const;
|
const Type_handler *type_handler_for_datetime() const;
|
||||||
bool timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts,
|
bool timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts,
|
||||||
ulong sec_part, ulonglong fuzzydate);
|
ulong sec_part, ulonglong fuzzydate);
|
||||||
inline my_time_t query_start() { return start_time; }
|
inline my_time_t query_start() { return start_time; }
|
||||||
|
@ -237,6 +237,7 @@ void
|
|||||||
st_parsing_options::reset()
|
st_parsing_options::reset()
|
||||||
{
|
{
|
||||||
allows_variable= TRUE;
|
allows_variable= TRUE;
|
||||||
|
lookup_keywords_after_qualifier= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1539,6 +1540,9 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
|
|||||||
yylval->lex_str.str= (char*) get_ptr();
|
yylval->lex_str.str= (char*) get_ptr();
|
||||||
yylval->lex_str.length= 1;
|
yylval->lex_str.length= 1;
|
||||||
c= yyGet(); // should be '.'
|
c= yyGet(); // should be '.'
|
||||||
|
if (lex->parsing_options.lookup_keywords_after_qualifier)
|
||||||
|
next_state= MY_LEX_IDENT_OR_KEYWORD;
|
||||||
|
else
|
||||||
next_state= MY_LEX_IDENT_START; // Next is ident (not keyword)
|
next_state= MY_LEX_IDENT_START; // Next is ident (not keyword)
|
||||||
if (!ident_map[(uchar) yyPeek()]) // Probably ` or "
|
if (!ident_map[(uchar) yyPeek()]) // Probably ` or "
|
||||||
next_state= MY_LEX_START;
|
next_state= MY_LEX_START;
|
||||||
@ -8286,3 +8290,31 @@ bool LEX::tvc_finalize_derived()
|
|||||||
current_select->linkage= DERIVED_TABLE_TYPE;
|
current_select->linkage= DERIVED_TABLE_TYPE;
|
||||||
return tvc_finalize();
|
return tvc_finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::map_data_type(const Lex_ident_sys_st &schema_name,
|
||||||
|
Lex_field_type_st *type) const
|
||||||
|
{
|
||||||
|
const Schema *schema= schema_name.str ?
|
||||||
|
Schema::find_by_name(schema_name) :
|
||||||
|
Schema::find_implied(thd);
|
||||||
|
if (!schema)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
const Name type_name= type->type_handler()->name();
|
||||||
|
my_snprintf(buf, sizeof(buf), "%.*s.%.*s",
|
||||||
|
(int) schema_name.length, schema_name.str,
|
||||||
|
(int) type_name.length(), type_name.ptr());
|
||||||
|
#if MYSQL_VERSION_ID > 100500
|
||||||
|
#error Please remove the old code
|
||||||
|
my_error(ER_UNKNOWN_DATA_TYPE, MYF(0), buf);
|
||||||
|
#else
|
||||||
|
my_printf_error(ER_UNKNOWN_ERROR, "Unknown data type: '%-.64s'",
|
||||||
|
MYF(0), buf);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const Type_handler *mapped= schema->map_data_type(thd, type->type_handler());
|
||||||
|
type->set_handler(mapped);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "sp.h" // enum stored_procedure_type
|
#include "sp.h" // enum stored_procedure_type
|
||||||
#include "sql_tvc.h"
|
#include "sql_tvc.h"
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
#include "sql_schema.h"
|
||||||
|
|
||||||
/* Used for flags of nesting constructs */
|
/* Used for flags of nesting constructs */
|
||||||
#define SELECT_NESTING_MAP_SIZE 64
|
#define SELECT_NESTING_MAP_SIZE 64
|
||||||
@ -2144,6 +2145,7 @@ private:
|
|||||||
struct st_parsing_options
|
struct st_parsing_options
|
||||||
{
|
{
|
||||||
bool allows_variable;
|
bool allows_variable;
|
||||||
|
bool lookup_keywords_after_qualifier;
|
||||||
|
|
||||||
st_parsing_options() { reset(); }
|
st_parsing_options() { reset(); }
|
||||||
void reset();
|
void reset();
|
||||||
@ -4052,6 +4054,9 @@ public:
|
|||||||
bool tvc_finalize();
|
bool tvc_finalize();
|
||||||
bool tvc_finalize_derived();
|
bool tvc_finalize_derived();
|
||||||
|
|
||||||
|
bool map_data_type(const Lex_ident_sys_st &schema,
|
||||||
|
Lex_field_type_st *type) const;
|
||||||
|
|
||||||
void mark_first_table_as_inserting();
|
void mark_first_table_as_inserting();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
80
sql/sql_schema.cc
Normal file
80
sql/sql_schema.cc
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2020, MariaDB Corporation.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||||
|
|
||||||
|
#include "mariadb.h"
|
||||||
|
#include "sql_type.h"
|
||||||
|
#include "sql_schema.h"
|
||||||
|
#include "sql_class.h"
|
||||||
|
|
||||||
|
class Schema_oracle: public Schema
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Schema_oracle(const LEX_CSTRING &name)
|
||||||
|
:Schema(name)
|
||||||
|
{ }
|
||||||
|
const Type_handler *map_data_type(THD *thd, const Type_handler *src)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
if (src == &type_handler_newdate)
|
||||||
|
return thd->type_handler_for_datetime();
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Schema_maxdb: public Schema
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Schema_maxdb(const LEX_CSTRING &name)
|
||||||
|
:Schema(name)
|
||||||
|
{ }
|
||||||
|
const Type_handler *map_data_type(THD *thd, const Type_handler *src)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
if (src == &type_handler_timestamp ||
|
||||||
|
src == &type_handler_timestamp2)
|
||||||
|
return thd->type_handler_for_datetime();
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Schema mariadb_schema(Lex_cstring(STRING_WITH_LEN("mariadb_schema")));
|
||||||
|
Schema_oracle oracle_schema(Lex_cstring(STRING_WITH_LEN("oracle_schema")));
|
||||||
|
Schema_maxdb maxdb_schema(Lex_cstring(STRING_WITH_LEN("maxdb_schema")));
|
||||||
|
|
||||||
|
|
||||||
|
Schema *Schema::find_by_name(const LEX_CSTRING &name)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(name.str);
|
||||||
|
if (mariadb_schema.eq_name(name))
|
||||||
|
return &mariadb_schema;
|
||||||
|
if (oracle_schema.eq_name(name))
|
||||||
|
return &oracle_schema;
|
||||||
|
if (maxdb_schema.eq_name(name))
|
||||||
|
return &maxdb_schema;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Schema *Schema::find_implied(THD *thd)
|
||||||
|
{
|
||||||
|
if (thd->variables.sql_mode & MODE_ORACLE)
|
||||||
|
return &oracle_schema;
|
||||||
|
if (thd->variables.sql_mode & MODE_MAXDB)
|
||||||
|
return &maxdb_schema;
|
||||||
|
return &mariadb_schema;
|
||||||
|
}
|
70
sql/sql_schema.h
Normal file
70
sql/sql_schema.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef SQL_SCHEMA_H_INCLUDED
|
||||||
|
#define SQL_SCHEMA_H_INCLUDED
|
||||||
|
/*
|
||||||
|
Copyright (c) 2020, MariaDB Corporation.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||||
|
|
||||||
|
#include "mysqld.h"
|
||||||
|
#include "lex_string.h"
|
||||||
|
|
||||||
|
class Schema
|
||||||
|
{
|
||||||
|
LEX_CSTRING m_name;
|
||||||
|
public:
|
||||||
|
Schema(const LEX_CSTRING &name)
|
||||||
|
:m_name(name)
|
||||||
|
{ }
|
||||||
|
virtual ~Schema() { }
|
||||||
|
const LEX_CSTRING &name() const { return m_name; }
|
||||||
|
virtual const Type_handler *map_data_type(THD *thd, const Type_handler *src)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
For now we have *hard-coded* compatibility schemas:
|
||||||
|
schema_mariadb, schema_oracle, schema_maxdb.
|
||||||
|
But eventually we'll turn then into real databases on disk.
|
||||||
|
So the code below compares names according to the filesystem
|
||||||
|
case sensitivity, like it is done for regular databases.
|
||||||
|
|
||||||
|
Note, this is different to information_schema, whose name
|
||||||
|
is always case insensitive. This is intentional!
|
||||||
|
The assymetry will be gone when we'll implement SQL standard
|
||||||
|
regular and delimited identifiers.
|
||||||
|
*/
|
||||||
|
bool eq_name(const LEX_CSTRING &name) const
|
||||||
|
{
|
||||||
|
#if MYSQL_VERSION_ID > 100500
|
||||||
|
#error Remove the old code
|
||||||
|
return !table_alias_charset->strnncoll(m_name.str, m_name.length,
|
||||||
|
name.str, name.length);
|
||||||
|
#else
|
||||||
|
// Please remove this when merging to 10.5
|
||||||
|
return !table_alias_charset->coll->strnncoll(table_alias_charset,
|
||||||
|
(const uchar *) m_name.str,
|
||||||
|
m_name.length,
|
||||||
|
(const uchar *) name.str,
|
||||||
|
name.length, FALSE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static Schema *find_by_name(const LEX_CSTRING &name);
|
||||||
|
static Schema *find_implied(THD *thd);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern Schema mariadb_schema;
|
||||||
|
|
||||||
|
#endif // SQL_SCHEMA_H_INCLUDED
|
@ -2224,6 +2224,13 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
|
|||||||
append_identifier(thd, packet, &field->field_name);
|
append_identifier(thd, packet, &field->field_name);
|
||||||
packet->append(' ');
|
packet->append(' ');
|
||||||
|
|
||||||
|
const Type_handler *th= field->type_handler();
|
||||||
|
const Schema *implied_schema= Schema::find_implied(thd);
|
||||||
|
if (th != implied_schema->map_data_type(thd, th))
|
||||||
|
{
|
||||||
|
packet->append(th->schema()->name(), system_charset_info);
|
||||||
|
packet->append(STRING_WITH_LEN("."), system_charset_info);
|
||||||
|
}
|
||||||
type.set(tmp, sizeof(tmp), system_charset_info);
|
type.set(tmp, sizeof(tmp), system_charset_info);
|
||||||
field->sql_type(type);
|
field->sql_type(type);
|
||||||
packet->append(type.ptr(), type.length(), system_charset_info);
|
packet->append(type.ptr(), type.length(), system_charset_info);
|
||||||
|
@ -488,6 +488,10 @@ public:
|
|||||||
}
|
}
|
||||||
bool append(const char *s, size_t size);
|
bool append(const char *s, size_t size);
|
||||||
bool append(const char *s, size_t arg_length, CHARSET_INFO *cs);
|
bool append(const char *s, size_t arg_length, CHARSET_INFO *cs);
|
||||||
|
bool append(const LEX_CSTRING &s, CHARSET_INFO *cs)
|
||||||
|
{
|
||||||
|
return append(s.str, s.length, cs);
|
||||||
|
}
|
||||||
bool append_ulonglong(ulonglong val);
|
bool append_ulonglong(ulonglong val);
|
||||||
bool append_longlong(longlong val);
|
bool append_longlong(longlong val);
|
||||||
bool append(IO_CACHE* file, uint32 arg_length);
|
bool append(IO_CACHE* file, uint32 arg_length);
|
||||||
|
@ -69,6 +69,12 @@ Type_handler_geometry type_handler_geometry;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
Schema *Type_handler::schema() const
|
||||||
|
{
|
||||||
|
return &mariadb_schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Type_handler_data::init()
|
bool Type_handler_data::init()
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SPATIAL
|
#ifdef HAVE_SPATIAL
|
||||||
|
@ -75,6 +75,7 @@ struct Schema_specification_st;
|
|||||||
struct TABLE;
|
struct TABLE;
|
||||||
struct SORT_FIELD_ATTR;
|
struct SORT_FIELD_ATTR;
|
||||||
class Vers_history_point;
|
class Vers_history_point;
|
||||||
|
class Schema;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1062,6 +1063,7 @@ public:
|
|||||||
Type_handler *aggregate_for_num_op_traditional(const Type_handler *h1,
|
Type_handler *aggregate_for_num_op_traditional(const Type_handler *h1,
|
||||||
const Type_handler *h2);
|
const Type_handler *h2);
|
||||||
|
|
||||||
|
virtual Schema *schema() const;
|
||||||
virtual const Name name() const= 0;
|
virtual const Name name() const= 0;
|
||||||
virtual enum_field_types field_type() const= 0;
|
virtual enum_field_types field_type() const= 0;
|
||||||
virtual enum_field_types real_field_type() const { return field_type(); }
|
virtual enum_field_types real_field_type() const { return field_type(); }
|
||||||
|
@ -1862,6 +1862,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
%type <type_handler> int_type real_type
|
%type <type_handler> int_type real_type
|
||||||
|
|
||||||
%type <Lex_field_type> type_with_opt_collate field_type
|
%type <Lex_field_type> type_with_opt_collate field_type
|
||||||
|
qualified_field_type
|
||||||
field_type_numeric
|
field_type_numeric
|
||||||
field_type_string
|
field_type_string
|
||||||
field_type_lob
|
field_type_lob
|
||||||
@ -6729,10 +6730,12 @@ field_spec:
|
|||||||
|
|
||||||
lex->init_last_field(f, &$1, NULL);
|
lex->init_last_field(f, &$1, NULL);
|
||||||
$<create_field>$= f;
|
$<create_field>$= f;
|
||||||
|
lex->parsing_options.lookup_keywords_after_qualifier= true;
|
||||||
}
|
}
|
||||||
field_type_or_serial opt_check_constraint
|
field_type_or_serial opt_check_constraint
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
lex->parsing_options.lookup_keywords_after_qualifier= false;
|
||||||
$$= $<create_field>2;
|
$$= $<create_field>2;
|
||||||
|
|
||||||
$$->check_constraint= $4;
|
$$->check_constraint= $4;
|
||||||
@ -6751,7 +6754,7 @@ field_spec:
|
|||||||
;
|
;
|
||||||
|
|
||||||
field_type_or_serial:
|
field_type_or_serial:
|
||||||
field_type { Lex->last_field->set_attributes($1, Lex->charset); }
|
qualified_field_type { Lex->last_field->set_attributes($1, Lex->charset); }
|
||||||
field_def
|
field_def
|
||||||
| SERIAL_SYM
|
| SERIAL_SYM
|
||||||
{
|
{
|
||||||
@ -6917,6 +6920,18 @@ column_default_expr:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
qualified_field_type:
|
||||||
|
field_type
|
||||||
|
{
|
||||||
|
Lex->map_data_type(Lex_ident_sys(), &($$= $1));
|
||||||
|
}
|
||||||
|
| sp_decl_ident '.' field_type
|
||||||
|
{
|
||||||
|
if (Lex->map_data_type($1, &($$= $3)))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
field_type:
|
field_type:
|
||||||
field_type_numeric
|
field_type_numeric
|
||||||
| field_type_temporal
|
| field_type_temporal
|
||||||
@ -7038,7 +7053,7 @@ field_type_temporal:
|
|||||||
}
|
}
|
||||||
$$.set(&type_handler_year, $2);
|
$$.set(&type_handler_year, $2);
|
||||||
}
|
}
|
||||||
| DATE_SYM { $$.set(thd->type_handler_for_date()); }
|
| DATE_SYM { $$.set(&type_handler_newdate); }
|
||||||
| TIME_SYM opt_field_length
|
| TIME_SYM opt_field_length
|
||||||
{
|
{
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
$$.set(opt_mysql56_temporal_format ?
|
||||||
@ -7048,31 +7063,14 @@ field_type_temporal:
|
|||||||
}
|
}
|
||||||
| TIMESTAMP opt_field_length
|
| TIMESTAMP opt_field_length
|
||||||
{
|
{
|
||||||
if (thd->variables.sql_mode & MODE_MAXDB)
|
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime2) :
|
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime),
|
|
||||||
$2);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Unlike other types TIMESTAMP fields are NOT NULL by default.
|
|
||||||
Unless --explicit-defaults-for-timestamp is given.
|
|
||||||
*/
|
|
||||||
if (!opt_explicit_defaults_for_timestamp)
|
|
||||||
Lex->last_field->flags|= NOT_NULL_FLAG;
|
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
$$.set(opt_mysql56_temporal_format ?
|
||||||
static_cast<const Type_handler*>(&type_handler_timestamp2):
|
static_cast<const Type_handler*>(&type_handler_timestamp2):
|
||||||
static_cast<const Type_handler*>(&type_handler_timestamp),
|
static_cast<const Type_handler*>(&type_handler_timestamp),
|
||||||
$2);
|
$2);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
| DATETIME opt_field_length
|
| DATETIME opt_field_length
|
||||||
{
|
{
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
$$.set(thd->type_handler_for_datetime(), $2);
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime2) :
|
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime),
|
|
||||||
$2);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -7400,14 +7398,14 @@ with_or_without_system:
|
|||||||
type_with_opt_collate:
|
type_with_opt_collate:
|
||||||
field_type opt_collate
|
field_type opt_collate
|
||||||
{
|
{
|
||||||
$$= $1;
|
Lex->map_data_type(Lex_ident_sys(), &($$= $1));
|
||||||
|
|
||||||
if ($2)
|
if ($2)
|
||||||
{
|
{
|
||||||
if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
|
if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
Lex->last_field->set_attributes($1, Lex->charset);
|
Lex->last_field->set_attributes($$, Lex->charset);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1260,6 +1260,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
%type <type_handler> int_type real_type
|
%type <type_handler> int_type real_type
|
||||||
|
|
||||||
%type <Lex_field_type> type_with_opt_collate field_type
|
%type <Lex_field_type> type_with_opt_collate field_type
|
||||||
|
qualified_field_type
|
||||||
sp_param_type_with_opt_collate
|
sp_param_type_with_opt_collate
|
||||||
sp_param_field_type
|
sp_param_field_type
|
||||||
sp_param_field_type_string
|
sp_param_field_type_string
|
||||||
@ -6573,10 +6574,12 @@ field_spec:
|
|||||||
|
|
||||||
lex->init_last_field(f, &$1, NULL);
|
lex->init_last_field(f, &$1, NULL);
|
||||||
$<create_field>$= f;
|
$<create_field>$= f;
|
||||||
|
lex->parsing_options.lookup_keywords_after_qualifier= true;
|
||||||
}
|
}
|
||||||
field_type_or_serial opt_check_constraint
|
field_type_or_serial opt_check_constraint
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
lex->parsing_options.lookup_keywords_after_qualifier= false;
|
||||||
$$= $<create_field>2;
|
$$= $<create_field>2;
|
||||||
|
|
||||||
$$->check_constraint= $4;
|
$$->check_constraint= $4;
|
||||||
@ -6595,7 +6598,7 @@ field_spec:
|
|||||||
;
|
;
|
||||||
|
|
||||||
field_type_or_serial:
|
field_type_or_serial:
|
||||||
field_type { Lex->last_field->set_attributes($1, Lex->charset); }
|
qualified_field_type { Lex->last_field->set_attributes($1, Lex->charset); }
|
||||||
field_def
|
field_def
|
||||||
| SERIAL_SYM
|
| SERIAL_SYM
|
||||||
{
|
{
|
||||||
@ -6761,6 +6764,18 @@ column_default_expr:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
qualified_field_type:
|
||||||
|
field_type
|
||||||
|
{
|
||||||
|
Lex->map_data_type(Lex_ident_sys(), &($$= $1));
|
||||||
|
}
|
||||||
|
| sp_decl_ident '.' field_type
|
||||||
|
{
|
||||||
|
if (Lex->map_data_type($1, &($$= $3)))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
field_type:
|
field_type:
|
||||||
field_type_numeric
|
field_type_numeric
|
||||||
| field_type_temporal
|
| field_type_temporal
|
||||||
@ -6934,7 +6949,7 @@ field_type_temporal:
|
|||||||
}
|
}
|
||||||
$$.set(&type_handler_year, $2);
|
$$.set(&type_handler_year, $2);
|
||||||
}
|
}
|
||||||
| DATE_SYM { $$.set(thd->type_handler_for_date()); }
|
| DATE_SYM { $$.set(&type_handler_newdate); }
|
||||||
| TIME_SYM opt_field_length
|
| TIME_SYM opt_field_length
|
||||||
{
|
{
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
$$.set(opt_mysql56_temporal_format ?
|
||||||
@ -6944,31 +6959,14 @@ field_type_temporal:
|
|||||||
}
|
}
|
||||||
| TIMESTAMP opt_field_length
|
| TIMESTAMP opt_field_length
|
||||||
{
|
{
|
||||||
if (thd->variables.sql_mode & MODE_MAXDB)
|
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime2) :
|
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime),
|
|
||||||
$2);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Unlike other types TIMESTAMP fields are NOT NULL by default.
|
|
||||||
Unless --explicit-defaults-for-timestamp is given.
|
|
||||||
*/
|
|
||||||
if (!opt_explicit_defaults_for_timestamp)
|
|
||||||
Lex->last_field->flags|= NOT_NULL_FLAG;
|
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
$$.set(opt_mysql56_temporal_format ?
|
||||||
static_cast<const Type_handler*>(&type_handler_timestamp2):
|
static_cast<const Type_handler*>(&type_handler_timestamp2):
|
||||||
static_cast<const Type_handler*>(&type_handler_timestamp),
|
static_cast<const Type_handler*>(&type_handler_timestamp),
|
||||||
$2);
|
$2);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
| DATETIME opt_field_length
|
| DATETIME opt_field_length
|
||||||
{
|
{
|
||||||
$$.set(opt_mysql56_temporal_format ?
|
$$.set(thd->type_handler_for_datetime(), $2);
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime2) :
|
|
||||||
static_cast<const Type_handler*>(&type_handler_datetime),
|
|
||||||
$2);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -7324,27 +7322,28 @@ with_or_without_system:
|
|||||||
type_with_opt_collate:
|
type_with_opt_collate:
|
||||||
field_type opt_collate
|
field_type opt_collate
|
||||||
{
|
{
|
||||||
$$= $1;
|
Lex->map_data_type(Lex_ident_sys(), &($$= $1));
|
||||||
|
|
||||||
if ($2)
|
if ($2)
|
||||||
{
|
{
|
||||||
if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
|
if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
Lex->last_field->set_attributes($1, Lex->charset);
|
Lex->last_field->set_attributes($$, Lex->charset);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
sp_param_type_with_opt_collate:
|
sp_param_type_with_opt_collate:
|
||||||
sp_param_field_type opt_collate
|
sp_param_field_type opt_collate
|
||||||
{
|
{
|
||||||
$$= $1;
|
Lex->map_data_type(Lex_ident_sys(), &($$= $1));
|
||||||
|
|
||||||
if ($2)
|
if ($2)
|
||||||
{
|
{
|
||||||
if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
|
if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
Lex->last_field->set_attributes($1, Lex->charset);
|
Lex->last_field->set_attributes($$, Lex->charset);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -610,6 +610,10 @@ public:
|
|||||||
{
|
{
|
||||||
set(handler, 0, 0);
|
set(handler, 0, 0);
|
||||||
}
|
}
|
||||||
|
void set_handler(const Type_handler *handler)
|
||||||
|
{
|
||||||
|
m_handler= handler;
|
||||||
|
}
|
||||||
const Type_handler *type_handler() const { return m_handler; }
|
const Type_handler *type_handler() const { return m_handler; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ select * from t1;
|
|||||||
ERROR HY000: Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a uint)'
|
ERROR HY000: Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a uint)'
|
||||||
show warnings;
|
show warnings;
|
||||||
Level Code Message
|
Level Code Message
|
||||||
Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'uint)' at line 1
|
Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
|
||||||
Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a uint)'
|
Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a uint)'
|
||||||
set @@test_sql_discovery_statement='t1:create table t1 (a int)';
|
set @@test_sql_discovery_statement='t1:create table t1 (a int)';
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user