/** * Obtain an editor for the table with the given ID. This method does not lock the set of table definitions, so use * with caution. The resulting editor can be used to modify the table definition, but when completed the new {@link Table} * needs to be added back to this object via {@link #overwriteTable(Table)}. * * @param tableId the identifier of the table * @return the editor for the table, or null if there is no table with the specified ID */ public TableEditor editTable(TableId tableId) { Table table = forTable(tableId); return table == null ? null : table.edit(); }
/** * Get the {@link Table} meta-data for the table with the given identifier, if that table exists and is * included by the filter configuration * * @param id the table identifier; may be null * @return the current table definition, or null if there is no table with the given identifier, if the identifier is null, * or if the table has been excluded by the filters */ public Table tableFor(TableId id) { return tableFilter.isIncluded(id) ? tables.forTable(id) : null; }
private void createSchemaChangeEventsForTables(ChangeEventSourceContext sourceContext, SnapshotContext snapshotContext) throws Exception { for (TableId tableId : snapshotContext.capturedTables) { if (!sourceContext.isRunning()) { throw new InterruptedException("Interrupted while capturing schema of table " + tableId); } LOGGER.debug("Capturing structure of table {}", tableId); Table table = snapshotContext.tables.forTable(tableId); schema.applySchemaChange(getCreateTableEvent(snapshotContext, table)); } }
/** * Obtain an editor for the table with the given ID. This method does not lock or modify the set of table definitions, so use * with caution. The resulting editor can be used to modify the table definition, but when completed the new {@link Table} * needs to be added back to this object via {@link #overwriteTable(Table)}. * * @param tableId the identifier of the table * @return the editor for the table, or null if there is no table with the specified ID */ public TableEditor editOrCreateTable(TableId tableId) { Table table = forTable(tableId); return table == null ? Table.editor().tableId(tableId) : table.edit(); }
@Test public void shouldParseStatementsWithQuotedIdentifiers() { parser.parse(readFile("ddl/mysql-quoted.ddl"), tables); Testing.print(tables); assertThat(tables.size()).isEqualTo(4); assertThat(listener.total()).isEqualTo(10); assertThat(tables.forTable("connector_test_ro", null, "products")).isNotNull(); assertThat(tables.forTable("connector_test_ro", null, "products_on_hand")).isNotNull(); assertThat(tables.forTable("connector_test_ro", null, "customers")).isNotNull(); assertThat(tables.forTable("connector_test_ro", null, "orders")).isNotNull(); }
@Test @FixFor("DBZ-901") public void parseAlterTableTruncatedDefaulDateTime() { String sql = "CREATE TABLE TIME_TABLE (" + " A datetime(3) NOT NULL DEFAULT '0000-00-00 00:00:00.000'" + ");"; String alterSql = "ALTER TABLE TIME_TABLE ADD COLUMN B DATETIME(3) NOT NULL DEFAULT '1970-01-01 00:00:00';"; parser.parse(sql, tables); parser.parse(alterSql, tables); Table table = tables.forTable(new TableId(null, null, "TIME_TABLE")); assertThat(table.columnWithName("A").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0)))); assertThat(table.columnWithName("B").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0)))); }
@Override public void exitCopyCreateTable(MySqlParser.CopyCreateTableContext ctx) { TableId tableId = parser.parseQualifiedTableId(ctx.tableName(0).fullId()); TableId originalTableId = parser.parseQualifiedTableId(ctx.tableName(1).fullId()); Table original = parser.databaseTables().forTable(originalTableId); if (original != null) { parser.databaseTables().overwriteTable(tableId, original.columns(), original.primaryKeyColumnNames(), original.defaultCharsetName()); parser.signalCreateTable(tableId, ctx); } super.exitCopyCreateTable(ctx); }
@Test @FixFor("DBZ-688") public void parseGeomCollection() { String ddl = "CREATE TABLE geomtable (id int(11) PRIMARY KEY, collection GEOMCOLLECTION DEFAULT NULL)"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); assertThat(tables.forTable(new TableId(null, null, "geomtable"))).isNotNull(); }
@Test public void parseRealDefaultValue() { String sql = "CREATE TABLE REAL_TABLE (\n" + " A REAL NOT NULL DEFAULT 1,\n" + " B REAL NULL DEFAULT NULL \n" + ");"; parser.parse(sql, tables); Table table = tables.forTable(new TableId(null, null, "REAL_TABLE")); assertThat(table.columnWithName("A").defaultValue()).isEqualTo(1f); assertThat(table.columnWithName("B").defaultValue()).isEqualTo(null); }
@Test @FixFor("DBZ-428") public void shouldParseCreateTableWithTextType() { String ddl = "CREATE TABLE DBZ428 (" + "limtext TEXT(20), " + "unltext TEXT);"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table mytable = tables.forTable(new TableId(null, null, "DBZ428")); assertThat(mytable).isNotNull(); assertColumn(mytable, "unltext", "TEXT", Types.VARCHAR, -1, -1, true, false, false); assertColumn(mytable, "limtext", "TEXT", Types.VARCHAR, 20, -1, true, false, false); }
@FixFor("DBZ-419") @Test public void shouldParseCreateTableWithUnnamedPrimaryKeyConstraint() { final String ddl = "CREATE TABLE IF NOT EXISTS tables_exception (table_name VARCHAR(100), create_date TIMESTAMP DEFAULT NOW(), enabled INT(1), retention int(1) default 30, CONSTRAINT PRIMARY KEY (table_name));"; parser.parse(ddl, tables); Testing.print(tables); Table t = tables.forTable(new TableId(null, null, "tables_exception")); assertThat(t).isNotNull(); assertThat(t.primaryKeyColumnNames()).containsExactly("table_name"); assertThat(tables.size()).isEqualTo(1); }
@Test @FixFor("DBZ-474") public void shouldParseCreateTableStatementWithCollate() { String ddl = "CREATE TABLE c1 (pk INT PRIMARY KEY, v1 CHAR(36) NOT NULL COLLATE utf8_unicode_ci);"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table table = tables.forTable(new TableId(null, null, "c1")); assertThat(table).isNotNull(); assertColumn(table, "v1", "CHAR", Types.CHAR, 36, -1, false, false, false); Column column = table.columnWithName("v1"); assertThat(column.typeUsesCharset()).isTrue(); }
@Test public void shouldParseCreateTableStatementWithCharacterSetForColumns() { String ddl = "CREATE TABLE t ( col1 VARCHAR(25) CHARACTER SET greek ); "; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table t = tables.forTable(new TableId(null, null, "t")); assertThat(t).isNotNull(); assertThat(t.retrieveColumnNames()).containsExactly("col1"); assertThat(t.primaryKeyColumnNames()).isEmpty(); assertColumn(t, "col1", "VARCHAR", Types.VARCHAR, 25, -1, true, false, false); }
@Test public void parseNumericAndDecimalToDoubleDefaultValue() { String sql = "CREATE TABLE NUMERIC_DECIMAL_TABLE (\n" + " A NUMERIC NOT NULL DEFAULT 1.23,\n" + " B DECIMAL NOT NULL DEFAULT 2.321,\n" + " C NUMERIC NULL DEFAULT '12.678'\n" + ");"; parser.parse(sql, tables); Table table = tables.forTable(new TableId(null, null, "NUMERIC_DECIMAL_TABLE")); assertThat(table.columnWithName("A").defaultValue()).isEqualTo(1.23d); assertThat(table.columnWithName("B").defaultValue()).isEqualTo(2.321d); assertThat(table.columnWithName("C").defaultValue()).isEqualTo(12.678d); }
@Test public void parseTableWithPageChecksum() { String ddl = "CREATE TABLE t (id INT NOT NULL, PRIMARY KEY (`id`)) PAGE_CHECKSUM=1;" + "ALTER TABLE t PAGE_CHECKSUM=0;"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table t = tables.forTable(new TableId(null, null, "t")); assertThat(t).isNotNull(); assertThat(t.retrieveColumnNames()).containsExactly("id"); assertThat(t.primaryKeyColumnNames()).hasSize(1); assertColumn(t, "id", "INT", Types.INTEGER, -1, -1, false, false, false); }
@Test public void shouldParseCreateUserTable() { String ddl = "CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(32) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, plugin char(64) DEFAULT 'mysql_native_password' NOT NULL, authentication_string TEXT, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, password_last_changed timestamp NULL DEFAULT NULL, password_lifetime smallint unsigned NULL DEFAULT NULL, account_locked ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table foo = tables.forTable(new TableId(null, null, "user")); assertThat(foo).isNotNull(); assertThat(foo.retrieveColumnNames()).contains("Host", "User", "Select_priv"); assertColumn(foo, "Host", "CHAR BINARY", Types.BINARY, 60, -1, false, false, false); parser.parse("DROP TABLE user", tables); assertThat(tables.size()).isEqualTo(0); }
@Test @FixFor("DBZ-429") public void parseTableWithNegativeDefault() { String ddl = "CREATE TABLE t (id INT NOT NULL, myvalue INT DEFAULT -10, PRIMARY KEY (`id`));"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table t = tables.forTable(new TableId(null, null, "t")); assertThat(t).isNotNull(); assertThat(t.retrieveColumnNames()).containsExactly("id", "myvalue"); assertThat(t.primaryKeyColumnNames()).hasSize(1); assertColumn(t, "myvalue", "INT", Types.INTEGER, -1, -1, true, false, false); }
@FixFor("DBZ-160") @Test public void shouldParseCreateTableWithEnumDefault() { String ddl = "CREATE TABLE t ( c1 ENUM('a','b','c') NOT NULL DEFAULT 'b', c2 ENUM('a', 'b', 'c') NOT NULL DEFAULT 'a');"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table t = tables.forTable(new TableId(null, null, "t")); assertThat(t).isNotNull(); assertThat(t.retrieveColumnNames()).containsExactly("c1", "c2"); assertThat(t.primaryKeyColumnNames()).isEmpty(); assertColumn(t, "c1", "ENUM", Types.CHAR, 1, -1, false, false, false); assertColumn(t, "c2", "ENUM", Types.CHAR, 1, -1, false, false, false); }
@FixFor("DBZ-160") @Test public void shouldParseCreateTableWithBitDefault() { String ddl = "CREATE TABLE t ( c1 Bit(2) NOT NULL DEFAULT b'1', c2 Bit(2) NOT NULL);"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table t = tables.forTable(new TableId(null, null, "t")); assertThat(t).isNotNull(); assertThat(t.retrieveColumnNames()).containsExactly("c1", "c2"); assertThat(t.primaryKeyColumnNames()).isEmpty(); assertColumn(t, "c1", "BIT", Types.BIT, 2, -1, false, false, false); assertColumn(t, "c2", "BIT", Types.BIT, 2, -1, false, false, false); }
@Test public void parseDdlForDecAndFixed() { String ddl = "CREATE TABLE t ( c1 DEC(2) NOT NULL, c2 FIXED(1,0) NOT NULL, c3 NUMERIC(3) NOT NULL);"; parser.parse(ddl, tables); assertThat(tables.size()).isEqualTo(1); Table t = tables.forTable(new TableId(null, null, "t")); assertThat(t).isNotNull(); assertThat(t.retrieveColumnNames()).containsExactly("c1", "c2", "c3"); assertThat(t.primaryKeyColumnNames()).isEmpty(); assertColumn(t, "c1", "DEC", Types.DECIMAL, 2, 0, false, false, false); assertColumn(t, "c2", "FIXED", Types.DECIMAL, 1, 0, false, false, false); assertColumn(t, "c3", "NUMERIC", Types.NUMERIC, 3, 0, false, false, false); }