DBZ-252 test fixes + grammar fixes + some bug repairs in antlr parser
This commit is contained in:
parent
1124f81d94
commit
07212043b5
@ -228,6 +228,8 @@ protected void parseSetVariable(Marker start, AtomicReference<MySqlScope> scope)
|
||||
}
|
||||
systemVariables.setVariable(scope.get(), "character_set_client", charsetName);
|
||||
systemVariables.setVariable(scope.get(), "character_set_results", charsetName);
|
||||
systemVariables.setVariable(MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_CONNECTION,
|
||||
systemVariables.getVariable(MySqlSystemVariables.CHARSET_NAME_DATABASE));
|
||||
// systemVariables.setVariable(scope.get(), "collation_connection", ...);
|
||||
} else if (tokens.canConsume("NAMES")) {
|
||||
// https://dev.mysql.com/doc/refman/5.7/en/set-statement.html
|
||||
|
@ -28,6 +28,7 @@
|
||||
import io.debezium.relational.TableId;
|
||||
import io.debezium.relational.Tables;
|
||||
import io.debezium.relational.ddl.DdlChanges;
|
||||
import io.debezium.relational.ddl.DdlParser;
|
||||
import io.debezium.relational.ddl.DdlParserListener.Event;
|
||||
import io.debezium.relational.ddl.SimpleDdlParserListener;
|
||||
import io.debezium.util.IoUtil;
|
||||
@ -36,7 +37,7 @@
|
||||
|
||||
public class MySqlDdlParserTest {
|
||||
|
||||
private MySqlDdlParser parser;
|
||||
private DdlParser parser;
|
||||
private Tables tables;
|
||||
private SimpleDdlParserListener listener;
|
||||
|
||||
@ -284,7 +285,7 @@ public void shouldParseCreateDatabaseAndTableThatUsesDefaultCharacterSets() {
|
||||
+ "CREATE TABLE t1 (" + System.lineSeparator()
|
||||
+ " id int(11) not null auto_increment," + System.lineSeparator()
|
||||
+ " c1 varchar(255) default null," + System.lineSeparator()
|
||||
+ " c2 varchar(255) charset default not null," + System.lineSeparator()
|
||||
+ " c2 varchar(255) not null," + System.lineSeparator()
|
||||
+ " c3 varchar(255) charset latin2 not null," + System.lineSeparator()
|
||||
+ " primary key ('id')" + System.lineSeparator()
|
||||
+ ") engine=InnoDB auto_increment=1006 default charset=latin1;" + System.lineSeparator();
|
||||
@ -305,7 +306,7 @@ public void shouldParseCreateDatabaseAndTableThatUsesDefaultCharacterSets() {
|
||||
ddl = "CREATE TABLE t2 (" + System.lineSeparator()
|
||||
+ " id int(11) not null auto_increment," + System.lineSeparator()
|
||||
+ " c1 varchar(255) default null," + System.lineSeparator()
|
||||
+ " c2 varchar(255) charset default not null," + System.lineSeparator()
|
||||
+ " c2 varchar(255) not null," + System.lineSeparator()
|
||||
+ " c3 varchar(255) charset latin2 not null," + System.lineSeparator()
|
||||
+ " primary key ('id')" + System.lineSeparator()
|
||||
+ ") engine=InnoDB auto_increment=1006;" + System.lineSeparator();
|
||||
@ -384,20 +385,21 @@ public void shouldParseSetCharacterSetStatement() {
|
||||
assertVariable("character_set_connection", null);
|
||||
assertVariable("character_set_database", null);
|
||||
|
||||
parser.parse("CREATE DATABASE db1 CHARACTER SET cs1;", tables);
|
||||
parser.parse("CREATE DATABASE db1 CHARACTER SET LATIN1;", tables);
|
||||
assertVariable("character_set_server", "utf8");
|
||||
assertVariable("character_set_database", null); // changes when we USE a different database
|
||||
|
||||
parser.parse("USE db1;", tables);// changes the "character_set_database" system variable ...
|
||||
assertVariable("character_set_server", "utf8");
|
||||
assertVariable("character_set_database", "cs1");
|
||||
assertVariable("character_set_connection", null);
|
||||
assertVariable("character_set_database", "LATIN1");
|
||||
|
||||
parser.parse("SET CHARSET default;", tables);
|
||||
assertVariable("character_set_server", "utf8");
|
||||
assertVariable("character_set_client", "cs1");
|
||||
assertVariable("character_set_results", "cs1");
|
||||
assertVariable("character_set_connection", null);
|
||||
assertVariable("character_set_database", "cs1");
|
||||
assertVariable("character_set_client", "LATIN1");
|
||||
assertVariable("character_set_results", "LATIN1");
|
||||
assertVariable("character_set_connection", "LATIN1");
|
||||
assertVariable("character_set_database", "LATIN1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -429,20 +431,20 @@ public void shouldParseSetNamesStatement() {
|
||||
assertVariable("character_set_connection", "utf16");
|
||||
assertVariable("character_set_database", null);
|
||||
|
||||
parser.parse("CREATE DATABASE db1 CHARACTER SET cs1;", tables);
|
||||
parser.parse("CREATE DATABASE db1 CHARACTER SET LATIN1;", tables);
|
||||
assertVariable("character_set_server", "utf8");
|
||||
assertVariable("character_set_database", null); // changes when we USE a different database
|
||||
|
||||
parser.parse("USE db1;", tables);// changes the "character_set_database" system variable ...
|
||||
assertVariable("character_set_server", "utf8");
|
||||
assertVariable("character_set_database", "cs1");
|
||||
assertVariable("character_set_database", "LATIN1");
|
||||
|
||||
parser.parse("SET NAMES default;", tables);
|
||||
assertVariable("character_set_server", "utf8");
|
||||
assertVariable("character_set_client", "cs1");
|
||||
assertVariable("character_set_results", "cs1");
|
||||
assertVariable("character_set_connection", "cs1");
|
||||
assertVariable("character_set_database", "cs1");
|
||||
assertVariable("character_set_client", "LATIN1");
|
||||
assertVariable("character_set_results", "LATIN1");
|
||||
assertVariable("character_set_connection", "LATIN1");
|
||||
assertVariable("character_set_database", "LATIN1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -526,7 +528,7 @@ public void shouldParseCreateTableWithEnumAndSetColumns() {
|
||||
|
||||
@Test
|
||||
public void shouldParseDefiner() {
|
||||
String function = "FUNCTION fnA( a int, b int ) RETURNS tinyint(1) begin anything end;";
|
||||
String function = "FUNCTION fnA( a int, b int ) RETURNS tinyint(1) begin -- anything end;";
|
||||
String ddl = "CREATE DEFINER='mysqluser'@'%' " + function;
|
||||
parser.parse(ddl, tables);
|
||||
assertThat(tables.size()).isEqualTo(0); // no tables
|
||||
@ -699,23 +701,23 @@ public void shouldParseSetOfSessionVariable() {
|
||||
|
||||
@Test
|
||||
public void shouldParseButNotSetUserVariableWithHyphenDelimiter() {
|
||||
String ddl = "SET @a-b-c-d:=1";
|
||||
String ddl = "SET @a_b_c_d:=1";
|
||||
parser.parse(ddl, tables);
|
||||
assertLocalVariable("a-b-c-d", null);
|
||||
assertSessionVariable("a-b-c-d", null);
|
||||
assertGlobalVariable("a-b-c-d", null);
|
||||
assertLocalVariable("a_b_c_d", null);
|
||||
assertSessionVariable("a_b_c_d", null);
|
||||
assertGlobalVariable("a_b_c_d", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseVariableWithHyphenDelimiter() {
|
||||
String ddl = "SET a-b-c-d=1";
|
||||
String ddl = "SET a_b_c_d=1";
|
||||
parser.parse(ddl, tables);
|
||||
assertSessionVariable("a-b-c-d", "1");
|
||||
assertSessionVariable("a_b_c_d", "1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseAndIgnoreDeleteStatements() {
|
||||
String ddl = "DELETE FROM blah blah";
|
||||
String ddl = "DELETE FROM blah";
|
||||
parser.parse(ddl, tables);
|
||||
assertThat(tables.size()).isEqualTo(0);
|
||||
assertThat(listener.total()).isEqualTo(0);
|
||||
@ -723,7 +725,7 @@ public void shouldParseAndIgnoreDeleteStatements() {
|
||||
|
||||
@Test
|
||||
public void shouldParseAndIgnoreInsertStatements() {
|
||||
String ddl = "INSERT INTO blah blah";
|
||||
String ddl = "INSERT INTO blah (id) values (1)";
|
||||
parser.parse(ddl, tables);
|
||||
assertThat(tables.size()).isEqualTo(0);
|
||||
assertThat(listener.total()).isEqualTo(0);
|
||||
@ -778,7 +780,7 @@ public void shouldParseTestStatements() {
|
||||
parser.parse(readFile("ddl/mysql-test-statements.ddl"), tables);
|
||||
Testing.print(tables);
|
||||
assertThat(tables.size()).isEqualTo(6);
|
||||
assertThat(listener.total()).isEqualTo(61);
|
||||
assertThat(listener.total()).isEqualTo(58);
|
||||
listener.forEach(this::printEvent);
|
||||
}
|
||||
|
||||
@ -1025,7 +1027,7 @@ public void shouldParseStatementForDbz200() {
|
||||
"ISDEFAULT", "ISREQUIRED", "NAME", "VALUES", "AMOUNTS", "DESCRIPTION",
|
||||
"TYPE", "VALUELENGTH", "INDEXINLIST", "CUSTOMFIELDSET_ENCODEDKEY_OID",
|
||||
"STATE", "VALIDATIONPATTERN", "VIEWUSAGERIGHTSKEY", "EDITUSAGERIGHTSKEY",
|
||||
"BUILTINCUSTOMFIELDID", "UNIQUE");
|
||||
"BUILTINCUSTOMFIELDID", "UNIQUE", "STORAGE");
|
||||
assertColumn(t, "ENCODEDKEY", "VARCHAR", Types.VARCHAR, 32, -1, false, false, false);
|
||||
assertColumn(t, "ID", "VARCHAR", Types.VARCHAR, 32, -1, true, false, false);
|
||||
assertColumn(t, "CREATIONDATE", "DATETIME", Types.TIMESTAMP, -1, -1, true, false, false);
|
||||
@ -1047,6 +1049,7 @@ public void shouldParseStatementForDbz200() {
|
||||
assertColumn(t, "EDITUSAGERIGHTSKEY", "VARCHAR", Types.VARCHAR, 32, -1, true, false, false);
|
||||
assertColumn(t, "BUILTINCUSTOMFIELDID", "VARCHAR", Types.VARCHAR, 255, -1, true, false, false);
|
||||
assertColumn(t, "UNIQUE", "VARCHAR", Types.VARCHAR, 32, -1, false, false, false);
|
||||
assertColumn(t, "STORAGE", "VARCHAR", Types.VARCHAR, 32, -1, false, false, false);
|
||||
assertThat(t.columnWithName("ENCODEDKEY").position()).isEqualTo(1);
|
||||
assertThat(t.columnWithName("id").position()).isEqualTo(2);
|
||||
assertThat(t.columnWithName("CREATIONDATE").position()).isEqualTo(3);
|
||||
@ -1481,7 +1484,7 @@ public void parseUserDdlStatements() {
|
||||
public void parsePartitionReorganize() {
|
||||
String ddl =
|
||||
"CREATE TABLE flat_view_request_log (id INT NOT NULL, myvalue INT DEFAULT -10, PRIMARY KEY (`id`));"
|
||||
+ "ALTER TABLE flat_view_request_log REORGANIZE PARTITION p_max INTO ( PARTITION p_2018_01_17 VALUES LESS THAN ('2018-01-17'), PARTITION p_2018_01_18 VALUES LESS THAN ('2018-01-18'), PARTITION p_max VALUES LESS THAN MAXVALUE);";
|
||||
+ "ALTER TABLE flat_view_request_log REORGANIZE PARTITION p_max INTO ( PARTITION p_2018_01_17 VALUES LESS THAN ('2018-01-17'), PARTITION p_2018_01_18 VALUES LESS THAN ('2018-01-18'), PARTITION p_max VALUES LESS THAN (MAXVALUE));";
|
||||
parser.parse(ddl, tables);
|
||||
assertThat(tables.size()).isEqualTo(1);
|
||||
}
|
||||
@ -1632,6 +1635,7 @@ protected void assertColumn(Table table, String name, String typeName, int jdbcT
|
||||
|
||||
class MysqlDdlParserWithSimpleTestListener extends MySqlDdlParser {
|
||||
public MysqlDdlParserWithSimpleTestListener(DdlChanges changesListener) {
|
||||
// super(false);
|
||||
super();
|
||||
this.ddlChanges = changesListener;
|
||||
}
|
||||
|
@ -41,6 +41,6 @@ BEGIN
|
||||
DECLARE i int default 0;
|
||||
doubleNestedBegin: BEGIN
|
||||
DECLARE i int default 0;
|
||||
END doubleNestedBegin
|
||||
END
|
||||
END doubleNestedBegin;
|
||||
END;
|
||||
END
|
||||
|
@ -1,4 +1,4 @@
|
||||
--ONE DDL TEST CASE FOR FUNCTION
|
||||
-- ONE DDL TEST CASE FOR FUNCTION
|
||||
|
||||
CREATE DEFINER=`root`@`localhost` FUNCTION `ROUND_OFF`(IN_VAL DOUBLE,TECHNIQUE INT,PRECESSION_VAL INT) RETURNS double
|
||||
DETERMINISTIC
|
||||
|
@ -1,4 +1,4 @@
|
||||
--ONE DDL TEST CASE FOR FUNCTION
|
||||
-- ONE DDL TEST CASE FOR FUNCTION
|
||||
|
||||
CREATE DEFINER=`root`@`localhost` FUNCTION `ROUND_OFF`(IN_VAL DOUBLE,TECHNIQUE INT,PRECESSION_VAL INT) RETURNS double
|
||||
DETERMINISTIC
|
||||
|
@ -1,4 +1,4 @@
|
||||
--ONE DDL TEST CASE FOR PROCEDURE WITH CURSOR
|
||||
-- ONE DDL TEST CASE FOR PROCEDURE WITH CURSOR
|
||||
CREATE DEFINER=`parasshah`@`%` PROCEDURE `SP_GETCHILDBYID`(GIVEN_ID INT,GIVEN_EXAM_ID INT)
|
||||
BEGIN
|
||||
DECLARE done INT DEFAULT 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
--ONE more DDL TEST CASE FOR FUNCTION
|
||||
-- ONE more DDL TEST CASE FOR FUNCTION
|
||||
CREATE DEFINER=`kiranb`@`%` FUNCTION `CHECK_FOR_BED_ALLOCATED`(BRANCHID BIGINT, STUDENTID BIGINT) RETURNS varchar(255) CHARSET utf8
|
||||
DETERMINISTIC
|
||||
BEGIN
|
||||
|
@ -14,6 +14,6 @@ create table `NextTimeTable`.`TIMETABLE_SUBJECT_GROUP_MAPPING` (
|
||||
Alter table `NextTimeTable`.`TIMETABLE_SUBJECT_GROUP_MAPPING`
|
||||
drop column `SUBJECT_ID`,
|
||||
drop index `FK69atxmt7wrwpb4oekyravsx9l`,
|
||||
drop foreign key `FK69atxmt7wrwpb4oekyravsx9l`
|
||||
drop foreign key `FK69atxmt7wrwpb4oekyravsx9l`;
|
||||
|
||||
create table `db1`.`table1` ( pk1 int not null, `id` int not null, `other` int );
|
||||
|
@ -19,6 +19,7 @@ CREATE TABLE `customfield` (
|
||||
`VIEWUSAGERIGHTSKEY` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
`EDITUSAGERIGHTSKEY` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
`BUILTINCUSTOMFIELDID` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
UNIQUE varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`UNIQUE` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
STORAGE varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
KEY `index1` (`ID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
@ -1074,7 +1074,7 @@ CREATE OR REPLACE VIEW MMR_FEATURE_VALUES AS
|
||||
NULL AS FLOAT_VALUE,
|
||||
NULL AS INT_VALUE,
|
||||
NULL AS LONG_VALUE,
|
||||
NULL AS SHORT_VALUE,0
|
||||
NULL AS SHORT_VALUE,
|
||||
NULL AS STRING_VALUE,
|
||||
VALUE AS CLOB_VALUE,
|
||||
NULL AS ENUM_ID,
|
||||
|
@ -7,9 +7,9 @@ RENAME TABLE blue_table TO red_table,
|
||||
orange_table TO green_table,
|
||||
black_table TO white_table;
|
||||
|
||||
RENAME DATABASE blue_db TO red_db;
|
||||
-- RENAME DATABASE blue_db TO red_db;
|
||||
|
||||
RENAME SCHEMA blue_schema TO red_schema;
|
||||
-- RENAME SCHEMA blue_schema TO red_schema;
|
||||
|
||||
CREATE TABLE RT_VDB_MDLS
|
||||
(
|
||||
@ -152,7 +152,7 @@ CREATE EVENT myevent
|
||||
DO
|
||||
UPDATE myschema.mytable SET mycol = mycol + 1;
|
||||
|
||||
--ALTER
|
||||
-- ALTER
|
||||
-- [DEFINER = { user | CURRENT_USER }]
|
||||
-- EVENT event_name
|
||||
-- [ON SCHEDULE schedule]
|
||||
@ -182,7 +182,7 @@ ALTER EVENT myevent
|
||||
ALTER EVENT olddb.myevent
|
||||
RENAME TO newdb.myevent;
|
||||
|
||||
--ALTER LOGFILE GROUP logfile_group
|
||||
-- ALTER LOGFILE GROUP logfile_group
|
||||
-- ADD UNDOFILE 'file_name'
|
||||
-- [INITIAL_SIZE [=] size]
|
||||
-- [WAIT]
|
||||
@ -193,9 +193,9 @@ ALTER LOGFILE GROUP lg_3
|
||||
INITIAL_SIZE=32M
|
||||
ENGINE=NDBCLUSTER;
|
||||
|
||||
--ALTER FUNCTION func_name [characteristic ...]
|
||||
-- ALTER FUNCTION func_name [characteristic ...]
|
||||
--
|
||||
--characteristic:
|
||||
-- characteristic:
|
||||
-- { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
|
||||
-- | SQL SECURITY { DEFINER | INVOKER }
|
||||
-- | COMMENT 'string'
|
||||
@ -214,15 +214,15 @@ ALTER PROCEDURE fall_back COMMENT 'no more wind please';
|
||||
|
||||
ALTER SERVER s OPTIONS (USER 'sally');
|
||||
|
||||
--ALTER TABLESPACE tablespace_name
|
||||
-- ALTER TABLESPACE tablespace_name
|
||||
-- {ADD|DROP} DATAFILE 'file_name'
|
||||
-- [INITIAL_SIZE [=] size]
|
||||
-- [WAIT]
|
||||
-- ENGINE [=] engine_name
|
||||
|
||||
ALTER TABLESPACE tspace_name ADD DATAFILE 'file_name'INITIAL_SIZE = 9999 WAIT;
|
||||
ALTER TABLESPACE tspace_name ADD DATAFILE 'file_name'INITIAL_SIZE = 9999 WAIT ENGINE = MEMORY;
|
||||
|
||||
--ALTER
|
||||
-- ALTER
|
||||
-- [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
|
||||
-- [DEFINER = { user | CURRENT_USER }]
|
||||
-- [SQL SECURITY { DEFINER | INVOKER }]
|
||||
@ -234,18 +234,18 @@ ALTER VIEW great_view (c1, c2) AS SELECT * FROM table_a;
|
||||
|
||||
ALTER VIEW great_view (c1, c2) AS SELECT * FROM table_a WITH LOCAL CHECK OPTION;
|
||||
|
||||
ALTER VIEW ALGORITHM = MERGE great_view AS SELECT * FROM table_a;
|
||||
ALTER ALGORITHM = MERGE VIEW great_view AS SELECT * FROM table_a;
|
||||
|
||||
ALTER VIEW DEFINER = 'joe'@'there.com' great_view AS SELECT * FROM table_a;
|
||||
ALTER DEFINER = 'joe'@'there.com' VIEW great_view AS SELECT * FROM table_a;
|
||||
-- ============ 50 STATEMENTS ====================
|
||||
ALTER VIEW SQL SECURITY INVOKER great_view AS SELECT * FROM table_a;
|
||||
ALTER SQL SECURITY INVOKER VIEW great_view AS SELECT * FROM table_a;
|
||||
|
||||
ALTER VIEW ALGORITHM = MERGE DEFINER = 'joe'@'there.com' SQL SECURITY INVOKER great_view AS SELECT * FROM table_a;
|
||||
ALTER ALGORITHM = MERGE DEFINER = 'joe'@'there.com' SQL SECURITY INVOKER VIEW great_view AS SELECT * FROM table_a;
|
||||
|
||||
--CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
|
||||
-- CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
|
||||
-- [create_specification] ...
|
||||
--
|
||||
--create_specification:
|
||||
-- create_specification:
|
||||
-- [DEFAULT] CHARACTER SET [=] charset_name
|
||||
-- | [DEFAULT] COLLATE [=] collation_name
|
||||
|
||||
@ -253,7 +253,7 @@ CREATE DATABASE db_1;
|
||||
|
||||
CREATE DATABASE db_2 DEFAULT CHARACTER SET = utf8;
|
||||
|
||||
CREATE DATABASE db_3 CHARACTER SET utf10;
|
||||
CREATE DATABASE db_3 CHARACTER SET utf16;
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS db_4 DEFAULT CHARACTER SET = utf8;
|
||||
|
||||
@ -261,7 +261,7 @@ CREATE SCHEMA schema_1;
|
||||
|
||||
CREATE SCHEMA schema_2 DEFAULT CHARACTER SET = utf8;
|
||||
|
||||
CREATE SCHEMA schema_3 CHARACTER SET utf10;
|
||||
CREATE SCHEMA schema_3 CHARACTER SET utf16;
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS schema_4 DEFAULT CHARACTER SET = utf8;
|
||||
-- ============ 60 STATEMENTS ====================
|
||||
@ -271,21 +271,21 @@ CREATE INDEX id_index USING BTREE ON lookup (id);
|
||||
|
||||
-- CREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
|
||||
|
||||
CREATE ONLINE INDEX index_1;
|
||||
# CREATE ONLINE INDEX index_1;
|
||||
#
|
||||
# CREATE OFFLINE INDEX index_2;
|
||||
#
|
||||
# CREATE ONLINE UNIQUE INDEX index_3;
|
||||
#
|
||||
# CREATE OFFLINE FULLTEXT INDEX index_4;
|
||||
#
|
||||
# CREATE UNIQUE INDEX index_5;
|
||||
#
|
||||
# CREATE FULLTEXT INDEX index_6;
|
||||
#
|
||||
# CREATE SPATIAL INDEX index_7;
|
||||
|
||||
CREATE OFFLINE INDEX index_2;
|
||||
|
||||
CREATE ONLINE UNIQUE INDEX index_3;
|
||||
|
||||
CREATE OFFLINE FULLTEXT INDEX index_4;
|
||||
|
||||
CREATE UNIQUE INDEX index_5;
|
||||
|
||||
CREATE FULLTEXT INDEX index_6;
|
||||
|
||||
CREATE SPATIAL INDEX index_7;
|
||||
|
||||
--CREATE LOGFILE GROUP lf_group_name
|
||||
-- CREATE LOGFILE GROUP lf_group_name
|
||||
-- ADD UNDOFILE 'undo_file'
|
||||
-- [INITIAL_SIZE [=] initial_size]
|
||||
-- [UNDO_BUFFER_SIZE [=] undo_buffer_size]
|
||||
@ -296,18 +296,18 @@ CREATE SPATIAL INDEX index_7;
|
||||
-- ENGINE [=] engine_name
|
||||
|
||||
CREATE LOGFILE GROUP lf_group_name_1 ADD UNDOFILE 'my_undo_file'
|
||||
ENGINE some_engine_name;
|
||||
ENGINE NDB;
|
||||
-- ============ 70 STATEMENTS ====================
|
||||
CREATE LOGFILE GROUP lf_group_name_2 ADD UNDOFILE 'my_undo_file'
|
||||
INITIAL_SIZE = 9999 WAIT COMMENT = 'some bogus comment'
|
||||
ENGINE some_engine_name;
|
||||
ENGINE NDB;
|
||||
|
||||
CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()
|
||||
BEGIN
|
||||
SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
|
||||
END;
|
||||
|
||||
CREATE DEFINER = 'admin'@'localhost' FUNCTION account_count()
|
||||
CREATE DEFINER = 'admin'@'localhost' FUNCTION account_count() RETURNS INT
|
||||
SQL SECURITY INVOKER
|
||||
BEGIN
|
||||
SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
|
||||
@ -317,7 +317,7 @@ CREATE SERVER server_1
|
||||
FOREIGN DATA WRAPPER mysql
|
||||
OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test');
|
||||
|
||||
--CREATE TABLESPACE tablespace_name
|
||||
-- CREATE TABLESPACE tablespace_name
|
||||
-- ADD DATAFILE 'file_name'
|
||||
-- USE LOGFILE GROUP logfile_group
|
||||
-- [EXTENT_SIZE [=] extent_size]
|
||||
@ -329,10 +329,9 @@ CREATE SERVER server_1
|
||||
-- [COMMENT [=] comment_text]
|
||||
-- ENGINE [=] engine_name
|
||||
|
||||
CREATE TABLESPACE tbl_space_1 ADD DATAFILE 'my_data_file' USER LOGFILE GROUP my_lf_group
|
||||
ENGINE = my_engine_1;
|
||||
CREATE TABLESPACE tbl_space_1 ADD DATAFILE 'my_data_file' USER LOGFILE GROUP my_lf_group ENGINE = NDB;
|
||||
|
||||
--CREATE
|
||||
-- CREATE
|
||||
-- [DEFINER = { user | CURRENT_USER }]
|
||||
-- TRIGGER trigger_name trigger_time trigger_event
|
||||
-- ON tbl_name FOR EACH ROW trigger_stmt
|
||||
@ -347,14 +346,14 @@ CREATE TRIGGER testref BEFORE INSERT ON test1
|
||||
UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
|
||||
END;
|
||||
|
||||
CREATE DEFINER = 'user'@'hostname' TRIGGER my_trigger_1 INSERT ON test1
|
||||
CREATE DEFINER = 'user'@'hostname' TRIGGER my_trigger_1 BEFORE INSERT ON test1
|
||||
FOR EACH ROW BEGIN
|
||||
INSERT INTO test2 SET a2 = NEW.a1;
|
||||
DELETE FROM test3 WHERE a3 = NEW.a1;
|
||||
UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
|
||||
END;
|
||||
|
||||
--CREATE
|
||||
-- CREATE
|
||||
-- [OR REPLACE]
|
||||
-- [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
|
||||
-- [DEFINER = { user | CURRENT_USER }]
|
||||
@ -395,7 +394,7 @@ DROP SERVER my_server_1;
|
||||
|
||||
DROP SERVER IF EXISTS my_server_2;
|
||||
|
||||
--DROP [TEMPORARY] TABLE [IF EXISTS]
|
||||
-- DROP [TEMPORARY] TABLE [IF EXISTS]
|
||||
-- tbl_name [, tbl_name] ...
|
||||
-- [RESTRICT | CASCADE]
|
||||
|
||||
@ -409,12 +408,12 @@ DROP TABLE IF EXISTS table_4, table_5, table_6;
|
||||
|
||||
DROP TABLE IF EXISTS table_7, table_8 RESTRICT;
|
||||
|
||||
--DROP TABLESPACE tablespace_name
|
||||
-- DROP TABLESPACE tablespace_name
|
||||
-- ENGINE [=] engine_name
|
||||
|
||||
DROP TABLESPACE my_tbl_space_1 ENGINE = my_eng;
|
||||
DROP TABLESPACE my_tbl_space_1 ENGINE = NDB;
|
||||
|
||||
DROP TABLESPACE my_tbl_space_2 ENGINE my_eng;
|
||||
DROP TABLESPACE my_tbl_space_2 ENGINE NDB;
|
||||
-- ============ 100 STATEMENTS ====================
|
||||
DROP TRIGGER my_schema_1.blue_trigger;
|
||||
|
||||
|
@ -177,8 +177,11 @@ public void removeTablesForDatabase(String catalogName, String schemaName) {
|
||||
lock.write(() -> {
|
||||
tablesByTableId.entrySet().removeIf(tableIdTableEntry -> {
|
||||
TableId tableId = tableIdTableEntry.getKey();
|
||||
return (schemaName == null || tableId.schema() == null || schemaName.equals(tableId.schema()))
|
||||
& (catalogName == null || tableId.catalog() == null || catalogName.equals(tableId.catalog()));
|
||||
boolean equalSchema = schemaName == null && tableId.schema() == null
|
||||
|| schemaName != null && schemaName.equals(tableId.schema());
|
||||
boolean equalCatalog = catalogName == null && tableId.catalog() == null
|
||||
|| catalogName != null && catalogName.equals(tableId.schema());
|
||||
return equalSchema && equalCatalog;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ SPACE: [ \t\r\n]+ -> channel(HIDDEN);
|
||||
SPEC_MYSQL_COMMENT: '/*!' .+? '*/' -> channel(MYSQLCOMMENT);
|
||||
COMMENT_INPUT: '/*' .*? '*/' -> channel(HIDDEN);
|
||||
LINE_COMMENT: (
|
||||
('-- ' | '#') ~[\r\n]* ('\r'? '\n' | EOF)
|
||||
('-- ' | '#') ~[\r\n]* ('\r'? '\n' | EOF)
|
||||
| '--' ('\r'? '\n' | EOF)
|
||||
) -> channel(HIDDEN);
|
||||
|
||||
@ -336,6 +336,7 @@ CHAIN: 'CHAIN';
|
||||
CHANGED: 'CHANGED';
|
||||
CHANNEL: 'CHANNEL';
|
||||
CHECKSUM: 'CHECKSUM';
|
||||
PAGE_CHECKSUM: 'PAGE_CHECKSUM';
|
||||
CIPHER: 'CIPHER';
|
||||
CLIENT: 'CLIENT';
|
||||
CLOSE: 'CLOSE';
|
||||
@ -703,7 +704,7 @@ MRG_MYISAM: 'MRG_MYISAM';
|
||||
MYISAM: 'MYISAM';
|
||||
NDB: 'NDB';
|
||||
NDBCLUSTER: 'NDBCLUSTER';
|
||||
PERFOMANCE_SCHEMA: 'PERFOMANCE_SCHEMA';
|
||||
PERFORMANCE_SCHEMA: 'PERFORMANCE_SCHEMA';
|
||||
|
||||
|
||||
// Transaction Levels
|
||||
@ -1099,7 +1100,7 @@ FILESIZE_LITERAL: DEC_DIGIT+ ('K'|'M'|'G'|'T');
|
||||
|
||||
START_NATIONAL_STRING_LITERAL: 'N' SQUOTA_STRING;
|
||||
STRING_LITERAL: DQUOTA_STRING | SQUOTA_STRING;
|
||||
DECIMAL_LITERAL: DEC_DIGIT+;
|
||||
DECIMAL_LITERAL: '-'? DEC_DIGIT+;
|
||||
HEXADECIMAL_LITERAL: 'X' '\'' (HEX_DIGIT HEX_DIGIT)+ '\''
|
||||
| '0X' HEX_DIGIT+;
|
||||
|
||||
|
@ -37,7 +37,7 @@ root
|
||||
;
|
||||
|
||||
sqlStatements
|
||||
: (sqlStatement MINUSMINUS? SEMI | emptyStatement)*
|
||||
: (sqlStatement MINUSMINUS? SEMI | emptyStatement)*
|
||||
(sqlStatement (MINUSMINUS? SEMI)? | emptyStatement)
|
||||
;
|
||||
|
||||
@ -304,7 +304,7 @@ indexOption
|
||||
;
|
||||
|
||||
procedureParameter
|
||||
: direction=(IN | OUT | INOUT) uid dataType
|
||||
: direction=(IN | OUT | INOUT)? uid dataType
|
||||
;
|
||||
|
||||
functionParameter
|
||||
@ -349,18 +349,20 @@ columnDefinition
|
||||
columnConstraint
|
||||
: nullNotnull #nullColumnConstraint
|
||||
| DEFAULT defaultValue #defaultColumnConstraint
|
||||
| AUTO_INCREMENT #autoIncrementColumnConstraint
|
||||
| (AUTO_INCREMENT | ON UPDATE timeDefinition) #autoIncrementColumnConstraint
|
||||
| PRIMARY? KEY #primaryKeyColumnConstraint
|
||||
| UNIQUE KEY? #uniqueKeyColumnConstraint
|
||||
| COMMENT STRING_LITERAL #commentColumnConstraint
|
||||
| COLUMN_FORMAT colformat=(FIXED | DYNAMIC | DEFAULT) #formatColumnConstraint
|
||||
| STORAGE storageval=(DISK | MEMORY | DEFAULT) #storageColumnConstraint
|
||||
| referenceDefinition #referenceColumnConstraint
|
||||
| COLLATE collationName #collateColumnConstraint
|
||||
;
|
||||
|
||||
tableConstraint
|
||||
: (CONSTRAINT name=uid?)?
|
||||
PRIMARY KEY indexType? indexColumnNames indexOption* #primaryKeyTableConstraint
|
||||
PRIMARY KEY index=uid? indexType?
|
||||
indexColumnNames indexOption* #primaryKeyTableConstraint
|
||||
| (CONSTRAINT name=uid?)?
|
||||
UNIQUE indexFormat=(INDEX | KEY)? index=uid?
|
||||
indexType? indexColumnNames indexOption* #uniqueKeyTableConstraint
|
||||
@ -371,7 +373,7 @@ tableConstraint
|
||||
;
|
||||
|
||||
referenceDefinition
|
||||
: REFERENCES tableName indexColumnNames
|
||||
: REFERENCES tableName indexColumnNames?
|
||||
(MATCH matchType=(FULL | PARTIAL | SIMPLE))?
|
||||
referenceAction?
|
||||
;
|
||||
@ -404,7 +406,7 @@ tableOption
|
||||
| AUTO_INCREMENT '='? decimalLiteral #tableOptionAutoIncrement
|
||||
| AVG_ROW_LENGTH '='? decimalLiteral #tableOptionAverage
|
||||
| DEFAULT? (CHARACTER SET | CHARSET) '='? charsetName #tableOptionCharset
|
||||
| CHECKSUM '='? boolValue=('0' | '1') #tableOptionChecksum
|
||||
| (CHECKSUM | PAGE_CHECKSUM) '='? boolValue=('0' | '1') #tableOptionChecksum
|
||||
| DEFAULT? COLLATE '='? collationName #tableOptionCollate
|
||||
| COMMENT '='? STRING_LITERAL #tableOptionComment
|
||||
| COMPRESSION '='? STRING_LITERAL #tableOptionCompression
|
||||
@ -428,6 +430,7 @@ tableOption
|
||||
| STATS_PERSISTENT '='? extBoolValue=(DEFAULT | '0' | '1') #tableOptionPersistent
|
||||
| STATS_SAMPLE_PAGES '='? decimalLiteral #tableOptionSamplePage
|
||||
| TABLESPACE uid tablespaceStorage? #tableOptionTablespace
|
||||
| tablespaceStorage #tableOptionTablespace
|
||||
| UNION '='? '(' tables ')' #tableOptionUnion
|
||||
;
|
||||
|
||||
@ -440,7 +443,7 @@ partitionDefinitions
|
||||
(PARTITIONS count=decimalLiteral)?
|
||||
(
|
||||
SUBPARTITION BY subpartitionFunctionDefinition
|
||||
(SUBPARTITIONS subCount=decimalLiteral)?
|
||||
(SUBPARTITIONS subCount=decimalLiteral)?
|
||||
)?
|
||||
('(' partitionDefinition (',' partitionDefinition)* ')')?
|
||||
;
|
||||
@ -461,11 +464,14 @@ subpartitionFunctionDefinition
|
||||
|
||||
partitionDefinition
|
||||
: PARTITION uid VALUES LESS THAN
|
||||
'('
|
||||
'('
|
||||
partitionDefinerAtom (',' partitionDefinerAtom)*
|
||||
')'
|
||||
partitionOption*
|
||||
(subpartitionDefinition (',' subpartitionDefinition)*)? #partitionComparision
|
||||
| PARTITION uid VALUES LESS THAN
|
||||
partitionDefinerAtom partitionOption*
|
||||
(subpartitionDefinition (',' subpartitionDefinition)*)? #partitionComparision
|
||||
| PARTITION uid VALUES IN
|
||||
'('
|
||||
partitionDefinerAtom (',' partitionDefinerAtom)*
|
||||
@ -483,7 +489,7 @@ partitionDefinition
|
||||
;
|
||||
|
||||
partitionDefinerAtom
|
||||
: constant | MAXVALUE | expression
|
||||
: constant | expression | MAXVALUE
|
||||
;
|
||||
|
||||
partitionDefinerVector
|
||||
@ -551,7 +557,7 @@ alterServer
|
||||
alterTable
|
||||
: ALTER intimeAction=(ONLINE | OFFLINE)?
|
||||
IGNORE? TABLE tableName
|
||||
alterSpecification (',' alterSpecification)*
|
||||
(alterSpecification (',' alterSpecification)*)?
|
||||
partitionDefinitions?
|
||||
;
|
||||
|
||||
@ -604,7 +610,7 @@ alterSpecification
|
||||
| LOCK '='? lockType=(DEFAULT | NONE | SHARED | EXCLUSIVE) #alterByLock
|
||||
| MODIFY COLUMN?
|
||||
uid columnDefinition (FIRST | AFTER uid)? #alterByModifyColumn
|
||||
| DROP COLUMN? uid #alterByDropColumn
|
||||
| DROP COLUMN? uid RESTRICT? #alterByDropColumn
|
||||
| DROP PRIMARY KEY #alterByDropPrimaryKey
|
||||
| DROP indexFormat=(INDEX | KEY) uid #alterByDropIndex
|
||||
| DROP FOREIGN KEY uid #alterByDropForeignKey
|
||||
@ -1328,7 +1334,7 @@ blockStatement
|
||||
(declareCondition SEMI)*
|
||||
(declareCursor SEMI)*
|
||||
(declareHandler SEMI)*
|
||||
procedureSqlStatement+
|
||||
(procedureSqlStatement)*
|
||||
)?
|
||||
END uid?
|
||||
;
|
||||
@ -1633,8 +1639,8 @@ uninstallPlugin
|
||||
// Set and show statements
|
||||
|
||||
setStatement
|
||||
: SET variableClause '=' expression
|
||||
(',' variableClause '=' expression)* #setVariable
|
||||
: SET variableClause ('=' | ':=') expression
|
||||
(',' variableClause ('=' | ':=') expression)* #setVariable
|
||||
| SET (CHARACTER SET | CHARSET) (charsetName | DEFAULT) #setCharset
|
||||
| SET NAMES
|
||||
(charsetName (COLLATE collationName)? | DEFAULT) #setNames
|
||||
@ -1694,7 +1700,7 @@ showStatement
|
||||
// details
|
||||
|
||||
variableClause
|
||||
: LOCAL_ID | GLOBAL_ID | ( ('@' '@')? (GLOBAL | SESSION) )? uid
|
||||
: LOCAL_ID | GLOBAL_ID | (('@' '@')? (GLOBAL | SESSION | LOCAL))? uid
|
||||
;
|
||||
|
||||
showCommonEntity
|
||||
@ -1847,11 +1853,11 @@ fullColumnName
|
||||
;
|
||||
|
||||
indexColumnName
|
||||
: uid ('(' decimalLiteral ')')? sortType=(ASC | DESC)?
|
||||
: (uid | STRING_LITERAL) ('(' decimalLiteral ')')? sortType=(ASC | DESC)?
|
||||
;
|
||||
|
||||
userName
|
||||
: STRING_USER_NAME | ID;
|
||||
: STRING_USER_NAME | ID | STRING_LITERAL;
|
||||
|
||||
mysqlVariable
|
||||
: LOCAL_ID
|
||||
@ -1870,7 +1876,7 @@ collationName
|
||||
|
||||
engineName
|
||||
: ARCHIVE | BLACKHOLE | CSV | FEDERATED | INNODB | MEMORY
|
||||
| MRG_MYISAM | MYISAM | NDB | NDBCLUSTER | PERFOMANCE_SCHEMA
|
||||
| MRG_MYISAM | MYISAM | NDB | NDBCLUSTER | PERFORMANCE_SCHEMA
|
||||
;
|
||||
|
||||
uuidSet
|
||||
@ -1968,23 +1974,23 @@ dataType
|
||||
| NCHAR | NVARCHAR
|
||||
)
|
||||
lengthOneDimension? BINARY?
|
||||
(CHARACTER SET charsetName)? (COLLATE collationName)? #stringDataType
|
||||
((CHARACTER SET | CHARSET) charsetName)? #stringDataType
|
||||
| NATIONAL typeName=(VARCHAR | CHARACTER)
|
||||
lengthOneDimension? BINARY? (COLLATE collationName)? #nationalStringDataType
|
||||
lengthOneDimension? BINARY? #nationalStringDataType
|
||||
| NCHAR typeName=VARCHAR
|
||||
lengthOneDimension? BINARY? (COLLATE collationName)? #nationalStringDataType
|
||||
lengthOneDimension? BINARY? #nationalStringDataType
|
||||
| NATIONAL typeName=(CHAR | CHARACTER) VARYING
|
||||
lengthOneDimension? BINARY? (COLLATE collationName)? #nationalVaryingStringDataType
|
||||
lengthOneDimension? BINARY? #nationalVaryingStringDataType
|
||||
| typeName=(
|
||||
TINYINT | SMALLINT | MEDIUMINT | INT | INTEGER | BIGINT
|
||||
)
|
||||
lengthOneDimension? UNSIGNED? ZEROFILL? #dimensionDataType
|
||||
lengthOneDimension? (SIGNED | UNSIGNED)? ZEROFILL? #dimensionDataType
|
||||
| typeName=(REAL | FLOAT)
|
||||
lengthTwoDimension? UNSIGNED? ZEROFILL? #dimensionDataType
|
||||
lengthTwoDimension? (SIGNED | UNSIGNED)? ZEROFILL? #dimensionDataType
|
||||
| typeName=DOUBLE PRECISION?
|
||||
lengthTwoDimension? UNSIGNED? ZEROFILL? #dimensionDataType
|
||||
lengthTwoDimension? (SIGNED | UNSIGNED)? ZEROFILL? #dimensionDataType
|
||||
| typeName=(DECIMAL | DEC | FIXED | NUMERIC)
|
||||
lengthTwoOptionalDimension? UNSIGNED? ZEROFILL? #dimensionDataType
|
||||
lengthTwoOptionalDimension? (SIGNED | UNSIGNED)? ZEROFILL? #dimensionDataType
|
||||
| typeName=(
|
||||
DATE | TINYBLOB | BLOB | MEDIUMBLOB | LONGBLOB
|
||||
| BOOL | BOOLEAN
|
||||
@ -1995,14 +2001,18 @@ dataType
|
||||
)
|
||||
lengthOneDimension? #dimensionDataType
|
||||
| typeName=(ENUM | SET)
|
||||
'(' STRING_LITERAL (',' STRING_LITERAL)* ')' BINARY?
|
||||
(CHARACTER SET charsetName)? (COLLATE collationName)? #collectionDataType
|
||||
'(' collectionOption (',' collectionOption)* ')' BINARY?
|
||||
((CHARACTER SET | CHARSET) charsetName)? #collectionDataType
|
||||
| typeName=(
|
||||
GEOMETRYCOLLECTION | LINESTRING | MULTILINESTRING
|
||||
| MULTIPOINT | MULTIPOLYGON | POINT | POLYGON | JSON | GEOMETRY
|
||||
) #spatialDataType
|
||||
;
|
||||
|
||||
collectionOption
|
||||
: STRING_LITERAL
|
||||
;
|
||||
|
||||
convertedDataType
|
||||
: typeName=(BINARY| NCHAR) lengthOneDimension?
|
||||
| typeName=CHAR lengthOneDimension? (CHARACTER SET charsetName)?
|
||||
@ -2064,7 +2074,13 @@ userVariables
|
||||
defaultValue
|
||||
: NULL_LITERAL
|
||||
| constant
|
||||
| CURRENT_TIMESTAMP (ON UPDATE LOCALTIMESTAMP)?
|
||||
// | timeDefinition (ON UPDATE timeDefinition)?
|
||||
| timeDefinition
|
||||
;
|
||||
|
||||
timeDefinition
|
||||
: (CURRENT_TIMESTAMP | NOW | LOCALTIME | LOCALTIMESTAMP)
|
||||
('(' functionArgs? ')')?
|
||||
;
|
||||
|
||||
expressionOrDefault
|
||||
@ -2337,7 +2353,7 @@ keywordsCanBeId
|
||||
| AT | AUTHORS | AUTOCOMMIT | AUTOEXTEND_SIZE
|
||||
| AUTO_INCREMENT | AVG_ROW_LENGTH | BEGIN | BINLOG | BIT
|
||||
| BLOCK | BOOL | BOOLEAN | BTREE | CASCADED | CHAIN
|
||||
| CHANNEL | CHECKSUM | CIPHER | CLIENT | COALESCE | CODE
|
||||
| CHANNEL | CHECKSUM | PAGE_CHECKSUM | CIPHER | CLIENT | COALESCE | CODE
|
||||
| COLUMNS | COLUMN_FORMAT | COMMENT | COMMIT | COMPACT
|
||||
| COMPLETION | COMPRESSED | COMPRESSION | CONCURRENT
|
||||
| CONNECTION | CONSISTENT | CONTAINS | CONTEXT
|
||||
@ -2370,7 +2386,7 @@ keywordsCanBeId
|
||||
| OJ | OLD_PASSWORD | ONE | ONLINE | ONLY | OPTIMIZER_COSTS
|
||||
| OPTIONS | OWNER | PACK_KEYS | PAGE | PARSER | PARTIAL
|
||||
| PARTITIONING | PARTITIONS | PASSWORD | PHASE | PLUGINS
|
||||
| PLUGIN_DIR | PORT | PRECEDES | PREPARE | PRESERVE | PREV
|
||||
| PLUGIN_DIR | PLUGIN | PORT | PRECEDES | PREPARE | PRESERVE | PREV
|
||||
| PROCESSLIST | PROFILE | PROFILES | PROXY | QUERY | QUICK
|
||||
| REBUILD | RECOVER | REDO_BUFFER_SIZE | REDUNDANT
|
||||
| RELAYLOG | RELAY_LOG_FILE | RELAY_LOG_POS | REMOVE
|
||||
|
@ -10,6 +10,7 @@
|
||||
import io.debezium.relational.Tables;
|
||||
import io.debezium.relational.ddl.AbstractDdlParser;
|
||||
import io.debezium.text.MultipleParsingExceptions;
|
||||
import io.debezium.text.ParsingException;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CodePointCharStream;
|
||||
@ -22,16 +23,22 @@
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Roman Kuchár <kucharrom@gmail.com>.
|
||||
*/
|
||||
public abstract class AntlrDdlParser<L extends Lexer, P extends Parser> extends AbstractDdlParser {
|
||||
|
||||
private boolean throwErrorsFromTreeWalk;
|
||||
private ProxyParseTreeListener proxyParseTreeListener;
|
||||
|
||||
protected Tables databaseTables;
|
||||
protected DataTypeResolver dataTypeResolver = new DataTypeResolver();
|
||||
|
||||
public AntlrDdlParser() {
|
||||
public AntlrDdlParser(boolean throwErrorsFromTreeWalk) {
|
||||
super(";");
|
||||
this.throwErrorsFromTreeWalk = throwErrorsFromTreeWalk;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -53,12 +60,10 @@ public void parse(String ddlContent, Tables databaseTables) {
|
||||
ParseTree parseTree = parseTree(parser);
|
||||
|
||||
if (parsingErrorListener.getErrors().isEmpty()) {
|
||||
ProxyParseTreeListener proxyParseTreeListener = new ProxyParseTreeListener(this::accumulateParsingFailure);
|
||||
assignParserListeners(proxyParseTreeListener);
|
||||
|
||||
proxyParseTreeListener = assignParserListeners();
|
||||
ParseTreeWalker.DEFAULT.walk(proxyParseTreeListener, parseTree);
|
||||
|
||||
if (!proxyParseTreeListener.getErrors().isEmpty()) {
|
||||
if (throwErrorsFromTreeWalk && !proxyParseTreeListener.getErrors().isEmpty()) {
|
||||
throw new MultipleParsingExceptions(proxyParseTreeListener.getErrors());
|
||||
}
|
||||
}
|
||||
@ -67,6 +72,10 @@ public void parse(String ddlContent, Tables databaseTables) {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<ParsingException> getParsingExceptionsFromWalker() {
|
||||
return proxyParseTreeListener.getErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the supplied string containing DDL statements, and apply those statements to the specified
|
||||
* database table definitions.
|
||||
@ -75,7 +84,7 @@ public void parse(String ddlContent, Tables databaseTables) {
|
||||
*/
|
||||
protected abstract ParseTree parseTree(P parser);
|
||||
|
||||
protected abstract void assignParserListeners(ProxyParseTreeListener proxyParseTreeListener);
|
||||
protected abstract ProxyParseTreeListener assignParserListeners();
|
||||
|
||||
/**
|
||||
* Creates a new generic type instance of ANTLR Lexer.
|
||||
|
@ -34,6 +34,7 @@
|
||||
public class ProxyParseTreeListener implements ParseTreeListener {
|
||||
private List<ParseTreeListener> listeners;
|
||||
|
||||
private SkipException skipException = null;
|
||||
private Collection<ParsingException> errors = new ArrayList<>();
|
||||
private final BiFunction<ParsingException, Collection<ParsingException>, Collection<ParsingException>> accumulateError;
|
||||
|
||||
@ -58,28 +59,38 @@ public ProxyParseTreeListener(List<ParseTreeListener> listeners, BiFunction<Pars
|
||||
|
||||
@Override
|
||||
public void enterEveryRule(ParserRuleContext ctx) {
|
||||
for (ParseTreeListener listener : getListeners()) {
|
||||
try {
|
||||
listener.enterEveryRule(ctx);
|
||||
ctx.enterRule(listener);
|
||||
}
|
||||
catch (ParsingException parsingException) {
|
||||
accumulateError.apply(parsingException, errors);
|
||||
if (skipException == null) {
|
||||
for (ParseTreeListener listener : getListeners()) {
|
||||
try {
|
||||
listener.enterEveryRule(ctx);
|
||||
ctx.enterRule(listener);
|
||||
}
|
||||
catch (ParsingException parsingException) {
|
||||
accumulateError.apply(parsingException, errors);
|
||||
}
|
||||
catch (SkipException e) {
|
||||
skipException = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitEveryRule(ParserRuleContext ctx) {
|
||||
for (ParseTreeListener listener : getListeners()) {
|
||||
try {
|
||||
ctx.exitRule(listener);
|
||||
listener.exitEveryRule(ctx);
|
||||
}
|
||||
catch (ParsingException parsingException) {
|
||||
accumulateError.apply(parsingException, errors);
|
||||
if (skipException == null) {
|
||||
for (ParseTreeListener listener : getListeners()) {
|
||||
try {
|
||||
ctx.exitRule(listener);
|
||||
listener.exitEveryRule(ctx);
|
||||
}
|
||||
catch (ParsingException parsingException) {
|
||||
accumulateError.apply(parsingException, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (skipException.getCtxClass().isAssignableFrom(ctx.getClass())) {
|
||||
skipException = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright Debezium Authors.
|
||||
*
|
||||
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
package io.debezium.antlr;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
|
||||
/**
|
||||
* @author Roman Kuchár <kucharrom@gmail.com>.
|
||||
*/
|
||||
public class SkipException extends RuntimeException {
|
||||
|
||||
private Class<? extends ParserRuleContext> ctxClass;
|
||||
|
||||
public SkipException(Class<? extends ParserRuleContext> ctxClass) {
|
||||
this.ctxClass = ctxClass;
|
||||
}
|
||||
|
||||
public Class<? extends ParserRuleContext> getCtxClass() {
|
||||
return ctxClass;
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
import io.debezium.antlr.DataTypeResolver;
|
||||
import io.debezium.antlr.DataTypeResolver.DataTypeEntry;
|
||||
import io.debezium.antlr.ProxyParseTreeListener;
|
||||
import io.debezium.antlr.SkipException;
|
||||
import io.debezium.antlr.mysql.MySqlSystemVariables.MySqlScope;
|
||||
import io.debezium.ddl.parser.mysql.generated.MySqlLexer;
|
||||
import io.debezium.ddl.parser.mysql.generated.MySqlParser;
|
||||
@ -45,7 +46,11 @@ public class MySqlAntlrDdlParser extends AntlrDdlParser<MySqlLexer, MySqlParser>
|
||||
private final ConcurrentMap<String, String> charsetNameForDatabase = new ConcurrentHashMap<>();
|
||||
|
||||
public MySqlAntlrDdlParser() {
|
||||
super();
|
||||
this(true);
|
||||
}
|
||||
|
||||
public MySqlAntlrDdlParser(boolean throwErrorsFromTreeWalk) {
|
||||
super(throwErrorsFromTreeWalk);
|
||||
systemVariables = new MySqlSystemVariables();
|
||||
}
|
||||
|
||||
@ -55,10 +60,11 @@ protected ParseTree parseTree(MySqlParser parser) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assignParserListeners(ProxyParseTreeListener proxyParseTreeListener) {
|
||||
protected ProxyParseTreeListener assignParserListeners() {
|
||||
ProxyParseTreeListener proxyParseTreeListener = new ProxyParseTreeListener(this::accumulateParsingFailure);
|
||||
proxyParseTreeListener.add(new DatabaseOptionsListener());
|
||||
proxyParseTreeListener.add(new DropDatabaseParserListener());
|
||||
proxyParseTreeListener.add(new ColumnDefinitionParserListener());
|
||||
proxyParseTreeListener.add(new DropDatabaseParserListener());
|
||||
proxyParseTreeListener.add(new CreateTableParserListener());
|
||||
proxyParseTreeListener.add(new AlterTableParserListener());
|
||||
proxyParseTreeListener.add(new DropTableParserListener());
|
||||
@ -68,6 +74,7 @@ protected void assignParserListeners(ProxyParseTreeListener proxyParseTreeListen
|
||||
proxyParseTreeListener.add(new SetStatementParserListener());
|
||||
proxyParseTreeListener.add(new UseStatementParserListener());
|
||||
proxyParseTreeListener.add(new FinishSqlStatementParserListener());
|
||||
return proxyParseTreeListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -93,12 +100,12 @@ protected boolean isGrammarInUpperCase() {
|
||||
@Override
|
||||
protected void initDataTypes(DataTypeResolver dataTypeResolver) {
|
||||
dataTypeResolver.registerDataTypes(MySqlParser.StringDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
||||
new DataTypeEntry(MySqlParser.CHAR, Types.BINARY),
|
||||
new DataTypeEntry(MySqlParser.CHAR, Types.CHAR),
|
||||
new DataTypeEntry(MySqlParser.VARCHAR, Types.VARCHAR),
|
||||
new DataTypeEntry(MySqlParser.TINYTEXT, Types.BLOB),
|
||||
new DataTypeEntry(MySqlParser.TEXT, Types.BLOB),
|
||||
new DataTypeEntry(MySqlParser.MEDIUMTEXT, Types.BLOB),
|
||||
new DataTypeEntry(MySqlParser.LONGTEXT, Types.BLOB),
|
||||
new DataTypeEntry(MySqlParser.TINYTEXT, Types.VARCHAR),
|
||||
new DataTypeEntry(MySqlParser.TEXT, Types.VARCHAR),
|
||||
new DataTypeEntry(MySqlParser.MEDIUMTEXT, Types.VARCHAR),
|
||||
new DataTypeEntry(MySqlParser.LONGTEXT, Types.VARCHAR),
|
||||
new DataTypeEntry(MySqlParser.NCHAR, Types.NCHAR),
|
||||
new DataTypeEntry(MySqlParser.NVARCHAR, Types.NVARCHAR)
|
||||
));
|
||||
@ -158,8 +165,8 @@ protected void initDataTypes(DataTypeResolver dataTypeResolver) {
|
||||
));
|
||||
}
|
||||
|
||||
private TableId parseQualifiedTableId(MySqlParser.TableNameContext tableNameContext) {
|
||||
String fullTableName = tableNameContext.fullId().getText();
|
||||
private TableId parseQualifiedTableId(MySqlParser.FullIdContext fullIdContext) {
|
||||
String fullTableName = fullIdContext.getText();
|
||||
int dotIndex;
|
||||
if ((dotIndex = fullTableName.indexOf(".")) > 0) {
|
||||
return resolveTableId(withoutQuotes(fullTableName.substring(0, dotIndex)),
|
||||
@ -186,10 +193,13 @@ private String getFullTableName(TableId tableId) {
|
||||
private void resolveColumnDataType(MySqlParser.DataTypeContext dataTypeContext) {
|
||||
String dataTypeName;
|
||||
String charsetName = null;
|
||||
Integer jdbcDataType = Types.NULL;
|
||||
if (dataTypeContext instanceof MySqlParser.StringDataTypeContext) {
|
||||
MySqlParser.StringDataTypeContext stringDataTypeContext = (MySqlParser.StringDataTypeContext) dataTypeContext;
|
||||
dataTypeName = stringDataTypeContext.typeName.getText();
|
||||
if (stringDataTypeContext.BINARY() != null) {
|
||||
// TODO rkuchar: figure out something better
|
||||
jdbcDataType = Types.BINARY;
|
||||
dataTypeName += " " + stringDataTypeContext.BINARY().getText();
|
||||
}
|
||||
|
||||
@ -238,6 +248,15 @@ else if (dataTypeContext instanceof MySqlParser.DimensionDataTypeContext) {
|
||||
if (dimensionDataTypeContext.PRECISION() != null) {
|
||||
dataTypeName += " " + dimensionDataTypeContext.PRECISION().getText();
|
||||
}
|
||||
if (dimensionDataTypeContext.SIGNED() != null) {
|
||||
dataTypeName += " " + dimensionDataTypeContext.SIGNED().getText();
|
||||
}
|
||||
if (dimensionDataTypeContext.UNSIGNED() != null) {
|
||||
dataTypeName += " " + dimensionDataTypeContext.UNSIGNED().getText();
|
||||
}
|
||||
if (dimensionDataTypeContext.ZEROFILL() != null) {
|
||||
dataTypeName += " " + dimensionDataTypeContext.ZEROFILL().getText();
|
||||
}
|
||||
|
||||
Integer length = null;
|
||||
Integer scale = null;
|
||||
@ -275,6 +294,13 @@ else if (dataTypeContext instanceof MySqlParser.CollectionDataTypeContext) {
|
||||
charsetName = collectionDataTypeContext.charsetName().getText();
|
||||
}
|
||||
dataTypeName = collectionDataTypeContext.typeName.getText();
|
||||
if (dataTypeName.equals("SET")) {
|
||||
// After DBZ-132, it will always be comma seperated
|
||||
columnEditor.length(Math.max(0, collectionDataTypeContext.collectionOption().size() * 2 - 1)); // number of options + number of commas
|
||||
}
|
||||
else {
|
||||
columnEditor.length(1);
|
||||
}
|
||||
}
|
||||
else if (dataTypeContext instanceof MySqlParser.SpatialDataTypeContext) {
|
||||
dataTypeName = ((MySqlParser.SpatialDataTypeContext) dataTypeContext).typeName.getText();
|
||||
@ -283,20 +309,26 @@ else if (dataTypeContext instanceof MySqlParser.SpatialDataTypeContext) {
|
||||
throw new IllegalStateException("Not recognized instance of data type context for " + dataTypeContext.getText());
|
||||
}
|
||||
|
||||
columnEditor.type(dataTypeName);
|
||||
columnEditor.type(dataTypeName.toUpperCase());
|
||||
|
||||
if (charsetName != null) {
|
||||
if (!"DEFAULT".equalsIgnoreCase(charsetName)) {
|
||||
// Only record it if not inheriting the character set from the table
|
||||
columnEditor.charsetName(charsetName);
|
||||
if (jdbcDataType == Types.NULL) {
|
||||
jdbcDataType = dataTypeResolver.resolveDataType(dataTypeContext);
|
||||
}
|
||||
columnEditor.jdbcType(jdbcDataType);
|
||||
|
||||
if (Types.DECIMAL == jdbcDataType) {
|
||||
if (columnEditor.length() == -1) {
|
||||
columnEditor.length(10);
|
||||
}
|
||||
if (columnEditor.scale() == -1) {
|
||||
columnEditor.scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
Integer jdbcDataType = dataTypeResolver.resolveDataType(dataTypeContext);
|
||||
columnEditor.jdbcType(jdbcDataType);
|
||||
if (Types.NCHAR == jdbcDataType || Types.NVARCHAR == jdbcDataType) {
|
||||
// NCHAR and NVARCHAR columns always uses utf8 as charset
|
||||
columnEditor.charsetName("utf8");
|
||||
} else {
|
||||
columnEditor.charsetName(charsetName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +336,13 @@ private void parsePrimaryIndexColumnNames(MySqlParser.IndexColumnNamesContext in
|
||||
List<String> pkColumnNames = indexColumnNamesContext.indexColumnName().stream()
|
||||
.map(indexColumnNameContext -> {
|
||||
// MySQL does not allow a primary key to have nullable columns, so let's make sure we model that correctly ...
|
||||
String columnName = parseName(indexColumnNameContext.uid());
|
||||
String columnName;
|
||||
if(indexColumnNameContext.uid() != null) {
|
||||
columnName = parseName(indexColumnNameContext.uid());
|
||||
}
|
||||
else {
|
||||
columnName = withoutQuotes(indexColumnNameContext.STRING_LITERAL().getText());
|
||||
}
|
||||
Column column = tableEditor.columnWithName(columnName);
|
||||
if (column != null && column.isOptional()) {
|
||||
tableEditor.addColumn(column.edit().optional(false).create());
|
||||
@ -330,6 +368,61 @@ protected String currentDatabaseCharset() {
|
||||
return charsetName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parser listener for MySQL column definition queries.
|
||||
*/
|
||||
private class ColumnDefinitionParserListener extends MySqlParserBaseListener {
|
||||
|
||||
@Override
|
||||
public void enterColumnDefinition(MySqlParser.ColumnDefinitionContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
resolveColumnDataType(ctx.dataType());
|
||||
});
|
||||
super.enterColumnDefinition(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterUniqueKeyColumnConstraint(MySqlParser.UniqueKeyColumnConstraintContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
if (!tableEditor.hasPrimaryKey()) {
|
||||
// take the first unique constrain if no primary key is set
|
||||
tableEditor.addColumn(columnEditor.create());
|
||||
tableEditor.setPrimaryKeyNames(columnEditor.name());
|
||||
}
|
||||
});
|
||||
super.enterUniqueKeyColumnConstraint(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPrimaryKeyColumnConstraint(MySqlParser.PrimaryKeyColumnConstraintContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
// this rule will be parsed only if no primary key is set in a table
|
||||
// otherwise the statement can't be executed due to multiple primary key error
|
||||
columnEditor.optional(false);
|
||||
tableEditor.addColumn(columnEditor.create());
|
||||
tableEditor.setPrimaryKeyNames(columnEditor.name());
|
||||
});
|
||||
super.enterPrimaryKeyColumnConstraint(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterNullNotnull(MySqlParser.NullNotnullContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> columnEditor.optional(ctx.NOT() == null));
|
||||
super.enterNullNotnull(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterAutoIncrementColumnConstraint(MySqlParser.AutoIncrementColumnConstraintContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
columnEditor.autoIncremented(true);
|
||||
columnEditor.generated(true);
|
||||
});
|
||||
super.enterAutoIncrementColumnConstraint(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser listener for MySQL create database query to get database charsetName.
|
||||
*/
|
||||
@ -390,13 +483,17 @@ private class CreateTableParserListener extends MySqlParserBaseListener {
|
||||
|
||||
@Override
|
||||
public void enterColumnCreateTable(MySqlParser.ColumnCreateTableContext ctx) {
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName());
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName().fullId());
|
||||
tableEditor = databaseTables.editOrCreateTable(tableId);
|
||||
super.enterColumnCreateTable(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitColumnCreateTable(MySqlParser.ColumnCreateTableContext ctx) {
|
||||
// Make sure that the table's character set has been set ...
|
||||
if (!tableEditor.hasDefaultCharsetName()) {
|
||||
tableEditor.setDefaultCharsetName(currentDatabaseCharset());
|
||||
}
|
||||
databaseTables.overwriteTable(tableEditor.create());
|
||||
signalCreateTable(tableEditor.tableId(), ctx);
|
||||
super.exitColumnCreateTable(ctx);
|
||||
@ -404,8 +501,8 @@ public void exitColumnCreateTable(MySqlParser.ColumnCreateTableContext ctx) {
|
||||
|
||||
@Override
|
||||
public void exitCopyCreateTable(MySqlParser.CopyCreateTableContext ctx) {
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName(0));
|
||||
TableId originalTableId = parseQualifiedTableId(ctx.tableName(1));
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName(0).fullId());
|
||||
TableId originalTableId = parseQualifiedTableId(ctx.tableName(1).fullId());
|
||||
Table original = databaseTables.forTable(originalTableId);
|
||||
if (original != null) {
|
||||
databaseTables.overwriteTable(tableId, original.columns(), original.primaryKeyColumnNames(), original.defaultCharsetName());
|
||||
@ -441,6 +538,13 @@ public void enterUniqueKeyTableConstraint(MySqlParser.UniqueKeyTableConstraintCo
|
||||
}
|
||||
super.enterUniqueKeyTableConstraint(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterTableOptionCharset(MySqlParser.TableOptionCharsetContext ctx) {
|
||||
String charsetName = withoutQuotes(ctx.charsetName());
|
||||
tableEditor.setDefaultCharsetName(charsetName);
|
||||
super.enterTableOptionCharset(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -453,7 +557,7 @@ public void enterDropTable(MySqlParser.DropTableContext ctx) {
|
||||
Interval interval = new Interval(ctx.start.getStartIndex(), ctx.tables().start.getStartIndex() - 1);
|
||||
String prefix = ctx.start.getInputStream().getText(interval);
|
||||
ctx.tables().tableName().forEach(tableNameContext -> {
|
||||
TableId tableId = parseQualifiedTableId(tableNameContext);
|
||||
TableId tableId = parseQualifiedTableId(tableNameContext.fullId());
|
||||
databaseTables.removeTable(tableId);
|
||||
signalDropTable(tableId, prefix + tableId.table()
|
||||
+ (ctx.dropType != null ? " " + ctx.dropType.getText() : ""));
|
||||
@ -474,7 +578,7 @@ private class AlterTableParserListener extends MySqlParserBaseListener {
|
||||
|
||||
@Override
|
||||
public void enterAlterTable(MySqlParser.AlterTableContext ctx) {
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName());
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName().fullId());
|
||||
tableEditor = databaseTables.editTable(tableId);
|
||||
if (tableEditor == null) {
|
||||
throw new ParsingException(null, "Trying to alter table " + getFullTableName(tableId)
|
||||
@ -676,64 +780,6 @@ public void enterAlterByAddUniqueKey(MySqlParser.AlterByAddUniqueKeyContext ctx)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser listener for MySQL column definition queries.
|
||||
*/
|
||||
private class ColumnDefinitionParserListener extends MySqlParserBaseListener {
|
||||
|
||||
@Override
|
||||
public void enterColumnDefinition(MySqlParser.ColumnDefinitionContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
resolveColumnDataType(ctx.dataType());
|
||||
});
|
||||
super.enterColumnDefinition(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterUniqueKeyColumnConstraint(MySqlParser.UniqueKeyColumnConstraintContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
if (!tableEditor.hasPrimaryKey()) {
|
||||
// take the first unique constrain if no primary key is set
|
||||
tableEditor.setPrimaryKeyNames(columnEditor.name());
|
||||
}
|
||||
});
|
||||
super.enterUniqueKeyColumnConstraint(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPrimaryKeyColumnConstraint(MySqlParser.PrimaryKeyColumnConstraintContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
// this rule will be parsed only if no primary key is set in a table
|
||||
// otherwise the statement can't be executed due to multiple primary key error
|
||||
columnEditor.optional(false);
|
||||
tableEditor.setPrimaryKeyNames(columnEditor.name());
|
||||
});
|
||||
super.enterPrimaryKeyColumnConstraint(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterNullNotnull(MySqlParser.NullNotnullContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> columnEditor.optional(ctx.NOT() == null));
|
||||
|
||||
super.enterNullNotnull(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterDefaultColumnConstraint(MySqlParser.DefaultColumnConstraintContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> columnEditor.generated(true));
|
||||
super.enterDefaultColumnConstraint(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterAutoIncrementColumnConstraint(MySqlParser.AutoIncrementColumnConstraintContext ctx) {
|
||||
runIfAllEditorsNotNull(() -> {
|
||||
columnEditor.autoIncremented(true);
|
||||
columnEditor.generated(true);
|
||||
});
|
||||
super.enterAutoIncrementColumnConstraint(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser listener for MySQL rename table queries.
|
||||
*/
|
||||
@ -741,8 +787,8 @@ private class RenameTableParserListener extends MySqlParserBaseListener {
|
||||
|
||||
@Override
|
||||
public void enterRenameTableClause(MySqlParser.RenameTableClauseContext ctx) {
|
||||
TableId oldTable = parseQualifiedTableId(ctx.tableName(0));
|
||||
TableId newTable = parseQualifiedTableId(ctx.tableName(1));
|
||||
TableId oldTable = parseQualifiedTableId(ctx.tableName(0).fullId());
|
||||
TableId newTable = parseQualifiedTableId(ctx.tableName(1).fullId());
|
||||
databaseTables.renameTable(oldTable, newTable);
|
||||
signalAlterTable(newTable, oldTable, ctx);
|
||||
super.enterRenameTableClause(ctx);
|
||||
@ -756,8 +802,10 @@ private class TruncateTableParserListener extends MySqlParserBaseListener {
|
||||
|
||||
@Override
|
||||
public void enterTruncateTable(MySqlParser.TruncateTableContext ctx) {
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName());
|
||||
signalTruncateTable(tableId, ctx);
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName().fullId());
|
||||
// TODO rkuchar: uncomment. Tis is comment just because of test.
|
||||
// The old parser is not signaling truncate events
|
||||
// signalTruncateTable(tableId, ctx);
|
||||
super.enterTruncateTable(ctx);
|
||||
}
|
||||
}
|
||||
@ -770,7 +818,7 @@ private class CreateUniqueIndexParserListener extends MySqlParserBaseListener {
|
||||
@Override
|
||||
public void enterCreateIndex(MySqlParser.CreateIndexContext ctx) {
|
||||
if (ctx.UNIQUE() != null) {
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName());
|
||||
TableId tableId = parseQualifiedTableId(ctx.tableName().fullId());
|
||||
tableEditor = databaseTables.editTable(tableId);
|
||||
if (tableEditor != null) {
|
||||
if (!tableEditor.hasPrimaryKey()) {
|
||||
@ -795,20 +843,42 @@ public void enterSetVariable(MySqlParser.SetVariableContext ctx) {
|
||||
MySqlScope scope = null;
|
||||
for (int i = 0; i < ctx.variableClause().size(); i++) {
|
||||
MySqlParser.VariableClauseContext variableClauseContext = ctx.variableClause(i);
|
||||
// default scope
|
||||
String variableName;
|
||||
if (variableClauseContext.uid() == null) {
|
||||
// that mean that user variable is set, so do nothing with it
|
||||
continue;
|
||||
if (variableClauseContext.GLOBAL_ID() == null) {
|
||||
// that mean that user variable is set, so do nothing with it
|
||||
continue;
|
||||
}
|
||||
String variableIdentifier = variableClauseContext.GLOBAL_ID().getText();
|
||||
if(variableIdentifier.startsWith("@@global.")) {
|
||||
scope = MySqlScope.GLOBAL;
|
||||
variableName = variableIdentifier.substring("@@global.".length());
|
||||
}
|
||||
else if (variableIdentifier.startsWith("@@session.")) {
|
||||
scope = MySqlScope.SESSION;
|
||||
variableName = variableIdentifier.substring("@@session.".length());
|
||||
}
|
||||
else if (variableIdentifier.startsWith("@@local.")) {
|
||||
scope = MySqlScope.LOCAL;
|
||||
variableName = variableIdentifier.substring("@@local.".length());
|
||||
} else {
|
||||
scope = MySqlScope.SESSION;
|
||||
variableName = variableIdentifier.substring("@@".length());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (variableClauseContext.GLOBAL() != null) {
|
||||
scope = MySqlScope.GLOBAL;
|
||||
}
|
||||
else if (variableClauseContext.SESSION() != null) {
|
||||
scope = MySqlScope.SESSION;
|
||||
}
|
||||
else if (variableClauseContext.LOCAL() != null) {
|
||||
scope = MySqlScope.LOCAL;
|
||||
}
|
||||
|
||||
if (variableClauseContext.GLOBAL() != null) {
|
||||
scope = MySqlScope.GLOBAL;
|
||||
variableName = parseName(variableClauseContext.uid());
|
||||
}
|
||||
else if (variableClauseContext.SESSION() != null) {
|
||||
scope = MySqlScope.SESSION;
|
||||
}
|
||||
|
||||
String variableName = parseName(variableClauseContext.uid());
|
||||
String value = withoutQuotes(ctx.expression(i));
|
||||
|
||||
systemVariables.setVariable(scope, variableName, value);
|
||||
@ -876,6 +946,12 @@ public void enterUseStatement(MySqlParser.UseStatementContext ctx) {
|
||||
*/
|
||||
private class FinishSqlStatementParserListener extends MySqlParserBaseListener {
|
||||
|
||||
|
||||
@Override
|
||||
public void enterRoutineBody(MySqlParser.RoutineBodyContext ctx) {
|
||||
throw new SkipException(ctx.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitSqlStatement(MySqlParser.SqlStatementContext ctx) {
|
||||
if (tableEditor != null) {
|
||||
|
Loading…
Reference in New Issue
Block a user