init
Some checks failed
Build Debezium (Push) / Update Dependencies (push) Has been cancelled
Build Debezium (Push) / Checkstyle and Formatting (push) Has been cancelled
Build Debezium (Push) / MongoDB ${{ matrix.version-mongo-server }} (5.0) (push) Has been cancelled
Build Debezium (Push) / MongoDB ${{ matrix.version-mongo-server }} (7.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci, 9.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-gtids, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-gtids, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-gtids, 9.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-percona, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-percona, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-percona, 9.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-ssl, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-ssl, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-ssl, 9.0) (push) Has been cancelled
Build Debezium (Push) / MariaDB - ${{ matrix.profile }} (mysql-ci) (push) Has been cancelled
Build Debezium (Push) / MariaDB - ${{ matrix.profile }} (mysql-ci-gtids) (push) Has been cancelled
Build Debezium (Push) / PostgreSQL - ${{ matrix.profile }} (assembly,postgres-12) (push) Has been cancelled
Build Debezium (Push) / PostgreSQL - ${{ matrix.profile }} (assembly,postgres-16,pgoutput-decoder) (push) Has been cancelled
Build Debezium (Push) / SQL Server (push) Has been cancelled
Build Debezium (Push) / Oracle (push) Has been cancelled
Build Debezium (Push) / Quarkus Outbox Extension (push) Has been cancelled
Build Debezium (Push) / REST Extension (push) Has been cancelled
Build Debezium (Push) / Schema Generator (push) Has been cancelled
Build Debezium (Push) / Testing Module (push) Has been cancelled
Build Debezium (Push) / Storage Module (push) Has been cancelled
Build Debezium (Push) / Cassandra (push) Has been cancelled
Build Debezium (Push) / Db2 (push) Has been cancelled
Build Debezium (Push) / Informix (push) Has been cancelled
Build Debezium (Push) / IBMi (push) Has been cancelled
Build Debezium (Push) / Vitess (push) Has been cancelled
Build Debezium (Push) / Spanner (push) Has been cancelled
Build Debezium (Push) / JDBC (push) Has been cancelled
Build Debezium (Push) / Debezium Server (push) Has been cancelled
Some checks failed
Build Debezium (Push) / Update Dependencies (push) Has been cancelled
Build Debezium (Push) / Checkstyle and Formatting (push) Has been cancelled
Build Debezium (Push) / MongoDB ${{ matrix.version-mongo-server }} (5.0) (push) Has been cancelled
Build Debezium (Push) / MongoDB ${{ matrix.version-mongo-server }} (7.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci, 9.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-gtids, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-gtids, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-gtids, 9.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-percona, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-percona, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-percona, 9.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-ssl, 8.0) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-ssl, 8.4) (push) Has been cancelled
Build Debezium (Push) / MySQL ${{ matrix.version-mysql-server }} - ${{ matrix.profile }} (mysql-ci-ssl, 9.0) (push) Has been cancelled
Build Debezium (Push) / MariaDB - ${{ matrix.profile }} (mysql-ci) (push) Has been cancelled
Build Debezium (Push) / MariaDB - ${{ matrix.profile }} (mysql-ci-gtids) (push) Has been cancelled
Build Debezium (Push) / PostgreSQL - ${{ matrix.profile }} (assembly,postgres-12) (push) Has been cancelled
Build Debezium (Push) / PostgreSQL - ${{ matrix.profile }} (assembly,postgres-16,pgoutput-decoder) (push) Has been cancelled
Build Debezium (Push) / SQL Server (push) Has been cancelled
Build Debezium (Push) / Oracle (push) Has been cancelled
Build Debezium (Push) / Quarkus Outbox Extension (push) Has been cancelled
Build Debezium (Push) / REST Extension (push) Has been cancelled
Build Debezium (Push) / Schema Generator (push) Has been cancelled
Build Debezium (Push) / Testing Module (push) Has been cancelled
Build Debezium (Push) / Storage Module (push) Has been cancelled
Build Debezium (Push) / Cassandra (push) Has been cancelled
Build Debezium (Push) / Db2 (push) Has been cancelled
Build Debezium (Push) / Informix (push) Has been cancelled
Build Debezium (Push) / IBMi (push) Has been cancelled
Build Debezium (Push) / Vitess (push) Has been cancelled
Build Debezium (Push) / Spanner (push) Has been cancelled
Build Debezium (Push) / JDBC (push) Has been cancelled
Build Debezium (Push) / Debezium Server (push) Has been cancelled
This commit is contained in:
parent
23b8aaa56f
commit
3547a160b1
@ -1,1044 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<parent>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-parent</artifactId>
|
|
||||||
<version>3.0.0-SNAPSHOT</version>
|
|
||||||
<relativePath>../debezium-parent/pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>debezium-connector-mariadb</artifactId>
|
|
||||||
<name>Debezium Connector for MariaDB</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<!-- Runtime dependencies -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-connector-binlog</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.kafka</groupId>
|
|
||||||
<artifactId>connect-api</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mariadb.jdbc</groupId>
|
|
||||||
<artifactId>mariadb-java-client</artifactId>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Testing dependencies -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-connector-binlog</artifactId>
|
|
||||||
<type>test-jar</type>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-core</artifactId>
|
|
||||||
<type>test-jar</type>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-embedded</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-embedded</artifactId>
|
|
||||||
<type>test-jar</type>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-testing-testcontainers</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.junit.platform</groupId>
|
|
||||||
<artifactId>junit-platform-launcher</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.qos.logback</groupId>
|
|
||||||
<artifactId>logback-classic</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>mil.nga</groupId>
|
|
||||||
<artifactId>wkb</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-core</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.assertj</groupId>
|
|
||||||
<artifactId>assertj-core</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.awaitility</groupId>
|
|
||||||
<artifactId>awaitility</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.confluent</groupId>
|
|
||||||
<artifactId>kafka-connect-avro-converter</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.apicurio</groupId>
|
|
||||||
<artifactId>apicurio-registry-utils-converter</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>slf4j-jboss-logmanager</artifactId>
|
|
||||||
<groupId>org.jboss.slf4j</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.testcontainers</groupId>
|
|
||||||
<artifactId>testcontainers</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.testcontainers</groupId>
|
|
||||||
<artifactId>mariadb</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.rest-assured</groupId>
|
|
||||||
<artifactId>rest-assured</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- Used for unit testing with Kafka -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.kafka</groupId>
|
|
||||||
<artifactId>kafka_${version.kafka.scala}</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<!--
|
|
||||||
Specify the properties for the various Docker containers.
|
|
||||||
-->
|
|
||||||
<mariadb.server.image.source>mariadb</mariadb.server.image.source>
|
|
||||||
<version.mariadb.server>11.4.3</version.mariadb.server>
|
|
||||||
<mariadb.user>mysqluser</mariadb.user>
|
|
||||||
<mariadb.password>mysqlpw</mariadb.password>
|
|
||||||
<mariadb.replica.user>mysqlreplica</mariadb.replica.user>
|
|
||||||
<mariadb.replica.password>mysqlpw</mariadb.replica.password>
|
|
||||||
<mariadb.port>3306</mariadb.port>
|
|
||||||
<mariadb.percona.port>3306</mariadb.percona.port>
|
|
||||||
<mariadb.gtid.port>3306</mariadb.gtid.port>
|
|
||||||
<mariadb.gtid.replica.port>3306</mariadb.gtid.replica.port>
|
|
||||||
<mariadb.ssl.port>3306</mariadb.ssl.port>
|
|
||||||
<mariadb.replica.port>3306</mariadb.replica.port> <!-- by default use primary as 'replica' -->
|
|
||||||
<mariadb.init.timeout>60000</mariadb.init.timeout> <!-- 60 seconds -->
|
|
||||||
<apicurio.port>8080</apicurio.port>
|
|
||||||
<apicurio.init.timeout>60000</apicurio.init.timeout> <!-- 60 seconds -->
|
|
||||||
<mariadb.replica.fileset.path>${project.basedir}/src/test/docker/init-replica</mariadb.replica.fileset.path>
|
|
||||||
<!--
|
|
||||||
By default, we should use the docker image maintained by the MariaDB team. This property is changed with different profiles.
|
|
||||||
However, we run one container with GTIDs and one without.
|
|
||||||
-->
|
|
||||||
<docker.dbs>debezium/mariadb-server-test-database</docker.dbs>
|
|
||||||
<docker.filter>${docker.dbs}</docker.filter>
|
|
||||||
<docker.skip>false</docker.skip>
|
|
||||||
<docker.initimage>rm -f /etc/localtime; ln -s /usr/share/zoneinfo/Pacific/Samoa /etc/localtime</docker.initimage>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>io.fabric8</groupId>
|
|
||||||
<artifactId>docker-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<watchInterval>500</watchInterval>
|
|
||||||
<logDate>default</logDate>
|
|
||||||
<verbose>true</verbose>
|
|
||||||
<imagePullPolicy>IfNotPresent</imagePullPolicy>
|
|
||||||
<images>
|
|
||||||
<!--
|
|
||||||
Images based on "${mariadb.server.image.source}" Docker image
|
|
||||||
-->
|
|
||||||
<image>
|
|
||||||
<!-- A Docker image using a partial MariaDB installation maintained by MariaDB team. -->
|
|
||||||
<name>debezium/mariadb-server-test-database</name>
|
|
||||||
<run>
|
|
||||||
<namingStrategy>none</namingStrategy>
|
|
||||||
<env>
|
|
||||||
<MARIADB_ROOT_PASSWORD>debezium-rocks</MARIADB_ROOT_PASSWORD>
|
|
||||||
<MARIADB_DATABASE>mysql</MARIADB_DATABASE> <!-- database created upon init -->
|
|
||||||
<MARIADB_USER>${mariadb.user}</MARIADB_USER>
|
|
||||||
<MARIADB_PASSWORD>${mariadb.password}</MARIADB_PASSWORD>
|
|
||||||
</env>
|
|
||||||
<ports>
|
|
||||||
<port>${mariadb.port}:3306</port>
|
|
||||||
</ports>
|
|
||||||
<log>
|
|
||||||
<prefix>mariadb</prefix>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
<color>yellow</color>
|
|
||||||
</log>
|
|
||||||
<wait>
|
|
||||||
<log>(MariaDB) init process done. Ready for start up.(?s)(.*)(mariadbd): ready for connections.</log>
|
|
||||||
<time>${mariadb.init.timeout}</time>
|
|
||||||
</wait>
|
|
||||||
</run>
|
|
||||||
<build>
|
|
||||||
<from>${mariadb.server.image.source}:${version.mariadb.server}</from>
|
|
||||||
<runCmds>
|
|
||||||
<run>${docker.initimage}</run>
|
|
||||||
</runCmds>
|
|
||||||
<assembly>
|
|
||||||
<inline>
|
|
||||||
<fileSets>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/server</directory>
|
|
||||||
<includes>
|
|
||||||
<include>my.cnf</include>
|
|
||||||
</includes>
|
|
||||||
<outputDirectory>etc/mysql</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/init</directory>
|
|
||||||
<outputDirectory>docker-entrypoint-initdb.d</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
</fileSets>
|
|
||||||
</inline>
|
|
||||||
<targetDir>/</targetDir>
|
|
||||||
</assembly>
|
|
||||||
</build>
|
|
||||||
<external>
|
|
||||||
<type>properties</type>
|
|
||||||
<mode>override</mode>
|
|
||||||
</external>
|
|
||||||
</image>
|
|
||||||
<image>
|
|
||||||
<!-- A Docker image using a partial MariaDB installation maintained by MariaDB team
|
|
||||||
that enable MariaDB ssl connection -->
|
|
||||||
<name>debezium/mariadb-server-test-database-ssl</name>
|
|
||||||
<run>
|
|
||||||
<namingStrategy>none</namingStrategy>
|
|
||||||
<env>
|
|
||||||
<MARIADB_ROOT_PASSWORD>debezium-rocks</MARIADB_ROOT_PASSWORD>
|
|
||||||
<MARIADB_DATABASE>mysql</MARIADB_DATABASE> <!-- database created upon init -->
|
|
||||||
<MARIADB_USER>${mariadb.user}</MARIADB_USER>
|
|
||||||
<MARIADB_PASSWORD>${mariadb.password}</MARIADB_PASSWORD>
|
|
||||||
</env>
|
|
||||||
<ports>
|
|
||||||
<port>${mariadb.ssl.port}:3306</port>
|
|
||||||
</ports>
|
|
||||||
<volumes>
|
|
||||||
<bind>
|
|
||||||
<volume>${project.basedir}/src/test/resources/ssl-certs:/etc/certs</volume>
|
|
||||||
</bind>
|
|
||||||
</volumes>
|
|
||||||
<log>
|
|
||||||
<prefix>mariadb</prefix>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
<color>yellow</color>
|
|
||||||
</log>
|
|
||||||
<wait>
|
|
||||||
<log>(MariaDB) init process done. Ready for start up.(?s)(.*)(mariadbd): ready for connections.</log>
|
|
||||||
<time>${mariadb.init.timeout}</time>
|
|
||||||
</wait>
|
|
||||||
</run>
|
|
||||||
<build>
|
|
||||||
<from>${mariadb.server.image.source}:${version.mariadb.server}</from>
|
|
||||||
<runCmds>
|
|
||||||
<run>${docker.initimage}</run>
|
|
||||||
</runCmds>
|
|
||||||
<assembly>
|
|
||||||
<inline>
|
|
||||||
<fileSets>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/server-ssl</directory>
|
|
||||||
<includes>
|
|
||||||
<include>my.cnf</include>
|
|
||||||
</includes>
|
|
||||||
<outputDirectory>etc/mysql</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/init</directory>
|
|
||||||
<outputDirectory>docker-entrypoint-initdb.d</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/init-ssl</directory>
|
|
||||||
<outputDirectory>docker-entrypoint-initdb.d</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
</fileSets>
|
|
||||||
</inline>
|
|
||||||
<targetDir>/</targetDir>
|
|
||||||
</assembly>
|
|
||||||
</build>
|
|
||||||
<external>
|
|
||||||
<type>properties</type>
|
|
||||||
<mode>override</mode>
|
|
||||||
</external>
|
|
||||||
</image>
|
|
||||||
<image>
|
|
||||||
<!-- A Docker image using a partial MariaDB installation maintained by MariaDB team. -->
|
|
||||||
<name>debezium/mariadb-server-gtids-test-database</name>
|
|
||||||
<alias>database-gtids</alias>
|
|
||||||
<run>
|
|
||||||
<namingStrategy>alias</namingStrategy>
|
|
||||||
<env>
|
|
||||||
<MARIADB_ROOT_PASSWORD>debezium-rocks</MARIADB_ROOT_PASSWORD>
|
|
||||||
<MARIADB_DATABASE>mysql</MARIADB_DATABASE> <!-- database created upon init -->
|
|
||||||
<MARIADB_USER>${mariadb.user}</MARIADB_USER>
|
|
||||||
<MARIADB_PASSWORD>${mariadb.password}</MARIADB_PASSWORD>
|
|
||||||
</env>
|
|
||||||
<ports>
|
|
||||||
<port>${mariadb.gtid.port}:3306</port>
|
|
||||||
</ports>
|
|
||||||
<log>
|
|
||||||
<prefix>mariadb-gtids</prefix>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
<color>cyan</color>
|
|
||||||
</log>
|
|
||||||
<wait>
|
|
||||||
<log>(MariaDB) init process done. Ready for start up.(?s)(.*)(mariadbd): ready for connections.</log>
|
|
||||||
<time>${mariadb.init.timeout}</time>
|
|
||||||
</wait>
|
|
||||||
</run>
|
|
||||||
<build>
|
|
||||||
<from>${mariadb.server.image.source}:${version.mariadb.server}</from>
|
|
||||||
<runCmds>
|
|
||||||
<run>${docker.initimage}</run>
|
|
||||||
</runCmds>
|
|
||||||
<assembly>
|
|
||||||
<inline>
|
|
||||||
<fileSets>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/server-gtids</directory>
|
|
||||||
<includes>
|
|
||||||
<include>my.cnf</include>
|
|
||||||
</includes>
|
|
||||||
<outputDirectory>etc/mysql</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/init</directory>
|
|
||||||
<outputDirectory>docker-entrypoint-initdb.d</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
</fileSets>
|
|
||||||
</inline>
|
|
||||||
<targetDir>/</targetDir>
|
|
||||||
</assembly>
|
|
||||||
</build>
|
|
||||||
<external>
|
|
||||||
<type>properties</type>
|
|
||||||
<mode>override</mode>
|
|
||||||
</external>
|
|
||||||
</image>
|
|
||||||
<image>
|
|
||||||
<!--
|
|
||||||
A Docker image using a MariaDB installation maintained by MariaDB team
|
|
||||||
that is a replica of `debezium/mariadb-server-gtids-test-database`
|
|
||||||
-->
|
|
||||||
<name>debezium/mariadb-server-gtids-test-database-replica</name>
|
|
||||||
<run>
|
|
||||||
<namingStrategy>none</namingStrategy>
|
|
||||||
<env>
|
|
||||||
<MARIADB_ROOT_PASSWORD>debezium-rocks</MARIADB_ROOT_PASSWORD>
|
|
||||||
<MARIADB_USER>${mariadb.replica.user}</MARIADB_USER>
|
|
||||||
<MARIADB_PASSWORD>${mariadb.replica.password}</MARIADB_PASSWORD>
|
|
||||||
</env>
|
|
||||||
<links>
|
|
||||||
<link>database-gtids</link>
|
|
||||||
</links>
|
|
||||||
<ports>
|
|
||||||
<port>${mariadb.gtid.replica.port}:3306</port>
|
|
||||||
</ports>
|
|
||||||
<log>
|
|
||||||
<prefix>mariadb-gtids-replica</prefix>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
<color>magenta</color>
|
|
||||||
</log>
|
|
||||||
<wait>
|
|
||||||
<log>(MariaDB) init process done. Ready for start up.(?s)(.*)(mariadbd): ready for connections.</log>
|
|
||||||
<time>${mariadb.init.timeout}</time>
|
|
||||||
</wait>
|
|
||||||
</run>
|
|
||||||
<build>
|
|
||||||
<from>${mariadb.server.image.source}:${version.mariadb.server}</from>
|
|
||||||
<runCmds>
|
|
||||||
<run>${docker.initimage}</run>
|
|
||||||
</runCmds>
|
|
||||||
<assembly>
|
|
||||||
<inline>
|
|
||||||
<fileSets>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.basedir}/src/test/docker/server-replica</directory>
|
|
||||||
<includes>
|
|
||||||
<include>my.cnf</include>
|
|
||||||
</includes>
|
|
||||||
<outputDirectory>etc/mysql</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${mariadb.replica.fileset.path}</directory>
|
|
||||||
<outputDirectory>docker-entrypoint-initdb.d</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
</fileSets>
|
|
||||||
</inline>
|
|
||||||
<targetDir>/</targetDir>
|
|
||||||
</assembly>
|
|
||||||
</build>
|
|
||||||
<external>
|
|
||||||
<type>properties</type>
|
|
||||||
<mode>override</mode>
|
|
||||||
</external>
|
|
||||||
</image>
|
|
||||||
<image>
|
|
||||||
<name>apicurio/apicurio-registry-mem:${version.apicurio}</name>
|
|
||||||
<run>
|
|
||||||
<namingStrategy>none</namingStrategy>
|
|
||||||
<ports>
|
|
||||||
<port>${apicurio.port}:8080</port>
|
|
||||||
</ports>
|
|
||||||
<log>
|
|
||||||
<prefix>apicurio</prefix>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
<color>blue</color>
|
|
||||||
</log>
|
|
||||||
<wait>
|
|
||||||
<log>.*apicurio-registry-app.*started in.*</log>
|
|
||||||
<time>${apicurio.init.timeout}</time>
|
|
||||||
</wait>
|
|
||||||
</run>
|
|
||||||
</image>
|
|
||||||
</images>
|
|
||||||
</configuration>
|
|
||||||
<!--
|
|
||||||
Connect this plugin to the maven lifecycle around the integration-test phase:
|
|
||||||
start the container in pre-integration-test and stop it in post-integration-test.
|
|
||||||
-->
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>start</id>
|
|
||||||
<phase>pre-integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>build</goal>
|
|
||||||
<goal>start</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>stop</id>
|
|
||||||
<phase>post-integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>stop</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<!--
|
|
||||||
Unlike surefire, the failsafe plugin ensures 'post-integration-test' phase always runs, even
|
|
||||||
when there are failed integration tests. We rely upon this to always shut down the Docker container
|
|
||||||
after the integration tests (defined as '*IT.java') are run.
|
|
||||||
-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<skipTests>${skipITs}</skipTests>
|
|
||||||
<enableAssertions>true</enableAssertions>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- Make these available to the tests via system properties -->
|
|
||||||
<database.hostname>${docker.host.address}</database.hostname>
|
|
||||||
<database.port>${mariadb.port}</database.port>
|
|
||||||
<database.user>${mariadb.user}</database.user>
|
|
||||||
<database.password>${mariadb.password}</database.password>
|
|
||||||
<database.replica.hostname>${docker.host.address}</database.replica.hostname>
|
|
||||||
<database.replica.port>${mariadb.replica.port}</database.replica.port>
|
|
||||||
<!-- Specifies which driver to use for the tests -->
|
|
||||||
<skipLongRunningTests>${skipLongRunningTests}</skipLongRunningTests>
|
|
||||||
<database.ssl.mode>disabled</database.ssl.mode>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
<runOrder>${runOrder}</runOrder>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>integration-test</id>
|
|
||||||
<goals>
|
|
||||||
<goal>integration-test</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>verify</id>
|
|
||||||
<goals>
|
|
||||||
<goal>verify</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-schema-generator</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>generate-connector-metadata</id>
|
|
||||||
<goals>
|
|
||||||
<goal>generate-api-spec</goal>
|
|
||||||
</goals>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.outputDirectory}/META-INF/resources/</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
<resources>
|
|
||||||
<!-- Apply the properties set in the POM to the resource files -->
|
|
||||||
<resource>
|
|
||||||
<filtering>true</filtering>
|
|
||||||
<directory>src/main/resources</directory>
|
|
||||||
<includes>
|
|
||||||
<include>*</include>
|
|
||||||
<include>**/*</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
<testResources>
|
|
||||||
<testResource>
|
|
||||||
<directory>src/test/resources</directory>
|
|
||||||
<filtering>false</filtering>
|
|
||||||
<includes>
|
|
||||||
<include>*</include>
|
|
||||||
<include>**/*</include>
|
|
||||||
</includes>
|
|
||||||
</testResource>
|
|
||||||
</testResources>
|
|
||||||
</build>
|
|
||||||
<!--
|
|
||||||
Define several useful profiles
|
|
||||||
-->
|
|
||||||
<profiles>
|
|
||||||
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
This assembly profile is used during official builds. In addition to
|
|
||||||
compiling, and running the unit and integration tests like the non-assembly
|
|
||||||
profiles, this profile creates additional (like the connector plugin archives),
|
|
||||||
starts up all three Docker containers (normal MariaDB, MariaDB+GTIDs, and alt-MariaDB)
|
|
||||||
and runs the integration tests against each of them.
|
|
||||||
|
|
||||||
To use, specify "-Passembly" on the Maven command line.
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
|
||||||
<profile>
|
|
||||||
<id>assembly</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<!-- Run multiple images at the same time, but use different ports for all MariaDB servers -->
|
|
||||||
<docker.dbs>
|
|
||||||
debezium/mariadb-server-test-database,debezium/mariadb-server-gtids-test-database,debezium/mariadb-server-gtids-test-database-replica,debezium/mariadb-server-test-database-ssl
|
|
||||||
</docker.dbs>
|
|
||||||
<mariadb.port>4301</mariadb.port>
|
|
||||||
<mariadb.gtid.port>4302</mariadb.gtid.port>
|
|
||||||
<mariadb.gtid.replica.port>4303</mariadb.gtid.replica.port>
|
|
||||||
<mariadb.percona.port>4304</mariadb.percona.port>
|
|
||||||
<mariadb.ssl.port>4305</mariadb.ssl.port>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-assembly-descriptors</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>default</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
|
||||||
<attach>true</attach> <!-- we want attach & deploy these to Maven -->
|
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>${assembly.descriptor}</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
<tarLongFileMode>posix</tarLongFileMode>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<!--
|
|
||||||
Override the failsafe plugin to run the integration tests for each set of databases.
|
|
||||||
But make sure each database server is used only once ...
|
|
||||||
-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
|
||||||
<version>${version.failsafe.plugin}</version>
|
|
||||||
<configuration>
|
|
||||||
<skipTests>${skipITs}</skipTests>
|
|
||||||
<enableAssertions>true</enableAssertions>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- Make these available to the tests via system properties -->
|
|
||||||
<database.hostname>${docker.host.address}</database.hostname>
|
|
||||||
<database.user>${mariadb.user}</database.user>
|
|
||||||
<database.password>${mariadb.password}</database.password>
|
|
||||||
<database.replica.hostname>${docker.host.address}</database.replica.hostname>
|
|
||||||
<database.replica.user>${mariadb.replica.user}</database.replica.user>
|
|
||||||
<database.replica.password>${mariadb.replica.password}</database.replica.password>
|
|
||||||
<database.port>${mariadb.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.port}</database.replica.port>
|
|
||||||
<database.ssl.mode>disabled</database.ssl.mode>
|
|
||||||
<!-- Specifies which driver to use for the tests -->
|
|
||||||
<skipLongRunningTests>false</skipLongRunningTests>
|
|
||||||
<isAssemblyProfileActive>true</isAssemblyProfileActive>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
<runOrder>${runOrder}</runOrder>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<!-- First run the integration tests with the non-GTID server alone -->
|
|
||||||
<execution>
|
|
||||||
<id>integration-test-mariadb</id>
|
|
||||||
<goals>
|
|
||||||
<goal>integration-test</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- same port for both, since we're only running one server -->
|
|
||||||
<database.port>${mariadb.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.port}</database.replica.port>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<!-- Then run the integration tests with the GTID server + replica server -->
|
|
||||||
<execution>
|
|
||||||
<id>integration-test-mariadb-gtids-with-replica</id>
|
|
||||||
<goals>
|
|
||||||
<goal>integration-test</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<database.port>${mariadb.gtid.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.gtid.replica.port}</database.replica.port>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<!-- SSL -->
|
|
||||||
<execution>
|
|
||||||
<id>integration-test-ssl</id>
|
|
||||||
<goals>
|
|
||||||
<goal>integration-test</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<database.ssl.mode>verify_ca</database.ssl.mode>
|
|
||||||
<database.ssl.truststore>${project.basedir}/src/test/resources/ssl/truststore</database.ssl.truststore>
|
|
||||||
<database.ssl.truststore.password>debezium</database.ssl.truststore.password>
|
|
||||||
<database.ssl.keystore>${project.basedir}/src/test/resources/ssl/keystore</database.ssl.keystore>
|
|
||||||
<database.ssl.keystore.password>debezium</database.ssl.keystore.password>
|
|
||||||
<!-- same port for both, since we're only running one server -->
|
|
||||||
<database.port>${mariadb.ssl.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.ssl.port}</database.replica.port>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>verify</id>
|
|
||||||
<goals>
|
|
||||||
<goal>verify</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Do not perform any Docker-related functionality
|
|
||||||
To use, specify "-DskipITs" on the Maven command line.
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
|
||||||
<profile>
|
|
||||||
<id>skip-integration-tests</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
<property>
|
|
||||||
<name>skipITs</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<docker.skip>true</docker.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>quick</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
<property>
|
|
||||||
<name>quick</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<skipITs>true</skipITs>
|
|
||||||
<docker.skip>true</docker.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Use the alternative Docker image for MariaDB.
|
|
||||||
To use, specify "-Dmariadb-gtids" or -Pmariadb-gtids on the Maven command line.
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
|
||||||
<profile>
|
|
||||||
<id>mariadb-gtids</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
<property>
|
|
||||||
<name>mariadb-gtids</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<!-- Docker properties -->
|
|
||||||
<docker.dbs>debezium/mariadb-server-gtids-test-database</docker.dbs>
|
|
||||||
<!-- Integration test properties -->
|
|
||||||
<database.port>${mariadb.gtid.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.gtid.port}</database.replica.port>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Use the Docker image for a MariaDB replica of another MariaDB server
|
|
||||||
configured to use GTIDs. To use, specify "-Dmariadb-replica"
|
|
||||||
or -Pmariadb-replica on the Maven command line.
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
<id>mariadb-replica</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
<property>
|
|
||||||
<name>mariadb-replica</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<!-- Docker properties -->
|
|
||||||
<mariadb.gtid.port>3306</mariadb.gtid.port>
|
|
||||||
<mariadb.gtid.replica.port>4306</mariadb.gtid.replica.port>
|
|
||||||
<docker.dbs>debezium/mariadb-server-gtids-test-database,debezium/mariadb-server-gtids-test-database-replica</docker.dbs>
|
|
||||||
<!-- Integration test properties -->
|
|
||||||
<database.port>${mariadb.gtid.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.gtid.replica.port}</database.replica.port>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Use the alternative Docker image for MariaDB.
|
|
||||||
To use, specify "-Dmariadb-ssl" or -Pmariadb-ssl on the Maven command line.
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
|
||||||
<profile>
|
|
||||||
<id>mariadb-ssl</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
<property>
|
|
||||||
<name>mariadb-ssl</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<!-- Docker properties -->
|
|
||||||
<docker.dbs>debezium/mariadb-server-test-database-ssl</docker.dbs>
|
|
||||||
<!-- Integration test properties -->
|
|
||||||
<database.port>${mariadb.ssl.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.ssl.port}</database.replica.port>
|
|
||||||
<docker.initimage>rm -f /etc/localtime; ln -s /usr/share/zoneinfo/Pacific/Pago_Pago /etc/localtime</docker.initimage>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>apicurio</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
<property>
|
|
||||||
<name>apicurio</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<use.apicurio>true</use.apicurio>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<properties>
|
|
||||||
<docker.filter>${docker.dbs},apicurio/apicurio-registry-mem:${version.apicurio}</docker.filter>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<!-- CI configurations, used for parallel execution on GH actions -->
|
|
||||||
|
|
||||||
<!-- Runs tests only with standalone -->
|
|
||||||
<profile>
|
|
||||||
<id>mariadb-ci</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<docker.dbs>debezium/mariadb-server-test-database</docker.dbs>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-assembly-descriptors</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>default</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
|
||||||
<attach>true</attach> <!-- we want attach & deploy these to Maven -->
|
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>${assembly.descriptor}</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
<tarLongFileMode>posix</tarLongFileMode>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
|
||||||
<version>${version.failsafe.plugin}</version>
|
|
||||||
<configuration>
|
|
||||||
<skipTests>${skipITs}</skipTests>
|
|
||||||
<enableAssertions>true</enableAssertions>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- Make these available to the tests via system properties -->
|
|
||||||
<database.hostname>${docker.host.address}</database.hostname>
|
|
||||||
<database.user>${mariadb.user}</database.user>
|
|
||||||
<database.password>${mariadb.password}</database.password>
|
|
||||||
<database.replica.hostname>${docker.host.address}</database.replica.hostname>
|
|
||||||
<database.replica.user>${mariadb.replica.user}</database.replica.user>
|
|
||||||
<database.replica.password>${mariadb.replica.password}</database.replica.password>
|
|
||||||
<database.port>${mariadb.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.port}</database.replica.port>
|
|
||||||
<database.ssl.mode>disabled</database.ssl.mode>
|
|
||||||
<!-- Specifies which driver to use for the tests -->
|
|
||||||
<skipLongRunningTests>false</skipLongRunningTests>
|
|
||||||
<isAssemblyProfileActive>true</isAssemblyProfileActive>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
<runOrder>${runOrder}</runOrder>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>integration-test-mariadb</id>
|
|
||||||
<goals>
|
|
||||||
<goal>integration-test</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<!-- Runs tests only with GTID setup -->
|
|
||||||
<profile>
|
|
||||||
<id>mariadb-ci-gtids</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<docker.dbs>debezium/mariadb-server-gtids-test-database,debezium/mariadb-server-gtids-test-database-replica</docker.dbs>
|
|
||||||
<mariadb.gtid.port>4302</mariadb.gtid.port>
|
|
||||||
<mariadb.gtid.replica.port>4303</mariadb.gtid.replica.port>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-assembly-descriptors</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>default</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
|
||||||
<attach>true</attach> <!-- we want attach & deploy these to Maven -->
|
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>${assembly.descriptor}</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
<tarLongFileMode>posix</tarLongFileMode>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
|
||||||
<version>${version.failsafe.plugin}</version>
|
|
||||||
<configuration>
|
|
||||||
<skipTests>${skipITs}</skipTests>
|
|
||||||
<enableAssertions>true</enableAssertions>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- Make these available to the tests via system properties -->
|
|
||||||
<database.hostname>${docker.host.address}</database.hostname>
|
|
||||||
<database.user>${mariadb.user}</database.user>
|
|
||||||
<database.password>${mariadb.password}</database.password>
|
|
||||||
<database.replica.hostname>${docker.host.address}</database.replica.hostname>
|
|
||||||
<database.replica.user>${mariadb.replica.user}</database.replica.user>
|
|
||||||
<database.replica.password>${mariadb.replica.password}</database.replica.password>
|
|
||||||
<database.port>${mariadb.gtid.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.gtid.replica.port}</database.replica.port>
|
|
||||||
<database.ssl.mode>disabled</database.ssl.mode>
|
|
||||||
<!-- Specifies which driver to use for the tests -->
|
|
||||||
<skipLongRunningTests>false</skipLongRunningTests>
|
|
||||||
<isAssemblyProfileActive>true</isAssemblyProfileActive>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
<runOrder>${runOrder}</runOrder>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>integration-test-mariadb-gtids-with-replica</id>
|
|
||||||
<goals>
|
|
||||||
<goal>integration-test</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<!-- Runs tests only with SSL setup -->
|
|
||||||
<profile>
|
|
||||||
<id>mariadb-ci-ssl</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>false</activeByDefault>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<docker.dbs>debezium/mariadb-server-test-database-ssl</docker.dbs>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.debezium</groupId>
|
|
||||||
<artifactId>debezium-assembly-descriptors</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>default</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
|
||||||
<attach>true</attach> <!-- we want attach & deploy these to Maven -->
|
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>${assembly.descriptor}</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
<tarLongFileMode>posix</tarLongFileMode>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
|
||||||
<version>${version.failsafe.plugin}</version>
|
|
||||||
<configuration>
|
|
||||||
<skipTests>${skipITs}</skipTests>
|
|
||||||
<enableAssertions>true</enableAssertions>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<!-- Make these available to the tests via system properties -->
|
|
||||||
<database.hostname>${docker.host.address}</database.hostname>
|
|
||||||
<database.user>${mariadb.user}</database.user>
|
|
||||||
<database.password>${mariadb.password}</database.password>
|
|
||||||
<database.replica.hostname>${docker.host.address}</database.replica.hostname>
|
|
||||||
<database.replica.user>${mariadb.replica.user}</database.replica.user>
|
|
||||||
<database.replica.password>${mariadb.replica.password}</database.replica.password>
|
|
||||||
<database.port>${mariadb.port}</database.port>
|
|
||||||
<database.replica.port>${mariadb.port}</database.replica.port>
|
|
||||||
<database.ssl.mode>verify_ca</database.ssl.mode>
|
|
||||||
<!-- Specifies which driver to use for the tests -->
|
|
||||||
<skipLongRunningTests>false</skipLongRunningTests>
|
|
||||||
<isAssemblyProfileActive>true</isAssemblyProfileActive>
|
|
||||||
<database.ssl.truststore>${project.basedir}/src/test/resources/ssl/truststore</database.ssl.truststore>
|
|
||||||
<database.ssl.truststore.password>debezium</database.ssl.truststore.password>
|
|
||||||
<database.ssl.keystore>${project.basedir}/src/test/resources/ssl/keystore</database.ssl.keystore>
|
|
||||||
<database.ssl.keystore.password>debezium</database.ssl.keystore.password>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
<runOrder>${runOrder}</runOrder>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>integration-test-ssl</id>
|
|
||||||
<goals>
|
|
||||||
<goal>integration-test</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
</profiles>
|
|
||||||
</project>
|
|
@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.apache.kafka.connect.source.SourceRecord;
|
|
||||||
|
|
||||||
import io.debezium.connector.base.ChangeEventQueue;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogConnectorConnection;
|
|
||||||
import io.debezium.connector.mariadb.metrics.MariaDbSnapshotChangeEventSourceMetrics;
|
|
||||||
import io.debezium.connector.mariadb.metrics.MariaDbStreamingChangeEventSourceMetrics;
|
|
||||||
import io.debezium.jdbc.MainConnectionProvidingConnectionFactory;
|
|
||||||
import io.debezium.pipeline.DataChangeEvent;
|
|
||||||
import io.debezium.pipeline.ErrorHandler;
|
|
||||||
import io.debezium.pipeline.EventDispatcher;
|
|
||||||
import io.debezium.pipeline.notification.NotificationService;
|
|
||||||
import io.debezium.pipeline.source.snapshot.incremental.IncrementalSnapshotChangeEventSource;
|
|
||||||
import io.debezium.pipeline.source.snapshot.incremental.SignalBasedIncrementalSnapshotChangeEventSource;
|
|
||||||
import io.debezium.pipeline.source.spi.ChangeEventSourceFactory;
|
|
||||||
import io.debezium.pipeline.source.spi.DataChangeEventListener;
|
|
||||||
import io.debezium.pipeline.source.spi.SnapshotChangeEventSource;
|
|
||||||
import io.debezium.pipeline.source.spi.SnapshotProgressListener;
|
|
||||||
import io.debezium.pipeline.source.spi.StreamingChangeEventSource;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.snapshot.SnapshotterService;
|
|
||||||
import io.debezium.spi.schema.DataCollectionId;
|
|
||||||
import io.debezium.util.Clock;
|
|
||||||
import io.debezium.util.Strings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbChangeEventSourceFactory implements ChangeEventSourceFactory<MariaDbPartition, MariaDbOffsetContext> {
|
|
||||||
|
|
||||||
private final MariaDbConnectorConfig configuration;
|
|
||||||
private final MainConnectionProvidingConnectionFactory<BinlogConnectorConnection> connectionFactory;
|
|
||||||
private final ErrorHandler errorHandler;
|
|
||||||
private final EventDispatcher<MariaDbPartition, TableId> dispatcher;
|
|
||||||
private final Clock clock;
|
|
||||||
private final MariaDbTaskContext taskContext;
|
|
||||||
private final MariaDbStreamingChangeEventSourceMetrics streamingMetrics;
|
|
||||||
private final MariaDbDatabaseSchema schema;
|
|
||||||
// Snapshot requires buffering to modify the last record in the snapshot as sometimes it is
|
|
||||||
// impossible to detect it till the snapshot is ended. Mainly when the last snapshotted table is empty.
|
|
||||||
// Based on the DBZ-3113 the code can change in the future, and it will be handled in the core shared code.
|
|
||||||
private final ChangeEventQueue<DataChangeEvent> queue;
|
|
||||||
private final SnapshotterService snapshotterService;
|
|
||||||
|
|
||||||
public MariaDbChangeEventSourceFactory(MariaDbConnectorConfig configuration,
|
|
||||||
MainConnectionProvidingConnectionFactory<BinlogConnectorConnection> connectionFactory,
|
|
||||||
ErrorHandler errorHandler,
|
|
||||||
EventDispatcher<MariaDbPartition, TableId> dispatcher,
|
|
||||||
Clock clock,
|
|
||||||
MariaDbDatabaseSchema schema,
|
|
||||||
MariaDbTaskContext taskContext,
|
|
||||||
MariaDbStreamingChangeEventSourceMetrics streamingMetrics,
|
|
||||||
ChangeEventQueue<DataChangeEvent> queue,
|
|
||||||
SnapshotterService snapshotterService) {
|
|
||||||
this.configuration = configuration;
|
|
||||||
this.connectionFactory = connectionFactory;
|
|
||||||
this.errorHandler = errorHandler;
|
|
||||||
this.dispatcher = dispatcher;
|
|
||||||
this.clock = clock;
|
|
||||||
this.taskContext = taskContext;
|
|
||||||
this.streamingMetrics = streamingMetrics;
|
|
||||||
this.queue = queue;
|
|
||||||
this.schema = schema;
|
|
||||||
this.snapshotterService = snapshotterService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SnapshotChangeEventSource<MariaDbPartition, MariaDbOffsetContext> getSnapshotChangeEventSource(
|
|
||||||
SnapshotProgressListener<MariaDbPartition> snapshotProgressListener,
|
|
||||||
NotificationService<MariaDbPartition, MariaDbOffsetContext> notificationService) {
|
|
||||||
return new MariaDbSnapshotChangeEventSource(
|
|
||||||
configuration,
|
|
||||||
connectionFactory,
|
|
||||||
taskContext.getSchema(),
|
|
||||||
dispatcher,
|
|
||||||
clock,
|
|
||||||
(MariaDbSnapshotChangeEventSourceMetrics) snapshotProgressListener,
|
|
||||||
this::modifyAndFlushLastRecord,
|
|
||||||
this::preSnapshot,
|
|
||||||
notificationService,
|
|
||||||
snapshotterService);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamingChangeEventSource<MariaDbPartition, MariaDbOffsetContext> getStreamingChangeEventSource() {
|
|
||||||
queue.disableBuffering();
|
|
||||||
return new MariaDbStreamingChangeEventSource(
|
|
||||||
configuration,
|
|
||||||
connectionFactory.mainConnection(),
|
|
||||||
dispatcher,
|
|
||||||
errorHandler,
|
|
||||||
clock,
|
|
||||||
taskContext,
|
|
||||||
streamingMetrics,
|
|
||||||
snapshotterService);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<IncrementalSnapshotChangeEventSource<MariaDbPartition, ? extends DataCollectionId>> getIncrementalSnapshotChangeEventSource(
|
|
||||||
MariaDbOffsetContext offsetContext,
|
|
||||||
SnapshotProgressListener<MariaDbPartition> snapshotProgressListener,
|
|
||||||
DataChangeEventListener<MariaDbPartition> dataChangeEventListener,
|
|
||||||
NotificationService<MariaDbPartition, MariaDbOffsetContext> notificationService) {
|
|
||||||
if (configuration.isReadOnlyConnection()) {
|
|
||||||
if (connectionFactory.mainConnection().isGtidModeEnabled()) {
|
|
||||||
return Optional.of(new MariaDbReadOnlyIncrementalSnapshotChangeEventSource(
|
|
||||||
configuration,
|
|
||||||
connectionFactory.mainConnection(),
|
|
||||||
dispatcher,
|
|
||||||
schema,
|
|
||||||
clock,
|
|
||||||
snapshotProgressListener,
|
|
||||||
dataChangeEventListener,
|
|
||||||
notificationService));
|
|
||||||
}
|
|
||||||
throw new UnsupportedOperationException("Read only connection requires GTID_MODE to be ON");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no data collection id is provided, don't return an instance as the implement requires the table
|
|
||||||
if (Strings.isNullOrBlank(configuration.getSignalingDataCollectionId())) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Optional.of(new SignalBasedIncrementalSnapshotChangeEventSource<>(
|
|
||||||
configuration,
|
|
||||||
connectionFactory.mainConnection(),
|
|
||||||
dispatcher,
|
|
||||||
schema,
|
|
||||||
clock,
|
|
||||||
snapshotProgressListener,
|
|
||||||
dataChangeEventListener,
|
|
||||||
notificationService));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void preSnapshot() {
|
|
||||||
queue.enableBuffering();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void modifyAndFlushLastRecord(Function<SourceRecord, SourceRecord> modify) throws InterruptedException {
|
|
||||||
queue.flushBuffer(dataChange -> new DataChangeEvent(modify.apply(dataChange.getRecord())));
|
|
||||||
queue.disableBuffering();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.kafka.common.config.ConfigDef;
|
|
||||||
import org.apache.kafka.common.config.ConfigValue;
|
|
||||||
import org.apache.kafka.connect.connector.Task;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnector;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbConnection;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbConnectionConfiguration;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbFieldReader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Debezium source connector that creates tasks and reads changes from MariaDB's binary transaction logs,
|
|
||||||
* generating change events.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnector extends BinlogConnector<MariaDbConnectorConfig> {
|
|
||||||
|
|
||||||
public MariaDbConnector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String version() {
|
|
||||||
return Module.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Task> taskClass() {
|
|
||||||
return MariaDbConnectorTask.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConfigDef config() {
|
|
||||||
return MariaDbConnectorConfig.configDef();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ConfigValue> validateAllFields(Configuration config) {
|
|
||||||
return config.validate(MariaDbConnectorConfig.ALL_FIELDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbConnection createConnection(Configuration config, MariaDbConnectorConfig connectorConfig) {
|
|
||||||
return new MariaDbConnection(new MariaDbConnectionConfiguration(config), new MariaDbFieldReader(connectorConfig));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbConnectorConfig createConnectorConfig(Configuration config) {
|
|
||||||
return new MariaDbConnectorConfig(config);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,301 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import org.apache.kafka.common.config.ConfigDef;
|
|
||||||
import org.apache.kafka.common.config.ConfigDef.Importance;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.config.CommonConnectorConfig;
|
|
||||||
import io.debezium.config.ConfigDefinition;
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.config.EnumeratedValue;
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.config.Field.ValidationOutput;
|
|
||||||
import io.debezium.connector.AbstractSourceInfo;
|
|
||||||
import io.debezium.connector.SourceInfoStructMaker;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSetFactory;
|
|
||||||
import io.debezium.connector.mariadb.charset.MariaDbCharsetRegistryServiceProvider;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSetFactory;
|
|
||||||
import io.debezium.connector.mariadb.history.MariaDbHistoryRecordComparator;
|
|
||||||
import io.debezium.function.Predicates;
|
|
||||||
import io.debezium.relational.history.HistoryRecordComparator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration properties for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnectorConfig extends BinlogConnectorConfig {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MariaDbConnectorConfig.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For MariaDB to mimic MySQL behavior using {@link Integer#MIN_VALUE}, the default fetch
|
|
||||||
* size must explicitly be set to {@code 1}. This is because MariaDB drivers 3.x+ do not
|
|
||||||
* support the old non-compliant JDBC-spec style that MySQL uses.
|
|
||||||
*/
|
|
||||||
private static final int DEFAULT_NON_STREAMING_FETCH_SIZE = 1;
|
|
||||||
|
|
||||||
public static final Field SOURCE_INFO_STRUCT_MAKER = CommonConnectorConfig.SOURCE_INFO_STRUCT_MAKER
|
|
||||||
.withDefault(MariaDbSourceInfoStructMaker.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The set of predefined snapshot locking mode options.
|
|
||||||
*/
|
|
||||||
public enum SnapshotLockingMode implements EnumeratedValue {
|
|
||||||
/**
|
|
||||||
* This mode will block all writes for the entire duration of the snapshot.<p></p>
|
|
||||||
*
|
|
||||||
* Replaces deprecated configuration option snapshot.locking.minimal with a value of false.
|
|
||||||
*/
|
|
||||||
EXTENDED("extended"),
|
|
||||||
/**
|
|
||||||
* The connector holds the global read lock for just the initial portion of the snapshot while the connector reads the database
|
|
||||||
* schemas and other metadata. The remaining work in a snapshot involves selecting all rows from each table, and this can be done
|
|
||||||
* in a consistent fashion using the REPEATABLE READ transaction even when the global read lock is no longer held and while other
|
|
||||||
* MySQL clients are updating the database.<p></p>
|
|
||||||
*
|
|
||||||
* Replaces deprecated configuration option snapshot.locking.minimal with a value of true.
|
|
||||||
*/
|
|
||||||
MINIMAL("minimal"),
|
|
||||||
/**
|
|
||||||
* This mode will avoid using ANY table locks during the snapshot process. This mode can only be used with SnapShotMode
|
|
||||||
* set to schema_only or schema_only_recovery.
|
|
||||||
*/
|
|
||||||
NONE("none"),
|
|
||||||
/**
|
|
||||||
* Inject a custom mode, which allows for more control over snapshot locking.
|
|
||||||
*/
|
|
||||||
CUSTOM("custom");
|
|
||||||
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
SnapshotLockingMode(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean usesMinimalLocking() {
|
|
||||||
return value.equals(MINIMAL.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean usesLocking() {
|
|
||||||
return !value.equals(NONE.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean flushResetsIsolationLevel() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the supplied value is one of the predefined options.
|
|
||||||
*
|
|
||||||
* @param value the configuration property value; may not be null
|
|
||||||
* @return the matching option, or null if no match is found
|
|
||||||
*/
|
|
||||||
public static SnapshotLockingMode parse(String value) {
|
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
value = value.trim();
|
|
||||||
for (SnapshotLockingMode option : SnapshotLockingMode.values()) {
|
|
||||||
if (option.getValue().equalsIgnoreCase(value)) {
|
|
||||||
return option;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the supplied value is one of the predefined options.
|
|
||||||
*
|
|
||||||
* @param value the configuration property value; may not be null
|
|
||||||
* @param defaultValue the default value; may be null
|
|
||||||
* @return the matching option, or null if no match is found and the non-null default is invalid
|
|
||||||
*/
|
|
||||||
public static SnapshotLockingMode parse(String value, String defaultValue) {
|
|
||||||
SnapshotLockingMode mode = parse(value);
|
|
||||||
if (mode == null && defaultValue != null) {
|
|
||||||
mode = parse(defaultValue);
|
|
||||||
}
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Field SNAPSHOT_LOCKING_MODE = Field.create(SNAPSHOT_LOCKING_MODE_PROPERTY_NAME)
|
|
||||||
.withDisplayName("Snapshot locking mode")
|
|
||||||
.withEnum(SnapshotLockingMode.class, SnapshotLockingMode.MINIMAL)
|
|
||||||
.withImportance(Importance.LOW)
|
|
||||||
.withDescription("Controls how long the connector holds onto the global read lock while it is performing "
|
|
||||||
+ "a snapshot. The default is 'minimal', meaning the connector holds the global read lock (and thus "
|
|
||||||
+ "prevents updates) for just the initial portion of the snapshot while the database schemas and other "
|
|
||||||
+ "metadata are being read. The remaining work in a snapshot involves selecting all rows from each table, "
|
|
||||||
+ "and this can be done using the snapshot process' REPEATABLE READ transaction isolation even when the "
|
|
||||||
+ "lock is no longer held and other operations are updating the database. However, in some cases it may "
|
|
||||||
+ "be desirable to block all writes for the entire duration of the snapshot; in such cases set this "
|
|
||||||
+ "to 'extended'. Using a value of 'none' will prevent the connector from acquiring any table locks "
|
|
||||||
+ "during the snapshot process. This mode can only be used in combination with snapshot.mode values of "
|
|
||||||
+ "'schema_only' or 'schema_only_recovery' and is only safe to use if no schema changes are happening "
|
|
||||||
+ "while the snapshot is taken.")
|
|
||||||
.withValidation(MariaDbConnectorConfig::validateSnapshotLockingMode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MariaDB GTID format uses "{@code domain-server-sequence}". This configuration should specify a
|
|
||||||
* comma-separated list of regular expressions that match the "{@code domain-server}" tuples when
|
|
||||||
* locating the binlog position in a MariaDB server. Only the GTID ranges that have sources that
|
|
||||||
* match one of these patterns will be used.
|
|
||||||
*/
|
|
||||||
public static final Field GTID_SOURCE_INCLUDES = BinlogConnectorConfig.GTID_SOURCE_INCLUDES
|
|
||||||
.withDescription("The source domain IDs used to include GTID ranges when determining the starting "
|
|
||||||
+ "position in the MariaDB server's binlog.");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MariaDB GTID format uses "{@code domain-server-sequence}". This configuration should specify a
|
|
||||||
* comma-separataed list of regular expressions that match the "{@code domain-server}" tuples when
|
|
||||||
* locating the binlog position in a MariaDB server. GTIDs that do not match any of these patterns
|
|
||||||
* will be used.
|
|
||||||
*/
|
|
||||||
public static final Field GTID_SOURCE_EXCLUDES = BinlogConnectorConfig.GTID_SOURCE_EXCLUDES
|
|
||||||
.withDescription("The source domain IDs used to exclude GTID ranges when determining the starting "
|
|
||||||
+ "position in the MariaDB server's binlog.");
|
|
||||||
|
|
||||||
private static final ConfigDefinition CONFIG_DEFINITION = BinlogConnectorConfig.CONFIG_DEFINITION.edit()
|
|
||||||
.name("MariaDB")
|
|
||||||
.excluding(
|
|
||||||
BinlogConnectorConfig.GTID_SOURCE_INCLUDES,
|
|
||||||
BinlogConnectorConfig.GTID_SOURCE_EXCLUDES)
|
|
||||||
.connector(SNAPSHOT_LOCKING_MODE)
|
|
||||||
.events(
|
|
||||||
GTID_SOURCE_INCLUDES,
|
|
||||||
GTID_SOURCE_EXCLUDES,
|
|
||||||
SOURCE_INFO_STRUCT_MAKER)
|
|
||||||
.create();
|
|
||||||
|
|
||||||
protected static ConfigDef configDef() {
|
|
||||||
return CONFIG_DEFINITION.configDef();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The set of {@link Field}s defined as part of this connector configuration.
|
|
||||||
*/
|
|
||||||
public static Field.Set ALL_FIELDS = Field.setOf(CONFIG_DEFINITION.all());
|
|
||||||
|
|
||||||
private final GtidSetFactory gtidSetFactory;
|
|
||||||
private final Predicate<String> gtidSourceFilter;
|
|
||||||
private final SnapshotLockingMode snapshotLockingMode;
|
|
||||||
private final SnapshotLockingStrategy snapshotLockingStrategy;
|
|
||||||
|
|
||||||
public MariaDbConnectorConfig(Configuration config) {
|
|
||||||
super(MariaDbConnector.class, config, DEFAULT_NON_STREAMING_FETCH_SIZE);
|
|
||||||
this.gtidSetFactory = new MariaDbGtidSetFactory();
|
|
||||||
|
|
||||||
final String gtidIncludes = config.getString(GTID_SOURCE_INCLUDES);
|
|
||||||
final String gtidExcludes = config.getString(GTID_SOURCE_EXCLUDES);
|
|
||||||
this.gtidSourceFilter = gtidIncludes != null ? Predicates.includes(gtidIncludes)
|
|
||||||
: (gtidExcludes != null ? Predicates.excludes(gtidExcludes) : null);
|
|
||||||
|
|
||||||
this.snapshotLockingMode = SnapshotLockingMode.parse(config.getString(SNAPSHOT_LOCKING_MODE));
|
|
||||||
this.snapshotLockingStrategy = new MariaDbSnapshotLockingStrategy(snapshotLockingMode);
|
|
||||||
|
|
||||||
getServiceRegistry().registerServiceProvider(new MariaDbCharsetRegistryServiceProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SourceInfoStructMaker<? extends AbstractSourceInfo> getSourceInfoStructMaker(Version version) {
|
|
||||||
return getSourceInfoStructMaker(SOURCE_INFO_STRUCT_MAKER, Module.name(), Module.version(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getContextName() {
|
|
||||||
return Module.contextName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getConnectorName() {
|
|
||||||
return Module.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Predicate<String> getGtidSourceFilter() {
|
|
||||||
return gtidSourceFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GtidSetFactory getGtidSetFactory() {
|
|
||||||
return gtidSetFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected HistoryRecordComparator getHistoryRecordComparator() {
|
|
||||||
return new MariaDbHistoryRecordComparator(gtidSourceFilter, getGtidSetFactory());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SnapshotLockingStrategy getSnapshotLockingStrategy() {
|
|
||||||
return snapshotLockingStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<SnapshotLockingMode> getSnapshotLockingMode() {
|
|
||||||
return Optional.of(snapshotLockingMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom {@link io.debezium.connector.binlog.BinlogConnectorConfig.SnapshotLockingStrategy} for MariaDB.
|
|
||||||
*/
|
|
||||||
public static class MariaDbSnapshotLockingStrategy implements SnapshotLockingStrategy {
|
|
||||||
|
|
||||||
public final SnapshotLockingMode snapshotLockingMode;
|
|
||||||
|
|
||||||
public MariaDbSnapshotLockingStrategy(SnapshotLockingMode snapshotLockingMode) {
|
|
||||||
this.snapshotLockingMode = snapshotLockingMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLockingEnabled() {
|
|
||||||
return snapshotLockingMode.usesLocking();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMinimalLockingEnabled() {
|
|
||||||
return snapshotLockingMode.usesMinimalLocking();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isIsolationLevelResetOnFlush() {
|
|
||||||
return snapshotLockingMode.flushResetsIsolationLevel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the new snapshot.locking.mode configuration.
|
|
||||||
*
|
|
||||||
* @param config the connector configuration
|
|
||||||
* @param field the field being validated
|
|
||||||
* @param problems the validation output
|
|
||||||
* @return the number of problems detected
|
|
||||||
*/
|
|
||||||
private static int validateSnapshotLockingMode(Configuration config, Field field, ValidationOutput problems) {
|
|
||||||
if (config.hasKey(SNAPSHOT_LOCKING_MODE.name())) {
|
|
||||||
SnapshotLockingMode lockingModeValue = SnapshotLockingMode.parse(config.getString(SNAPSHOT_LOCKING_MODE));
|
|
||||||
if (lockingModeValue == null) {
|
|
||||||
problems.accept(SNAPSHOT_LOCKING_MODE, lockingModeValue, "Must be a valid snapshot.locking.mode value");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,296 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import static io.debezium.connector.binlog.BinlogConnectorConfig.TOPIC_NAMING_STRATEGY;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.apache.kafka.connect.source.SourceRecord;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.DebeziumException;
|
|
||||||
import io.debezium.bean.StandardBeanNames;
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.base.ChangeEventQueue;
|
|
||||||
import io.debezium.connector.binlog.BinlogEventMetadataProvider;
|
|
||||||
import io.debezium.connector.binlog.BinlogSourceTask;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogConnectorConnection;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogFieldReader;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbConnection;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbConnectionConfiguration;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbFieldReader;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbValueConverters;
|
|
||||||
import io.debezium.connector.mariadb.metrics.MariaDbChangeEventSourceMetricsFactory;
|
|
||||||
import io.debezium.connector.mariadb.metrics.MariaDbStreamingChangeEventSourceMetrics;
|
|
||||||
import io.debezium.document.DocumentReader;
|
|
||||||
import io.debezium.jdbc.DefaultMainConnectionProvidingConnectionFactory;
|
|
||||||
import io.debezium.jdbc.MainConnectionProvidingConnectionFactory;
|
|
||||||
import io.debezium.pipeline.ChangeEventSourceCoordinator;
|
|
||||||
import io.debezium.pipeline.DataChangeEvent;
|
|
||||||
import io.debezium.pipeline.ErrorHandler;
|
|
||||||
import io.debezium.pipeline.EventDispatcher;
|
|
||||||
import io.debezium.pipeline.notification.NotificationService;
|
|
||||||
import io.debezium.pipeline.signal.SignalProcessor;
|
|
||||||
import io.debezium.pipeline.spi.Offsets;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.schema.SchemaFactory;
|
|
||||||
import io.debezium.schema.SchemaNameAdjuster;
|
|
||||||
import io.debezium.snapshot.SnapshotterService;
|
|
||||||
import io.debezium.spi.snapshot.Snapshotter;
|
|
||||||
import io.debezium.spi.topic.TopicNamingStrategy;
|
|
||||||
import io.debezium.util.Clock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The MariaDB connector task that performs snapshot and streaming of changes from the database.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnectorTask extends BinlogSourceTask<MariaDbPartition, MariaDbOffsetContext> {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MariaDbConnectorTask.class);
|
|
||||||
private static final String CONTEXT_NAME = "mariadb-connector-task";
|
|
||||||
|
|
||||||
private volatile MariaDbTaskContext taskContext;
|
|
||||||
private volatile ChangeEventQueue<DataChangeEvent> queue;
|
|
||||||
private volatile BinlogConnectorConnection connection;
|
|
||||||
private volatile BinlogConnectorConnection beanRegistryJdbcConnection;
|
|
||||||
private volatile ErrorHandler errorHandler;
|
|
||||||
private volatile MariaDbDatabaseSchema schema;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String version() {
|
|
||||||
return Module.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Iterable<Field> getAllConfigurationFields() {
|
|
||||||
return MariaDbConnectorConfig.ALL_FIELDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ChangeEventSourceCoordinator<MariaDbPartition, MariaDbOffsetContext> start(Configuration configuration) {
|
|
||||||
final Clock clock = Clock.system();
|
|
||||||
final MariaDbConnectorConfig connectorConfig = new MariaDbConnectorConfig(configuration);
|
|
||||||
final TopicNamingStrategy<TableId> topicNamingStrategy = connectorConfig.getTopicNamingStrategy(TOPIC_NAMING_STRATEGY);
|
|
||||||
final SchemaNameAdjuster schemaNameAdjuster = connectorConfig.schemaNameAdjuster();
|
|
||||||
final MariaDbValueConverters valueConverters = getValueConverters(connectorConfig);
|
|
||||||
|
|
||||||
// DBZ-3238
|
|
||||||
// Automatically set useCursorFetch to true when a snapshot fetch size other than the default is given.
|
|
||||||
// By default, do not load whole result sets into memory.
|
|
||||||
final Configuration config = configuration.edit()
|
|
||||||
.withDefault("database.responseBuffering", "adaptive")
|
|
||||||
.withDefault("database.fetchSize", 10_000)
|
|
||||||
.withDefault("database.useCursorFetch", connectorConfig.useCursorFetch())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final MainConnectionProvidingConnectionFactory<BinlogConnectorConnection> connectionFactory = new DefaultMainConnectionProvidingConnectionFactory<>(() -> {
|
|
||||||
final MariaDbConnectionConfiguration connectionConfig = new MariaDbConnectionConfiguration(config);
|
|
||||||
return new MariaDbConnection(connectionConfig, new MariaDbFieldReader(connectorConfig));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.connection = connectionFactory.mainConnection();
|
|
||||||
|
|
||||||
final Offsets<MariaDbPartition, MariaDbOffsetContext> previousOffsets = getPreviousOffsets(
|
|
||||||
new MariaDbPartition.Provider(connectorConfig, config),
|
|
||||||
new MariaDbOffsetContext.Loader(connectorConfig));
|
|
||||||
|
|
||||||
final boolean tableIdCaseInsensitive = connection.isTableIdCaseSensitive();
|
|
||||||
this.schema = new MariaDbDatabaseSchema(connectorConfig, valueConverters, topicNamingStrategy, schemaNameAdjuster, tableIdCaseInsensitive);
|
|
||||||
|
|
||||||
// Manual Bean Registration
|
|
||||||
beanRegistryJdbcConnection = connectionFactory.newConnection();
|
|
||||||
connectorConfig.getBeanRegistry().add(StandardBeanNames.CONFIGURATION, config);
|
|
||||||
connectorConfig.getBeanRegistry().add(StandardBeanNames.CONNECTOR_CONFIG, connectorConfig);
|
|
||||||
connectorConfig.getBeanRegistry().add(StandardBeanNames.DATABASE_SCHEMA, schema);
|
|
||||||
connectorConfig.getBeanRegistry().add(StandardBeanNames.JDBC_CONNECTION, beanRegistryJdbcConnection);
|
|
||||||
connectorConfig.getBeanRegistry().add(StandardBeanNames.VALUE_CONVERTER, valueConverters);
|
|
||||||
connectorConfig.getBeanRegistry().add(StandardBeanNames.OFFSETS, previousOffsets);
|
|
||||||
|
|
||||||
// Service providers
|
|
||||||
registerServiceProviders(connectorConfig.getServiceRegistry());
|
|
||||||
|
|
||||||
final SnapshotterService snapshotterService = connectorConfig.getServiceRegistry().tryGetService(SnapshotterService.class);
|
|
||||||
final Snapshotter snapshotter = snapshotterService.getSnapshotter();
|
|
||||||
|
|
||||||
validateBinlogConfiguration(snapshotter, connection);
|
|
||||||
|
|
||||||
// If the binlog position is not available, it is necessary to re-execute the snapshot
|
|
||||||
if (validateSnapshotFeasibility(snapshotter, previousOffsets.getTheOnlyOffset(), connection)) {
|
|
||||||
previousOffsets.resetOffset(previousOffsets.getTheOnlyPartition());
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("Closing JDBC connection before starting schema recovery.");
|
|
||||||
try {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw new DebeziumException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
MariaDbOffsetContext previousOffset = previousOffsets.getTheOnlyOffset();
|
|
||||||
|
|
||||||
validateAndLoadSchemaHistory(connectorConfig, connection::validateLogPosition, previousOffsets, schema, snapshotter);
|
|
||||||
|
|
||||||
LOGGER.info("Reconnecting after finishing schema recovery");
|
|
||||||
try {
|
|
||||||
connection.setAutoCommit(false);
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw new DebeziumException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the binlog position is not available it is necessary to re-execute snapshot
|
|
||||||
if (previousOffset == null) {
|
|
||||||
LOGGER.info("No previous offset found");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOGGER.info("Found previous offset {}", previousOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
taskContext = new MariaDbTaskContext(connectorConfig, schema);
|
|
||||||
|
|
||||||
// Set up the task record queue ...
|
|
||||||
this.queue = new ChangeEventQueue.Builder<DataChangeEvent>()
|
|
||||||
.pollInterval(connectorConfig.getPollInterval())
|
|
||||||
.maxBatchSize(connectorConfig.getMaxBatchSize())
|
|
||||||
.maxQueueSize(connectorConfig.getMaxQueueSize())
|
|
||||||
.maxQueueSizeInBytes(connectorConfig.getMaxQueueSizeInBytes())
|
|
||||||
.loggingContextSupplier(() -> taskContext.configureLoggingContext(CONTEXT_NAME))
|
|
||||||
.buffering()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
errorHandler = new MariaDbErrorHandler(connectorConfig, queue, errorHandler);
|
|
||||||
|
|
||||||
final BinlogEventMetadataProvider metadataProvider = new BinlogEventMetadataProvider();
|
|
||||||
|
|
||||||
SignalProcessor<MariaDbPartition, MariaDbOffsetContext> signalProcessor = new SignalProcessor<>(
|
|
||||||
MariaDbConnector.class,
|
|
||||||
connectorConfig,
|
|
||||||
Map.of(),
|
|
||||||
getAvailableSignalChannels(),
|
|
||||||
DocumentReader.defaultReader(),
|
|
||||||
previousOffsets);
|
|
||||||
resetOffset(connectorConfig, previousOffset, signalProcessor);
|
|
||||||
|
|
||||||
final Configuration heartbeatConfig = config;
|
|
||||||
final EventDispatcher<MariaDbPartition, TableId> dispatcher = new EventDispatcher<>(
|
|
||||||
connectorConfig,
|
|
||||||
topicNamingStrategy,
|
|
||||||
schema,
|
|
||||||
queue,
|
|
||||||
connectorConfig.getTableFilters().dataCollectionFilter(),
|
|
||||||
DataChangeEvent::new,
|
|
||||||
null,
|
|
||||||
metadataProvider,
|
|
||||||
connectorConfig.createHeartbeat(
|
|
||||||
topicNamingStrategy,
|
|
||||||
schemaNameAdjuster,
|
|
||||||
() -> new MariaDbConnection(
|
|
||||||
new MariaDbConnectionConfiguration(heartbeatConfig),
|
|
||||||
getFieldReader(connectorConfig)),
|
|
||||||
new BinlogHeartbeatErrorHandler()),
|
|
||||||
schemaNameAdjuster,
|
|
||||||
signalProcessor);
|
|
||||||
|
|
||||||
final MariaDbStreamingChangeEventSourceMetrics streamingMetrics = new MariaDbStreamingChangeEventSourceMetrics(
|
|
||||||
taskContext,
|
|
||||||
queue,
|
|
||||||
metadataProvider);
|
|
||||||
|
|
||||||
NotificationService<MariaDbPartition, MariaDbOffsetContext> notificationService = new NotificationService<>(
|
|
||||||
getNotificationChannels(),
|
|
||||||
connectorConfig,
|
|
||||||
SchemaFactory.get(),
|
|
||||||
dispatcher::enqueueNotification);
|
|
||||||
|
|
||||||
ChangeEventSourceCoordinator<MariaDbPartition, MariaDbOffsetContext> coordinator = new ChangeEventSourceCoordinator<>(
|
|
||||||
previousOffsets,
|
|
||||||
errorHandler,
|
|
||||||
MariaDbConnector.class,
|
|
||||||
connectorConfig,
|
|
||||||
new MariaDbChangeEventSourceFactory(
|
|
||||||
connectorConfig,
|
|
||||||
connectionFactory,
|
|
||||||
errorHandler,
|
|
||||||
dispatcher,
|
|
||||||
clock,
|
|
||||||
schema,
|
|
||||||
taskContext,
|
|
||||||
streamingMetrics,
|
|
||||||
queue,
|
|
||||||
snapshotterService),
|
|
||||||
new MariaDbChangeEventSourceMetricsFactory(streamingMetrics),
|
|
||||||
dispatcher,
|
|
||||||
schema,
|
|
||||||
signalProcessor,
|
|
||||||
notificationService,
|
|
||||||
snapshotterService);
|
|
||||||
|
|
||||||
coordinator.start(taskContext, this.queue, metadataProvider);
|
|
||||||
|
|
||||||
return coordinator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doStop() {
|
|
||||||
try {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
LOGGER.error("Exception while closing the JDBC connection.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (beanRegistryJdbcConnection != null) {
|
|
||||||
beanRegistryJdbcConnection.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
LOGGER.error("Exception while closing the Bean Registry JDBC connection.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema != null) {
|
|
||||||
schema.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<SourceRecord> doPoll() throws InterruptedException {
|
|
||||||
final List<DataChangeEvent> records = queue.poll();
|
|
||||||
return records.stream().map(DataChangeEvent::getRecord).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Long getReadOnlyIncrementalSnapshotSignalOffset(MariaDbOffsetContext previousOffset) {
|
|
||||||
return ((MariaDbReadOnlyIncrementalSnapshotContext<TableId>) previousOffset.getIncrementalSnapshotContext()).getSignalOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MariaDbValueConverters getValueConverters(MariaDbConnectorConfig connectorConfig) {
|
|
||||||
return new MariaDbValueConverters(
|
|
||||||
connectorConfig.getDecimalMode(),
|
|
||||||
connectorConfig.getTemporalPrecisionMode(),
|
|
||||||
connectorConfig.getBigIntUnsignedHandlingMode().asBigIntUnsignedMode(),
|
|
||||||
connectorConfig.binaryHandlingMode(),
|
|
||||||
connectorConfig.isTimeAdjustedEnabled() ? MariaDbValueConverters::adjustTemporal : x -> x,
|
|
||||||
connectorConfig.getEventConvertingFailureHandlingMode(),
|
|
||||||
connectorConfig.getServiceRegistry());
|
|
||||||
}
|
|
||||||
|
|
||||||
private BinlogFieldReader getFieldReader(MariaDbConnectorConfig connectorConfig) {
|
|
||||||
return new MariaDbFieldReader(connectorConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogDatabaseSchema;
|
|
||||||
import io.debezium.connector.binlog.charset.BinlogCharsetRegistry;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbDefaultValueConverter;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbValueConverters;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.relational.ddl.DdlParser;
|
|
||||||
import io.debezium.schema.SchemaNameAdjuster;
|
|
||||||
import io.debezium.spi.topic.TopicNamingStrategy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A concrete implementation of database schema for MariaDB databases.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbDatabaseSchema extends BinlogDatabaseSchema<MariaDbPartition, MariaDbOffsetContext, MariaDbValueConverters, MariaDbDefaultValueConverter> {
|
|
||||||
|
|
||||||
public MariaDbDatabaseSchema(MariaDbConnectorConfig connectorConfig, MariaDbValueConverters valueConverter,
|
|
||||||
TopicNamingStrategy<TableId> topicNamingStrategy, SchemaNameAdjuster schemaNameAdjuster,
|
|
||||||
boolean tableIdCaseInsensitive) {
|
|
||||||
super(connectorConfig,
|
|
||||||
valueConverter,
|
|
||||||
new MariaDbDefaultValueConverter(valueConverter),
|
|
||||||
topicNamingStrategy,
|
|
||||||
schemaNameAdjuster,
|
|
||||||
tableIdCaseInsensitive);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DdlParser createDdlParser(BinlogConnectorConfig connectorConfig, MariaDbValueConverters valueConverter) {
|
|
||||||
return new MariaDbAntlrDdlParser(
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
connectorConfig.isSchemaChangesHistoryEnabled(),
|
|
||||||
valueConverter,
|
|
||||||
getTableFilter(),
|
|
||||||
connectorConfig.getServiceRegistry().getService(BinlogCharsetRegistry.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.debezium.connector.base.ChangeEventQueue;
|
|
||||||
import io.debezium.pipeline.ErrorHandler;
|
|
||||||
import io.debezium.util.Collect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error handler for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbErrorHandler extends ErrorHandler {
|
|
||||||
|
|
||||||
public MariaDbErrorHandler(MariaDbConnectorConfig connectorConfig, ChangeEventQueue<?> queue, ErrorHandler replacedErrorHandler) {
|
|
||||||
super(MariaDbConnector.class, connectorConfig, queue, replacedErrorHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Set<Class<? extends Exception>> communicationExceptions() {
|
|
||||||
return Collect.unmodifiableSet(IOException.class, SQLException.class);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import static io.debezium.connector.common.OffsetUtils.longOffsetValue;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.kafka.connect.errors.ConnectException;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogOffsetContext;
|
|
||||||
import io.debezium.connector.binlog.BinlogSourceInfo;
|
|
||||||
import io.debezium.pipeline.source.snapshot.incremental.IncrementalSnapshotContext;
|
|
||||||
import io.debezium.pipeline.source.snapshot.incremental.SignalBasedIncrementalSnapshotContext;
|
|
||||||
import io.debezium.pipeline.txmetadata.TransactionContext;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context that manages the connector offset details.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbOffsetContext extends BinlogOffsetContext<SourceInfo> {
|
|
||||||
|
|
||||||
public MariaDbOffsetContext(boolean snapshot, boolean snapshotCompleted, TransactionContext transactionContext,
|
|
||||||
IncrementalSnapshotContext<TableId> incrementalSnapshotContext, SourceInfo sourceInfo) {
|
|
||||||
super(snapshot, snapshotCompleted, transactionContext, incrementalSnapshotContext, sourceInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MariaDbOffsetContext initial(MariaDbConnectorConfig config) {
|
|
||||||
final MariaDbOffsetContext offset = new MariaDbOffsetContext(
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
new TransactionContext(),
|
|
||||||
config.isReadOnlyConnection()
|
|
||||||
? new MariaDbReadOnlyIncrementalSnapshotContext<>()
|
|
||||||
: new SignalBasedIncrementalSnapshotContext<>(),
|
|
||||||
new SourceInfo(config));
|
|
||||||
offset.setBinlogStartPoint("", 0L);
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Loader extends BinlogOffsetContext.Loader<MariaDbOffsetContext> {
|
|
||||||
private final MariaDbConnectorConfig connectorConfig;
|
|
||||||
|
|
||||||
public Loader(MariaDbConnectorConfig connectorConfig) {
|
|
||||||
this.connectorConfig = connectorConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MariaDbOffsetContext load(Map<String, ?> offset) {
|
|
||||||
final String binlogFilename = (String) offset.get(BinlogSourceInfo.BINLOG_FILENAME_OFFSET_KEY);
|
|
||||||
if (binlogFilename == null) {
|
|
||||||
throw new ConnectException("Source offset '" + BinlogSourceInfo.BINLOG_FILENAME_OFFSET_KEY + "' parameter is missing");
|
|
||||||
}
|
|
||||||
final long binlogPosition = longOffsetValue(offset, BinlogSourceInfo.BINLOG_POSITION_OFFSET_KEY);
|
|
||||||
|
|
||||||
final MariaDbOffsetContext offsetContext = new MariaDbOffsetContext(
|
|
||||||
isTrue(offset, BinlogSourceInfo.SNAPSHOT_KEY),
|
|
||||||
isTrue(offset, SNAPSHOT_COMPLETED_KEY),
|
|
||||||
TransactionContext.load(offset),
|
|
||||||
connectorConfig.isReadOnlyConnection()
|
|
||||||
? MariaDbReadOnlyIncrementalSnapshotContext.load(offset)
|
|
||||||
: SignalBasedIncrementalSnapshotContext.load(offset),
|
|
||||||
new SourceInfo(connectorConfig));
|
|
||||||
offsetContext.setBinlogStartPoint(binlogFilename, binlogPosition);
|
|
||||||
offsetContext.setInitialSkips(longOffsetValue(offset, EVENTS_TO_SKIP_OFFSET_KEY),
|
|
||||||
(int) longOffsetValue(offset, BinlogSourceInfo.BINLOG_ROW_IN_EVENT_OFFSET_KEY));
|
|
||||||
offsetContext.setCompletedGtidSet((String) offset.get(GTID_SET_KEY)); // may be null
|
|
||||||
return offsetContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import static io.debezium.relational.RelationalDatabaseConnectorConfig.DATABASE_NAME;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogPartition;
|
|
||||||
import io.debezium.pipeline.spi.Partition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Describes the partition scheme used by the MariaDB connector.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbPartition extends BinlogPartition {
|
|
||||||
public MariaDbPartition(String serverName, String databaseName) {
|
|
||||||
super(serverName, databaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Provider implements Partition.Provider<MariaDbPartition> {
|
|
||||||
private final BinlogConnectorConfig connectorConfig;
|
|
||||||
private final Configuration taskConfig;
|
|
||||||
|
|
||||||
public Provider(BinlogConnectorConfig connectorConfig, Configuration taskConfig) {
|
|
||||||
this.connectorConfig = connectorConfig;
|
|
||||||
this.taskConfig = taskConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<MariaDbPartition> getPartitions() {
|
|
||||||
return Collections.singleton(new MariaDbPartition(
|
|
||||||
connectorConfig.getLogicalName(), taskConfig.getString(DATABASE_NAME.name())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import io.debezium.DebeziumException;
|
|
||||||
import io.debezium.connector.binlog.BinlogReadOnlyIncrementalSnapshotChangeEventSource;
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSet;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSet;
|
|
||||||
import io.debezium.jdbc.JdbcConnection;
|
|
||||||
import io.debezium.pipeline.EventDispatcher;
|
|
||||||
import io.debezium.pipeline.notification.NotificationService;
|
|
||||||
import io.debezium.pipeline.source.spi.DataChangeEventListener;
|
|
||||||
import io.debezium.pipeline.source.spi.SnapshotProgressListener;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.schema.DatabaseSchema;
|
|
||||||
import io.debezium.util.Clock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbReadOnlyIncrementalSnapshotChangeEventSource
|
|
||||||
extends BinlogReadOnlyIncrementalSnapshotChangeEventSource<MariaDbPartition, MariaDbOffsetContext> {
|
|
||||||
|
|
||||||
public MariaDbReadOnlyIncrementalSnapshotChangeEventSource(MariaDbConnectorConfig connectorConfig,
|
|
||||||
JdbcConnection jdbcConnection,
|
|
||||||
EventDispatcher<MariaDbPartition, TableId> dispatcher,
|
|
||||||
DatabaseSchema<?> databaseSchema,
|
|
||||||
Clock clock,
|
|
||||||
SnapshotProgressListener<MariaDbPartition> progressListener,
|
|
||||||
DataChangeEventListener<MariaDbPartition> dataChangeEventListener,
|
|
||||||
NotificationService<MariaDbPartition, MariaDbOffsetContext> notificationService) {
|
|
||||||
super(connectorConfig, jdbcConnection, dispatcher, databaseSchema, clock, progressListener, dataChangeEventListener, notificationService);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getExecutedGtidSet(Consumer<GtidSet> watermark) {
|
|
||||||
try {
|
|
||||||
jdbcConnection.query("SHOW GLOBAL VARIABLES LIKE 'GTID_BINLOG_POS'", rs -> {
|
|
||||||
if (rs.next()) {
|
|
||||||
if (rs.getMetaData().getColumnCount() > 0) {
|
|
||||||
final String gtidSet = rs.getString(2);
|
|
||||||
watermark.accept(new MariaDbGtidSet(gtidSet));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException("Need to add support for executed GTIDs for versions prior to 5.6.5");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
jdbcConnection.commit();
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw new DebeziumException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogReadOnlyIncrementalSnapshotContext;
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSet;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSet;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSet.MariaDbGtid;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSet.MariaDbStreamSet;
|
|
||||||
import io.debezium.pipeline.spi.OffsetContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbReadOnlyIncrementalSnapshotContext<T> extends BinlogReadOnlyIncrementalSnapshotContext<T> {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MariaDbReadOnlyIncrementalSnapshotContext.class);
|
|
||||||
|
|
||||||
private MariaDbGtidSet previousLowWatermark;
|
|
||||||
private MariaDbGtidSet previousHighWatermark;
|
|
||||||
private MariaDbGtidSet lowWatermark;
|
|
||||||
private MariaDbGtidSet highWatermark;
|
|
||||||
|
|
||||||
public MariaDbReadOnlyIncrementalSnapshotContext() {
|
|
||||||
this(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbReadOnlyIncrementalSnapshotContext(boolean useCatalogBeforeSchema) {
|
|
||||||
super(useCatalogBeforeSchema);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateWindowState(OffsetContext offsetContext) {
|
|
||||||
String currentGtid = getCurrentGtid(offsetContext);
|
|
||||||
if (!windowOpened && lowWatermark != null) {
|
|
||||||
boolean pastLowWatermark = !lowWatermark.contains(currentGtid);
|
|
||||||
if (pastLowWatermark) {
|
|
||||||
LOGGER.debug("Current gtid {}, low watermark {}", currentGtid, lowWatermark);
|
|
||||||
windowOpened = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (windowOpened && highWatermark != null) {
|
|
||||||
boolean pastHighWatermark = !highWatermark.contains(currentGtid);
|
|
||||||
if (pastHighWatermark) {
|
|
||||||
LOGGER.debug("Current gtid {}, high watermark {}", currentGtid, highWatermark);
|
|
||||||
closeWindow();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasServerIdentifierChanged() {
|
|
||||||
return serverStreamSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean reachedHighWatermark(String currentGtid) {
|
|
||||||
if (highWatermark == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (currentGtid == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
final MariaDbGtid currentMariaDbGtid = MariaDbGtidSet.parse(currentGtid);
|
|
||||||
final MariaDbStreamSet streamSet = getStreamSetForGtid(currentMariaDbGtid);
|
|
||||||
if (streamSet != null) {
|
|
||||||
long maxSequenceId = streamSet.stream()
|
|
||||||
.mapToLong(MariaDbGtid::getSequence)
|
|
||||||
.max()
|
|
||||||
.getAsLong();
|
|
||||||
if (maxSequenceId <= currentMariaDbGtid.getSequence()) {
|
|
||||||
LOGGER.debug("Gtid {} reached high watermark {}", currentGtid, highWatermark);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean watermarksChanged() {
|
|
||||||
return !previousLowWatermark.equals(lowWatermark) || !previousHighWatermark.equals(highWatermark);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void closeWindow() {
|
|
||||||
windowOpened = false;
|
|
||||||
previousHighWatermark = highWatermark;
|
|
||||||
highWatermark = null;
|
|
||||||
previousLowWatermark = lowWatermark;
|
|
||||||
lowWatermark = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLowWatermark(GtidSet lowWatermark) {
|
|
||||||
this.lowWatermark = (MariaDbGtidSet) lowWatermark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHighWatermark(GtidSet highWatermark) {
|
|
||||||
this.highWatermark = (MariaDbGtidSet) highWatermark.subtract(lowWatermark);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MariaDbStreamSet getStreamSetForGtid(MariaDbGtid currentGtid) {
|
|
||||||
return highWatermark.isEmpty()
|
|
||||||
? lowWatermark.forGtidStream(currentGtid)
|
|
||||||
: highWatermark.forGtidStream(currentGtid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean serverStreamSetChanged() {
|
|
||||||
return !highWatermark.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <U> MariaDbReadOnlyIncrementalSnapshotContext<U> load(Map<String, ?> offsets) {
|
|
||||||
return load(offsets, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <U> MariaDbReadOnlyIncrementalSnapshotContext<U> load(Map<String, ?> offsets, boolean useCatalogBeforeSchema) {
|
|
||||||
MariaDbReadOnlyIncrementalSnapshotContext<U> context = new MariaDbReadOnlyIncrementalSnapshotContext<>(useCatalogBeforeSchema);
|
|
||||||
init(context, offsets);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.schema.SchemaFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbSchemaFactory extends SchemaFactory {
|
|
||||||
private static final MariaDbSchemaFactory INSTANCE = new MariaDbSchemaFactory();
|
|
||||||
|
|
||||||
public static MariaDbSchemaFactory get() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.apache.kafka.connect.source.SourceRecord;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.DebeziumException;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogSnapshotChangeEventSource;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogConnectorConnection;
|
|
||||||
import io.debezium.connector.mariadb.metrics.MariaDbSnapshotChangeEventSourceMetrics;
|
|
||||||
import io.debezium.function.BlockingConsumer;
|
|
||||||
import io.debezium.jdbc.MainConnectionProvidingConnectionFactory;
|
|
||||||
import io.debezium.pipeline.EventDispatcher;
|
|
||||||
import io.debezium.pipeline.notification.NotificationService;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.snapshot.SnapshotterService;
|
|
||||||
import io.debezium.util.Clock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link io.debezium.pipeline.source.spi.SnapshotChangeEventSource} implementation for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbSnapshotChangeEventSource extends BinlogSnapshotChangeEventSource<MariaDbPartition, MariaDbOffsetContext> {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MariaDbSnapshotChangeEventSource.class);
|
|
||||||
|
|
||||||
private final MariaDbConnectorConfig connectorConfig;
|
|
||||||
|
|
||||||
public MariaDbSnapshotChangeEventSource(MariaDbConnectorConfig connectorConfig,
|
|
||||||
MainConnectionProvidingConnectionFactory<BinlogConnectorConnection> connectionFactory,
|
|
||||||
MariaDbDatabaseSchema schema,
|
|
||||||
EventDispatcher<MariaDbPartition, TableId> dispatcher,
|
|
||||||
Clock clock,
|
|
||||||
MariaDbSnapshotChangeEventSourceMetrics metrics,
|
|
||||||
BlockingConsumer<Function<SourceRecord, SourceRecord>> lastEventProcessor,
|
|
||||||
Runnable preSnapshotAction,
|
|
||||||
NotificationService<MariaDbPartition, MariaDbOffsetContext> notificationService,
|
|
||||||
SnapshotterService snapshotterService) {
|
|
||||||
super(connectorConfig, connectionFactory, schema, dispatcher, clock, metrics, lastEventProcessor,
|
|
||||||
preSnapshotAction, notificationService, snapshotterService);
|
|
||||||
this.connectorConfig = connectorConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbOffsetContext getInitialOffsetContext(BinlogConnectorConfig connectorConfig) {
|
|
||||||
return MariaDbOffsetContext.initial((MariaDbConnectorConfig) connectorConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setOffsetContextBinlogPositionAndGtidDetailsForSnapshot(MariaDbOffsetContext offsetContext,
|
|
||||||
BinlogConnectorConnection connection,
|
|
||||||
SnapshotterService snapshotterService)
|
|
||||||
throws Exception {
|
|
||||||
LOGGER.info("Read binlog position of MariaDB primary server");
|
|
||||||
final String showMasterStmt = connection.binaryLogStatusStatement();
|
|
||||||
connection.query(showMasterStmt, rs -> {
|
|
||||||
if (rs.next()) {
|
|
||||||
final String binlogFilename = rs.getString(1);
|
|
||||||
final long binlogPosition = rs.getLong(2);
|
|
||||||
offsetContext.setBinlogStartPoint(binlogFilename, binlogPosition);
|
|
||||||
|
|
||||||
connection.query("SHOW GLOBAL VARIABLES LIKE 'GTID_BINLOG_POS'", rs2 -> {
|
|
||||||
if (rs2.next() && rs2.getMetaData().getColumnCount() > 0) {
|
|
||||||
final String gtidSet = rs2.getString(2);
|
|
||||||
offsetContext.setCompletedGtidSet(gtidSet);
|
|
||||||
LOGGER.info("\t using binlog '{}' at position '{}' and gtid '{}'", binlogFilename, binlogPosition, gtidSet);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOGGER.info("\t using binlog '{}' at position '{}'", binlogFilename, binlogPosition);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (!snapshotterService.getSnapshotter().shouldStream()) {
|
|
||||||
LOGGER.warn("Failed retrieving binlog position, continuing as streaming CDC wasn't requested");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new DebeziumException("Cannot read the binlog filename and position via '" + showMasterStmt
|
|
||||||
+ "'. Make sure your server is correctly configured");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbOffsetContext copyOffset(RelationalSnapshotContext<MariaDbPartition, MariaDbOffsetContext> snapshotContext) {
|
|
||||||
return new MariaDbOffsetContext.Loader(connectorConfig).load(snapshotContext.offset.getOffset());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import org.apache.kafka.connect.data.Struct;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSourceInfoStructMaker;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@code source} {@link Struct} information maker for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbSourceInfoStructMaker extends BinlogSourceInfoStructMaker<SourceInfo> {
|
|
||||||
@Override
|
|
||||||
protected String getConnectorName() {
|
|
||||||
return Module.name();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,169 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import org.apache.kafka.connect.source.SourceConnector;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.github.shyiko.mysql.binlog.BinaryLogClient;
|
|
||||||
import com.github.shyiko.mysql.binlog.MariadbGtidSet;
|
|
||||||
import com.github.shyiko.mysql.binlog.event.AnnotateRowsEventData;
|
|
||||||
import com.github.shyiko.mysql.binlog.event.Event;
|
|
||||||
import com.github.shyiko.mysql.binlog.event.EventData;
|
|
||||||
import com.github.shyiko.mysql.binlog.event.EventType;
|
|
||||||
import com.github.shyiko.mysql.binlog.event.MariadbGtidEventData;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogStreamingChangeEventSource;
|
|
||||||
import io.debezium.connector.binlog.BinlogTaskContext;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogConnectorConnection;
|
|
||||||
import io.debezium.connector.mariadb.metrics.MariaDbStreamingChangeEventSourceMetrics;
|
|
||||||
import io.debezium.pipeline.ErrorHandler;
|
|
||||||
import io.debezium.pipeline.EventDispatcher;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.snapshot.SnapshotterService;
|
|
||||||
import io.debezium.util.Clock;
|
|
||||||
import io.debezium.util.Strings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbStreamingChangeEventSource extends BinlogStreamingChangeEventSource<MariaDbPartition, MariaDbOffsetContext> {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MariaDbStreamingChangeEventSource.class);
|
|
||||||
|
|
||||||
private final MariaDbConnectorConfig connectorConfig;
|
|
||||||
private final TableId signalDataCollectionId;
|
|
||||||
private MariadbGtidSet gtidSet;
|
|
||||||
|
|
||||||
public MariaDbStreamingChangeEventSource(MariaDbConnectorConfig connectorConfig,
|
|
||||||
BinlogConnectorConnection connection,
|
|
||||||
EventDispatcher<MariaDbPartition, TableId> dispatcher,
|
|
||||||
ErrorHandler errorHandler,
|
|
||||||
Clock clock,
|
|
||||||
MariaDbTaskContext taskContext,
|
|
||||||
MariaDbStreamingChangeEventSourceMetrics metrics,
|
|
||||||
SnapshotterService snapshotterService) {
|
|
||||||
super(connectorConfig, connection, dispatcher, errorHandler, clock, taskContext, taskContext.getSchema(), metrics, snapshotterService);
|
|
||||||
this.connectorConfig = connectorConfig;
|
|
||||||
this.signalDataCollectionId = getSignalDataCollectionId(connectorConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(MariaDbOffsetContext offsetContext) {
|
|
||||||
setEffectiveOffsetContext(offsetContext != null ? offsetContext : MariaDbOffsetContext.initial(connectorConfig));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<? extends SourceConnector> getConnectorClass() {
|
|
||||||
return MariaDbConnector.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BinaryLogClient createBinaryLogClient(BinlogTaskContext<?> taskContext,
|
|
||||||
BinlogConnectorConfig connectorConfig,
|
|
||||||
Map<String, Thread> clientThreads,
|
|
||||||
BinlogConnectorConnection connection) {
|
|
||||||
final BinaryLogClient client = super.createBinaryLogClient(taskContext, connectorConfig, clientThreads, connection);
|
|
||||||
if (connectorConfig.isSqlQueryIncluded()) {
|
|
||||||
// Binlog client explicitly needs to be told to enable ANNOTATE_ROWS events, which is the MariaDB
|
|
||||||
// equivalent of ROWS_QUERY for MySQL. This must be done ahead of the connection to make sure that
|
|
||||||
// the right negotiation bits are set during the handshake.
|
|
||||||
client.setUseSendAnnotateRowsEvent(true);
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureReplicaCompatibility(BinaryLogClient client) {
|
|
||||||
client.setMariaDbSlaveCapability(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setEventTimestamp(Event event, long eventTs) {
|
|
||||||
eventTimestamp = Instant.ofEpochMilli(eventTs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleGtidEvent(MariaDbPartition partition, MariaDbOffsetContext offsetContext, Event event,
|
|
||||||
Predicate<String> gtidDmlSourceFilter)
|
|
||||||
throws InterruptedException {
|
|
||||||
LOGGER.debug("MariaDB GTID transaction: {}", event);
|
|
||||||
|
|
||||||
// NOTE: MariadbGtidEventData (GTID_EVENT) does not include the server id in the event data payload.
|
|
||||||
// We need to manually construct the GTID combining the data from the GTID_EVENT payload and header.
|
|
||||||
MariadbGtidEventData gtidEvent = unwrapData(event);
|
|
||||||
String gtid = String.format("%d-%d-%d", gtidEvent.getDomainId(), event.getHeader().getServerId(), gtidEvent.getSequence());
|
|
||||||
|
|
||||||
// String gtid = gtidEvent.toString();
|
|
||||||
gtidSet.add(gtid);
|
|
||||||
offsetContext.startGtid(gtid, gtidSet.toString());
|
|
||||||
|
|
||||||
setIgnoreDmlEventByGtidSource(false);
|
|
||||||
if (gtidDmlSourceFilter != null && gtid != null) {
|
|
||||||
String uuid = gtidEvent.getDomainId() + "-" + gtidEvent.getServerId();
|
|
||||||
if (!gtidDmlSourceFilter.test(uuid)) {
|
|
||||||
setIgnoreDmlEventByGtidSource(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setGtidChanged(gtid);
|
|
||||||
|
|
||||||
// With compatibility mode 4, this event equates to a new transaction.
|
|
||||||
handleTransactionBegin(partition, offsetContext, event, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleRecordingQuery(MariaDbOffsetContext offsetContext, Event event) {
|
|
||||||
final EventData eventData = unwrapData(event);
|
|
||||||
if (eventData instanceof AnnotateRowsEventData) {
|
|
||||||
final String query = ((AnnotateRowsEventData) eventData).getRowsQuery();
|
|
||||||
// todo: Cache ANNOTATE_ROWS query with events
|
|
||||||
// During incremental snapshots, the updates made to the signal table can lead to a case where
|
|
||||||
// the query stored in the offsets mismatch the events being dispatched.
|
|
||||||
//
|
|
||||||
// IncrementalSnapshotIT#updates performs a series of updates where the pk/aa columns are changed
|
|
||||||
// i.e. [1,0] to [1,2000] and the ANNOTATE_ROWS event that conatins the query specifies this SQL:
|
|
||||||
// "UPDATE `schema`.`a` SET aa = aa + 2000 WHERE pk > 0 and pk <= 10"
|
|
||||||
//
|
|
||||||
// The problem is that signal events do not seem to record a query string in the offsets for MySQL
|
|
||||||
// but this gets recorded for MariaDB, and causes a mismatch of query string values that differs
|
|
||||||
// from MySQL's behavior. For now, this allows the tests to pass.
|
|
||||||
if (signalDataCollectionId != null) {
|
|
||||||
if (query.toLowerCase().contains(signalDataCollectionId.toQuotedString('`').toLowerCase())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offsetContext.setQuery(query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected EventType getIncludeQueryEventType() {
|
|
||||||
return EventType.ANNOTATE_ROWS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected EventType getGtidEventType() {
|
|
||||||
return EventType.MARIADB_GTID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initializeGtidSet(String value) {
|
|
||||||
this.gtidSet = new MariadbGtidSet(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TableId getSignalDataCollectionId(MariaDbConnectorConfig connectorConfig) {
|
|
||||||
if (!Strings.isNullOrBlank(connectorConfig.getSignalingDataCollectionId())) {
|
|
||||||
return TableId.parse(connectorConfig.getSignalingDataCollectionId());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTaskContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A state (context) associated with a MariaDB connector task.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbTaskContext extends BinlogTaskContext<MariaDbDatabaseSchema> {
|
|
||||||
public MariaDbTaskContext(MariaDbConnectorConfig config, MariaDbDatabaseSchema schema) {
|
|
||||||
super(config, schema);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import io.debezium.util.IoUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information about this MariaDb connector module.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class Module {
|
|
||||||
|
|
||||||
private static final Properties INFO = IoUtil.loadProperties(Module.class, "io/debezium/connector/mariadb/build.version");
|
|
||||||
|
|
||||||
public static String version() {
|
|
||||||
return INFO.getProperty("version");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the connector's symbolic name.
|
|
||||||
*
|
|
||||||
* @return the connector plug-in's symbolic name, never {@code null}.
|
|
||||||
*/
|
|
||||||
public static String name() {
|
|
||||||
return "mariadb";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the connector context name used for logging and JMX.
|
|
||||||
*
|
|
||||||
* @return the context name, never {@code null}
|
|
||||||
*/
|
|
||||||
public static String contextName() {
|
|
||||||
return "MariaDB";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.annotation.NotThreadSafe;
|
|
||||||
import io.debezium.connector.binlog.BinlogSourceInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information about the source, which includes the position in the binary transaction log.<p></p>
|
|
||||||
*
|
|
||||||
* The {@link MariaDbPartition#getSourcePartition() source partition} information describes the database whose
|
|
||||||
* log is being consumed. Typically, the database is identified by the host address and port number of the
|
|
||||||
* MariaDB server and the name of the database. Here's an example JSON representation:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* {
|
|
||||||
* "server": "production-server"
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* The offset includes the {@link #binlogFileName() binlog filename}, the {@link #binlogPosition() position of the first event}
|
|
||||||
* in the transaction log, the {@link MariaDbOffsetContext#eventsToSkipUponRestart() number of events to skip on restart},
|
|
||||||
* and the {@link MariaDbOffsetContext#rowsToSkipUponRestart() number of rows to skip}. An example:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* {
|
|
||||||
* "server_id": 112233,
|
|
||||||
* "ts_ms": 123456789,
|
|
||||||
* "gtid": "0-1-3",
|
|
||||||
* "file": "binlog.000003",
|
|
||||||
* "pos": 990,
|
|
||||||
* "event": 0,
|
|
||||||
* "row": 0,
|
|
||||||
* "snapshot": true
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* The "{@code snapshot}" field only appears in offsets produced during the snapshot phase. The "{@code ts_ms}" field
|
|
||||||
* contains the <em>milliseconds</em> since Unix epoch (since Jan 1 1970) of the MariaDB event.<p></p>
|
|
||||||
*
|
|
||||||
* Each change event {@link io.debezium.data.Envelope} also contains a {@link #struct() source} struct that contains
|
|
||||||
* the MariaDB information about that specific event, including a mixture of fields from the binary log filename and
|
|
||||||
* position where the event can be found, GTID details, etc. Like with the offset, the "{@code snapshot}" field will
|
|
||||||
* only appear for events produced during the snapshot phase.<p></p>
|
|
||||||
*
|
|
||||||
* Here's a JSON example of the source metadata for an event:
|
|
||||||
* <pre>
|
|
||||||
* {
|
|
||||||
* "name": "production-server",
|
|
||||||
* "server_id": 112233,
|
|
||||||
* "ts_ms": 123456789,
|
|
||||||
* "gtid": "0-1-3",
|
|
||||||
* "file": "binlog.000003",
|
|
||||||
* "pos": 1081,
|
|
||||||
* "row": 0,
|
|
||||||
* "snapshot": true,
|
|
||||||
* "thread": 1,
|
|
||||||
* "db": "inventory",
|
|
||||||
* "table": "products"
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@NotThreadSafe
|
|
||||||
public class SourceInfo extends BinlogSourceInfo {
|
|
||||||
public SourceInfo(MariaDbConnectorConfig connectorConfig) {
|
|
||||||
super(connectorConfig);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,505 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr;
|
|
||||||
|
|
||||||
import java.sql.Types;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.CharStream;
|
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
|
||||||
import org.antlr.v4.runtime.misc.Interval;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
|
||||||
|
|
||||||
import io.debezium.annotation.VisibleForTesting;
|
|
||||||
import io.debezium.antlr.AntlrDdlParser;
|
|
||||||
import io.debezium.antlr.AntlrDdlParserListener;
|
|
||||||
import io.debezium.antlr.DataTypeResolver;
|
|
||||||
import io.debezium.connector.binlog.charset.BinlogCharsetRegistry;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogSystemVariables;
|
|
||||||
import io.debezium.connector.mariadb.antlr.listener.MariaDbAntlrDdlParserListener;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbValueConverters;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBLexer;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser.CharsetNameContext;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser.CollationNameContext;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser.RenameTableClauseContext;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser.RenameTableContext;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.ColumnEditor;
|
|
||||||
import io.debezium.relational.SystemVariables;
|
|
||||||
import io.debezium.relational.TableEditor;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.relational.Tables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An ANTLR based parser for MariaDB DDL statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbAntlrDdlParser extends AntlrDdlParser<MariaDBLexer, MariaDBParser> {
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<String, String> charsetNameForDatabase = new ConcurrentHashMap<>();
|
|
||||||
private final MariaDbValueConverters converters;
|
|
||||||
private final Tables.TableFilter tableFilter;
|
|
||||||
private final BinlogCharsetRegistry charsetRegistry;
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public MariaDbAntlrDdlParser() {
|
|
||||||
this(null, Tables.TableFilter.includeAll());
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public MariaDbAntlrDdlParser(MariaDbValueConverters valueConverters) {
|
|
||||||
this(valueConverters, Tables.TableFilter.includeAll());
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public MariaDbAntlrDdlParser(MariaDbValueConverters valueConverters, Tables.TableFilter tableFilter) {
|
|
||||||
this(true, false, true, valueConverters, tableFilter, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbAntlrDdlParser(boolean throwWerrorsFromTreeWalk, boolean includeViews, boolean includeComments,
|
|
||||||
MariaDbValueConverters valueConverters, Tables.TableFilter tableFilter, BinlogCharsetRegistry charsetRegistry) {
|
|
||||||
super(throwWerrorsFromTreeWalk, includeViews, includeComments);
|
|
||||||
systemVariables = new BinlogSystemVariables();
|
|
||||||
this.converters = valueConverters;
|
|
||||||
this.tableFilter = tableFilter;
|
|
||||||
this.charsetRegistry = charsetRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ParseTree parseTree(MariaDBParser parser) {
|
|
||||||
return parser.root();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AntlrDdlParserListener createParseTreeWalkerListener() {
|
|
||||||
return new MariaDbAntlrDdlParserListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDBLexer createNewLexerInstance(CharStream charStreams) {
|
|
||||||
return new MariaDBLexer(charStreams);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDBParser createNewParserInstance(CommonTokenStream commonTokenStream) {
|
|
||||||
return new MariaDBParser(commonTokenStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SystemVariables createNewSystemVariablesInstance() {
|
|
||||||
return new BinlogSystemVariables();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isGrammarInUpperCase() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DataTypeResolver initializeDataTypeResolver() {
|
|
||||||
DataTypeResolver.Builder dataTypeResolverBuilder = new DataTypeResolver.Builder();
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.StringDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.CHAR, MariaDBParser.CHAR),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.CHAR, MariaDBParser.VARYING),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.VARCHAR),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.TINYTEXT),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.TEXT),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.MEDIUMTEXT),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.LONGTEXT),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.LONG),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NCHAR, MariaDBParser.NCHAR),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NVARCHAR, MariaDBParser.NCHAR, MariaDBParser.VARYING),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NVARCHAR, MariaDBParser.NVARCHAR),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.CHAR, MariaDBParser.CHAR, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.VARCHAR, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.TINYTEXT, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.TEXT, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.MEDIUMTEXT, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.LONGTEXT, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NCHAR, MariaDBParser.NCHAR, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NVARCHAR, MariaDBParser.NVARCHAR, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.CHAR, MariaDBParser.CHARACTER),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.CHARACTER, MariaDBParser.VARYING)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.NationalStringDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NVARCHAR, MariaDBParser.NATIONAL, MariaDBParser.VARCHAR).setSuffixTokens(MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NCHAR, MariaDBParser.NATIONAL, MariaDBParser.CHARACTER).setSuffixTokens(MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NCHAR, MariaDBParser.NATIONAL, MariaDBParser.CHAR).setSuffixTokens(MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NVARCHAR, MariaDBParser.NCHAR, MariaDBParser.VARCHAR).setSuffixTokens(MariaDBParser.BINARY)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.NationalVaryingStringDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NVARCHAR, MariaDBParser.NATIONAL, MariaDBParser.CHAR, MariaDBParser.VARYING),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NVARCHAR, MariaDBParser.NATIONAL, MariaDBParser.CHARACTER, MariaDBParser.VARYING)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.DimensionDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.SMALLINT, MariaDBParser.TINYINT)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.SMALLINT, MariaDBParser.INT1)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.SMALLINT, MariaDBParser.SMALLINT)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.SMALLINT, MariaDBParser.INT2)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.INTEGER, MariaDBParser.MEDIUMINT)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.INTEGER, MariaDBParser.INT3)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.INTEGER, MariaDBParser.MIDDLEINT)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.INTEGER, MariaDBParser.INT)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.INTEGER, MariaDBParser.INTEGER)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.INTEGER, MariaDBParser.INT4)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BIGINT, MariaDBParser.BIGINT)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BIGINT, MariaDBParser.INT8)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.REAL, MariaDBParser.REAL)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.DOUBLE, MariaDBParser.DOUBLE)
|
|
||||||
.setSuffixTokens(MariaDBParser.PRECISION, MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.DOUBLE, MariaDBParser.FLOAT8)
|
|
||||||
.setSuffixTokens(MariaDBParser.PRECISION, MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.FLOAT, MariaDBParser.FLOAT)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.FLOAT, MariaDBParser.FLOAT4)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.DECIMAL, MariaDBParser.DECIMAL)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL)
|
|
||||||
.setDefaultLengthScaleDimension(10, 0),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.DECIMAL, MariaDBParser.DEC)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL)
|
|
||||||
.setDefaultLengthScaleDimension(10, 0),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.DECIMAL, MariaDBParser.FIXED)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL)
|
|
||||||
.setDefaultLengthScaleDimension(10, 0),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.NUMERIC, MariaDBParser.NUMERIC)
|
|
||||||
.setSuffixTokens(MariaDBParser.SIGNED, MariaDBParser.UNSIGNED, MariaDBParser.ZEROFILL)
|
|
||||||
.setDefaultLengthScaleDimension(10, 0),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BIT, MariaDBParser.BIT)
|
|
||||||
.setDefaultLengthDimension(1),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.TIME, MariaDBParser.TIME),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.TIMESTAMP_WITH_TIMEZONE, MariaDBParser.TIMESTAMP),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.TIMESTAMP, MariaDBParser.DATETIME),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BINARY, MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARBINARY, MariaDBParser.VARBINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BLOB, MariaDBParser.BLOB),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.INTEGER, MariaDBParser.YEAR)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.SimpleDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.DATE, MariaDBParser.DATE),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BLOB, MariaDBParser.TINYBLOB),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BLOB, MariaDBParser.MEDIUMBLOB),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BLOB, MariaDBParser.LONGBLOB),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BOOLEAN, MariaDBParser.BOOL),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BOOLEAN, MariaDBParser.BOOLEAN),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BIGINT, MariaDBParser.SERIAL)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.CollectionDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.CHAR, MariaDBParser.ENUM).setSuffixTokens(MariaDBParser.BINARY),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.CHAR, MariaDBParser.SET).setSuffixTokens(MariaDBParser.BINARY)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.SpatialDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.GEOMETRYCOLLECTION),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.GEOMCOLLECTION),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.LINESTRING),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.MULTILINESTRING),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.MULTIPOINT),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.MULTIPOLYGON),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.POINT),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.POLYGON),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.JSON),
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.OTHER, MariaDBParser.GEOMETRY)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.LongVarbinaryDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.BLOB, MariaDBParser.LONG)
|
|
||||||
.setSuffixTokens(MariaDBParser.VARBINARY)));
|
|
||||||
|
|
||||||
dataTypeResolverBuilder.registerDataTypes(MariaDBParser.LongVarcharDataTypeContext.class.getCanonicalName(), Arrays.asList(
|
|
||||||
new DataTypeResolver.DataTypeEntry(Types.VARCHAR, MariaDBParser.LONG)
|
|
||||||
.setSuffixTokens(MariaDBParser.VARCHAR)));
|
|
||||||
|
|
||||||
return dataTypeResolverBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the character set registry.
|
|
||||||
*
|
|
||||||
* @return the character set registry
|
|
||||||
*/
|
|
||||||
public BinlogCharsetRegistry getCharsetRegistry() {
|
|
||||||
return charsetRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a map of default character sets by database/schema name.
|
|
||||||
*
|
|
||||||
* @return map of default character sets.
|
|
||||||
*/
|
|
||||||
public ConcurrentMap<String, String> charsetNameForDatabase() {
|
|
||||||
return charsetNameForDatabase;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a name from {@link MariaDBParser.UidContext}.
|
|
||||||
*
|
|
||||||
* @param uidContext uid context
|
|
||||||
* @return name without quotes.
|
|
||||||
*/
|
|
||||||
public String parseName(MariaDBParser.UidContext uidContext) {
|
|
||||||
return withoutQuotes(uidContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse qualified table identification from {@link MariaDBParser.FullIdContext}.
|
|
||||||
* {@link MariaDbAntlrDdlParser#currentSchema()} will be used if definition of schema name is not part of the context.
|
|
||||||
*
|
|
||||||
* @param fullIdContext full id context.
|
|
||||||
* @return qualified {@link TableId}.
|
|
||||||
*/
|
|
||||||
public TableId parseQualifiedTableId(MariaDBParser.FullIdContext fullIdContext) {
|
|
||||||
final char[] fullTableName = fullIdContext.getText().toCharArray();
|
|
||||||
StringBuilder component = new StringBuilder();
|
|
||||||
String dbName = null;
|
|
||||||
String tableName = null;
|
|
||||||
final char EMPTY = '\0';
|
|
||||||
char lastQuote = EMPTY;
|
|
||||||
for (int i = 0; i < fullTableName.length; i++) {
|
|
||||||
char c = fullTableName[i];
|
|
||||||
if (isQuote(c)) {
|
|
||||||
// Opening quote
|
|
||||||
if (lastQuote == EMPTY) {
|
|
||||||
lastQuote = c;
|
|
||||||
}
|
|
||||||
// Closing quote
|
|
||||||
else if (lastQuote == c) {
|
|
||||||
// escape of quote by doubling
|
|
||||||
if (i < fullTableName.length - 1 && fullTableName[i + 1] == c) {
|
|
||||||
component.append(c);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lastQuote = EMPTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Quote that is part of name
|
|
||||||
else {
|
|
||||||
component.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// dot that is not in quotes, so name separator
|
|
||||||
else if (c == '.' && lastQuote == EMPTY) {
|
|
||||||
dbName = component.toString();
|
|
||||||
component = new StringBuilder();
|
|
||||||
}
|
|
||||||
// Any char is part of name including quoted dot
|
|
||||||
else {
|
|
||||||
component.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tableName = component.toString();
|
|
||||||
return resolveTableId(dbName != null ? dbName : currentSchema(), tableName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse column names for primary index from {@link MariaDBParser.IndexColumnNamesContext}. This method will update
|
|
||||||
* column to be not optional and set primary key column names to table.
|
|
||||||
*
|
|
||||||
* @param indexColumnNamesContext primary key index column names context.
|
|
||||||
* @param tableEditor editor for table where primary key index is parsed.
|
|
||||||
*/
|
|
||||||
public void parsePrimaryIndexColumnNames(MariaDBParser.IndexColumnNamesContext indexColumnNamesContext, TableEditor tableEditor) {
|
|
||||||
List<String> pkColumnNames = indexColumnNamesContext.indexColumnName().stream()
|
|
||||||
.map(indexColumnNameContext -> {
|
|
||||||
// MariaDB does not allow a primary key to have nullable columns, so let's make sure we model that correctly ...
|
|
||||||
String columnName;
|
|
||||||
if (indexColumnNameContext.uid() != null) {
|
|
||||||
columnName = parseName(indexColumnNameContext.uid());
|
|
||||||
}
|
|
||||||
else if (indexColumnNameContext.STRING_LITERAL() != null) {
|
|
||||||
columnName = withoutQuotes(indexColumnNameContext.STRING_LITERAL().getText());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnName = indexColumnNameContext.expression().getText();
|
|
||||||
}
|
|
||||||
Column column = tableEditor.columnWithName(columnName);
|
|
||||||
if (column != null && column.isOptional()) {
|
|
||||||
final ColumnEditor ce = column.edit().optional(false);
|
|
||||||
if (ce.hasDefaultValue() && !ce.defaultValueExpression().isPresent()) {
|
|
||||||
ce.unsetDefaultValueExpression();
|
|
||||||
}
|
|
||||||
tableEditor.addColumn(ce.create());
|
|
||||||
}
|
|
||||||
return column != null ? column.name() : columnName;
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
tableEditor.setPrimaryKeyNames(pkColumnNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse column names for unique index from {@link MariaDBParser.IndexColumnNamesContext}. This method will set
|
|
||||||
* unique key column names to table if there are no optional.
|
|
||||||
*
|
|
||||||
* @param indexColumnNamesContext unique key index column names context.
|
|
||||||
* @param tableEditor editor for table where primary key index is parsed.
|
|
||||||
*/
|
|
||||||
public void parseUniqueIndexColumnNames(MariaDBParser.IndexColumnNamesContext indexColumnNamesContext, TableEditor tableEditor) {
|
|
||||||
List<Column> indexColumns = getIndexColumns(indexColumnNamesContext, tableEditor);
|
|
||||||
if (indexColumns.stream().filter(col -> Objects.isNull(col) || col.isOptional()).count() > 0) {
|
|
||||||
logger.warn("Skip to set unique index columns {} to primary key which including optional columns", indexColumns);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tableEditor.setPrimaryKeyNames(indexColumns.stream().map(Column::name).collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a table's unique index should be included when parsing relative unique index statement.
|
|
||||||
*
|
|
||||||
* @param indexColumnNamesContext unique index column names context.
|
|
||||||
* @param tableEditor editor for table where unique index is parsed.
|
|
||||||
* @return true if the index is to be included; false otherwise.
|
|
||||||
*/
|
|
||||||
public boolean isTableUniqueIndexIncluded(MariaDBParser.IndexColumnNamesContext indexColumnNamesContext, TableEditor tableEditor) {
|
|
||||||
return getIndexColumns(indexColumnNamesContext, tableEditor).stream().filter(Objects::isNull).count() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Column> getIndexColumns(MariaDBParser.IndexColumnNamesContext indexColumnNamesContext, TableEditor tableEditor) {
|
|
||||||
return indexColumnNamesContext.indexColumnName().stream()
|
|
||||||
.map(indexColumnNameContext -> {
|
|
||||||
String columnName;
|
|
||||||
if (indexColumnNameContext.uid() != null) {
|
|
||||||
columnName = parseName(indexColumnNameContext.uid());
|
|
||||||
}
|
|
||||||
else if (indexColumnNameContext.STRING_LITERAL() != null) {
|
|
||||||
columnName = withoutQuotes(indexColumnNameContext.STRING_LITERAL().getText());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnName = indexColumnNameContext.expression().getText();
|
|
||||||
}
|
|
||||||
return tableEditor.columnWithName(columnName);
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the character set for the current database, via the "character_set_database" system property.
|
|
||||||
*
|
|
||||||
* @return the name of the character set for the current database, or null if not known ...
|
|
||||||
*/
|
|
||||||
public String currentDatabaseCharset() {
|
|
||||||
String charsetName = systemVariables.getVariable(BinlogSystemVariables.CHARSET_NAME_DATABASE);
|
|
||||||
if (charsetName == null || "DEFAULT".equalsIgnoreCase(charsetName)) {
|
|
||||||
charsetName = systemVariables.getVariable(BinlogSystemVariables.CHARSET_NAME_SERVER);
|
|
||||||
}
|
|
||||||
return charsetName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the character set for the give table name.
|
|
||||||
*
|
|
||||||
* @return the name of the character set for the given table, or null if not known ...
|
|
||||||
*/
|
|
||||||
public String charsetForTable(TableId tableId) {
|
|
||||||
final String defaultDatabaseCharset = tableId.catalog() != null ? charsetNameForDatabase().get(tableId.catalog()) : null;
|
|
||||||
return defaultDatabaseCharset != null ? defaultDatabaseCharset : currentDatabaseCharset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a function if all given object are not null.
|
|
||||||
*
|
|
||||||
* @param function function to run; may not be null
|
|
||||||
* @param nullableObjects object to be tested, if they are null.
|
|
||||||
*/
|
|
||||||
public void runIfNotNull(Runnable function, Object... nullableObjects) {
|
|
||||||
for (Object nullableObject : nullableObjects) {
|
|
||||||
if (nullableObject == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the enumeration values properly parsed and escaped.
|
|
||||||
*
|
|
||||||
* @param enumValues the raw enumeration values from the parsed column definition
|
|
||||||
* @return the list of options allowed for the {@code ENUM} or {@code SET}; never null.
|
|
||||||
*/
|
|
||||||
public static List<String> extractEnumAndSetOptions(List<String> enumValues) {
|
|
||||||
return enumValues.stream()
|
|
||||||
.map(MariaDbAntlrDdlParser::withoutQuotes)
|
|
||||||
.map(MariaDbAntlrDdlParser::escapeOption)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String escapeOption(String option) {
|
|
||||||
// Replace comma to backslash followed by comma (this escape sequence implies comma is part of the option)
|
|
||||||
// Replace backlash+single-quote to a single-quote.
|
|
||||||
// Replace double single-quote to a single-quote.
|
|
||||||
return option.replaceAll(",", "\\\\,").replaceAll("\\\\'", "'").replace("''", "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbValueConverters getConverters() {
|
|
||||||
return converters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tables.TableFilter getTableFilter() {
|
|
||||||
return tableFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains the charset name either form charset if present or from collation.
|
|
||||||
*
|
|
||||||
* @param charsetNode
|
|
||||||
* @param collationNode
|
|
||||||
* @return character set
|
|
||||||
*/
|
|
||||||
public String extractCharset(CharsetNameContext charsetNode, CollationNameContext collationNode) {
|
|
||||||
String charsetName = null;
|
|
||||||
if (charsetNode != null && charsetNode.getText() != null) {
|
|
||||||
charsetName = withoutQuotes(charsetNode.getText());
|
|
||||||
// System.out.println("[charSetNode]: charSetName => " + charsetName + " (" + charsetNode.getText() + ")");
|
|
||||||
}
|
|
||||||
else if (collationNode != null && collationNode.getText() != null) {
|
|
||||||
final String collationName = withoutQuotes(collationNode.getText()).toLowerCase();
|
|
||||||
for (int index = 0; index < charsetRegistry.getCharsetMapSize(); index++) {
|
|
||||||
if (collationName.equals(charsetRegistry.getCollationNameForCollationIndex(index))) {
|
|
||||||
charsetName = charsetRegistry.getCharsetNameForCollationIndex(index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// System.out.println("[collationNode]: charSetName => " + charsetName + " (" + collationNode.getText() + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
return charsetName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal an alter table event to ddl changes listener.
|
|
||||||
*
|
|
||||||
* @param id the table identifier; may not be null
|
|
||||||
* @param previousId the previous name of the view if it was renamed, or null if it was not renamed
|
|
||||||
* @param ctx the start of the statement; may not be null
|
|
||||||
*/
|
|
||||||
public void signalAlterTable(TableId id, TableId previousId, RenameTableClauseContext ctx) {
|
|
||||||
final RenameTableContext parent = (RenameTableContext) ctx.getParent();
|
|
||||||
Interval interval = new Interval(ctx.getParent().start.getStartIndex(),
|
|
||||||
parent.renameTableClause().get(0).start.getStartIndex() - 1);
|
|
||||||
String prefix = ctx.getParent().start.getInputStream().getText(interval);
|
|
||||||
signalAlterTable(id, previousId, prefix + getText(ctx));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,362 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import static io.debezium.antlr.AntlrDdlParser.getText;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.ColumnEditor;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.text.ParsingException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A parser listener that parses ALTER TABLE statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class AlterTableParserListener extends TableCommonParserListener {
|
|
||||||
|
|
||||||
private static final int STARTING_INDEX = 1;
|
|
||||||
|
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(AlterTableParserListener.class);
|
|
||||||
|
|
||||||
private ColumnEditor defaultValueColumnEditor;
|
|
||||||
private DefaultValueParserListener defaultValueListener;
|
|
||||||
|
|
||||||
private List<ColumnEditor> columnEditors;
|
|
||||||
private int parsingColumnIndex = STARTING_INDEX;
|
|
||||||
|
|
||||||
public AlterTableParserListener(MariaDbAntlrDdlParser parser, List<ParseTreeListener> listeners) {
|
|
||||||
super(parser, listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterTable(MariaDBParser.AlterTableContext ctx) {
|
|
||||||
final TableId tableId = parser.parseQualifiedTableId(ctx.tableName().fullId());
|
|
||||||
if (parser.databaseTables().forTable(tableId) == null) {
|
|
||||||
LOG.debug("Ignoring ALTER TABLE statement for non-captured table {}", tableId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tableEditor = parser.databaseTables().editTable(tableId);
|
|
||||||
if (tableEditor == null) {
|
|
||||||
throw new ParsingException(null, "Trying to alter table " + tableId.toString()
|
|
||||||
+ ", which does not exist. Query: " + getText(ctx));
|
|
||||||
}
|
|
||||||
super.enterAlterTable(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterTable(MariaDBParser.AlterTableContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
listeners.remove(columnDefinitionListener);
|
|
||||||
parser.databaseTables().overwriteTable(tableEditor.create());
|
|
||||||
parser.signalAlterTable(tableEditor.tableId(), null, ctx.getParent());
|
|
||||||
}, tableEditor);
|
|
||||||
super.exitAlterTable(ctx);
|
|
||||||
tableEditor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByAddColumn(MariaDBParser.AlterByAddColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
String columnName = parser.parseName(ctx.uid(0));
|
|
||||||
ColumnEditor columnEditor = Column.editor().name(columnName);
|
|
||||||
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parser, listeners);
|
|
||||||
listeners.add(columnDefinitionListener);
|
|
||||||
}, tableEditor);
|
|
||||||
super.exitAlterByAddColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterByAddColumn(MariaDBParser.AlterByAddColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
Column column = columnDefinitionListener.getColumn();
|
|
||||||
tableEditor.addColumn(column);
|
|
||||||
|
|
||||||
String columnName = column.name();
|
|
||||||
if (ctx.FIRST() != null) {
|
|
||||||
tableEditor.reorderColumn(columnName, null);
|
|
||||||
}
|
|
||||||
else if (ctx.AFTER() != null) {
|
|
||||||
String afterColumn = parser.parseName(ctx.uid(1));
|
|
||||||
tableEditor.reorderColumn(columnName, afterColumn);
|
|
||||||
}
|
|
||||||
listeners.remove(columnDefinitionListener);
|
|
||||||
}, tableEditor, columnDefinitionListener);
|
|
||||||
super.exitAlterByAddColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByAddColumns(MariaDBParser.AlterByAddColumnsContext ctx) {
|
|
||||||
// multiple columns are added. Initialize a list of column editors for them
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
columnEditors = new ArrayList<>(ctx.uid().size());
|
|
||||||
for (MariaDBParser.UidContext uidContext : ctx.uid()) {
|
|
||||||
String columnName = parser.parseName(uidContext);
|
|
||||||
columnEditors.add(Column.editor().name(columnName));
|
|
||||||
}
|
|
||||||
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditors.get(0), parser, listeners);
|
|
||||||
listeners.add(columnDefinitionListener);
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByAddColumns(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitColumnDefinition(MariaDBParser.ColumnDefinitionContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
if (columnEditors != null) {
|
|
||||||
// column editor list is not null when a multiple columns are parsed in one statement
|
|
||||||
if (columnEditors.size() > parsingColumnIndex) {
|
|
||||||
// assign next column editor to parse another column definition
|
|
||||||
columnDefinitionListener.setColumnEditor(columnEditors.get(parsingColumnIndex++));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// all columns parsed
|
|
||||||
// reset global variables for next parsed statement
|
|
||||||
columnEditors.forEach(columnEditor -> tableEditor.addColumn(columnEditor.create()));
|
|
||||||
columnEditors = null;
|
|
||||||
parsingColumnIndex = STARTING_INDEX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, tableEditor, columnEditors);
|
|
||||||
super.exitColumnDefinition(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterByAddColumns(MariaDBParser.AlterByAddColumnsContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
columnEditors.forEach(columnEditor -> tableEditor.addColumn(columnEditor.create()));
|
|
||||||
listeners.remove(columnDefinitionListener);
|
|
||||||
}, tableEditor, columnEditors);
|
|
||||||
super.exitAlterByAddColumns(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByChangeColumn(MariaDBParser.AlterByChangeColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
String oldColumnName = parser.parseName(ctx.oldColumn);
|
|
||||||
Column existingColumn = tableEditor.columnWithName(oldColumnName);
|
|
||||||
if (existingColumn != null) {
|
|
||||||
// DBZ-771 unset previously set default value, as it's not kept by MariaDB; for any column modifications a new
|
|
||||||
// default value (which could be the same) has to be provided by the column_definition which we'll parse later
|
|
||||||
// on; only in 8.0 (not yet supported by this parser) columns can be renamed without repeating the full column
|
|
||||||
// definition; so in fact it's arguably not correct to use edit() on the existing column to begin with, but
|
|
||||||
// I'm going to leave this as is for now, to be prepared for the ability of updating column definitions in 8.0
|
|
||||||
ColumnEditor columnEditor = existingColumn.edit();
|
|
||||||
columnEditor.unsetDefaultValueExpression();
|
|
||||||
columnEditor.unsetLength();
|
|
||||||
if (columnEditor.scale().isPresent()) {
|
|
||||||
columnEditor.unsetScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parser, listeners);
|
|
||||||
listeners.add(columnDefinitionListener);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new ParsingException(null, "Trying to change column " + oldColumnName + " in "
|
|
||||||
+ tableEditor.tableId().toString() + " table, which does not exist. Query: " + getText(ctx));
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByChangeColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterByChangeColumn(MariaDBParser.AlterByChangeColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
Column column = columnDefinitionListener.getColumn();
|
|
||||||
tableEditor.addColumn(column);
|
|
||||||
String newColumnName = parser.parseName(ctx.newColumn);
|
|
||||||
if (newColumnName != null && !column.name().equals(newColumnName)) {
|
|
||||||
tableEditor.renameColumn(column.name(), newColumnName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.FIRST() != null) {
|
|
||||||
tableEditor.reorderColumn(newColumnName, null);
|
|
||||||
}
|
|
||||||
else if (ctx.afterColumn != null) {
|
|
||||||
tableEditor.reorderColumn(newColumnName, parser.parseName(ctx.afterColumn));
|
|
||||||
}
|
|
||||||
listeners.remove(columnDefinitionListener);
|
|
||||||
}, tableEditor, columnDefinitionListener);
|
|
||||||
super.exitAlterByChangeColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByModifyColumn(MariaDBParser.AlterByModifyColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
String columnName = parser.parseName(ctx.uid(0));
|
|
||||||
Column existingColumn = tableEditor.columnWithName(columnName);
|
|
||||||
if (existingColumn != null) {
|
|
||||||
ColumnEditor columnEditor = Column.editor().name(columnName);
|
|
||||||
|
|
||||||
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parser, listeners);
|
|
||||||
listeners.add(columnDefinitionListener);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new ParsingException(null, "Trying to change column " + columnName + " in "
|
|
||||||
+ tableEditor.tableId().toString() + " table, which does not exist. Query: " + getText(ctx));
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByModifyColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterByModifyColumn(MariaDBParser.AlterByModifyColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
Column column = columnDefinitionListener.getColumn();
|
|
||||||
tableEditor.addColumn(column);
|
|
||||||
|
|
||||||
if (ctx.FIRST() != null) {
|
|
||||||
tableEditor.reorderColumn(column.name(), null);
|
|
||||||
}
|
|
||||||
else if (ctx.AFTER() != null) {
|
|
||||||
String afterColumn = parser.parseName(ctx.uid(1));
|
|
||||||
tableEditor.reorderColumn(column.name(), afterColumn);
|
|
||||||
}
|
|
||||||
listeners.remove(columnDefinitionListener);
|
|
||||||
}, tableEditor, columnDefinitionListener);
|
|
||||||
super.exitAlterByModifyColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByDropColumn(MariaDBParser.AlterByDropColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
tableEditor.removeColumn(parser.parseName(ctx.uid()));
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByDropColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByRename(MariaDBParser.AlterByRenameContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
final TableId newTableId = ctx.uid() != null
|
|
||||||
? parser.resolveTableId(parser.currentSchema(), parser.parseName(ctx.uid()))
|
|
||||||
: parser.parseQualifiedTableId(ctx.fullId());
|
|
||||||
parser.databaseTables().overwriteTable(tableEditor.create());
|
|
||||||
parser.databaseTables().renameTable(tableEditor.tableId(), newTableId);
|
|
||||||
tableEditor = parser.databaseTables().editTable(newTableId);
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByRename(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByChangeDefault(MariaDBParser.AlterByChangeDefaultContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
String columnName = parser.parseName(ctx.uid());
|
|
||||||
Column column = tableEditor.columnWithName(columnName);
|
|
||||||
if (column != null) {
|
|
||||||
defaultValueColumnEditor = column.edit();
|
|
||||||
if (ctx.SET() != null) {
|
|
||||||
defaultValueListener = new DefaultValueParserListener(defaultValueColumnEditor,
|
|
||||||
new AtomicReference<>(column.isOptional()));
|
|
||||||
listeners.add(defaultValueListener);
|
|
||||||
}
|
|
||||||
else if (ctx.DROP() != null) {
|
|
||||||
defaultValueColumnEditor.unsetDefaultValueExpression();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByChangeDefault(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterByChangeDefault(MariaDBParser.AlterByChangeDefaultContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
tableEditor.updateColumn(defaultValueColumnEditor.create());
|
|
||||||
listeners.remove(defaultValueListener);
|
|
||||||
defaultValueColumnEditor = null;
|
|
||||||
}, defaultValueColumnEditor);
|
|
||||||
super.exitAlterByChangeDefault(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByAddPrimaryKey(MariaDBParser.AlterByAddPrimaryKeyContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
parser.parsePrimaryIndexColumnNames(ctx.indexColumnNames(), tableEditor);
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByAddPrimaryKey(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByDropPrimaryKey(MariaDBParser.AlterByDropPrimaryKeyContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
tableEditor.setPrimaryKeyNames(new ArrayList<>());
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByDropPrimaryKey(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByAddUniqueKey(MariaDBParser.AlterByAddUniqueKeyContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
if (!tableEditor.hasPrimaryKey() && parser.isTableUniqueIndexIncluded(ctx.indexColumnNames(), tableEditor)) {
|
|
||||||
// this may eventually get overwritten by a real PK
|
|
||||||
parser.parseUniqueIndexColumnNames(ctx.indexColumnNames(), tableEditor);
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByAddUniqueKey(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterByRenameColumn(MariaDBParser.AlterByRenameColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
String oldColumnName = parser.parseName(ctx.oldColumn);
|
|
||||||
Column existingColumn = tableEditor.columnWithName(oldColumnName);
|
|
||||||
if (existingColumn != null) {
|
|
||||||
// DBZ-771 unset previously set default value, as it's not kept by MariaDB; for any column modifications a new
|
|
||||||
// default value (which could be the same) has to be provided by the column_definition which we'll parse later
|
|
||||||
// on; only in 8.0 (not yet supported by this parser) columns can be renamed without repeating the full column
|
|
||||||
// definition; so in fact it's arguably not correct to use edit() on the existing column to begin with, but
|
|
||||||
// I'm going to leave this as is for now, to be prepared for the ability of updating column definitions in 8.0
|
|
||||||
ColumnEditor columnEditor = existingColumn.edit();
|
|
||||||
// columnEditor.unsetDefaultValue();
|
|
||||||
|
|
||||||
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parser, listeners);
|
|
||||||
listeners.add(columnDefinitionListener);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new ParsingException(null, "Trying to change column " + oldColumnName + " in "
|
|
||||||
+ tableEditor.tableId().toString() + " table, which does not exist. Query: " + getText(ctx));
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterAlterByRenameColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterByRenameColumn(MariaDBParser.AlterByRenameColumnContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
Column column = columnDefinitionListener.getColumn();
|
|
||||||
tableEditor.addColumn(column);
|
|
||||||
String newColumnName = parser.parseName(ctx.newColumn);
|
|
||||||
if (newColumnName != null && !column.name().equals(newColumnName)) {
|
|
||||||
tableEditor.renameColumn(column.name(), newColumnName);
|
|
||||||
}
|
|
||||||
listeners.remove(columnDefinitionListener);
|
|
||||||
}, tableEditor, columnDefinitionListener);
|
|
||||||
super.exitAlterByRenameColumn(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterTableOptionComment(MariaDBParser.TableOptionCommentContext ctx) {
|
|
||||||
if (!parser.skipComments()) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
if (ctx.COMMENT() != null) {
|
|
||||||
tableEditor.setComment(parser.withoutQuotes(ctx.STRING_LITERAL().getText()));
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
}
|
|
||||||
super.enterTableOptionComment(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
|
|
||||||
import io.debezium.antlr.AntlrDdlParser;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.TableEditor;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.text.ParsingException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener that parses ALTER VIEW statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class AlterViewParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
private final List<ParseTreeListener> listeners;
|
|
||||||
|
|
||||||
private TableEditor tableEditor;
|
|
||||||
private ViewSelectedColumnsParserListener selectColumnsListener;
|
|
||||||
|
|
||||||
public AlterViewParserListener(MariaDbAntlrDdlParser parser, List<ParseTreeListener> listeners) {
|
|
||||||
this.parser = parser;
|
|
||||||
this.listeners = listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterView(MariaDBParser.AlterViewContext ctx) {
|
|
||||||
if (!parser.skipViews()) {
|
|
||||||
TableId tableId = parser.parseQualifiedTableId(ctx.fullId());
|
|
||||||
|
|
||||||
tableEditor = parser.databaseTables().editTable(tableId);
|
|
||||||
if (tableEditor == null) {
|
|
||||||
throw new ParsingException(null, "Trying to alter view " + tableId.toString()
|
|
||||||
+ ", which does not exist. Query:" + AntlrDdlParser.getText(ctx));
|
|
||||||
}
|
|
||||||
// alter view will override existing columns for a new one
|
|
||||||
tableEditor.columnNames().forEach(tableEditor::removeColumn);
|
|
||||||
// create new columns just with specified name for now
|
|
||||||
if (ctx.uidList() != null) {
|
|
||||||
ctx.uidList().uid().stream().map(parser::parseName).forEach(columnName -> {
|
|
||||||
tableEditor.addColumn(Column.editor().name(columnName).create());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
selectColumnsListener = new ViewSelectedColumnsParserListener(tableEditor, parser);
|
|
||||||
listeners.add(selectColumnsListener);
|
|
||||||
}
|
|
||||||
super.enterAlterView(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAlterView(MariaDBParser.AlterViewContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
tableEditor.addColumns(selectColumnsListener.getSelectedColumns());
|
|
||||||
// Make sure that the table's character set has been set ...
|
|
||||||
if (!tableEditor.hasDefaultCharsetName()) {
|
|
||||||
tableEditor.setDefaultCharsetName(parser.currentDatabaseCharset());
|
|
||||||
}
|
|
||||||
parser.databaseTables().overwriteTable(tableEditor.create());
|
|
||||||
listeners.remove(selectColumnsListener);
|
|
||||||
}, tableEditor);
|
|
||||||
// signal view even if it was skipped
|
|
||||||
parser.signalAlterView(parser.parseQualifiedTableId(ctx.fullId()), null, ctx);
|
|
||||||
super.exitAlterView(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,304 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import java.sql.Types;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.antlr.AntlrDdlParser;
|
|
||||||
import io.debezium.antlr.DataTypeResolver;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.ColumnEditor;
|
|
||||||
import io.debezium.relational.TableEditor;
|
|
||||||
import io.debezium.relational.ddl.DataType;
|
|
||||||
import io.debezium.util.Strings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for column definitions.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ColumnDefinitionParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ColumnDefinitionParserListener.class);
|
|
||||||
|
|
||||||
private static final Pattern DOT = Pattern.compile("\\.");
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
private final DataTypeResolver dataTypeResolver;
|
|
||||||
private final TableEditor tableEditor;
|
|
||||||
private ColumnEditor columnEditor;
|
|
||||||
private boolean uniqueColumn;
|
|
||||||
private AtomicReference<Boolean> optionalColumn = new AtomicReference<>();
|
|
||||||
private DefaultValueParserListener defaultValueListener;
|
|
||||||
|
|
||||||
private final List<ParseTreeListener> listeners;
|
|
||||||
|
|
||||||
public ColumnDefinitionParserListener(TableEditor tableEditor,
|
|
||||||
ColumnEditor columnEditor,
|
|
||||||
MariaDbAntlrDdlParser parser,
|
|
||||||
List<ParseTreeListener> listeners) {
|
|
||||||
this.tableEditor = tableEditor;
|
|
||||||
this.columnEditor = columnEditor;
|
|
||||||
this.parser = parser;
|
|
||||||
this.dataTypeResolver = parser.dataTypeResolver();
|
|
||||||
this.listeners = listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumnEditor(ColumnEditor columnEditor) {
|
|
||||||
this.columnEditor = columnEditor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ColumnEditor getColumnEditor() {
|
|
||||||
return columnEditor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Column getColumn() {
|
|
||||||
return columnEditor.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterColumnDefinition(MariaDBParser.ColumnDefinitionContext ctx) {
|
|
||||||
uniqueColumn = false;
|
|
||||||
optionalColumn = new AtomicReference<>();
|
|
||||||
resolveColumnDataType(ctx.dataType());
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
defaultValueListener = new DefaultValueParserListener(columnEditor, optionalColumn);
|
|
||||||
listeners.add(defaultValueListener);
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterColumnDefinition(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitColumnDefinition(MariaDBParser.ColumnDefinitionContext ctx) {
|
|
||||||
if (optionalColumn.get() != null) {
|
|
||||||
columnEditor.optional(optionalColumn.get().booleanValue());
|
|
||||||
}
|
|
||||||
if (uniqueColumn && !tableEditor.hasPrimaryKey()) {
|
|
||||||
// take the first unique constrain if no primary key is set
|
|
||||||
tableEditor.addColumn(columnEditor.create());
|
|
||||||
tableEditor.setPrimaryKeyNames(columnEditor.name());
|
|
||||||
}
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
defaultValueListener.exitDefaultValue(false);
|
|
||||||
listeners.remove(defaultValueListener);
|
|
||||||
}, tableEditor);
|
|
||||||
super.exitColumnDefinition(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterUniqueKeyColumnConstraint(MariaDBParser.UniqueKeyColumnConstraintContext ctx) {
|
|
||||||
uniqueColumn = true;
|
|
||||||
super.enterUniqueKeyColumnConstraint(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterPrimaryKeyColumnConstraint(MariaDBParser.PrimaryKeyColumnConstraintContext ctx) {
|
|
||||||
// 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
|
|
||||||
optionalColumn.set(Boolean.FALSE);
|
|
||||||
tableEditor.addColumn(columnEditor.create());
|
|
||||||
tableEditor.setPrimaryKeyNames(columnEditor.name());
|
|
||||||
super.enterPrimaryKeyColumnConstraint(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterCommentColumnConstraint(MariaDBParser.CommentColumnConstraintContext ctx) {
|
|
||||||
if (!parser.skipComments()) {
|
|
||||||
if (ctx.STRING_LITERAL() != null) {
|
|
||||||
columnEditor.comment(parser.withoutQuotes(ctx.STRING_LITERAL().getText()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.enterCommentColumnConstraint(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterNullNotnull(MariaDBParser.NullNotnullContext ctx) {
|
|
||||||
optionalColumn.set(Boolean.valueOf(ctx.NOT() == null));
|
|
||||||
super.enterNullNotnull(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAutoIncrementColumnConstraint(MariaDBParser.AutoIncrementColumnConstraintContext ctx) {
|
|
||||||
columnEditor.autoIncremented(true);
|
|
||||||
columnEditor.generated(true);
|
|
||||||
super.enterAutoIncrementColumnConstraint(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterSerialDefaultColumnConstraint(MariaDBParser.SerialDefaultColumnConstraintContext ctx) {
|
|
||||||
serialColumn();
|
|
||||||
super.enterSerialDefaultColumnConstraint(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resolveColumnDataType(MariaDBParser.DataTypeContext dataTypeContext) {
|
|
||||||
String charsetName = null;
|
|
||||||
DataType dataType = dataTypeResolver.resolveDataType(dataTypeContext);
|
|
||||||
|
|
||||||
if (dataTypeContext instanceof MariaDBParser.StringDataTypeContext) {
|
|
||||||
// Same as LongVarcharDataTypeContext but with dimension handling
|
|
||||||
MariaDBParser.StringDataTypeContext stringDataTypeContext = (MariaDBParser.StringDataTypeContext) dataTypeContext;
|
|
||||||
|
|
||||||
if (stringDataTypeContext.lengthOneDimension() != null) {
|
|
||||||
Integer length = parseLength(stringDataTypeContext.lengthOneDimension().decimalLiteral().getText());
|
|
||||||
columnEditor.length(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
charsetName = parser.extractCharset(stringDataTypeContext.charsetName(), stringDataTypeContext.collationName());
|
|
||||||
}
|
|
||||||
else if (dataTypeContext instanceof MariaDBParser.LongVarcharDataTypeContext) {
|
|
||||||
// Same as StringDataTypeContext but without dimension handling
|
|
||||||
MariaDBParser.LongVarcharDataTypeContext longVarcharTypeContext = (MariaDBParser.LongVarcharDataTypeContext) dataTypeContext;
|
|
||||||
|
|
||||||
charsetName = parser.extractCharset(longVarcharTypeContext.charsetName(), longVarcharTypeContext.collationName());
|
|
||||||
}
|
|
||||||
else if (dataTypeContext instanceof MariaDBParser.NationalStringDataTypeContext) {
|
|
||||||
MariaDBParser.NationalStringDataTypeContext nationalStringDataTypeContext = (MariaDBParser.NationalStringDataTypeContext) dataTypeContext;
|
|
||||||
|
|
||||||
if (nationalStringDataTypeContext.lengthOneDimension() != null) {
|
|
||||||
Integer length = parseLength(nationalStringDataTypeContext.lengthOneDimension().decimalLiteral().getText());
|
|
||||||
columnEditor.length(length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dataTypeContext instanceof MariaDBParser.NationalVaryingStringDataTypeContext) {
|
|
||||||
MariaDBParser.NationalVaryingStringDataTypeContext nationalVaryingStringDataTypeContext = (MariaDBParser.NationalVaryingStringDataTypeContext) dataTypeContext;
|
|
||||||
|
|
||||||
if (nationalVaryingStringDataTypeContext.lengthOneDimension() != null) {
|
|
||||||
Integer length = parseLength(nationalVaryingStringDataTypeContext.lengthOneDimension().decimalLiteral().getText());
|
|
||||||
columnEditor.length(length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dataTypeContext instanceof MariaDBParser.DimensionDataTypeContext) {
|
|
||||||
MariaDBParser.DimensionDataTypeContext dimensionDataTypeContext = (MariaDBParser.DimensionDataTypeContext) dataTypeContext;
|
|
||||||
|
|
||||||
Integer length = null;
|
|
||||||
Integer scale = null;
|
|
||||||
if (dimensionDataTypeContext.lengthOneDimension() != null) {
|
|
||||||
length = parseLength(dimensionDataTypeContext.lengthOneDimension().decimalLiteral().getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dimensionDataTypeContext.lengthTwoDimension() != null) {
|
|
||||||
List<MariaDBParser.DecimalLiteralContext> decimalLiterals = dimensionDataTypeContext.lengthTwoDimension().decimalLiteral();
|
|
||||||
length = parseLength(decimalLiterals.get(0).getText());
|
|
||||||
scale = Integer.valueOf(decimalLiterals.get(1).getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dimensionDataTypeContext.lengthTwoOptionalDimension() != null) {
|
|
||||||
List<MariaDBParser.DecimalLiteralContext> decimalLiterals = dimensionDataTypeContext.lengthTwoOptionalDimension().decimalLiteral();
|
|
||||||
if (decimalLiterals.get(0).REAL_LITERAL() != null) {
|
|
||||||
String[] digits = DOT.split(decimalLiterals.get(0).getText());
|
|
||||||
if (Strings.isNullOrEmpty(digits[0]) || Integer.valueOf(digits[0]) == 0) {
|
|
||||||
// Set default value 10 according mariadb engine
|
|
||||||
length = 10;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
length = parseLength(digits[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
length = parseLength(decimalLiterals.get(0).getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decimalLiterals.size() > 1) {
|
|
||||||
scale = Integer.valueOf(decimalLiterals.get(1).getText());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (length != null) {
|
|
||||||
columnEditor.length(length);
|
|
||||||
}
|
|
||||||
if (scale != null) {
|
|
||||||
columnEditor.scale(scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dataTypeContext instanceof MariaDBParser.CollectionDataTypeContext) {
|
|
||||||
MariaDBParser.CollectionDataTypeContext collectionDataTypeContext = (MariaDBParser.CollectionDataTypeContext) dataTypeContext;
|
|
||||||
if (collectionDataTypeContext.charsetName() != null) {
|
|
||||||
charsetName = collectionDataTypeContext.charsetName().getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataType.name().equalsIgnoreCase("SET")) {
|
|
||||||
// After DBZ-132, it will always be comma separated
|
|
||||||
int optionsSize = collectionDataTypeContext.collectionOptions().collectionOption().size();
|
|
||||||
columnEditor.length(Math.max(0, optionsSize * 2 - 1)); // number of options + number of commas
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnEditor.length(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String dataTypeName = dataType.name().toUpperCase();
|
|
||||||
|
|
||||||
if (dataTypeName.equals("ENUM") || dataTypeName.equals("SET")) {
|
|
||||||
// type expression has to be set, because the value converter needs to know the enum or set options
|
|
||||||
MariaDBParser.CollectionDataTypeContext collectionDataTypeContext = (MariaDBParser.CollectionDataTypeContext) dataTypeContext;
|
|
||||||
|
|
||||||
List<String> collectionOptions = collectionDataTypeContext.collectionOptions().collectionOption().stream()
|
|
||||||
.map(AntlrDdlParser::getText)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
columnEditor.type(dataTypeName);
|
|
||||||
columnEditor.enumValues(collectionOptions);
|
|
||||||
}
|
|
||||||
else if (dataTypeName.equals("SERIAL")) {
|
|
||||||
// SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
|
|
||||||
columnEditor.type("BIGINT UNSIGNED");
|
|
||||||
serialColumn();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnEditor.type(dataTypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
int jdbcDataType = dataType.jdbcType();
|
|
||||||
columnEditor.jdbcType(jdbcDataType);
|
|
||||||
|
|
||||||
if (columnEditor.length() == -1) {
|
|
||||||
columnEditor.length((int) dataType.length());
|
|
||||||
}
|
|
||||||
if (!columnEditor.scale().isPresent() && dataType.scale() != Column.UNSET_INT_VALUE) {
|
|
||||||
columnEditor.scale(dataType.scale());
|
|
||||||
}
|
|
||||||
if (Types.NCHAR == jdbcDataType || Types.NVARCHAR == jdbcDataType) {
|
|
||||||
// NCHAR and NVARCHAR columns always uses utf8 as charset
|
|
||||||
columnEditor.charsetName("utf8");
|
|
||||||
|
|
||||||
if (Types.NCHAR == jdbcDataType && columnEditor.length() == -1) {
|
|
||||||
// Explicitly set NCHAR column size as 1 when no length specified
|
|
||||||
columnEditor.length(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnEditor.charsetName(charsetName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer parseLength(String lengthStr) {
|
|
||||||
Long length = Long.parseLong(lengthStr);
|
|
||||||
if (length > Integer.MAX_VALUE) {
|
|
||||||
LOGGER.warn("The length '{}' of the column `{}`.`{}` is too large to be supported, truncating it to '{}'",
|
|
||||||
length, tableEditor.tableId(), columnEditor.name(), Integer.MAX_VALUE);
|
|
||||||
length = (long) Integer.MAX_VALUE;
|
|
||||||
}
|
|
||||||
return length.intValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void serialColumn() {
|
|
||||||
if (optionalColumn.get() == null) {
|
|
||||||
optionalColumn.set(Boolean.FALSE);
|
|
||||||
}
|
|
||||||
uniqueColumn = true;
|
|
||||||
columnEditor.autoIncremented(true);
|
|
||||||
columnEditor.generated(true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogSystemVariables;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for CREATE DATABASE and ALTER DATABASE statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class CreateAndAlterDatabaseParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
private String databaseName;
|
|
||||||
|
|
||||||
public CreateAndAlterDatabaseParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterCreateDatabase(MariaDBParser.CreateDatabaseContext ctx) {
|
|
||||||
databaseName = parser.parseName(ctx.uid());
|
|
||||||
super.enterCreateDatabase(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitCreateDatabase(MariaDBParser.CreateDatabaseContext ctx) {
|
|
||||||
parser.signalCreateDatabase(databaseName, ctx);
|
|
||||||
super.exitCreateDatabase(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterAlterSimpleDatabase(MariaDBParser.AlterSimpleDatabaseContext ctx) {
|
|
||||||
databaseName = ctx.uid() == null ? parser.currentSchema() : parser.parseName(ctx.uid());
|
|
||||||
super.enterAlterSimpleDatabase(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterCreateDatabaseOption(MariaDBParser.CreateDatabaseOptionContext ctx) {
|
|
||||||
String charsetName = parser.extractCharset(ctx.charsetName(), ctx.collationName());
|
|
||||||
if (ctx.charsetName() != null) {
|
|
||||||
if ("DEFAULT".equalsIgnoreCase(charsetName)) {
|
|
||||||
charsetName = parser.systemVariables().getVariable(BinlogSystemVariables.CHARSET_NAME_SERVER);
|
|
||||||
}
|
|
||||||
parser.charsetNameForDatabase().put(databaseName, charsetName);
|
|
||||||
}
|
|
||||||
// Collation is used only if the database charset was not set by charset setting
|
|
||||||
else if (ctx.charsetName() != null && !parser.charsetNameForDatabase().containsKey(charsetName)) {
|
|
||||||
parser.charsetNameForDatabase().put(databaseName, charsetName);
|
|
||||||
}
|
|
||||||
super.enterCreateDatabaseOption(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.relational.ColumnEditor;
|
|
||||||
import io.debezium.relational.Table;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for CREATE TABLE statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class CreateTableParserListener extends TableCommonParserListener {
|
|
||||||
|
|
||||||
public CreateTableParserListener(MariaDbAntlrDdlParser parser, List<ParseTreeListener> listeners) {
|
|
||||||
super(parser, listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterColumnCreateTable(MariaDBParser.ColumnCreateTableContext ctx) {
|
|
||||||
TableId tableId = parser.parseQualifiedTableId(ctx.tableName().fullId());
|
|
||||||
if (parser.databaseTables().forTable(tableId) == null) {
|
|
||||||
tableEditor = parser.databaseTables().editOrCreateTable(tableId);
|
|
||||||
super.enterColumnCreateTable(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitColumnCreateTable(MariaDBParser.ColumnCreateTableContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
// Make sure that the table's character set has been set ...
|
|
||||||
if (!tableEditor.hasDefaultCharsetName()) {
|
|
||||||
tableEditor.setDefaultCharsetName(parser.charsetForTable(tableEditor.tableId()));
|
|
||||||
}
|
|
||||||
listeners.remove(columnDefinitionListener);
|
|
||||||
columnDefinitionListener = null;
|
|
||||||
// remove column definition parser listener
|
|
||||||
final String defaultCharsetName = tableEditor.create().defaultCharsetName();
|
|
||||||
tableEditor.setColumns(tableEditor.columns().stream()
|
|
||||||
.map(
|
|
||||||
column -> {
|
|
||||||
final ColumnEditor columnEditor = column.edit();
|
|
||||||
if (columnEditor.charsetNameOfTable() == null) {
|
|
||||||
columnEditor.charsetNameOfTable(defaultCharsetName);
|
|
||||||
}
|
|
||||||
return columnEditor;
|
|
||||||
})
|
|
||||||
.map(ColumnEditor::create)
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
parser.databaseTables().overwriteTable(tableEditor.create());
|
|
||||||
parser.signalCreateTable(tableEditor.tableId(), ctx);
|
|
||||||
}, tableEditor);
|
|
||||||
super.exitColumnCreateTable(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitCopyCreateTable(MariaDBParser.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(), original.attributes());
|
|
||||||
parser.signalCreateTable(tableId, ctx);
|
|
||||||
}
|
|
||||||
super.exitCopyCreateTable(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterTableOptionCharset(MariaDBParser.TableOptionCharsetContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
if (ctx.charsetName() != null) {
|
|
||||||
tableEditor.setDefaultCharsetName(parser.withoutQuotes(ctx.charsetName()));
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterTableOptionCharset(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterTableOptionComment(MariaDBParser.TableOptionCommentContext ctx) {
|
|
||||||
if (!parser.skipComments()) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
if (ctx.COMMENT() != null) {
|
|
||||||
tableEditor.setComment(parser.withoutQuotes(ctx.STRING_LITERAL().getText()));
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
}
|
|
||||||
super.enterTableOptionComment(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import static io.debezium.antlr.AntlrDdlParser.getText;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.TableEditor;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
import io.debezium.text.ParsingException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for CREATE UNIQUE INDEX statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class CreateUniqueIndexParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(AlterTableParserListener.class);
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public CreateUniqueIndexParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterCreateIndex(MariaDBParser.CreateIndexContext ctx) {
|
|
||||||
if (ctx.UNIQUE() != null) {
|
|
||||||
TableId tableId = parser.parseQualifiedTableId(ctx.tableName().fullId());
|
|
||||||
if (!parser.getTableFilter().isIncluded(tableId)) {
|
|
||||||
LOG.debug("{} is not monitored, no need to process unique index", tableId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TableEditor tableEditor = parser.databaseTables().editTable(tableId);
|
|
||||||
if (tableEditor != null) {
|
|
||||||
if (!tableEditor.hasPrimaryKey() && parser.isTableUniqueIndexIncluded(ctx.indexColumnNames(), tableEditor)) {
|
|
||||||
parser.parseUniqueIndexColumnNames(ctx.indexColumnNames(), tableEditor);
|
|
||||||
parser.databaseTables().overwriteTable(tableEditor.create());
|
|
||||||
parser.signalCreateIndex(parser.parseName(ctx.uid()), tableId, ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new ParsingException(null, "Trying to create index on non existing table " + tableId.toString() + "."
|
|
||||||
+ "Query: " + getText(ctx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.enterCreateIndex(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.TableEditor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for CREATE VIEW statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class CreateViewParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
private final List<ParseTreeListener> listeners;
|
|
||||||
|
|
||||||
private TableEditor tableEditor;
|
|
||||||
private ViewSelectedColumnsParserListener selectColumnsListener;
|
|
||||||
|
|
||||||
public CreateViewParserListener(MariaDbAntlrDdlParser parser, List<ParseTreeListener> listeners) {
|
|
||||||
this.parser = parser;
|
|
||||||
this.listeners = listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterCreateView(MariaDBParser.CreateViewContext ctx) {
|
|
||||||
if (!parser.skipViews()) {
|
|
||||||
tableEditor = parser.databaseTables().editOrCreateTable(parser.parseQualifiedTableId(ctx.fullId()));
|
|
||||||
// create new columns just with specified name for now
|
|
||||||
if (ctx.uidList() != null) {
|
|
||||||
ctx.uidList().uid().stream().map(parser::parseName).forEach(columnName -> {
|
|
||||||
tableEditor.addColumn(Column.editor().name(columnName).create());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
selectColumnsListener = new ViewSelectedColumnsParserListener(tableEditor, parser);
|
|
||||||
listeners.add(selectColumnsListener);
|
|
||||||
}
|
|
||||||
super.enterCreateView(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitCreateView(MariaDBParser.CreateViewContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
tableEditor.addColumns(selectColumnsListener.getSelectedColumns());
|
|
||||||
// Make sure that the table's character set has been set ...
|
|
||||||
if (!tableEditor.hasDefaultCharsetName()) {
|
|
||||||
tableEditor.setDefaultCharsetName(parser.charsetForTable(tableEditor.tableId()));
|
|
||||||
}
|
|
||||||
parser.databaseTables().overwriteTable(tableEditor.create());
|
|
||||||
listeners.remove(selectColumnsListener);
|
|
||||||
}, tableEditor);
|
|
||||||
// signal view even if it was skipped
|
|
||||||
parser.signalCreateView(parser.parseQualifiedTableId(ctx.fullId()), ctx);
|
|
||||||
super.exitCreateView(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser.CurrentTimestampContext;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser.DefaultValueContext;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.ColumnEditor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener that parses default value definitions.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DefaultValueParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final ColumnEditor columnEditor;
|
|
||||||
private final AtomicReference<Boolean> optionalColumn;
|
|
||||||
|
|
||||||
private boolean converted;
|
|
||||||
|
|
||||||
public DefaultValueParserListener(ColumnEditor columnEditor, AtomicReference<Boolean> optionalColumn) {
|
|
||||||
this.columnEditor = columnEditor;
|
|
||||||
this.optionalColumn = optionalColumn;
|
|
||||||
this.converted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterDefaultValue(DefaultValueContext ctx) {
|
|
||||||
String sign = "";
|
|
||||||
if (ctx.NULL_LITERAL() != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ctx.unaryOperator() != null) {
|
|
||||||
sign = ctx.unaryOperator().getText();
|
|
||||||
}
|
|
||||||
if (ctx.constant() != null) {
|
|
||||||
if (ctx.constant().stringLiteral() != null) {
|
|
||||||
if (ctx.constant().stringLiteral().COLLATE() == null) {
|
|
||||||
columnEditor.defaultValueExpression(sign + unquote(ctx.constant().stringLiteral().getText()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnEditor.defaultValueExpression(
|
|
||||||
sign + unquote(ctx.constant().stringLiteral().STRING_LITERAL(0).getText()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ctx.constant().decimalLiteral() != null) {
|
|
||||||
columnEditor.defaultValueExpression(sign + ctx.constant().decimalLiteral().getText());
|
|
||||||
}
|
|
||||||
else if (ctx.constant().BIT_STRING() != null) {
|
|
||||||
columnEditor.defaultValueExpression(unquoteBinary(ctx.constant().BIT_STRING().getText()));
|
|
||||||
}
|
|
||||||
else if (ctx.constant().booleanLiteral() != null) {
|
|
||||||
columnEditor.defaultValueExpression(ctx.constant().booleanLiteral().getText());
|
|
||||||
}
|
|
||||||
else if (ctx.constant().REAL_LITERAL() != null) {
|
|
||||||
columnEditor.defaultValueExpression(ctx.constant().REAL_LITERAL().getText());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ctx.currentTimestamp() != null && !ctx.currentTimestamp().isEmpty()) {
|
|
||||||
if (ctx.currentTimestamp().size() > 1 || (ctx.ON() == null && ctx.UPDATE() == null)) {
|
|
||||||
final CurrentTimestampContext currentTimestamp = ctx.currentTimestamp(0);
|
|
||||||
if (currentTimestamp.CURRENT_TIMESTAMP() != null || currentTimestamp.NOW() != null) {
|
|
||||||
columnEditor.defaultValueExpression("1970-01-01 00:00:00");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnEditor.defaultValueExpression(currentTimestamp.getText());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Default value is calculated.
|
|
||||||
// We thus handle it as NULL.
|
|
||||||
else if (ctx.expression() != null) {
|
|
||||||
columnEditor.defaultValueExpression(null);
|
|
||||||
}
|
|
||||||
exitDefaultValue(true);
|
|
||||||
super.enterDefaultValue(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exitDefaultValue(boolean skipIfUnknownOptional) {
|
|
||||||
boolean isOptionalColumn = optionalColumn.get() != null;
|
|
||||||
if (!converted && (isOptionalColumn || !skipIfUnknownOptional)) {
|
|
||||||
if (isOptionalColumn) {
|
|
||||||
columnEditor.optional(optionalColumn.get().booleanValue());
|
|
||||||
}
|
|
||||||
converted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String unquote(String stringLiteral) {
|
|
||||||
if (stringLiteral != null && ((stringLiteral.startsWith("'") && stringLiteral.endsWith("'"))
|
|
||||||
|| (stringLiteral.startsWith("\"") && stringLiteral.endsWith("\"")))) {
|
|
||||||
return stringLiteral.substring(1, stringLiteral.length() - 1);
|
|
||||||
}
|
|
||||||
return stringLiteral;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String unquoteBinary(String stringLiteral) {
|
|
||||||
return stringLiteral.substring(2, stringLiteral.length() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for DROP DATABASE statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DropDatabaseParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public DropDatabaseParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterDropDatabase(MariaDBParser.DropDatabaseContext ctx) {
|
|
||||||
String databaseName = parser.parseName(ctx.uid());
|
|
||||||
parser.databaseTables().removeTablesForDatabase(databaseName);
|
|
||||||
parser.charsetNameForDatabase().remove(databaseName);
|
|
||||||
parser.signalDropDatabase(databaseName, ctx);
|
|
||||||
super.enterDropDatabase(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.misc.Interval;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for parsing DROP TABLE statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DropTableParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public DropTableParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterDropTable(MariaDBParser.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 = parser.parseQualifiedTableId(tableNameContext.fullId());
|
|
||||||
parser.databaseTables().removeTable(tableId);
|
|
||||||
parser.signalDropTable(tableId, prefix + tableId.toQuotedString('`')
|
|
||||||
+ (ctx.dropType != null ? " " + ctx.dropType.getText() : ""));
|
|
||||||
});
|
|
||||||
super.enterDropTable(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for parsing DROP VIEW statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DropViewParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public DropViewParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterDropView(MariaDBParser.DropViewContext ctx) {
|
|
||||||
if (!parser.skipViews()) {
|
|
||||||
ctx.fullId().stream().map(parser::parseQualifiedTableId).forEach(tableId -> {
|
|
||||||
parser.databaseTables().removeTable(tableId);
|
|
||||||
parser.signalDropView(tableId, ctx);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
super.enterDropView(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.ParserRuleContext;
|
|
||||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
|
||||||
|
|
||||||
import io.debezium.antlr.AntlrDdlParserListener;
|
|
||||||
import io.debezium.antlr.ProxyParseTreeListenerUtil;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.text.ParsingException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for MariaDB column definition queries.<p></p>
|
|
||||||
*
|
|
||||||
* Its purpose is to delegate events to defined collections of concrete parser listeners. Each
|
|
||||||
* listener handles the specified type of DDL statement.<p></p>
|
|
||||||
*
|
|
||||||
* This listener is catching all parsing exceptions and implements a skip mechanism for BEGIN ... END
|
|
||||||
* statements. No event will be delegated during skipping phase.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbAntlrDdlParserListener extends MariaDBParserBaseListener implements AntlrDdlParserListener {
|
|
||||||
|
|
||||||
private final List<ParseTreeListener> listeners = new CopyOnWriteArrayList<>();
|
|
||||||
private final Collection<ParsingException> errors = new ArrayList<>();
|
|
||||||
private boolean skipNodes;
|
|
||||||
private int skippedNodesCount = 0;
|
|
||||||
|
|
||||||
public MariaDbAntlrDdlParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
listeners.add(new CreateAndAlterDatabaseParserListener(parser));
|
|
||||||
listeners.add(new DropDatabaseParserListener(parser));
|
|
||||||
listeners.add(new CreateTableParserListener(parser, listeners));
|
|
||||||
listeners.add(new AlterTableParserListener(parser, listeners));
|
|
||||||
listeners.add(new DropTableParserListener(parser));
|
|
||||||
listeners.add(new RenameTableParserListener(parser));
|
|
||||||
listeners.add(new TruncateTableParserListener(parser));
|
|
||||||
listeners.add(new CreateViewParserListener(parser, listeners));
|
|
||||||
listeners.add(new AlterViewParserListener(parser, listeners));
|
|
||||||
listeners.add(new DropViewParserListener(parser));
|
|
||||||
listeners.add(new CreateUniqueIndexParserListener(parser));
|
|
||||||
listeners.add(new SetStatementParserListener(parser));
|
|
||||||
listeners.add(new UseStatementParserListener(parser));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<ParsingException> getErrors() {
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterEveryRule(ParserRuleContext ctx) {
|
|
||||||
if (skipNodes) {
|
|
||||||
skippedNodesCount++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ProxyParseTreeListenerUtil.delegateEnterRule(ctx, listeners, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitEveryRule(ParserRuleContext ctx) {
|
|
||||||
if (skipNodes) {
|
|
||||||
if (skippedNodesCount == 0) {
|
|
||||||
// back in the node where skipping started
|
|
||||||
skipNodes = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// going up in a tree, means decreasing a number of skipped nodes
|
|
||||||
skippedNodesCount--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ProxyParseTreeListenerUtil.delegateExitRule(ctx, listeners, errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitErrorNode(ErrorNode node) {
|
|
||||||
ProxyParseTreeListenerUtil.visitErrorNode(node, listeners, errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitTerminal(TerminalNode node) {
|
|
||||||
ProxyParseTreeListenerUtil.visitTerminal(node, listeners, errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterRoutineBody(MariaDBParser.RoutineBodyContext ctx) {
|
|
||||||
// this is a grammar rule for BEGIN ... END part of statements. Skip it.
|
|
||||||
skipNodes = true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for parsing RENAME TABLE statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class RenameTableParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(RenameTableParserListener.class);
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public RenameTableParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterRenameTableClause(MariaDBParser.RenameTableClauseContext ctx) {
|
|
||||||
TableId oldTable = parser.parseQualifiedTableId(ctx.tableName(0).fullId());
|
|
||||||
TableId newTable = parser.parseQualifiedTableId(ctx.tableName(1).fullId());
|
|
||||||
if (parser.getTableFilter().isIncluded(oldTable) && !parser.getTableFilter().isIncluded(newTable)) {
|
|
||||||
LOG.warn("Renaming included table {} to non-included table {}, this can lead to schema inconsistency", oldTable, newTable);
|
|
||||||
}
|
|
||||||
else if (!parser.getTableFilter().isIncluded(oldTable) && parser.getTableFilter().isIncluded(newTable)) {
|
|
||||||
LOG.warn("Renaming non-included table {} to included table {}, this can lead to schema inconsistency", oldTable, newTable);
|
|
||||||
}
|
|
||||||
parser.databaseTables().renameTable(oldTable, newTable);
|
|
||||||
parser.signalAlterTable(newTable, oldTable, ctx);
|
|
||||||
super.enterRenameTableClause(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogSystemVariables;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogSystemVariables.BinlogScope;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener for parsing SET statements, which define system variables.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SetStatementParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public SetStatementParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterSetVariable(MariaDBParser.SetVariableContext ctx) {
|
|
||||||
// If you set multiple system variables, the most recent GLOBAL or SESSION modifier in the statement
|
|
||||||
// is used for following assignments that have no modifier specified.
|
|
||||||
BinlogScope scope = null;
|
|
||||||
for (int i = 0; i < ctx.variableClause().size(); i++) {
|
|
||||||
MariaDBParser.VariableClauseContext variableClauseContext = ctx.variableClause(i);
|
|
||||||
String variableName;
|
|
||||||
if (variableClauseContext.uid() == null) {
|
|
||||||
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 = BinlogScope.GLOBAL;
|
|
||||||
variableName = variableIdentifier.substring("@@global.".length());
|
|
||||||
}
|
|
||||||
else if (variableIdentifier.startsWith("@@session.")) {
|
|
||||||
scope = BinlogScope.SESSION;
|
|
||||||
variableName = variableIdentifier.substring("@@session.".length());
|
|
||||||
}
|
|
||||||
else if (variableIdentifier.startsWith("@@local.")) {
|
|
||||||
scope = BinlogScope.LOCAL;
|
|
||||||
variableName = variableIdentifier.substring("@@local.".length());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scope = BinlogScope.SESSION;
|
|
||||||
variableName = variableIdentifier.substring("@@".length());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (variableClauseContext.GLOBAL() != null) {
|
|
||||||
scope = BinlogScope.GLOBAL;
|
|
||||||
}
|
|
||||||
else if (variableClauseContext.SESSION() != null) {
|
|
||||||
scope = BinlogScope.SESSION;
|
|
||||||
}
|
|
||||||
else if (variableClauseContext.LOCAL() != null) {
|
|
||||||
scope = BinlogScope.LOCAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
variableName = parser.parseName(variableClauseContext.uid());
|
|
||||||
}
|
|
||||||
String value = parser.withoutQuotes(ctx.expression(i));
|
|
||||||
|
|
||||||
parser.systemVariables().setVariable(scope, variableName, value);
|
|
||||||
|
|
||||||
// If this is setting 'character_set_database', then we need to record the character set for
|
|
||||||
// the given database ...
|
|
||||||
if (BinlogSystemVariables.CHARSET_NAME_DATABASE.equalsIgnoreCase(variableName)) {
|
|
||||||
String currentDatabaseName = parser.currentSchema();
|
|
||||||
if (currentDatabaseName != null) {
|
|
||||||
parser.charsetNameForDatabase().put(currentDatabaseName, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signal that the variable was set ...
|
|
||||||
parser.signalSetVariable(variableName, value, i, ctx);
|
|
||||||
}
|
|
||||||
super.enterSetVariable(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterSetCharset(MariaDBParser.SetCharsetContext ctx) {
|
|
||||||
String charsetName = ctx.charsetName() != null ? parser.withoutQuotes(ctx.charsetName()) : parser.currentDatabaseCharset();
|
|
||||||
// Sets variables according to documentation at
|
|
||||||
// https://mariadb.com/kb/en/set-character-set/
|
|
||||||
// Using default scope for these variables, because this type of set statement you cannot specify
|
|
||||||
// the scope manually
|
|
||||||
parser.systemVariables().setVariable(BinlogScope.SESSION, BinlogSystemVariables.CHARSET_NAME_CLIENT, charsetName);
|
|
||||||
parser.systemVariables().setVariable(BinlogScope.SESSION, BinlogSystemVariables.CHARSET_NAME_RESULT, charsetName);
|
|
||||||
parser.systemVariables().setVariable(BinlogScope.SESSION, BinlogSystemVariables.CHARSET_NAME_CONNECTION,
|
|
||||||
parser.systemVariables().getVariable(BinlogSystemVariables.CHARSET_NAME_DATABASE));
|
|
||||||
super.enterSetCharset(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterSetNames(MariaDBParser.SetNamesContext ctx) {
|
|
||||||
String charsetName = ctx.charsetName() != null ? parser.withoutQuotes(ctx.charsetName()) : parser.currentDatabaseCharset();
|
|
||||||
// Sets variables according to documentation at
|
|
||||||
// https://mariadb.com/kb/en/set-names/
|
|
||||||
// Using default scope for these variables, because this type of set statement you cannot specify
|
|
||||||
// the scope manually
|
|
||||||
parser.systemVariables().setVariable(BinlogScope.SESSION, BinlogSystemVariables.CHARSET_NAME_CLIENT, charsetName);
|
|
||||||
parser.systemVariables().setVariable(BinlogScope.SESSION, BinlogSystemVariables.CHARSET_NAME_RESULT, charsetName);
|
|
||||||
parser.systemVariables().setVariable(BinlogScope.SESSION, BinlogSystemVariables.CHARSET_NAME_CONNECTION, charsetName);
|
|
||||||
super.enterSetNames(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.ColumnEditor;
|
|
||||||
import io.debezium.relational.TableEditor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener that parses CREATE TABLE and ALTER TABLE common statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TableCommonParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
protected final MariaDbAntlrDdlParser parser;
|
|
||||||
protected final List<ParseTreeListener> listeners;
|
|
||||||
|
|
||||||
protected TableEditor tableEditor;
|
|
||||||
protected ColumnDefinitionParserListener columnDefinitionListener;
|
|
||||||
|
|
||||||
public TableCommonParserListener(MariaDbAntlrDdlParser parser, List<ParseTreeListener> listeners) {
|
|
||||||
this.parser = parser;
|
|
||||||
this.listeners = listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterColumnDeclaration(MariaDBParser.ColumnDeclarationContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
MariaDBParser.UidContext fullColumnNameContext = ctx.uid();
|
|
||||||
String columnName = parser.parseName(fullColumnNameContext);
|
|
||||||
ColumnEditor columnEditor = Column.editor().name(columnName);
|
|
||||||
if (columnDefinitionListener == null) {
|
|
||||||
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parser, listeners);
|
|
||||||
listeners.add(columnDefinitionListener);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
columnDefinitionListener.setColumnEditor(columnEditor);
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterColumnDeclaration(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitColumnDeclaration(MariaDBParser.ColumnDeclarationContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
tableEditor.addColumn(columnDefinitionListener.getColumn());
|
|
||||||
}, tableEditor, columnDefinitionListener);
|
|
||||||
super.exitColumnDeclaration(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterPrimaryKeyTableConstraint(MariaDBParser.PrimaryKeyTableConstraintContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
parser.parsePrimaryIndexColumnNames(ctx.indexColumnNames(), tableEditor);
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterPrimaryKeyTableConstraint(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterUniqueKeyTableConstraint(MariaDBParser.UniqueKeyTableConstraintContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
if (!tableEditor.hasPrimaryKey() && parser.isTableUniqueIndexIncluded(ctx.indexColumnNames(), tableEditor)) {
|
|
||||||
parser.parseUniqueIndexColumnNames(ctx.indexColumnNames(), tableEditor);
|
|
||||||
}
|
|
||||||
}, tableEditor);
|
|
||||||
super.enterUniqueKeyTableConstraint(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener that parses TRUNCATE TABLE statements.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TruncateTableParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public TruncateTableParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterTruncateTable(MariaDBParser.TruncateTableContext ctx) {
|
|
||||||
TableId tableId = parser.parseQualifiedTableId(ctx.tableName().fullId());
|
|
||||||
|
|
||||||
// Be aware the legacy parser is not signaling truncate events
|
|
||||||
parser.signalTruncateTable(tableId, ctx);
|
|
||||||
super.enterTruncateTable(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogSystemVariables;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogSystemVariables.BinlogScope;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener that parses USE statements.<p></p>
|
|
||||||
*
|
|
||||||
* USE statements alter the current database/catalog for all changes that come thereafter.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class UseStatementParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
|
|
||||||
public UseStatementParserListener(MariaDbAntlrDdlParser parser) {
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enterUseStatement(MariaDBParser.UseStatementContext ctx) {
|
|
||||||
String dbName = parser.parseName(ctx.uid());
|
|
||||||
parser.setCurrentSchema(dbName);
|
|
||||||
|
|
||||||
// Every time the database switches to a different database, it sets the "character_set_database" and
|
|
||||||
// "collation_database" system variables. We replicate that behavior here (or the variable we care about)
|
|
||||||
// so that these variables are always right for the current database.
|
|
||||||
String charsetForDb = parser.charsetNameForDatabase().get(dbName);
|
|
||||||
parser.systemVariables().setVariable(BinlogScope.SESSION, BinlogSystemVariables.CHARSET_NAME_DATABASE, charsetForDb);
|
|
||||||
|
|
||||||
// Signal that the variable was set ...
|
|
||||||
parser.signalUseDatabase(ctx);
|
|
||||||
super.enterUseStatement(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,182 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.antlr.listener;
|
|
||||||
|
|
||||||
import static io.debezium.relational.ddl.AbstractDdlParser.withoutQuotes;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParser;
|
|
||||||
import io.debezium.ddl.parser.mariadb.generated.MariaDBParserBaseListener;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.Table;
|
|
||||||
import io.debezium.relational.TableEditor;
|
|
||||||
import io.debezium.relational.TableId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser listener that parses SELECT statements used for definitions of VIEWs.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ViewSelectedColumnsParserListener extends MariaDBParserBaseListener {
|
|
||||||
|
|
||||||
private final MariaDbAntlrDdlParser parser;
|
|
||||||
private final TableEditor tableEditor;
|
|
||||||
|
|
||||||
private TableEditor selectTableEditor;
|
|
||||||
private Map<TableId, Table> tableByAlias = new HashMap<>();
|
|
||||||
|
|
||||||
public ViewSelectedColumnsParserListener(TableEditor tableEditor, MariaDbAntlrDdlParser parser) {
|
|
||||||
this.tableEditor = tableEditor;
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Column> getSelectedColumns() {
|
|
||||||
return selectTableEditor.columns();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitQuerySpecification(MariaDBParser.QuerySpecificationContext ctx) {
|
|
||||||
if (ctx.fromClause() != null) {
|
|
||||||
parseQuerySpecification(ctx.selectElements());
|
|
||||||
}
|
|
||||||
super.exitQuerySpecification(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitQuerySpecificationNointo(MariaDBParser.QuerySpecificationNointoContext ctx) {
|
|
||||||
if (ctx.fromClause() != null) {
|
|
||||||
parseQuerySpecification(ctx.selectElements());
|
|
||||||
}
|
|
||||||
super.exitQuerySpecificationNointo(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAtomTableItem(MariaDBParser.AtomTableItemContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
parseAtomTableItem(ctx, tableByAlias);
|
|
||||||
}, tableEditor);
|
|
||||||
super.exitAtomTableItem(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitSubqueryTableItem(MariaDBParser.SubqueryTableItemContext ctx) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
// parsing subselect
|
|
||||||
String tableAlias = parser.parseName(ctx.uid());
|
|
||||||
TableId aliasTableId = parser.resolveTableId(parser.currentSchema(), tableAlias);
|
|
||||||
selectTableEditor.tableId(aliasTableId);
|
|
||||||
tableByAlias.put(aliasTableId, selectTableEditor.create());
|
|
||||||
}, tableEditor);
|
|
||||||
super.exitSubqueryTableItem(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseQuerySpecification(MariaDBParser.SelectElementsContext selectElementsContext) {
|
|
||||||
parser.runIfNotNull(() -> {
|
|
||||||
selectTableEditor = parseSelectElements(selectElementsContext);
|
|
||||||
}, tableEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseAtomTableItem(MariaDBParser.TableSourceItemContext ctx, Map<TableId, Table> tableByAlias) {
|
|
||||||
if (ctx instanceof MariaDBParser.AtomTableItemContext) {
|
|
||||||
MariaDBParser.AtomTableItemContext atomTableItemContext = (MariaDBParser.AtomTableItemContext) ctx;
|
|
||||||
|
|
||||||
TableId tableId = parser.parseQualifiedTableId(atomTableItemContext.tableName().fullId());
|
|
||||||
|
|
||||||
Table table = tableByAlias.get(tableId);
|
|
||||||
if (table == null) {
|
|
||||||
table = parser.databaseTables().forTable(tableId);
|
|
||||||
}
|
|
||||||
if (atomTableItemContext.alias != null) {
|
|
||||||
TableId aliasTableId = parser.resolveTableId(tableId.catalog(), parser.parseName(atomTableItemContext.alias));
|
|
||||||
tableByAlias.put(aliasTableId, table);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tableByAlias.put(tableId, table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TableEditor parseSelectElements(MariaDBParser.SelectElementsContext ctx) {
|
|
||||||
TableEditor table = Table.editor();
|
|
||||||
if (ctx.star != null) {
|
|
||||||
tableByAlias.keySet().forEach(tableId -> {
|
|
||||||
table.addColumns(tableByAlias.get(tableId).columns());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ctx.selectElement().forEach(selectElementContext -> {
|
|
||||||
if (selectElementContext instanceof MariaDBParser.SelectStarElementContext) {
|
|
||||||
TableId tableId = parser.parseQualifiedTableId(((MariaDBParser.SelectStarElementContext) selectElementContext).fullId());
|
|
||||||
Table selectedTable = tableByAlias.get(tableId);
|
|
||||||
table.addColumns(selectedTable.columns());
|
|
||||||
}
|
|
||||||
else if (selectElementContext instanceof MariaDBParser.SelectColumnElementContext) {
|
|
||||||
MariaDBParser.SelectColumnElementContext selectColumnElementContext = (MariaDBParser.SelectColumnElementContext) selectElementContext;
|
|
||||||
MariaDBParser.FullColumnNameContext fullColumnNameContext = selectColumnElementContext.fullColumnName();
|
|
||||||
|
|
||||||
String schemaName = parser.currentSchema();
|
|
||||||
String tableName = null;
|
|
||||||
String columnName;
|
|
||||||
|
|
||||||
columnName = parser.parseName(fullColumnNameContext.uid());
|
|
||||||
if (fullColumnNameContext.dottedId(0) != null) {
|
|
||||||
// shift by 1
|
|
||||||
tableName = columnName;
|
|
||||||
if (fullColumnNameContext.dottedId(1) != null) {
|
|
||||||
// shift by 2
|
|
||||||
// final look of fullColumnName e.q. inventory.Persons.FirstName
|
|
||||||
schemaName = tableName;
|
|
||||||
tableName = withoutQuotes(fullColumnNameContext.dottedId(0).getText().substring(1));
|
|
||||||
columnName = withoutQuotes(fullColumnNameContext.dottedId(1).getText().substring(1));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// final look of fullColumnName e.g. Persons.FirstName
|
|
||||||
columnName = withoutQuotes(fullColumnNameContext.dottedId(0).getText().substring(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String alias = columnName;
|
|
||||||
if (selectColumnElementContext.uid() != null) {
|
|
||||||
alias = parser.parseName(selectColumnElementContext.uid());
|
|
||||||
}
|
|
||||||
if (tableName != null) {
|
|
||||||
Table selectedTable = tableByAlias.get(parser.resolveTableId(schemaName, tableName));
|
|
||||||
addColumnFromTable(table, columnName, alias, selectedTable);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (Table selectedTable : tableByAlias.values()) {
|
|
||||||
addColumnFromTable(table, columnName, alias, selectedTable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
tableByAlias.clear();
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MariaDBParser.TableSourceItemContext getTableSourceItemContext(MariaDBParser.TableSourceContext tableSourceContext) {
|
|
||||||
if (tableSourceContext instanceof MariaDBParser.TableSourceBaseContext) {
|
|
||||||
return ((MariaDBParser.TableSourceBaseContext) tableSourceContext).tableSourceItem();
|
|
||||||
}
|
|
||||||
else if (tableSourceContext instanceof MariaDBParser.TableSourceNestedContext) {
|
|
||||||
return ((MariaDBParser.TableSourceNestedContext) tableSourceContext).tableSourceItem();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addColumnFromTable(TableEditor table, String columnName, String newColumnName, Table selectedTable) {
|
|
||||||
for (Column column : selectedTable.columns()) {
|
|
||||||
if (column.name().equals(columnName)) {
|
|
||||||
table.addColumn(column.edit().name(newColumnName).create());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,211 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.charset;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import io.debezium.DebeziumException;
|
|
||||||
import io.debezium.connector.binlog.charset.BinlogCharsetRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A registry that stores character set mappings from {@code charset_mappings.json} for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbCharsetRegistry implements BinlogCharsetRegistry {
|
|
||||||
|
|
||||||
private static final String CHARSET_MAPPINGS = "charset_mappings.json";
|
|
||||||
private static final int MAP_SIZE = 1024;
|
|
||||||
|
|
||||||
private final List<String> collationIndexToCollationName = new ArrayList<>(Collections.nCopies(MAP_SIZE, null));
|
|
||||||
private final Map<Integer, CharacterSetMapping> collationIndexToCharacterSet = new TreeMap<>();
|
|
||||||
private final Map<String, CharacterSetMapping> characterSetNameToCharacterSet = new HashMap<>();
|
|
||||||
|
|
||||||
public MariaDbCharsetRegistry() {
|
|
||||||
loadCharacterSetMappingsFromFileResource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCharsetMapSize() {
|
|
||||||
return MAP_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCollationNameForCollationIndex(Integer collationIndex) {
|
|
||||||
String newValue = null;
|
|
||||||
if (!Objects.isNull(collationIndex) && isWithinRange(collationIndex)) {
|
|
||||||
newValue = collationIndexToCollationName.get(collationIndex);
|
|
||||||
}
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCharsetNameForCollationIndex(Integer collationIndex) {
|
|
||||||
String newValue = null;
|
|
||||||
if (!Objects.isNull(collationIndex)) {
|
|
||||||
CharacterSetMapping mapping = collationIndexToCharacterSet.get(collationIndex);
|
|
||||||
if (!Objects.isNull(mapping)) {
|
|
||||||
newValue = mapping.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getJavaEncodingForCharSet(String characterSetName) {
|
|
||||||
final CharacterSetMapping mapping = characterSetNameToCharacterSet.get(characterSetName);
|
|
||||||
if (!Objects.isNull(mapping)) {
|
|
||||||
return mapping.getFirstEncoding();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadCharacterSetMappingsFromFileResource() {
|
|
||||||
try (InputStream stream = MariaDbCharsetRegistry.class.getClassLoader().getResourceAsStream(CHARSET_MAPPINGS)) {
|
|
||||||
final ObjectMapper mapper = new ObjectMapper();
|
|
||||||
final CharacterSetMappings mappings = mapper.readValue(stream, CharacterSetMappings.class);
|
|
||||||
loadCharacterSetMappings(mappings.characterSets);
|
|
||||||
loadCollationMappings(mappings.collations);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new DebeziumException("Failed to load character set mappings", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadCharacterSetMappings(List<CharacterSetMapping> characterSetMappings) {
|
|
||||||
for (CharacterSetMapping charsetMapping : characterSetMappings) {
|
|
||||||
final String characterSetName = charsetMapping.name;
|
|
||||||
characterSetNameToCharacterSet.put(characterSetName, charsetMapping);
|
|
||||||
if (!Objects.isNull(charsetMapping.aliases)) {
|
|
||||||
for (String alias : charsetMapping.aliases) {
|
|
||||||
characterSetNameToCharacterSet.put(alias, charsetMapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadCollationMappings(List<CollationMapping> collationMappings) {
|
|
||||||
for (CollationMapping collation : collationMappings) {
|
|
||||||
final CharacterSetMapping mapping = characterSetNameToCharacterSet.get(collation.charSetName);
|
|
||||||
collationIndexToCollationName.set(collation.index, collation.collations.get(0));
|
|
||||||
collationIndexToCharacterSet.put(collation.index, mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isWithinRange(int value) {
|
|
||||||
return value > 0 && value < MAP_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the data within the file {@code charset_mappings.json}.
|
|
||||||
*/
|
|
||||||
private static class CharacterSetMappings {
|
|
||||||
List<CharacterSetMapping> characterSets;
|
|
||||||
List<CollationMapping> collations;
|
|
||||||
|
|
||||||
@JsonCreator
|
|
||||||
CharacterSetMappings(@JsonProperty("character_sets") List<CharacterSetMapping> characterSets,
|
|
||||||
@JsonProperty("collation_mappings") List<CollationMapping> collationMappings) {
|
|
||||||
this.characterSets = characterSets;
|
|
||||||
this.collations = collationMappings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a character set mapping
|
|
||||||
*/
|
|
||||||
private static class CharacterSetMapping {
|
|
||||||
private static final String UTF8 = "UTF-8";
|
|
||||||
private static final String CP1252 = "Cp1252";
|
|
||||||
|
|
||||||
String name;
|
|
||||||
int multiByteLength;
|
|
||||||
int priority;
|
|
||||||
List<String> encodings;
|
|
||||||
List<String> aliases;
|
|
||||||
String comment;
|
|
||||||
|
|
||||||
@JsonCreator
|
|
||||||
CharacterSetMapping(@JsonProperty("name") String name,
|
|
||||||
@JsonProperty("mblen") int multiByteLength,
|
|
||||||
@JsonProperty("priority") int priority,
|
|
||||||
@JsonProperty("encodings") List<String> encodings,
|
|
||||||
@JsonProperty("aliases") List<String> aliases,
|
|
||||||
@JsonProperty("comment") String comment) {
|
|
||||||
this.name = name;
|
|
||||||
this.multiByteLength = multiByteLength;
|
|
||||||
this.priority = priority;
|
|
||||||
this.encodings = new ArrayList<>();
|
|
||||||
this.aliases = Objects.isNull(aliases) ? new ArrayList<>() : aliases;
|
|
||||||
this.comment = comment;
|
|
||||||
|
|
||||||
addEncodings(encodings);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getFirstEncoding() {
|
|
||||||
return encodings.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addEncodings(List<String> encodings) {
|
|
||||||
for (String encoding : encodings) {
|
|
||||||
try {
|
|
||||||
Charset charset = Charset.forName(encoding);
|
|
||||||
addEncodingMapping(charset.name());
|
|
||||||
charset.aliases().forEach(this::addEncodingMapping);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
if (multiByteLength == 1) {
|
|
||||||
addEncodingMapping(encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.encodings.isEmpty()) {
|
|
||||||
addEncodingMapping(multiByteLength > 1 ? UTF8 : CP1252);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addEncodingMapping(String encoding) {
|
|
||||||
final String encodingValue = encoding.toUpperCase(Locale.ENGLISH);
|
|
||||||
if (!encodings.contains(encodingValue)) {
|
|
||||||
encodings.add(encodingValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a collation mapping to a set of database character sets.
|
|
||||||
*/
|
|
||||||
private static class CollationMapping {
|
|
||||||
int index;
|
|
||||||
List<String> collations;
|
|
||||||
int priority;
|
|
||||||
String charSetName;
|
|
||||||
|
|
||||||
@JsonCreator
|
|
||||||
CollationMapping(@JsonProperty("index") int index,
|
|
||||||
@JsonProperty("collations") List<String> collations,
|
|
||||||
@JsonProperty("priority") int priority,
|
|
||||||
@JsonProperty("charset") String charSetName) {
|
|
||||||
this.index = index;
|
|
||||||
this.collations = collations;
|
|
||||||
this.priority = priority;
|
|
||||||
this.charSetName = charSetName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.charset;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.binlog.charset.BinlogCharsetRegistry;
|
|
||||||
import io.debezium.service.spi.ServiceProvider;
|
|
||||||
import io.debezium.service.spi.ServiceRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbCharsetRegistryServiceProvider implements ServiceProvider<BinlogCharsetRegistry> {
|
|
||||||
@Override
|
|
||||||
public Class<BinlogCharsetRegistry> getServiceClass() {
|
|
||||||
return BinlogCharsetRegistry.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BinlogCharsetRegistry createService(Configuration configuration, ServiceRegistry serviceRegistry) {
|
|
||||||
return new MariaDbCharsetRegistry();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.converters;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.debezium.connector.AbstractSourceInfo;
|
|
||||||
import io.debezium.converters.recordandmetadata.RecordAndMetadata;
|
|
||||||
import io.debezium.converters.spi.CloudEventsMaker;
|
|
||||||
import io.debezium.converters.spi.SerializerType;
|
|
||||||
import io.debezium.util.Collect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link CloudEventsMaker} implementation for records produced by the MariaDB connector.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbCloudEventsMaker extends CloudEventsMaker {
|
|
||||||
|
|
||||||
static final String TABLE_NAME_KEY = "table";
|
|
||||||
static final String SERVER_ID_KEY = "server_id";
|
|
||||||
static final String GTID_KEY = "gtid";
|
|
||||||
static final String BINLOG_FILENAME_OFFSET_KEY = "file";
|
|
||||||
static final String BINLOG_POSITION_OFFSET_KEY = "pos";
|
|
||||||
static final String BINLOG_ROW_IN_EVENT_OFFSET_KEY = "row";
|
|
||||||
static final String THREAD_KEY = "thread";
|
|
||||||
static final String QUERY_KEY = "query";
|
|
||||||
|
|
||||||
static final Set<String> MARIADB_SOURCE_FIELDS = Collect.unmodifiableSet(
|
|
||||||
TABLE_NAME_KEY,
|
|
||||||
SERVER_ID_KEY,
|
|
||||||
GTID_KEY,
|
|
||||||
BINLOG_FILENAME_OFFSET_KEY,
|
|
||||||
BINLOG_POSITION_OFFSET_KEY,
|
|
||||||
BINLOG_ROW_IN_EVENT_OFFSET_KEY,
|
|
||||||
THREAD_KEY,
|
|
||||||
QUERY_KEY);
|
|
||||||
|
|
||||||
public MariaDbCloudEventsMaker(RecordAndMetadata recordAndMetadata, SerializerType contentType, String dataSchemaUriBase, String schemaName) {
|
|
||||||
super(recordAndMetadata, contentType, dataSchemaUriBase, schemaName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String ceId() {
|
|
||||||
return "name:" + sourceField(AbstractSourceInfo.SERVER_NAME_KEY)
|
|
||||||
+ ";file:" + sourceField(BINLOG_FILENAME_OFFSET_KEY)
|
|
||||||
+ ";pos:" + sourceField(BINLOG_POSITION_OFFSET_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> connectorSpecificSourceFields() {
|
|
||||||
return MARIADB_SOURCE_FIELDS;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.converters;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.Module;
|
|
||||||
import io.debezium.converters.recordandmetadata.RecordAndMetadata;
|
|
||||||
import io.debezium.converters.spi.CloudEventsMaker;
|
|
||||||
import io.debezium.converters.spi.CloudEventsProvider;
|
|
||||||
import io.debezium.converters.spi.SerializerType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of {@link CloudEventsProvider} for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbCloudEventsProvider implements CloudEventsProvider {
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return Module.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CloudEventsMaker createMaker(RecordAndMetadata recordAndMetadata, SerializerType contentType, String dataSchemaUriBase, String cloudEventsSchemaName) {
|
|
||||||
return new MariaDbCloudEventsMaker(recordAndMetadata, contentType, dataSchemaUriBase, cloudEventsSchemaName);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,372 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.gtid;
|
|
||||||
|
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.github.shyiko.mysql.binlog.MariadbGtidSet;
|
|
||||||
import com.github.shyiko.mysql.binlog.MariadbGtidSet.MariaGtid;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSet;
|
|
||||||
import io.debezium.util.Strings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MariaDB-specific implementation of a Global Transaction Identifier set.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbGtidSet implements GtidSet {
|
|
||||||
|
|
||||||
private Map<MariaDbGtidStreamId, MariaDbStreamSet> streamSets = new TreeMap<>();
|
|
||||||
|
|
||||||
public MariaDbGtidSet(String gtidSet) {
|
|
||||||
if (gtidSet != null && !gtidSet.isEmpty()) {
|
|
||||||
String[] gtids = gtidSet.replaceAll("\n", "").split(",");
|
|
||||||
Arrays.stream(gtids).forEach(gtid -> {
|
|
||||||
if (MariadbGtidSet.isMariaGtidSet(gtid)) {
|
|
||||||
MariaDbGtid mariaGtid = MariaDbGtid.parse(gtid);
|
|
||||||
MariaDbGtidStreamId streamId = new MariaDbGtidStreamId(mariaGtid);
|
|
||||||
if (!streamSets.containsKey(streamId)) {
|
|
||||||
streamSets.put(streamId, new MariaDbStreamSet());
|
|
||||||
}
|
|
||||||
streamSets.get(streamId).add(mariaGtid);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MariaDbGtidSet(Map<MariaDbGtidStreamId, MariaDbStreamSet> streamSets) {
|
|
||||||
this.streamSets = streamSets;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return streamSets.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isContainedWithin(GtidSet other) {
|
|
||||||
if (!(other instanceof MariaDbGtidSet)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.equals(other)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
final MariaDbGtidSet theOther = (MariaDbGtidSet) other;
|
|
||||||
for (Map.Entry<MariaDbGtidStreamId, MariaDbStreamSet> entry : streamSets.entrySet()) {
|
|
||||||
MariaDbStreamSet thatSet = theOther.forStreamId(entry.getKey());
|
|
||||||
if (!entry.getValue().isContainedWith(thatSet)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(String gtid) {
|
|
||||||
if (!MariadbGtidSet.isMariaGtidSet(gtid)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final MariaDbGtid mariaGtid = MariaDbGtid.parse(gtid);
|
|
||||||
final Set<MariaDbGtid> streamSet = forGtidStream(mariaGtid);
|
|
||||||
if (streamSet == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return streamSet.contains(mariaGtid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GtidSet retainAll(Predicate<String> sourceFilter) {
|
|
||||||
if (sourceFilter == null) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<MariaDbGtidStreamId, MariaDbStreamSet> newSets = streamSets.entrySet()
|
|
||||||
.stream()
|
|
||||||
.filter(entry -> sourceFilter.test(entry.getKey().asSourceFilterValue()))
|
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
|
||||||
|
|
||||||
return new MariaDbGtidSet(newSets);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MariaDbGtidSet subtract(GtidSet other) {
|
|
||||||
if (other == null) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
final MariaDbGtidSet theOther = (MariaDbGtidSet) other;
|
|
||||||
Map<MariaDbGtidStreamId, MariaDbStreamSet> newSets = streamSets.entrySet()
|
|
||||||
.stream()
|
|
||||||
.filter(entry -> !entry.getValue().isContainedWith(theOther.forStreamId(entry.getKey())))
|
|
||||||
.map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue().subtract(theOther.forStreamId(entry.getKey()))))
|
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
|
||||||
|
|
||||||
return new MariaDbGtidSet(newSets);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GtidSet with(GtidSet other) {
|
|
||||||
final MariaDbGtidSet theOther = (MariaDbGtidSet) other;
|
|
||||||
if (theOther == null || theOther.streamSets.isEmpty()) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Map<MariaDbGtidStreamId, MariaDbStreamSet> newSet = new HashMap<>();
|
|
||||||
newSet.putAll(streamSets);
|
|
||||||
newSet.putAll(theOther.streamSets);
|
|
||||||
return new MariaDbGtidSet(newSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isKnown(MariaDbGtid gtid) {
|
|
||||||
final MariaDbStreamSet streamSet = forGtidStream(gtid);
|
|
||||||
if (streamSet == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return streamSet.hasSequence(gtid.getSequence());
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbStreamSet forGtidStream(MariaDbGtid gtid) {
|
|
||||||
return forStreamId(new MariaDbGtidStreamId(gtid));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbStreamSet forStreamId(MariaDbGtidStreamId streamId) {
|
|
||||||
return streamSets.get(streamId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MariaDbGtid parse(String gtid) {
|
|
||||||
if (Strings.isNullOrBlank(gtid)) {
|
|
||||||
throw new IllegalStateException("Cannot parse empty GTID");
|
|
||||||
}
|
|
||||||
return MariaDbGtid.parse(gtid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object value) {
|
|
||||||
if (this == value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (value == null || getClass() != value.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
MariaDbGtidSet that = (MariaDbGtidSet) value;
|
|
||||||
return Objects.equals(streamSets, that.streamSets);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(streamSets);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return streamSets.values().stream().map(MariaDbStreamSet::toString).collect(Collectors.joining(","));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a MariaDB stream, which is a {@code domain-server} tuple.
|
|
||||||
*/
|
|
||||||
public static class MariaDbGtidStreamId implements Comparable<MariaDbGtidStreamId> {
|
|
||||||
|
|
||||||
private final long domainId;
|
|
||||||
private final long serverId;
|
|
||||||
|
|
||||||
public MariaDbGtidStreamId(long domainId, long serverId) {
|
|
||||||
this.domainId = domainId;
|
|
||||||
this.serverId = serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbGtidStreamId(MariaDbGtid gtid) {
|
|
||||||
this(gtid.getDomainId(), gtid.getServerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getDomainId() {
|
|
||||||
return domainId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getServerId() {
|
|
||||||
return serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String asSourceFilterValue() {
|
|
||||||
return String.format("%d-%d", domainId, serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSameDomainAndServer(MariaGtid gtid) {
|
|
||||||
return gtid.getDomainId() == domainId && gtid.getServerId() == serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object value) {
|
|
||||||
if (this == value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (value == null || getClass() != value.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
MariaDbGtidStreamId that = (MariaDbGtidStreamId) value;
|
|
||||||
return domainId == that.domainId && serverId == that.serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(domainId, serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(MariaDbGtidStreamId other) {
|
|
||||||
final int domainComparison = Long.compare(domainId, other.domainId);
|
|
||||||
if (domainComparison == 0) {
|
|
||||||
return Long.compare(serverId, other.serverId);
|
|
||||||
}
|
|
||||||
return domainComparison;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "MariaDbGtidStreamId{" +
|
|
||||||
"domainId=" + domainId +
|
|
||||||
", serverId=" + serverId +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a stream set, which are global transaction identifiers that belong to the same domain
|
|
||||||
* and to the same server identifiers.
|
|
||||||
*/
|
|
||||||
public static class MariaDbStreamSet extends TreeSet<MariaDbGtid> {
|
|
||||||
|
|
||||||
public boolean hasSequence(long sequence) {
|
|
||||||
for (MariaDbGtid gtid : this) {
|
|
||||||
if (gtid.getSequence() == sequence) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public boolean isContainedWith(MariaDbStreamSet other) {
|
|
||||||
if (other == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (other.containsAll(this)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return isAllBefore(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAllBefore(MariaDbStreamSet other) {
|
|
||||||
final Long otherMinSequence = other.stream().mapToLong(MariaDbGtid::getSequence).min().getAsLong();
|
|
||||||
final Long minSequence = stream().mapToLong(MariaDbGtid::getSequence).min().getAsLong();
|
|
||||||
return minSequence <= otherMinSequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbStreamSet subtract(MariaDbStreamSet other) {
|
|
||||||
if (other == null) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
final MariaDbStreamSet streamSet = new MariaDbStreamSet();
|
|
||||||
streamSet.addAll(stream().filter(gtid -> !other.contains(gtid)).collect(Collectors.toSet()));
|
|
||||||
return streamSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbStreamSet asBeginning() {
|
|
||||||
MariaDbStreamSet newSet = new MariaDbStreamSet();
|
|
||||||
if (!isEmpty()) {
|
|
||||||
newSet.add(newSet.first());
|
|
||||||
}
|
|
||||||
return newSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return stream().map(MariaDbGtid::toString).collect(Collectors.joining(","));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a logical MariaDB global transaction identifier.
|
|
||||||
*/
|
|
||||||
public static class MariaDbGtid implements Comparable<MariaDbGtid> {
|
|
||||||
|
|
||||||
private final long domainId;
|
|
||||||
private final long serverId;
|
|
||||||
private final long sequence;
|
|
||||||
|
|
||||||
public MariaDbGtid(MariaGtid gtid) {
|
|
||||||
this.domainId = gtid.getDomainId();
|
|
||||||
this.serverId = gtid.getServerId();
|
|
||||||
this.sequence = gtid.getSequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getDomainId() {
|
|
||||||
return domainId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getServerId() {
|
|
||||||
return serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getSequence() {
|
|
||||||
return sequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MariaDbGtid parse(String gtid) {
|
|
||||||
return new MariaDbGtid(MariaGtid.parse(gtid));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object value) {
|
|
||||||
if (this == value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (value == null || getClass() != value.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
MariaDbGtid that = (MariaDbGtid) value;
|
|
||||||
return domainId == that.domainId && serverId == that.serverId && sequence == that.sequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(domainId, serverId, sequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(MariaDbGtid other) {
|
|
||||||
final int domainComparison = Long.compare(domainId, other.domainId);
|
|
||||||
if (domainComparison == 0) {
|
|
||||||
final int serverComparison = Long.compare(serverId, other.serverId);
|
|
||||||
if (serverComparison == 0) {
|
|
||||||
return Long.compare(sequence, other.sequence);
|
|
||||||
}
|
|
||||||
return serverComparison;
|
|
||||||
}
|
|
||||||
return domainComparison;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return domainId + "-" + serverId + "-" + sequence;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.gtid;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSet;
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSetFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MariaDB-specific implementation of the {@link GtidSetFactory} for creating {@link GtidSet}s.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbGtidSetFactory implements GtidSetFactory {
|
|
||||||
@Override
|
|
||||||
public GtidSet createGtidSet(String gtid) {
|
|
||||||
return new MariaDbGtidSet(gtid);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.history;
|
|
||||||
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSetFactory;
|
|
||||||
import io.debezium.connector.binlog.history.BinlogHistoryRecordComparator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schema history record comparator implementation for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbHistoryRecordComparator extends BinlogHistoryRecordComparator {
|
|
||||||
public MariaDbHistoryRecordComparator(Predicate<String> gtidSourceFilter, GtidSetFactory gtidSetFactory) {
|
|
||||||
super(gtidSourceFilter, gtidSetFactory);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.jdbc;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.debezium.DebeziumException;
|
|
||||||
import io.debezium.connector.binlog.gtid.GtidSet;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogConnectorConnection;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogFieldReader;
|
|
||||||
import io.debezium.connector.binlog.jdbc.ConnectionConfiguration;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSet;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSet.MariaDbGtid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A concrete implementation of {@link BinlogConnectorConnection} for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnection extends BinlogConnectorConnection {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(MariaDbConnection.class);
|
|
||||||
|
|
||||||
public MariaDbConnection(ConnectionConfiguration configuration, BinlogFieldReader fieldReader) {
|
|
||||||
super(configuration, fieldReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGtidModeEnabled() {
|
|
||||||
// Always has GTID enabled.
|
|
||||||
// GTID_STRICT_MODE can be enabled or disabled.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GtidSet knownGtidSet() {
|
|
||||||
// MariaDB does not store the executed GTID details in the SHOW MASTER STATUS output like MySQL;
|
|
||||||
// however, instead makes this information available as a variable. The GTID_BINLOG_POS gives
|
|
||||||
// the current GTID position of the binary log and can therefore be considered the equivalent to
|
|
||||||
// MySQL's executed GTID set.
|
|
||||||
try {
|
|
||||||
return queryAndMap("SHOW GLOBAL VARIABLES LIKE 'GTID_BINLOG_POS'", rs -> {
|
|
||||||
if (rs.next()) {
|
|
||||||
return new MariaDbGtidSet(rs.getString(2));
|
|
||||||
}
|
|
||||||
return new MariaDbGtidSet("");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw new DebeziumException("Unexpected error while looking at GTID_BINLOG_POS: ", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GtidSet subtractGtidSet(GtidSet set1, GtidSet set2) {
|
|
||||||
return set1.subtract(set2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GtidSet purgedGtidSet() {
|
|
||||||
// The MariaDB community mentioned we could get the purged GTID values from the GTID_LIST_EVENT; however,
|
|
||||||
// this value is only available after we connect and would require a temporary binlog connection to get
|
|
||||||
// the data, so for now simply returning an empty set until we split the code base.
|
|
||||||
return new MariaDbGtidSet("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GtidSet filterGtidSet(Predicate<String> gtidSourceFilter, String offsetGtids, GtidSet availableServerGtidSet, GtidSet purgedServerGtidSet) {
|
|
||||||
String gtidStr = offsetGtids;
|
|
||||||
if (gtidStr == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
LOGGER.info("Attempting to generate a filtered GTID set");
|
|
||||||
LOGGER.info("GTID set from previous recorded offset: {}", gtidStr);
|
|
||||||
MariaDbGtidSet filteredGtidSet = new MariaDbGtidSet(gtidStr);
|
|
||||||
if (gtidSourceFilter != null) {
|
|
||||||
filteredGtidSet = (MariaDbGtidSet) filteredGtidSet.retainAll(gtidSourceFilter);
|
|
||||||
LOGGER.info("GTID set after applying GTID source includes/excludes to previous recorded offset: {}", filteredGtidSet);
|
|
||||||
}
|
|
||||||
LOGGER.info("GTID set available on server: {}", availableServerGtidSet);
|
|
||||||
|
|
||||||
final MariaDbGtidSet knownGtidSet = filteredGtidSet;
|
|
||||||
LOGGER.info("Using first available positions for new GTID channels");
|
|
||||||
final GtidSet relevantAvailableServerGtidSet = (gtidSourceFilter != null) ? availableServerGtidSet.retainAll(gtidSourceFilter) : availableServerGtidSet;
|
|
||||||
LOGGER.info("Relevant GTID set available on server: {}", relevantAvailableServerGtidSet);
|
|
||||||
|
|
||||||
GtidSet mergedGtidSet = relevantAvailableServerGtidSet
|
|
||||||
.retainAll(serverId -> {
|
|
||||||
// ServerId in this context is "<domain-id>-<server-id>"
|
|
||||||
final MariaDbGtid compliantGtid = MariaDbGtid.parse(serverId + "-0");
|
|
||||||
return knownGtidSet.forGtidStream(compliantGtid) != null;
|
|
||||||
})
|
|
||||||
.with(purgedServerGtidSet)
|
|
||||||
.with(filteredGtidSet);
|
|
||||||
|
|
||||||
LOGGER.info("Final merged GTID set to use when connecting to MariaDB: {}", mergedGtidSet);
|
|
||||||
return mergedGtidSet;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.jdbc;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogConnectionConfiguration;
|
|
||||||
import io.debezium.jdbc.JdbcConnection;
|
|
||||||
import io.debezium.util.Strings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnectionConfiguration extends BinlogConnectionConfiguration {
|
|
||||||
|
|
||||||
private static final String JDBC_PROPERTY_MARIADB_TIME_ZONE = "timezone";
|
|
||||||
private static final String URL_PATTERN = "jdbc:mariadb://${hostname}:${port}/?useInformationSchema=true&nullCatalogMeansCurrent=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL&connectTimeout=${connectTimeout}";
|
|
||||||
|
|
||||||
public MariaDbConnectionConfiguration(Configuration configuration) {
|
|
||||||
super(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getConnectionTimeZonePropertyName() {
|
|
||||||
return JDBC_PROPERTY_MARIADB_TIME_ZONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String resolveConnectionTimeZone(Configuration configuration) {
|
|
||||||
// Debezium expects timezone data delivered in server timezone by default.
|
|
||||||
return Strings.defaultIfBlank(configuration.getString(JDBC_PROPERTY_MARIADB_TIME_ZONE), "auto");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JdbcConnection.ConnectionFactory createFactory(Configuration configuration) {
|
|
||||||
return JdbcConnection.patternBasedFactory(URL_PATTERN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUrlPattern() {
|
|
||||||
return URL_PATTERN;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.jdbc;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogDefaultValueConverter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbDefaultValueConverter extends BinlogDefaultValueConverter {
|
|
||||||
public MariaDbDefaultValueConverter(MariaDbValueConverters valueConverter) {
|
|
||||||
super(valueConverter);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.jdbc;
|
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogFieldReader;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.relational.Table;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link BinlogFieldReader} implementation for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbFieldReader extends BinlogFieldReader {
|
|
||||||
|
|
||||||
public MariaDbFieldReader(MariaDbConnectorConfig connectorConfig) {
|
|
||||||
super(connectorConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getCharacterSet(Column column) {
|
|
||||||
return getCharsetRegistry().getJavaEncodingForCharSet(column.charsetName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object readTimeField(ResultSet rs, int columnIndex, Column column, Table table) throws SQLException {
|
|
||||||
final String value = rs.getString(columnIndex);
|
|
||||||
return Objects.isNull(value) ? null : MariaDbValueConverters.stringToDuration(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object readDateField(ResultSet rs, int columnIndex, Column column, Table table) throws SQLException {
|
|
||||||
final String value = rs.getString(columnIndex);
|
|
||||||
return Objects.isNull(value) ? null : MariaDbValueConverters.stringToLocalDate(value, column, table);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object readTimestampField(ResultSet rs, int columnIndex, Column column, Table table) throws SQLException {
|
|
||||||
final String value = rs.getString(columnIndex);
|
|
||||||
if (Objects.isNull(value)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return MariaDbValueConverters.containsZeroValuesInDatePart(value, column, table)
|
|
||||||
? null
|
|
||||||
: rs.getTimestamp(columnIndex, Calendar.getInstance());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.jdbc;
|
|
||||||
|
|
||||||
import java.time.temporal.TemporalAdjuster;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.debezium.annotation.Immutable;
|
|
||||||
import io.debezium.config.CommonConnectorConfig.BinaryHandlingMode;
|
|
||||||
import io.debezium.config.CommonConnectorConfig.EventConvertingFailureHandlingMode;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogValueConverters;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.jdbc.TemporalPrecisionMode;
|
|
||||||
import io.debezium.relational.Column;
|
|
||||||
import io.debezium.service.spi.ServiceRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MariaDB specific converter handlers for JDBC values.<p></p>
|
|
||||||
*
|
|
||||||
* This class uses UTC for the default time zone when converting values without timezone details to values that
|
|
||||||
* require timezones. This is because MariaDB {@code TIMESTAMP} values are always stored in UTC, unlike types
|
|
||||||
* like {@code DATETIME}, and aare replicated as such. Meanwhile, the Binlog Client will deserialize these as
|
|
||||||
* {@link java.sql.Timestamp} which have no timezone; therefore, are presumed to be UTC.<p></p>
|
|
||||||
*
|
|
||||||
* If a column is {@link java.sql.Types#TIMESTAMP_WITH_TIMEZONE}, the converters will need to convert the value
|
|
||||||
* from a {@link java.sql.Timestamp} to an {@link java.time.OffsetDateTime} using the default time zone, which
|
|
||||||
* is always UTC.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@Immutable
|
|
||||||
public class MariaDbValueConverters extends BinlogValueConverters {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new instance of the value converters that always uses UTC for the default time zone when
|
|
||||||
* converting values without timezone information to values that require timezones.
|
|
||||||
*
|
|
||||||
* @param decimalMode how {@code DECIMAL} and {@code NUMERIC} values are treated; can be null if {@link DecimalMode#PRECISE} is used
|
|
||||||
* @param temporalPrecisionMode temporal precision mode
|
|
||||||
* @param bigIntUnsignedMode how {@code BIGINT UNSIGNED} values are treated; may be null if {@link BigIntUnsignedMode#PRECISE} is used.
|
|
||||||
* @param binaryHandlingMode how binary columns should be treated
|
|
||||||
* @param adjuster a temporal adjuster to make a database specific time before conversion
|
|
||||||
* @param eventConvertingFailureHandlingMode how to handle conversion failures
|
|
||||||
* @param serviceRegistry the service registry, should not be {@code null}
|
|
||||||
*/
|
|
||||||
public MariaDbValueConverters(DecimalMode decimalMode,
|
|
||||||
TemporalPrecisionMode temporalPrecisionMode,
|
|
||||||
BigIntUnsignedMode bigIntUnsignedMode,
|
|
||||||
BinaryHandlingMode binaryHandlingMode,
|
|
||||||
TemporalAdjuster adjuster,
|
|
||||||
EventConvertingFailureHandlingMode eventConvertingFailureHandlingMode,
|
|
||||||
ServiceRegistry serviceRegistry) {
|
|
||||||
super(decimalMode, temporalPrecisionMode, bigIntUnsignedMode, binaryHandlingMode, adjuster, eventConvertingFailureHandlingMode, serviceRegistry);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<String> extractEnumAndSetOptions(Column column) {
|
|
||||||
return MariaDbAntlrDdlParser.extractEnumAndSetOptions(column.enumValues());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.metadata;
|
|
||||||
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.connector.mariadb.Module;
|
|
||||||
import io.debezium.metadata.ConnectorDescriptor;
|
|
||||||
import io.debezium.metadata.ConnectorMetadata;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnectorMetadata implements ConnectorMetadata {
|
|
||||||
@Override
|
|
||||||
public ConnectorDescriptor getConnectorDescriptor() {
|
|
||||||
return new ConnectorDescriptor(MariaDbConnector.class.getName(), Module.version());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Field.Set getConnectorFields() {
|
|
||||||
return MariaDbConnectorConfig.ALL_FIELDS;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.metadata;
|
|
||||||
|
|
||||||
import io.debezium.metadata.ConnectorMetadata;
|
|
||||||
import io.debezium.metadata.ConnectorMetadataProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnectorMetadataProvider implements ConnectorMetadataProvider {
|
|
||||||
@Override
|
|
||||||
public ConnectorMetadata getConnectorMetadata() {
|
|
||||||
return new MariaDbConnectorMetadata();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.metrics;
|
|
||||||
|
|
||||||
import io.debezium.connector.base.ChangeEventQueueMetrics;
|
|
||||||
import io.debezium.connector.common.CdcSourceTaskContext;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbPartition;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbTaskContext;
|
|
||||||
import io.debezium.pipeline.metrics.DefaultChangeEventSourceMetricsFactory;
|
|
||||||
import io.debezium.pipeline.metrics.SnapshotChangeEventSourceMetrics;
|
|
||||||
import io.debezium.pipeline.metrics.StreamingChangeEventSourceMetrics;
|
|
||||||
import io.debezium.pipeline.source.spi.EventMetadataProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of the {@link io.debezium.pipeline.metrics.DefaultStreamingChangeEventSourceMetrics} for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbChangeEventSourceMetricsFactory extends DefaultChangeEventSourceMetricsFactory<MariaDbPartition> {
|
|
||||||
|
|
||||||
public MariaDbStreamingChangeEventSourceMetrics streamingMetrics;
|
|
||||||
|
|
||||||
public MariaDbChangeEventSourceMetricsFactory(MariaDbStreamingChangeEventSourceMetrics streamingMetrics) {
|
|
||||||
this.streamingMetrics = streamingMetrics;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends CdcSourceTaskContext> SnapshotChangeEventSourceMetrics<MariaDbPartition> getSnapshotMetrics(
|
|
||||||
T taskContext,
|
|
||||||
ChangeEventQueueMetrics changeEventQueueMetrics,
|
|
||||||
EventMetadataProvider eventMetadataProvider) {
|
|
||||||
return new MariaDbSnapshotChangeEventSourceMetrics((MariaDbTaskContext) taskContext, changeEventQueueMetrics, eventMetadataProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends CdcSourceTaskContext> StreamingChangeEventSourceMetrics<MariaDbPartition> getStreamingMetrics(
|
|
||||||
T taskContext,
|
|
||||||
ChangeEventQueueMetrics changeEventQueueMetrics,
|
|
||||||
EventMetadataProvider eventMetadataProvider) {
|
|
||||||
return streamingMetrics;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean connectionMetricHandledByCoordinator() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.metrics;
|
|
||||||
|
|
||||||
import io.debezium.connector.base.ChangeEventQueueMetrics;
|
|
||||||
import io.debezium.connector.binlog.metrics.BinlogSnapshotChangeEventSourceMetrics;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbPartition;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbTaskContext;
|
|
||||||
import io.debezium.pipeline.source.spi.EventMetadataProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks the snapshot metrics specific for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbSnapshotChangeEventSourceMetrics extends BinlogSnapshotChangeEventSourceMetrics<MariaDbPartition> {
|
|
||||||
public MariaDbSnapshotChangeEventSourceMetrics(MariaDbTaskContext taskContext,
|
|
||||||
ChangeEventQueueMetrics changeEventQueueMetrics,
|
|
||||||
EventMetadataProvider metadataProvider) {
|
|
||||||
super(taskContext, changeEventQueueMetrics, metadataProvider);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.metrics;
|
|
||||||
|
|
||||||
import io.debezium.connector.base.ChangeEventQueueMetrics;
|
|
||||||
import io.debezium.connector.binlog.metrics.BinlogStreamingChangeEventSourceMetrics;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbDatabaseSchema;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbPartition;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbTaskContext;
|
|
||||||
import io.debezium.pipeline.source.spi.EventMetadataProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks the streaming metrics specific for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbStreamingChangeEventSourceMetrics
|
|
||||||
extends BinlogStreamingChangeEventSourceMetrics<MariaDbDatabaseSchema, MariaDbPartition> {
|
|
||||||
public MariaDbStreamingChangeEventSourceMetrics(MariaDbTaskContext taskContext,
|
|
||||||
ChangeEventQueueMetrics changeEventQueueMetrics,
|
|
||||||
EventMetadataProvider eventMetadataProvider) {
|
|
||||||
super(taskContext, changeEventQueueMetrics, eventMetadataProvider);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.rest;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.kafka.common.utils.AppInfoParser;
|
|
||||||
import org.apache.kafka.connect.rest.ConnectRestExtension;
|
|
||||||
import org.apache.kafka.connect.rest.ConnectRestExtensionContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DebeziumMariaDbConnectRestExtension implements ConnectRestExtension {
|
|
||||||
private Map<String, ?> config;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(ConnectRestExtensionContext restPluginContext) {
|
|
||||||
restPluginContext.configurable().register(new DebeziumMariaDbConnectorResource(restPluginContext.clusterState()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(Map<String, ?> configs) {
|
|
||||||
this.config = configs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String version() {
|
|
||||||
return AppInfoParser.getVersion();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.rest;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
import org.apache.kafka.connect.health.ConnectClusterState;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.Module;
|
|
||||||
import io.debezium.rest.ConnectionValidationResource;
|
|
||||||
import io.debezium.rest.FilterValidationResource;
|
|
||||||
import io.debezium.rest.MetricsResource;
|
|
||||||
import io.debezium.rest.SchemaResource;
|
|
||||||
import io.debezium.rest.model.DataCollection;
|
|
||||||
import io.debezium.rest.model.MetricsDescriptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JAX-RS resource class defining endpoints of the Debezium MariaDB Connect REST extension.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@Path(DebeziumMariaDbConnectorResource.BASE_PATH)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public class DebeziumMariaDbConnectorResource
|
|
||||||
implements SchemaResource, ConnectionValidationResource, FilterValidationResource, MetricsResource {
|
|
||||||
|
|
||||||
public static final String BASE_PATH = "/debezium/mariadb";
|
|
||||||
public static final String VERSION_ENDPOINT = "/version";
|
|
||||||
private final ConnectClusterState connectClusterState;
|
|
||||||
|
|
||||||
public DebeziumMariaDbConnectorResource(ConnectClusterState connectClusterState) {
|
|
||||||
this.connectClusterState = connectClusterState;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSchemaFilePath() {
|
|
||||||
return "/META-INF/resources/mariadb.json";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MariaDbConnector getConnector() {
|
|
||||||
return new MariaDbConnector();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetricsDescriptor getMetrics(String connectorName) throws MalformedObjectNameException {
|
|
||||||
Map<String, String> connectorConfig = connectClusterState.connectorConfig(connectorName);
|
|
||||||
return queryMetrics(connectorConfig, connectorName, Module.contextName().toLowerCase(), "streaming");
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path(VERSION_ENDPOINT)
|
|
||||||
public String getConnectorVersion() {
|
|
||||||
return Module.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DataCollection> getMatchingCollections(Configuration configuration) {
|
|
||||||
return getConnector().getMatchingCollections(configuration).stream()
|
|
||||||
.map(tableId -> new DataCollection(tableId.catalog(), tableId.table()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.snapshot.lock;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import io.debezium.annotation.ConnectorSpecific;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@ConnectorSpecific(connector = MariaDbConnector.class)
|
|
||||||
public abstract class DefaultSnapshotLock {
|
|
||||||
public Optional<String> tableLockingStatement(Duration lockTimeout, String tableId) {
|
|
||||||
return Optional.of("FLUSH TABLES WITH READ LOCK");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.snapshot.lock;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.debezium.annotation.ConnectorSpecific;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.snapshot.spi.SnapshotLock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@ConnectorSpecific(connector = MariaDbConnector.class)
|
|
||||||
public class ExtendedSnapshotLock extends DefaultSnapshotLock implements SnapshotLock {
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return MariaDbConnectorConfig.SnapshotLockingMode.EXTENDED.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(Map<String, ?> properties) {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.snapshot.lock;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.debezium.annotation.ConnectorSpecific;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.snapshot.spi.SnapshotLock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@ConnectorSpecific(connector = MariaDbConnector.class)
|
|
||||||
public class MinimalSnapshotLock extends DefaultSnapshotLock implements SnapshotLock {
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return MariaDbConnectorConfig.SnapshotLockingMode.MINIMAL.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(Map<String, ?> properties) {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.snapshot.lock;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import io.debezium.annotation.ConnectorSpecific;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.snapshot.spi.SnapshotLock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@ConnectorSpecific(connector = MariaDbConnector.class)
|
|
||||||
public class NoneSnapshotLock implements SnapshotLock {
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return MariaDbConnectorConfig.SnapshotLockingMode.NONE.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(Map<String, ?> properties) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<String> tableLockingStatement(Duration lockTimeout, String tableId) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.snapshot.query;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import io.debezium.annotation.ConnectorSpecific;
|
|
||||||
import io.debezium.config.CommonConnectorConfig;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.snapshot.spi.SnapshotQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of {@link SnapshotQuery} for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
@ConnectorSpecific(connector = MariaDbConnector.class)
|
|
||||||
public class SelectAllSnapshotQuery implements SnapshotQuery {
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return CommonConnectorConfig.SnapshotQueryMode.SELECT_ALL.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(Map<String, ?> properties) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<String> snapshotQuery(String tableId, List<String> snapshotSelectColumns) {
|
|
||||||
return Optional.of(snapshotSelectColumns.stream()
|
|
||||||
.collect(Collectors.joining(", ", "SELECT ", " FROM " + tableId)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.converters.MariaDbCloudEventsProvider
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.metadata.MariaDbConnectorMetadataProvider
|
|
@ -1,3 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.snapshot.lock.ExtendedSnapshotLock
|
|
||||||
io.debezium.connector.mariadb.snapshot.lock.MinimalSnapshotLock
|
|
||||||
io.debezium.connector.mariadb.snapshot.lock.NoneSnapshotLock
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.snapshot.query.SelectAllSnapshotQuery
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.rest.DebeziumMariaDbConnectRestExtension
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.MariaDbConnector
|
|
@ -1,1971 +0,0 @@
|
|||||||
{
|
|
||||||
"character_sets": [
|
|
||||||
{
|
|
||||||
"name": "ascii",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "US-ASCII", "ASCII" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "big5",
|
|
||||||
"mblen": 2,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Big5" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gbk",
|
|
||||||
"mblen": 2,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "GBK" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sjis",
|
|
||||||
"mblen": 2,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "SHIFT_JIS", "Cp943", "WINDOWS-31J" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp932",
|
|
||||||
"mblen": 2,
|
|
||||||
"priority": 1,
|
|
||||||
"encodings": [ "GB2312" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gb2312",
|
|
||||||
"mblen": 2,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "GB2312" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ujis",
|
|
||||||
"mblen": 3,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "EUC_JP" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "eucjpms",
|
|
||||||
"mblen": 3,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "EUC_JP_Solaris" ],
|
|
||||||
"comment": "Added in MySQL 5.0.3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gb18030",
|
|
||||||
"mblen": 4,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "GB18030" ],
|
|
||||||
"comment": "Added in MySQL 5.74"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "euckr",
|
|
||||||
"mblen": 2,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "EUC-KR" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "latin1",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 1,
|
|
||||||
"encodings": [ "Cp1252", "ISO8859_1" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "swe7",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1252" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "hp8",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1252" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "dec8",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1252" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "armscii8",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1252" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "geostd8",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1252" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "latin2",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "ISO8859_2" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "greek",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "ISO8859_7", "greek" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "latin7",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "ISO-8859-13" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "hebrew",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "ISO8859_8" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "latin5",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "ISO8859_9" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp850",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp850", "Cp437" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp852",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp852" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "keybcs2",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp852" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp866",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp866" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "koi8r",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 1,
|
|
||||||
"encodings": [ "KOI8_R" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "koi8u",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "KOI8_R" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tis620",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "TIS620" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp1250",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1250" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp1251",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 1,
|
|
||||||
"encodings": [ "Cp1251" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp1256",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1256" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "cp1257",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "Cp1257" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macroman",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "MacRoman" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macce",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "MacCentralEurope" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "utf8mb3",
|
|
||||||
"mblen": 3,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "UTF-8" ],
|
|
||||||
"aliases": [ "utf8" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "utf8mb4",
|
|
||||||
"mblen": 4,
|
|
||||||
"priority": 1,
|
|
||||||
"encodings": [ "UTF-8" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "binary",
|
|
||||||
"mblen": 1,
|
|
||||||
"priority": 1,
|
|
||||||
"encodings": [ "ISO8859_1" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ucs2",
|
|
||||||
"mblen": 2,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "UnicodeBig" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "utf16",
|
|
||||||
"mblen": 4,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "UTF-16" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "utf16le",
|
|
||||||
"mblen": 4,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "UTF-16LE" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "utf32",
|
|
||||||
"mblen": 4,
|
|
||||||
"priority": 0,
|
|
||||||
"encodings": [ "UTF-32" ]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"collation_mappings": [
|
|
||||||
{
|
|
||||||
"index": 1,
|
|
||||||
"collations": [ "big5_chinese_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "big5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 2,
|
|
||||||
"collations": [ "latin2_czech_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 3,
|
|
||||||
"collations": [ "dec8_swedish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "dec8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 4,
|
|
||||||
"collations": [ "cp850_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp850"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 5,
|
|
||||||
"collations": [ "latin1_german1_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 6,
|
|
||||||
"collations": [ "hp8_english_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "hp8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 7,
|
|
||||||
"collations": [ "koi8r_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "koi8r"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 8,
|
|
||||||
"collations": [ "latin1_swedish_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 9,
|
|
||||||
"collations": [ "latin2_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "latin2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 10,
|
|
||||||
"collations": [ "swe7_swedish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "swe7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 11,
|
|
||||||
"collations": [ "ascii_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ascii"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 12,
|
|
||||||
"collations": [ "ujis_japanese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ujis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 13,
|
|
||||||
"collations": [ "sjis_japanese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "sjis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 14,
|
|
||||||
"collations": [ "cp1251_bulgarian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1251"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 15,
|
|
||||||
"collations": [ "latin1_danish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 16,
|
|
||||||
"collations": [ "hebrew_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "hebrew"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 18,
|
|
||||||
"collations": [ "tis620_thai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "tis620"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 19,
|
|
||||||
"collations": [ "euckr_korean_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "euckr"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 20,
|
|
||||||
"collations": [ "latin7_estonian_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 21,
|
|
||||||
"collations": [ "latin2_hungarian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 22,
|
|
||||||
"collations": [ "koi8u_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "koi8u"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 23,
|
|
||||||
"collations": [ "cp1251_ukrainian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1251"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 24,
|
|
||||||
"collations": [ "gb2312_chinese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "gb2312"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 25,
|
|
||||||
"collations": [ "greek_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "greek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 26,
|
|
||||||
"collations": [ "cp1250_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp1250"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 27,
|
|
||||||
"collations": [ "latin2_croatian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 28,
|
|
||||||
"collations": [ "gbk_chinese_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "gbk"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 29,
|
|
||||||
"collations": [ "cp1257_lithuanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1257"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 30,
|
|
||||||
"collations": [ "latin5_turkish_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "latin5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 31,
|
|
||||||
"collations": [ "latin1_german2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 32,
|
|
||||||
"collations": [ "armscii8_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "armscii8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 33,
|
|
||||||
"collations": [ "utf8mb3_general_ci", "utf8_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 34,
|
|
||||||
"collations": [ "cp1250_czech_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1250"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 35,
|
|
||||||
"collations": [ "ucs2_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 36,
|
|
||||||
"collations": [ "cp866_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp866"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 37,
|
|
||||||
"collations": [ "keybcs2_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "keybcs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 38,
|
|
||||||
"collations": [ "macce_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "macce"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 39,
|
|
||||||
"collations": [ "macroman_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "macroman"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 40,
|
|
||||||
"collations": [ "cp852_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp852"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 41,
|
|
||||||
"collations": [ "latin7_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "latin7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 42,
|
|
||||||
"collations": [ "latin7_general_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 43,
|
|
||||||
"collations": [ "macce_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "macce"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 44,
|
|
||||||
"collations": [ "cp1250_croatian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1250"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 45,
|
|
||||||
"collations": [ "utf8mb4_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 46,
|
|
||||||
"collations": [ "utf8mb4_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 47,
|
|
||||||
"collations": [ "latin1_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 48,
|
|
||||||
"collations": [ "latin1_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 49,
|
|
||||||
"collations": [ "latin1_general_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 50,
|
|
||||||
"collations": [ "cp1251_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1251"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 51,
|
|
||||||
"collations": [ "cp1251_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp1251"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 52,
|
|
||||||
"collations": [ "cp1251_general_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1251"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 53,
|
|
||||||
"collations": [ "macroman_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "macroman"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 54,
|
|
||||||
"collations": [ "utf16_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 55,
|
|
||||||
"collations": [ "utf16_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 56,
|
|
||||||
"collations": [ "utf16le_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "utf16le"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 57,
|
|
||||||
"collations": [ "cp1256_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp1256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 58,
|
|
||||||
"collations": [ "cp1257_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1257"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 59,
|
|
||||||
"collations": [ "cp1257_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp1257"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 60,
|
|
||||||
"collations": [ "utf32_general_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 61,
|
|
||||||
"collations": [ "utf32_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 62,
|
|
||||||
"collations": [ "utf16le_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16le"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 63,
|
|
||||||
"collations": [ "binary" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "binary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 64,
|
|
||||||
"collations": [ "armscii8_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "armscii8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 65,
|
|
||||||
"collations": [ "ascii_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ascii"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 66,
|
|
||||||
"collations": [ "cp1250_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1250"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 67,
|
|
||||||
"collations": [ "cp1256_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 68,
|
|
||||||
"collations": [ "cp866_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp866"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 69,
|
|
||||||
"collations": [ "dec8_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "dec8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 70,
|
|
||||||
"collations": [ "greek_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "greek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 71,
|
|
||||||
"collations": [ "hebrew_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "hebrew"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 72,
|
|
||||||
"collations": [ "hp8_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "hp8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 73,
|
|
||||||
"collations": [ "keybcs2_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "keybcs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 74,
|
|
||||||
"collations": [ "koi8r_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "koi8r"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 75,
|
|
||||||
"collations": [ "koi8u_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "koi8u"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 76,
|
|
||||||
"collations": [ "utf8mb3_tolower_ci", "utf8_tolower_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 77,
|
|
||||||
"collations": [ "latin2_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 78,
|
|
||||||
"collations": [ "latin5_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 79,
|
|
||||||
"collations": [ "latin7_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 80,
|
|
||||||
"collations": [ "cp850_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp850"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 81,
|
|
||||||
"collations": [ "cp852_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp852"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 82,
|
|
||||||
"collations": [ "swe7_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "swe7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 83,
|
|
||||||
"collations": [ "utf8mb3_bin", "utf8_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 84,
|
|
||||||
"collations": [ "big5_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "big5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 85,
|
|
||||||
"collations": [ "euckr_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "euckr"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 86,
|
|
||||||
"collations": [ "gb2312_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "gb2312"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 87,
|
|
||||||
"collations": [ "gbk_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "gbk"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 88,
|
|
||||||
"collations": [ "sjis_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "sjis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 89,
|
|
||||||
"collations": [ "tis620_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "tis620"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 90,
|
|
||||||
"collations": [ "ucs2_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 91,
|
|
||||||
"collations": [ "ujis_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ujis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 92,
|
|
||||||
"collations": [ "geostd8_general_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "geostd8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 93,
|
|
||||||
"collations": [ "geostd8_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "geostd8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 94,
|
|
||||||
"collations": [ "latin1_spanish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "latin1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 95,
|
|
||||||
"collations": [ "cp932_japanese_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "cp932"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 96,
|
|
||||||
"collations": [ "cp932_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp932"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 97,
|
|
||||||
"collations": [ "eucjpms_japanese_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "eucjpms"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 98,
|
|
||||||
"collations": [ "eucjpms_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "eucjpms"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 99,
|
|
||||||
"collations": [ "cp1250_polish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "cp1250"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 101,
|
|
||||||
"collations": [ "utf16_unicode_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 102,
|
|
||||||
"collations": [ "utf16_icelandic_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 103,
|
|
||||||
"collations": [ "utf16_latvian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 104,
|
|
||||||
"collations": [ "utf16_romanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 105,
|
|
||||||
"collations": [ "utf16_slovenian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 106,
|
|
||||||
"collations": [ "utf16_polish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 107,
|
|
||||||
"collations": [ "utf16_estonian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 108,
|
|
||||||
"collations": [ "utf16_spanish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 109,
|
|
||||||
"collations": [ "utf16_swedish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 110,
|
|
||||||
"collations": [ "utf16_turkish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 111,
|
|
||||||
"collations": [ "utf16_czech_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 112,
|
|
||||||
"collations": [ "utf16_danish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 113,
|
|
||||||
"collations": [ "utf16_lithuanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 114,
|
|
||||||
"collations": [ "utf16_slovak_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 115,
|
|
||||||
"collations": [ "utf16_spanish2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 116,
|
|
||||||
"collations": [ "utf16_roman_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 117,
|
|
||||||
"collations": [ "utf16_persian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 118,
|
|
||||||
"collations": [ "utf16_esperanto_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 119,
|
|
||||||
"collations": [ "utf16_hungarian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 120,
|
|
||||||
"collations": [ "utf16_sinhala_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 121,
|
|
||||||
"collations": [ "utf16_german2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 122,
|
|
||||||
"collations": [ "utf16_croatian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 123,
|
|
||||||
"collations": [ "utf16_unicode_520_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 124,
|
|
||||||
"collations": [ "utf16_vietnamese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 128,
|
|
||||||
"collations": [ "ucs2_unicode_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 129,
|
|
||||||
"collations": [ "ucs2_icelandic_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 130,
|
|
||||||
"collations": [ "ucs2_latvian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 131,
|
|
||||||
"collations": [ "ucs2_romanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 132,
|
|
||||||
"collations": [ "ucs2_slovenian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 133,
|
|
||||||
"collations": [ "ucs2_polish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 134,
|
|
||||||
"collations": [ "ucs2_estonian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 135,
|
|
||||||
"collations": [ "ucs2_spanish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 136,
|
|
||||||
"collations": [ "ucs2_swedish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 137,
|
|
||||||
"collations": [ "ucs2_turkish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 138,
|
|
||||||
"collations": [ "ucs2_czech_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 139,
|
|
||||||
"collations": [ "ucs2_danish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 140,
|
|
||||||
"collations": [ "ucs2_lithuanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 141,
|
|
||||||
"collations": [ "ucs2_slovak_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 142,
|
|
||||||
"collations": [ "ucs2_spanish2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 143,
|
|
||||||
"collations": [ "ucs2_roman_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 144,
|
|
||||||
"collations": [ "ucs2_persian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 145,
|
|
||||||
"collations": [ "ucs2_esperanto_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 146,
|
|
||||||
"collations": [ "ucs2_hungarian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 147,
|
|
||||||
"collations": [ "ucs2_sinhala_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 148,
|
|
||||||
"collations": [ "ucs2_german2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 149,
|
|
||||||
"collations": [ "ucs2_croatian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 150,
|
|
||||||
"collations": [ "ucs2_unicode_520_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 151,
|
|
||||||
"collations": [ "ucs2_vietnamese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 159,
|
|
||||||
"collations": [ "ucs2_general_mysql500_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "ucs2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 160,
|
|
||||||
"collations": [ "utf32_unicode_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 161,
|
|
||||||
"collations": [ "utf32_icelandic_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 162,
|
|
||||||
"collations": [ "utf32_latvian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 163,
|
|
||||||
"collations": [ "utf32_romanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 164,
|
|
||||||
"collations": [ "utf32_slovenian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 165,
|
|
||||||
"collations": [ "utf32_polish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 166,
|
|
||||||
"collations": [ "utf32_estonian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 167,
|
|
||||||
"collations": [ "utf32_spanish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 168,
|
|
||||||
"collations": [ "utf32_swedish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 169,
|
|
||||||
"collations": [ "utf32_turkish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 170,
|
|
||||||
"collations": [ "utf32_czech_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 171,
|
|
||||||
"collations": [ "utf32_danish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 172,
|
|
||||||
"collations": [ "utf32_lithuanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 173,
|
|
||||||
"collations": [ "utf32_slovak_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 174,
|
|
||||||
"collations": [ "utf32_spanish2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 175,
|
|
||||||
"collations": [ "utf32_roman_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 176,
|
|
||||||
"collations": [ "utf32_persian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 177,
|
|
||||||
"collations": [ "utf32_esperanto_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 178,
|
|
||||||
"collations": [ "utf32_hungarian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 179,
|
|
||||||
"collations": [ "utf32_sinhala_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 180,
|
|
||||||
"collations": [ "utf32_german2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 181,
|
|
||||||
"collations": [ "utf32_croatian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 182,
|
|
||||||
"collations": [ "utf32_unicode_520_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 183,
|
|
||||||
"collations": [ "utf32_vietnamese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 192,
|
|
||||||
"collations": [ "utf8mb3_unicode_ci", "utf8_unicode_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 193,
|
|
||||||
"collations": [ "utf8mb3_icelandic_ci", "utf8_icelandic_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 194,
|
|
||||||
"collations": [ "utf8mb3_latvian_ci", "utf8_latvian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 195,
|
|
||||||
"collations": [ "utf8mb3_romanian_ci", "utf8_romanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 196,
|
|
||||||
"collations": [ "utf8mb3_slovenian_ci", "utf8_slovenian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 197,
|
|
||||||
"collations": [ "utf8mb3_polish_ci", "utf8_polish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 198,
|
|
||||||
"collations": [ "utf8mb3_estonian_ci", "utf8_estonian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 199,
|
|
||||||
"collations": [ "utf8mb3_spanish_ci", "utf8_spanish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 200,
|
|
||||||
"collations": [ "utf8mb3_swedish_ci", "utf8_swedish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 201,
|
|
||||||
"collations": [ "utf8mb3_turkish_ci", "utf8_turkish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 202,
|
|
||||||
"collations": [ "utf8mb3_czech_ci", "utf8_czech_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 203,
|
|
||||||
"collations": [ "utf8mb3_danish_ci", "utf8_danish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 204,
|
|
||||||
"collations": [ "utf8mb3_lithuanian_ci", "utf8_lithuanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 205,
|
|
||||||
"collations": [ "utf8mb3_slovak_ci", "utf8_slovak_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 206,
|
|
||||||
"collations": [ "utf8mb3_spanish2_ci", "utf8_spanish2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 207,
|
|
||||||
"collations": [ "utf8mb3_roman_ci", "utf8_roman_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 208,
|
|
||||||
"collations": [ "utf8mb3_persian_ci", "utf8_persian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 209,
|
|
||||||
"collations": [ "utf8mb3_esperanto_ci", "utf8_esperanto_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 210,
|
|
||||||
"collations": [ "utf8mb3_hungarian_ci", "utf8_hungarian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 211,
|
|
||||||
"collations": [ "utf8mb3_sinhala_ci", "utf8_sinhala_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 212,
|
|
||||||
"collations": [ "utf8mb3_german2_ci", "utf8_german2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 213,
|
|
||||||
"collations": [ "utf8mb3_croatian_ci", "utf8_croatian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 214,
|
|
||||||
"collations": [ "utf8mb3_unicode_520_ci", "utf8_unicode_520_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 215,
|
|
||||||
"collations": [ "utf8mb3_vietnamese_ci", "utf8_vietnamese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 223,
|
|
||||||
"collations": [ "utf8mb3_general_mysql500_ci", "utf8_general_mysql500_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 224,
|
|
||||||
"collations": [ "utf8mb4_unicode_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 225,
|
|
||||||
"collations": [ "utf8mb4_icelandic_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 226,
|
|
||||||
"collations": [ "utf8mb4_latvian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 227,
|
|
||||||
"collations": [ "utf8mb4_romanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 228,
|
|
||||||
"collations": [ "utf8mb4_slovenian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 229,
|
|
||||||
"collations": [ "utf8mb4_polish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 230,
|
|
||||||
"collations": [ "utf8mb4_estonian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 231,
|
|
||||||
"collations": [ "utf8mb4_spanish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 232,
|
|
||||||
"collations": [ "utf8mb4_swedish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 233,
|
|
||||||
"collations": [ "utf8mb4_turkish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 234,
|
|
||||||
"collations": [ "utf8mb4_czech_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 235,
|
|
||||||
"collations": [ "utf8mb4_danish_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 236,
|
|
||||||
"collations": [ "utf8mb4_lithuanian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 237,
|
|
||||||
"collations": [ "utf8mb4_slovak_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 238,
|
|
||||||
"collations": [ "utf8mb4_spanish2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 239,
|
|
||||||
"collations": [ "utf8mb4_roman_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 240,
|
|
||||||
"collations": [ "utf8mb4_persian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 241,
|
|
||||||
"collations": [ "utf8mb4_esperanto_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 242,
|
|
||||||
"collations": [ "utf8mb4_hungarian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 243,
|
|
||||||
"collations": [ "utf8mb4_sinhala_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 244,
|
|
||||||
"collations": [ "utf8mb4_german2_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 245,
|
|
||||||
"collations": [ "utf8mb4_croatian_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 246,
|
|
||||||
"collations": [ "utf8mb4_unicode_520_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 247,
|
|
||||||
"collations": [ "utf8mb4_vietnamese_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 248,
|
|
||||||
"collations": [ "gb18030_chinese_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "gb18030"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 249,
|
|
||||||
"collations": [ "gb18030_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "gb18030"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 250,
|
|
||||||
"collations": [ "gb18030_unicode_520_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "gb18030"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 255,
|
|
||||||
"collations": [ "utf8mb4_0900_ai_ci" ],
|
|
||||||
"priority": 1,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 256,
|
|
||||||
"collations": [ "utf8mb4_de_pb_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 257,
|
|
||||||
"collations": [ "utf8mb4_is_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 258,
|
|
||||||
"collations": [ "utf8mb4_lv_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 259,
|
|
||||||
"collations": [ "utf8mb4_ro_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 260,
|
|
||||||
"collations": [ "utf8mb4_sl_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 261,
|
|
||||||
"collations": [ "utf8mb4_pl_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 262,
|
|
||||||
"collations": [ "utf8mb4_et_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 263,
|
|
||||||
"collations": [ "utf8mb4_es_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 264,
|
|
||||||
"collations": [ "utf8mb4_sv_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 265,
|
|
||||||
"collations": [ "utf8mb4_tr_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 266,
|
|
||||||
"collations": [ "utf8mb4_cs_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 267,
|
|
||||||
"collations": [ "utf8mb4_da_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 268,
|
|
||||||
"collations": [ "utf8mb4_lt_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 269,
|
|
||||||
"collations": [ "utf8mb4_sk_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 270,
|
|
||||||
"collations": [ "utf8mb4_es_trad_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 271,
|
|
||||||
"collations": [ "utf8mb4_la_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 273,
|
|
||||||
"collations": [ "utf8mb4_eo_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 274,
|
|
||||||
"collations": [ "utf8mb4_hu_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 275,
|
|
||||||
"collations": [ "utf8mb4_hr_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 277,
|
|
||||||
"collations": [ "utf8mb4_vi_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 278,
|
|
||||||
"collations": [ "utf8mb4_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 279,
|
|
||||||
"collations": [ "utf8mb4_de_pb_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 280,
|
|
||||||
"collations": [ "utf8mb4_is_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 281,
|
|
||||||
"collations": [ "utf8mb4_lv_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 282,
|
|
||||||
"collations": [ "utf8mb4_ro_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 283,
|
|
||||||
"collations": [ "utf8mb4_sl_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 284,
|
|
||||||
"collations": [ "utf8mb4_pl_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 285,
|
|
||||||
"collations": [ "utf8mb4_et_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 286,
|
|
||||||
"collations": [ "utf8mb4_es_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 287,
|
|
||||||
"collations": [ "utf8mb4_sv_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 288,
|
|
||||||
"collations": [ "utf8mb4_tr_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 289,
|
|
||||||
"collations": [ "utf8mb4_cs_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 290,
|
|
||||||
"collations": [ "utf8mb4_da_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 291,
|
|
||||||
"collations": [ "utf8mb4_lt_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 292,
|
|
||||||
"collations": [ "utf8mb4_sk_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 293,
|
|
||||||
"collations": [ "utf8mb4_es_trad_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 294,
|
|
||||||
"collations": [ "utf8mb4_la_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 296,
|
|
||||||
"collations": [ "utf8mb4_eo_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 297,
|
|
||||||
"collations": [ "utf8mb4_hu_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 298,
|
|
||||||
"collations": [ "utf8mb4_hr_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 300,
|
|
||||||
"collations": [ "utf8mb4_vi_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 303,
|
|
||||||
"collations": [ "utf8mb4_ja_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 304,
|
|
||||||
"collations": [ "utf8mb4_ja_0900_as_cs_ks" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 305,
|
|
||||||
"collations": [ "utf8mb4_0900_as_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 306,
|
|
||||||
"collations": [ "utf8mb4_ru_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 307,
|
|
||||||
"collations": [ "utf8mb4_ru_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 308,
|
|
||||||
"collations": [ "utf8mb4_zh_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 309,
|
|
||||||
"collations": [ "utf8mb4_0900_bin" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 310,
|
|
||||||
"collations": [ "utf8mb4_nb_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 311,
|
|
||||||
"collations": [ "utf8mb4_nb_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 312,
|
|
||||||
"collations": [ "utf8mb4_nn_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 313,
|
|
||||||
"collations": [ "utf8mb4_nn_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 314,
|
|
||||||
"collations": [ "utf8mb4_sr_latn_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 315,
|
|
||||||
"collations": [ "utf8mb4_sr_latn_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 316,
|
|
||||||
"collations": [ "utf8mb4_bs_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 317,
|
|
||||||
"collations": [ "utf8mb4_bs_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 318,
|
|
||||||
"collations": [ "utf8mb4_bg_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 319,
|
|
||||||
"collations": [ "utf8mb4_bg_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 320,
|
|
||||||
"collations": [ "utf8mb4_gl_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 321,
|
|
||||||
"collations": [ "utf8mb4_gl_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 322,
|
|
||||||
"collations": [ "utf8mb4_mn_cyrl_0900_ai_ci" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 323,
|
|
||||||
"collations": [ "utf8mb4_mn_cyrl_0900_as_cs" ],
|
|
||||||
"priority": 0,
|
|
||||||
"charset": "utf8mb4"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
version=${project.version}
|
|
@ -1,21 +0,0 @@
|
|||||||
-- In production you would almost certainly limit the replication user must be on the follower (replica) machine,
|
|
||||||
-- to prevent other clients accessing the log from other machines. For example, 'replicator'@'follower.acme.com'.
|
|
||||||
-- However, in this database we'll grant 3 users different privileges:
|
|
||||||
--
|
|
||||||
-- 1) 'replicator' - all privileges required by the binlog reader (setup through 'readbinlog.sql')
|
|
||||||
-- 2) 'snapper' - all privileges required by the snapshot reader AND binlog reader
|
|
||||||
-- 3) 'mysqluser' - all privileges
|
|
||||||
--
|
|
||||||
CREATE USER 'replicator' IDENTIFIED BY 'replpass';
|
|
||||||
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replicator';
|
|
||||||
CREATE USER 'snapper' IDENTIFIED BY 'snapperpass';
|
|
||||||
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'snapper'@'%';
|
|
||||||
CREATE USER 'cloud' IDENTIFIED BY 'cloudpass';
|
|
||||||
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT, LOCK TABLES ON *.* TO 'cloud'@'%';
|
|
||||||
GRANT ALL PRIVILEGES ON *.* TO 'mysqlreplica'@'%';
|
|
||||||
|
|
||||||
-- Start the GTID-based replication ...
|
|
||||||
CHANGE MASTER TO MASTER_HOST='database-gtids', MASTER_PORT=3306, MASTER_USER='replicator', MASTER_PASSWORD = 'replpass', MASTER_USE_GTID=slave_pos;
|
|
||||||
|
|
||||||
-- And start the replica ...
|
|
||||||
START SLAVE;
|
|
@ -1,2 +0,0 @@
|
|||||||
-- Enforce client certificate validation for user 'snapper'
|
|
||||||
ALTER USER 'snapper' REQUIRE X509;
|
|
@ -1,37 +0,0 @@
|
|||||||
-- In production you would almost certainly limit the replication user must be on the follower (replica) machine,
|
|
||||||
-- to prevent other clients accessing the log from other machines. For example, 'replicator'@'follower.acme.com'.
|
|
||||||
-- However, in this database we'll grant 3 users different privileges:
|
|
||||||
--
|
|
||||||
-- 1) 'replicator' - all privileges required by the binlog reader (setup through 'readbinlog.sql')
|
|
||||||
-- 2) 'snapper' - all privileges required by the snapshot reader AND binlog reader
|
|
||||||
-- 3) 'mysqluser' - all privileges
|
|
||||||
--
|
|
||||||
CREATE USER 'replicator' IDENTIFIED BY 'replpass';
|
|
||||||
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replicator';
|
|
||||||
CREATE USER 'snapper' IDENTIFIED BY 'snapperpass';
|
|
||||||
GRANT SELECT, INSERT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'snapper'@'%';
|
|
||||||
CREATE USER 'cloud' IDENTIFIED BY 'cloudpass';
|
|
||||||
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT, LOCK TABLES ON *.* TO 'cloud'@'%';
|
|
||||||
GRANT ALL PRIVILEGES ON *.* TO 'mysqluser'@'%';
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------------------------------------------------
|
|
||||||
-- DATABASE: emptydb
|
|
||||||
-- ----------------------------------------------------------------------------------------------------------------
|
|
||||||
CREATE DATABASE emptydb;
|
|
||||||
RESET MASTER;
|
|
||||||
CREATE DATABASE testing;
|
|
||||||
CREATE TABLE testing.testing (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
||||||
INSERT INTO testing.testing VALUES ();
|
|
@ -1,24 +0,0 @@
|
|||||||
# For advice on how to change settings please see
|
|
||||||
# http://dev.mysql.com/doc/refman/8.2/en/server-configuration-defaults.html
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
# This section specifies 5.5 and cross-version common configurations
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
[mariadb]
|
|
||||||
skip-host-cache
|
|
||||||
skip-name-resolve
|
|
||||||
user=mysql
|
|
||||||
|
|
||||||
# Disabling symbolic-links is recommended to prevent assorted security risks
|
|
||||||
symbolic-links=0
|
|
||||||
|
|
||||||
# Enable binary replication log and set the prefix, expiration, and log format.
|
|
||||||
# The prefix is arbitrary, expiration can be short for integration tests but would
|
|
||||||
# be longer on a production system. Row-level info is required for ingest to work.
|
|
||||||
# Server ID is required, but this will vary on production systems
|
|
||||||
server-id = 112233
|
|
||||||
log_bin = mysql-bin
|
|
||||||
binlog_format = row
|
|
||||||
log_slave_updates = on
|
|
||||||
log_bin_compress = off
|
|
||||||
default_authentication_plugin = mysql_native_password
|
|
@ -1,19 +0,0 @@
|
|||||||
# For advice on how to change settings please see
|
|
||||||
# http://dev.mysql.com/doc/refman/8.2/en/server-configuration-defaults.html
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
# This section specifies 5.5 and cross-version common configurations
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
[mariadb]
|
|
||||||
skip-host-cache
|
|
||||||
skip-name-resolve
|
|
||||||
user = mysql
|
|
||||||
symbolic-links = 0
|
|
||||||
log_slave_updates = on
|
|
||||||
server-id = 445566
|
|
||||||
log_bin = mysql-bin-slave
|
|
||||||
binlog_format = row
|
|
||||||
read_only = 1
|
|
||||||
relay_log = mysql-relay-bin
|
|
||||||
log_bin_compress = off
|
|
||||||
default_authentication_plugin = mysql_native_password
|
|
@ -1,48 +0,0 @@
|
|||||||
# For advice on how to change settings please see
|
|
||||||
# http://dev.mysql.com/doc/refman/8.2/en/server-configuration-defaults.html
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
# This section specifies 5.5 and cross-version common configurations
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
[mysqld]
|
|
||||||
#
|
|
||||||
# Remove leading # and set to the amount of RAM for the most important data
|
|
||||||
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
|
|
||||||
# innodb_buffer_pool_size = 128M
|
|
||||||
#
|
|
||||||
# Remove leading # to turn on a very important data integrity option: logging
|
|
||||||
# changes to the binary log between backups.
|
|
||||||
# log_bin
|
|
||||||
#
|
|
||||||
# Remove leading # to set options mainly useful for reporting servers.
|
|
||||||
# The server defaults are faster for transactions and fast SELECTs.
|
|
||||||
# Adjust sizes as needed, experiment to find the optimal values.
|
|
||||||
# join_buffer_size = 128M
|
|
||||||
# sort_buffer_size = 2M
|
|
||||||
# read_rnd_buffer_size = 2M
|
|
||||||
skip-host-cache
|
|
||||||
skip-name-resolve
|
|
||||||
#datadir=/var/lib/mysql
|
|
||||||
#socket=/var/lib/mysql/mysql.sock
|
|
||||||
#secure-file-priv=/var/lib/mysql-files
|
|
||||||
user=mysql
|
|
||||||
|
|
||||||
# Disabling symbolic-links is recommended to prevent assorted security risks
|
|
||||||
symbolic-links=0
|
|
||||||
|
|
||||||
#log-error=/var/log/mysqld.log
|
|
||||||
#pid-file=/var/run/mysqld/mysqld.pid
|
|
||||||
|
|
||||||
# Enable binary replication log and set the prefix, expiration, and log format.
|
|
||||||
# The prefix is arbitrary, expiration can be short for integration tests but would
|
|
||||||
# be longer on a production system. Row-level info is required for ingest to work.
|
|
||||||
# Server ID is required, but this will vary on production systems
|
|
||||||
server-id = 112233
|
|
||||||
log_bin = mysql-bin
|
|
||||||
binlog_format = row
|
|
||||||
log_bin_compress = off
|
|
||||||
|
|
||||||
ssl_ca=/etc/certs/ca.pem
|
|
||||||
ssl_cert=/etc/certs/server-cert.pem
|
|
||||||
ssl_key=/etc/certs/server-key.pem
|
|
||||||
require_secure_transport=ON
|
|
@ -1,43 +0,0 @@
|
|||||||
# For advice on how to change settings please see
|
|
||||||
# http://dev.mysql.com/doc/refman/8.2/en/server-configuration-defaults.html
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
# This section specifies 5.5 and cross-version common configurations
|
|
||||||
# --------------------------------------------------------------------------------------------
|
|
||||||
[mysqld]
|
|
||||||
#
|
|
||||||
# Remove leading # and set to the amount of RAM for the most important data
|
|
||||||
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
|
|
||||||
# innodb_buffer_pool_size = 128M
|
|
||||||
#
|
|
||||||
# Remove leading # to turn on a very important data integrity option: logging
|
|
||||||
# changes to the binary log between backups.
|
|
||||||
# log_bin
|
|
||||||
#
|
|
||||||
# Remove leading # to set options mainly useful for reporting servers.
|
|
||||||
# The server defaults are faster for transactions and fast SELECTs.
|
|
||||||
# Adjust sizes as needed, experiment to find the optimal values.
|
|
||||||
# join_buffer_size = 128M
|
|
||||||
# sort_buffer_size = 2M
|
|
||||||
# read_rnd_buffer_size = 2M
|
|
||||||
skip-host-cache
|
|
||||||
skip-name-resolve
|
|
||||||
#datadir=/var/lib/mysql
|
|
||||||
#socket=/var/lib/mysql/mysql.sock
|
|
||||||
#secure-file-priv=/var/lib/mysql-files
|
|
||||||
user=mysql
|
|
||||||
|
|
||||||
# Disabling symbolic-links is recommended to prevent assorted security risks
|
|
||||||
symbolic-links=0
|
|
||||||
|
|
||||||
#log-error=/var/log/mysqld.log
|
|
||||||
#pid-file=/var/run/mysqld/mysqld.pid
|
|
||||||
|
|
||||||
# Enable binary replication log and set the prefix, expiration, and log format.
|
|
||||||
# The prefix is arbitrary, expiration can be short for integration tests but would
|
|
||||||
# be longer on a production system. Row-level info is required for ingest to work.
|
|
||||||
# Server ID is required, but this will vary on production systems
|
|
||||||
server-id = 112233
|
|
||||||
log_bin = mysql-bin
|
|
||||||
binlog_format = row
|
|
||||||
log_bin_compress = off
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogBinaryModeIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class BinaryModeIT extends BinlogBinaryModeIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogBlockingSnapshotIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class BlockingSnapshotIT extends BinlogBlockingSnapshotIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogCloudEventsConverterIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class CloudEventsConverterIT extends BinlogCloudEventsConverterIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
public String getConnectorName() {
|
|
||||||
return Module.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<MariaDbConnector> getConnectorClass() {
|
|
||||||
return MariaDbConnector.class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.config.ConfigDefinitionMetadataTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ConfigDefTest extends ConfigDefinitionMetadataTest {
|
|
||||||
public ConfigDefTest() {
|
|
||||||
super(new MariaDbConnector());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.SQLTimeoutException;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectionIT;
|
|
||||||
import io.debezium.connector.binlog.util.BinlogTestConnection;
|
|
||||||
import io.debezium.connector.binlog.util.TestHelper;
|
|
||||||
import io.debezium.connector.binlog.util.UniqueDatabase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ConnectionIT extends BinlogConnectionIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void whenQueryTakesMoreThenConfiguredQueryTimeoutAnExceptionMustBeThrown() throws SQLException {
|
|
||||||
|
|
||||||
final UniqueDatabase DATABASE = TestHelper.getUniqueDatabase("readbinlog", "readbinlog_test");
|
|
||||||
DATABASE.createAndInitialize();
|
|
||||||
try (BinlogTestConnection conn = getTestDatabaseConnection(DATABASE.getDatabaseName(), 1000)) {
|
|
||||||
conn.connect();
|
|
||||||
|
|
||||||
assertThatThrownBy(() -> conn.execute("SELECT SLEEP(10)"))
|
|
||||||
.isInstanceOf(SQLTimeoutException.class)
|
|
||||||
.hasMessageContaining("Query execution was interrupted (max_statement_time exceeded)");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfigTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ConnectorConfigTest extends BinlogConnectorConfigTest<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected MariaDbConnector getConnectorInstance() {
|
|
||||||
return new MariaDbConnector();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Field.Set getAllFields() {
|
|
||||||
return MariaDbConnectorConfig.ALL_FIELDS;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogConvertingFailureIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ConvertingFailureIT extends BinlogConvertingFailureIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogCustomSnapshotterIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class CustomSnapshotterIT extends BinlogCustomSnapshotterIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected String getCustomSnapshotClassName() {
|
|
||||||
return CustomTestSnapshot.class.getName();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import io.debezium.bean.StandardBeanNames;
|
|
||||||
import io.debezium.bean.spi.BeanRegistry;
|
|
||||||
import io.debezium.bean.spi.BeanRegistryAware;
|
|
||||||
import io.debezium.connector.mariadb.snapshot.query.SelectAllSnapshotQuery;
|
|
||||||
import io.debezium.pipeline.spi.Offsets;
|
|
||||||
import io.debezium.spi.snapshot.Snapshotter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a small class used in CustomSnapshotterIT to test a custom snapshot
|
|
||||||
*
|
|
||||||
* It is tightly coupled to the test there, but needs to be placed here in order
|
|
||||||
* to allow for class loading to work
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CustomTestSnapshot extends SelectAllSnapshotQuery implements Snapshotter, BeanRegistryAware {
|
|
||||||
|
|
||||||
private boolean hasState;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return CustomTestSnapshot.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void injectBeanRegistry(BeanRegistry beanRegistry) {
|
|
||||||
Offsets<MariaDbPartition, MariaDbOffsetContext> mariaDbOffsetContext = beanRegistry.lookupByName(StandardBeanNames.OFFSETS, Offsets.class);
|
|
||||||
hasState = mariaDbOffsetContext.getTheOnlyOffset() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldSnapshotData(boolean offsetExists, boolean snapshotInProgress) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldStream() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldSnapshotSchema(boolean offsetExists, boolean snapshotInProgress) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldSnapshotOnSchemaError() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldSnapshotOnDataError() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<String> snapshotQuery(String tableId, List<String> snapshotSelectColumns) {
|
|
||||||
if (!hasState && tableId.contains("`b`")) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String query = snapshotSelectColumns.stream()
|
|
||||||
.collect(Collectors.joining(", ", "SELECT ", " FROM " + tableId));
|
|
||||||
|
|
||||||
return Optional.of(query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.debezium.config.CommonConnectorConfig;
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogDatabaseSchemaTest;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbValueConverters;
|
|
||||||
import io.debezium.connector.mariadb.util.MariaDbValueConvertersFactory;
|
|
||||||
import io.debezium.jdbc.TemporalPrecisionMode;
|
|
||||||
import io.debezium.relational.RelationalDatabaseConnectorConfig.DecimalHandlingMode;
|
|
||||||
import io.debezium.relational.history.AbstractSchemaHistory;
|
|
||||||
import io.debezium.schema.DefaultTopicNamingStrategy;
|
|
||||||
import io.debezium.schema.SchemaNameAdjuster;
|
|
||||||
import io.debezium.spi.topic.TopicNamingStrategy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DatabaseSchemaTest extends BinlogDatabaseSchemaTest<MariaDbConnectorConfig, MariaDbDatabaseSchema, MariaDbPartition, MariaDbOffsetContext> {
|
|
||||||
@Override
|
|
||||||
protected MariaDbConnectorConfig getConnectorConfig(Configuration config) {
|
|
||||||
config = config.edit().with(AbstractSchemaHistory.INTERNAL_PREFER_DDL, true).build();
|
|
||||||
return new MariaDbConnectorConfig(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbDatabaseSchema getSchema(Configuration config) {
|
|
||||||
this.connectorConfig = getConnectorConfig(config);
|
|
||||||
return new MariaDbDatabaseSchema(
|
|
||||||
connectorConfig,
|
|
||||||
new MariaDbValueConvertersFactory().create(
|
|
||||||
DecimalHandlingMode.PRECISE,
|
|
||||||
TemporalPrecisionMode.ADAPTIVE,
|
|
||||||
BinlogConnectorConfig.BigIntUnsignedHandlingMode.LONG,
|
|
||||||
CommonConnectorConfig.BinaryHandlingMode.BYTES,
|
|
||||||
MariaDbValueConverters::adjustTemporal,
|
|
||||||
CommonConnectorConfig.EventConvertingFailureHandlingMode.WARN),
|
|
||||||
(TopicNamingStrategy) DefaultTopicNamingStrategy.create(connectorConfig),
|
|
||||||
SchemaNameAdjuster.create(),
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbPartition initializePartition(MariaDbConnectorConfig connectorConfig, Configuration taskConfig) {
|
|
||||||
Set<MariaDbPartition> partitions = new MariaDbPartition.Provider(connectorConfig, taskConfig).getPartitions();
|
|
||||||
assertThat(partitions).hasSize(1);
|
|
||||||
return partitions.iterator().next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbOffsetContext initializeOffset(MariaDbConnectorConfig connectorConfig) {
|
|
||||||
return MariaDbOffsetContext.initial(connectorConfig);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDateTimeInKeyIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DateTimeInKeyIT extends BinlogDateTimeInKeyIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDdlParserIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DdlParserIT extends BinlogDdlParserIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDecimalColumnIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DecimalColumnIT extends BinlogDecimalColumnIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDecimalIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DecimalIT extends BinlogDecimalIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDefaultDatabaseCharsetIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DefaultDatabaseCharsetIT extends BinlogDefaultDatabaseCharsetIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDefaultGeneratedValueIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DefaultGeneratedValueIT extends BinlogDefaultGeneratedValueIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDefaultValueAllZeroTimeIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DefaultValueAllZeroTimeIT extends BinlogDefaultValueAllZeroTimeIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogDefaultValueIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DefaultValueIT extends BinlogDefaultValueIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.config.CommonConnectorConfig.BinaryHandlingMode;
|
|
||||||
import io.debezium.config.CommonConnectorConfig.EventConvertingFailureHandlingMode;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogDefaultValueTest;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogDefaultValueConverter;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbDefaultValueConverter;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbValueConverters;
|
|
||||||
import io.debezium.connector.mariadb.util.MariaDbValueConvertersFactory;
|
|
||||||
import io.debezium.jdbc.JdbcValueConverters.BigIntUnsignedMode;
|
|
||||||
import io.debezium.jdbc.JdbcValueConverters.DecimalMode;
|
|
||||||
import io.debezium.jdbc.TemporalPrecisionMode;
|
|
||||||
import io.debezium.relational.RelationalDatabaseConnectorConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DefaultValueTest extends BinlogDefaultValueTest<MariaDbValueConverters, MariaDbAntlrDdlParser> {
|
|
||||||
@Override
|
|
||||||
protected MariaDbAntlrDdlParser getDdlParser(MariaDbValueConverters valueConverters) {
|
|
||||||
return new MariaDbAntlrDdlParser(valueConverters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbValueConverters getValueConverter(DecimalMode decimalMode,
|
|
||||||
TemporalPrecisionMode temporalPrecisionMode,
|
|
||||||
BigIntUnsignedMode bigIntUnsignedMode,
|
|
||||||
BinaryHandlingMode binaryHandlingMode) {
|
|
||||||
return new MariaDbValueConvertersFactory().create(
|
|
||||||
RelationalDatabaseConnectorConfig.DecimalHandlingMode.parse(decimalMode.name()),
|
|
||||||
temporalPrecisionMode,
|
|
||||||
BinlogConnectorConfig.BigIntUnsignedHandlingMode.parse(bigIntUnsignedMode.name()),
|
|
||||||
binaryHandlingMode,
|
|
||||||
EventConvertingFailureHandlingMode.WARN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BinlogDefaultValueConverter getDefaultValueConverter(MariaDbValueConverters valueConverters) {
|
|
||||||
return new MariaDbDefaultValueConverter(valueConverters);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogEnumColumnIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class EnumColumnIT extends BinlogEnumColumnIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.binlog.BinlogFieldTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class FieldTest extends BinlogFieldTest<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected Field.Set getAllFields() {
|
|
||||||
return MariaDbConnectorConfig.ALL_FIELDS;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogFixedLengthBinaryColumnIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class FixedLengthBinaryColumnIT extends BinlogFixedLengthBinaryColumnIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogFloatIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class FloatIT extends BinlogFloatIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogGeometryIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class GeometryIT extends BinlogGeometryIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogIncrementalSnapshotIT;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbFieldReader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class IncrementalSnapshotIT extends BinlogIncrementalSnapshotIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected Class<?> getFieldReader() {
|
|
||||||
return MariaDbFieldReader.class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogJdbcSinkDataTypeConverterIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MariaDB-specific tests with the {@link io.debezium.connector.binlog.converters.JdbcSinkDataTypesConverter}.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class JdbcSinkDataTypeConverterIT extends BinlogJdbcSinkDataTypeConverterIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogJsonIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class JsonIT extends BinlogJsonIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.debezium.config.CommonConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogAntlrDdlParserTest;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.connector.mariadb.charset.MariaDbCharsetRegistry;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbDefaultValueConverter;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbValueConverters;
|
|
||||||
import io.debezium.connector.mariadb.util.MariaDbValueConvertersFactory;
|
|
||||||
import io.debezium.jdbc.TemporalPrecisionMode;
|
|
||||||
import io.debezium.relational.RelationalDatabaseConnectorConfig;
|
|
||||||
import io.debezium.relational.Tables;
|
|
||||||
import io.debezium.relational.ddl.DdlChanges;
|
|
||||||
import io.debezium.relational.ddl.SimpleDdlParserListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbAntlrDdlParserTest extends BinlogAntlrDdlParserTest<MariaDbValueConverters, MariaDbDefaultValueConverter, MariaDbAntlrDdlParser> {
|
|
||||||
@Override
|
|
||||||
protected MariaDbAntlrDdlParser getParser(SimpleDdlParserListener listener, MariaDbValueConverters converters) {
|
|
||||||
return new MariaDbDdlParserWithSimpleTestListener(listener, converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbAntlrDdlParser getParser(SimpleDdlParserListener listener, MariaDbValueConverters converters, boolean includeViews) {
|
|
||||||
return new MariaDbDdlParserWithSimpleTestListener(listener, includeViews, converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbAntlrDdlParser getParser(SimpleDdlParserListener listener, MariaDbValueConverters converters, Tables.TableFilter tableFilter) {
|
|
||||||
return new MariaDbDdlParserWithSimpleTestListener(listener, tableFilter, converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbAntlrDdlParser getParser(SimpleDdlParserListener listener, MariaDbValueConverters converters, boolean includeViews, boolean includeComments) {
|
|
||||||
return new MariaDbDdlParserWithSimpleTestListener(listener, includeViews, includeComments, converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbValueConverters getValueConverters() {
|
|
||||||
return new MariaDbValueConvertersFactory().create(
|
|
||||||
RelationalDatabaseConnectorConfig.DecimalHandlingMode.DOUBLE,
|
|
||||||
TemporalPrecisionMode.ADAPTIVE_TIME_MICROSECONDS,
|
|
||||||
BinlogConnectorConfig.BigIntUnsignedHandlingMode.PRECISE,
|
|
||||||
CommonConnectorConfig.BinaryHandlingMode.BYTES,
|
|
||||||
CommonConnectorConfig.EventConvertingFailureHandlingMode.WARN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbDefaultValueConverter getDefaultValueConverters(MariaDbValueConverters valueConverters) {
|
|
||||||
return new MariaDbDefaultValueConverter(valueConverters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<String> extractEnumAndSetOptions(List<String> enumValues) {
|
|
||||||
return MariaDbAntlrDdlParser.extractEnumAndSetOptions(enumValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MariaDbDdlParserWithSimpleTestListener extends MariaDbAntlrDdlParser {
|
|
||||||
public MariaDbDdlParserWithSimpleTestListener(DdlChanges listener, MariaDbValueConverters converters) {
|
|
||||||
this(listener, false, converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbDdlParserWithSimpleTestListener(DdlChanges listener, Tables.TableFilter tableFilter, MariaDbValueConverters converters) {
|
|
||||||
this(listener, false, false, tableFilter, converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbDdlParserWithSimpleTestListener(DdlChanges listener, boolean includeViews, MariaDbValueConverters converters) {
|
|
||||||
this(listener, includeViews, false, Tables.TableFilter.includeAll(), converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbDdlParserWithSimpleTestListener(DdlChanges listener, boolean includeViews, boolean includeComments, MariaDbValueConverters converters) {
|
|
||||||
this(listener, includeViews, includeComments, Tables.TableFilter.includeAll(), converters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbDdlParserWithSimpleTestListener(DdlChanges listener, boolean includeViews, boolean includeComments, Tables.TableFilter tableFilter,
|
|
||||||
MariaDbValueConverters converters) {
|
|
||||||
super(false, includeViews, includeComments, converters, tableFilter, new MariaDbCharsetRegistry());
|
|
||||||
this.ddlChanges = listener;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogReaderBufferIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbBinlogReaderBufferIT extends BinlogReaderBufferIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorTest;
|
|
||||||
import io.debezium.connector.binlog.util.BinlogTestConnection;
|
|
||||||
import io.debezium.connector.mariadb.util.MariaDbTestConnection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common implementation bits for MariaDB for a {@link BinlogConnectorTest}.<p></p>
|
|
||||||
*
|
|
||||||
* By using this common interface, we avoid needing to duplicate this information in each test, allowing for
|
|
||||||
* modifying or adding to the common interface in the future in a single location.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public interface MariaDbCommon extends BinlogConnectorTest<MariaDbConnector> {
|
|
||||||
@Override
|
|
||||||
default String getConnectorName() {
|
|
||||||
return Module.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default Class<MariaDbConnector> getConnectorClass() {
|
|
||||||
return MariaDbConnector.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default BinlogTestConnection getTestDatabaseConnection(String databaseName) {
|
|
||||||
return MariaDbTestConnection.forTestDatabase(databaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default BinlogTestConnection getTestDatabaseConnection(String databaseName, int queryTimeout) {
|
|
||||||
return MariaDbTestConnection.forTestDatabase(databaseName, queryTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default BinlogTestConnection getTestReplicaDatabaseConnection(String databaseName) {
|
|
||||||
return MariaDbTestConnection.forTestReplicaDatabase(databaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean isMariaDb() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.kafka.common.config.Config;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorIT;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig.SnapshotLockingMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbConnectorIT extends BinlogConnectorIT<MariaDbConnector, MariaDbPartition, MariaDbOffsetContext>
|
|
||||||
implements MariaDbCommon {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Config validateConfiguration(Configuration configuration) {
|
|
||||||
return new MariaDbConnector().validate(configuration.asMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void assertInvalidConfiguration(Config result) {
|
|
||||||
super.assertInvalidConfiguration(result);
|
|
||||||
assertNoConfigurationErrors(result, MariaDbConnectorConfig.SNAPSHOT_LOCKING_MODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void assertValidConfiguration(Config result) {
|
|
||||||
super.assertValidConfiguration(result);
|
|
||||||
validateConfigField(result, MariaDbConnectorConfig.SNAPSHOT_LOCKING_MODE, SnapshotLockingMode.MINIMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Field getSnapshotLockingModeField() {
|
|
||||||
return MariaDbConnectorConfig.SNAPSHOT_LOCKING_MODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getSnapshotLockingModeNone() {
|
|
||||||
return SnapshotLockingMode.NONE.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void assertSnapshotLockingModeIsNone(Configuration config) {
|
|
||||||
assertThat(new MariaDbConnectorConfig(config).getSnapshotLockingMode().get()).isEqualTo(SnapshotLockingMode.NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbPartition createPartition(String serverName, String databaseName) {
|
|
||||||
return new MariaDbPartition(serverName, databaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbOffsetContext loadOffsets(Configuration configuration, Map<String, ?> offsets) {
|
|
||||||
return new MariaDbOffsetContext.Loader(new MariaDbConnectorConfig(configuration)).load(offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void assertBinlogPosition(long offsetPosition, long beforeInsertsPosition) {
|
|
||||||
assertThat(offsetPosition).isGreaterThanOrEqualTo(beforeInsertsPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getExpectedQuery(String statement) {
|
|
||||||
|
|
||||||
return "SET STATEMENT max_statement_time=600 FOR " + statement;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MariaDB-specific global transaction identifier tests.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbGtidSetTest {
|
|
||||||
|
|
||||||
private static final String DOMAIN_SERVER_ID = "1-2";
|
|
||||||
|
|
||||||
private MariaDbGtidSet gtids;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void shouldParseGtid() {
|
|
||||||
gtids = new MariaDbGtidSet(DOMAIN_SERVER_ID + "-3");
|
|
||||||
assertThat(gtids.forStreamId(new MariaDbGtidSet.MariaDbGtidStreamId(1, 2)).hasSequence(3)).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogMetricsIT;
|
|
||||||
import io.debezium.connector.binlog.util.BinlogTestConnection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbMetricsIT extends BinlogMetricsIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<MariaDbConnector> getConnectorClass() {
|
|
||||||
return MariaDbCommon.super.getConnectorClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BinlogTestConnection getTestDatabaseConnection(String databaseName) {
|
|
||||||
return MariaDbCommon.super.getTestDatabaseConnection(databaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getConnectorName() {
|
|
||||||
return MariaDbCommon.super.getConnectorName();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogMetadataIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MetadataIT extends BinlogMetadataIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogMultiTableStatementIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MultiTableStatementIT extends BinlogMultiTableStatementIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogNonUtfDatabaseCharsetIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class NonUtfDatabaseCharsetIT extends BinlogNonUtfDatabaseCharsetIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogNotificationsIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class NotificationsIT extends BinlogNotificationsIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogNumericColumnIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class NumericColumnIT extends BinlogNumericColumnIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogPartitionTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class PartitionTest extends BinlogPartitionTest<MariaDbPartition> {
|
|
||||||
@Override
|
|
||||||
protected MariaDbPartition createPartition1() {
|
|
||||||
return new MariaDbPartition("server1", "database1");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbPartition createPartition2() {
|
|
||||||
return new MariaDbPartition("server2", "database1");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogReadBinLogIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ReadBinLogIT extends BinlogReadBinLogIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogReadOnlyIncrementalSnapshotIT;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbFieldReader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ReadOnlyIncrementalSnapshotIT extends BinlogReadOnlyIncrementalSnapshotIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected Class<?> getFieldReader() {
|
|
||||||
return MariaDbFieldReader.class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogRegressionIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class RegressionIT extends BinlogRegressionIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogReselectColumnsProcessorIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ReselectColumnsProcessorIT extends BinlogReselectColumnsProcessorIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
public Class<MariaDbConnector> getConnectorClass() {
|
|
||||||
return MariaDbConnector.class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogRestartIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class RestartIT extends BinlogRestartIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSchemaHistoryIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SchemaHistoryIT extends BinlogSchemaHistoryIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSchemaMigrationIT;
|
|
||||||
import io.debezium.connector.mariadb.antlr.listener.RenameTableParserListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SchemaMigrationIT extends BinlogSchemaMigrationIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected Class<?> getRenameTableParserListenerClass() {
|
|
||||||
return RenameTableParserListener.class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSchemaNameAdjustmentModeIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SchemaNameAdjustmentModeIT extends BinlogSchemaNameAdjustmentModeIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSchemaValidateIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SchemaValidateIT extends BinlogSchemaValidateIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSignalsIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SignalsIT extends BinlogSignalsIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSkipMessagesWithoutChangeConfigIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SkipMessagesWithoutChangeConfigIT extends BinlogSkipMessagesWithoutChangeConfigIT<MariaDbConnector>
|
|
||||||
implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.binlog.BinlogSnapshotParallelSourceIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SnapshotParallelSourceIT extends BinlogSnapshotParallelSourceIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected Field getSnapshotLockingModeField() {
|
|
||||||
return MariaDbConnectorConfig.SNAPSHOT_LOCKING_MODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getSnapshotLockingModeMinimal() {
|
|
||||||
return MariaDbConnectorConfig.SnapshotLockingMode.MINIMAL.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getSnapshotLockingModeNone() {
|
|
||||||
return MariaDbConnectorConfig.SnapshotLockingMode.NONE.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.binlog.BinlogSnapshotSourceIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SnapshotSourceIT extends BinlogSnapshotSourceIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected Field getSnapshotLockingModeField() {
|
|
||||||
return MariaDbConnectorConfig.SNAPSHOT_LOCKING_MODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getSnapshotLockingModeMinimal() {
|
|
||||||
return MariaDbConnectorConfig.SnapshotLockingMode.MINIMAL.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getSnapshotLockingModeNone() {
|
|
||||||
return MariaDbConnectorConfig.SnapshotLockingMode.NONE.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.binlog.BinlogSourceInfoTest;
|
|
||||||
import io.debezium.connector.binlog.history.BinlogHistoryRecordComparator;
|
|
||||||
import io.debezium.connector.mariadb.gtid.MariaDbGtidSetFactory;
|
|
||||||
import io.debezium.connector.mariadb.history.MariaDbHistoryRecordComparator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SourceInfoTest extends BinlogSourceInfoTest<SourceInfo, MariaDbOffsetContext> {
|
|
||||||
@Override
|
|
||||||
protected String getModuleName() {
|
|
||||||
return Module.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getModuleVersion() {
|
|
||||||
return Module.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BinlogHistoryRecordComparator getHistoryRecordComparator(Predicate<String> gtidFilter) {
|
|
||||||
return new MariaDbHistoryRecordComparator(gtidFilter, new MariaDbGtidSetFactory());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbOffsetContext createInitialOffsetContext(Configuration configuration) {
|
|
||||||
return MariaDbOffsetContext.initial(new MariaDbConnectorConfig(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbOffsetContext loadOffsetContext(Configuration configuration, Map<String, ?> offsets) {
|
|
||||||
return new MariaDbOffsetContext.Loader(new MariaDbConnectorConfig(configuration)).load(offsets);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogSourceTypeInSchemaIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class SourceTypeInSchemaIT extends BinlogSourceTypeInSchemaIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogStreamingSourceIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class StreamingSourceIT extends BinlogStreamingSourceIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTableAndColumnCommentIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TableAndColumnCommentIT extends BinlogTableAndColumnCommentIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTableMaintenanceStatementsIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TableMaintenanceStatementsIT extends BinlogTableMaintenanceStatementsIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTimestampColumnIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TimestampColumnIT extends BinlogTimestampColumnIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.config.Field;
|
|
||||||
import io.debezium.connector.binlog.BinlogTinyIntIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TinyIntIT extends BinlogTinyIntIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected Field getSnapshotLockingField() {
|
|
||||||
return MariaDbConnectorConfig.SNAPSHOT_LOCKING_MODE;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTopicNameSanitizationIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TopicNameSanitizationIT extends BinlogTopicNameSanitizationIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTopicNamingStrategyIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TopicNamingStrategyIT extends BinlogTopicNamingStrategyIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTransactionMetadataIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TransactionMetadataIT extends BinlogTransactionMetadataIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogTransactionPayloadIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class TransactionPayloadIT extends BinlogTransactionPayloadIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogUnsignedIntegerIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class UnsignedIntegerIT extends BinlogUnsignedIntegerIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import java.time.temporal.TemporalAdjuster;
|
|
||||||
|
|
||||||
import io.debezium.config.CommonConnectorConfig.BinaryHandlingMode;
|
|
||||||
import io.debezium.config.CommonConnectorConfig.EventConvertingFailureHandlingMode;
|
|
||||||
import io.debezium.connector.binlog.BinlogConnectorConfig;
|
|
||||||
import io.debezium.connector.binlog.BinlogValueConvertersTest;
|
|
||||||
import io.debezium.connector.binlog.jdbc.BinlogValueConverters;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.connector.mariadb.util.MariaDbValueConvertersFactory;
|
|
||||||
import io.debezium.jdbc.JdbcValueConverters.BigIntUnsignedMode;
|
|
||||||
import io.debezium.jdbc.JdbcValueConverters.DecimalMode;
|
|
||||||
import io.debezium.jdbc.TemporalPrecisionMode;
|
|
||||||
import io.debezium.relational.RelationalDatabaseConnectorConfig;
|
|
||||||
import io.debezium.relational.ddl.DdlParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ValueConvertersTest extends BinlogValueConvertersTest<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
@Override
|
|
||||||
protected BinlogValueConverters getValueConverters(DecimalMode decimalMode,
|
|
||||||
TemporalPrecisionMode temporalPrecisionMode,
|
|
||||||
BigIntUnsignedMode bigIntUnsignedMode,
|
|
||||||
BinaryHandlingMode binaryHandlingMode,
|
|
||||||
TemporalAdjuster temporalAdjuster,
|
|
||||||
EventConvertingFailureHandlingMode eventConvertingFailureHandlingMode) {
|
|
||||||
return new MariaDbValueConvertersFactory().create(
|
|
||||||
RelationalDatabaseConnectorConfig.DecimalHandlingMode.parse(decimalMode.name()),
|
|
||||||
temporalPrecisionMode,
|
|
||||||
BinlogConnectorConfig.BigIntUnsignedHandlingMode.parse(bigIntUnsignedMode.name()),
|
|
||||||
binaryHandlingMode,
|
|
||||||
temporalAdjuster,
|
|
||||||
eventConvertingFailureHandlingMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DdlParser getDdlParser() {
|
|
||||||
return new MariaDbAntlrDdlParser();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.BinlogYearIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class YearIT extends BinlogYearIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,258 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.rest;
|
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
|
||||||
import static org.hamcrest.CoreMatchers.hasItems;
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
|
||||||
import static org.hamcrest.CoreMatchers.startsWith;
|
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Assume;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.connector.mariadb.Module;
|
|
||||||
import io.debezium.storage.kafka.history.KafkaSchemaHistory;
|
|
||||||
import io.debezium.testing.testcontainers.Connector;
|
|
||||||
import io.debezium.testing.testcontainers.ConnectorConfiguration;
|
|
||||||
import io.debezium.testing.testcontainers.testhelper.TestInfrastructureHelper;
|
|
||||||
import io.restassured.http.ContentType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DebeziumMariaDbConnectorResourceIT {
|
|
||||||
@BeforeClass
|
|
||||||
public static void checkCondition() {
|
|
||||||
Assume.assumeThat(
|
|
||||||
"Skipping DebeziumMariaDbConnectorResourceIT tests when assembly profile is not active!",
|
|
||||||
System.getProperty("isAssemblyProfileActive", "false"),
|
|
||||||
is("true"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void start() {
|
|
||||||
TestInfrastructureHelper.setupDebeziumContainer(Module.version(), DebeziumMariaDbConnectRestExtension.class.getName());
|
|
||||||
TestInfrastructureHelper.startContainers(TestInfrastructureHelper.DATABASE.MARIADB);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void stop() {
|
|
||||||
TestInfrastructureHelper.stopContainers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidConnection() {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1);
|
|
||||||
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_CONNECTION_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("VALID"))
|
|
||||||
.body("validationResults.size()", is(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidHostnameConnection() {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1).with(MariaDbConnectorConfig.HOSTNAME.name(), "zzzzzzzzzz");
|
|
||||||
|
|
||||||
Locale.setDefault(new Locale("en", "US")); // to enforce errormessages in English
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_CONNECTION_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("INVALID"))
|
|
||||||
.body("validationResults.size()", is(1))
|
|
||||||
.rootPath("validationResults[0]")
|
|
||||||
.body("property", equalTo(MariaDbConnectorConfig.HOSTNAME.name()))
|
|
||||||
.body("message", startsWith("Unable to connect: Socket fail to connect"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidConnection() {
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body("{\"connector.class\": \"" + MariaDbConnector.class.getName() + "\"}")
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_CONNECTION_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("INVALID"))
|
|
||||||
.body("validationResults.size()", is(4))
|
|
||||||
.body("validationResults",
|
|
||||||
hasItems(
|
|
||||||
Map.of("property", MariaDbConnectorConfig.USER.name(), "message", "The 'database.user' value is invalid: A value is required"),
|
|
||||||
Map.of("property", MariaDbConnectorConfig.TOPIC_PREFIX.name(), "message", "The 'topic.prefix' value is invalid: A value is required"),
|
|
||||||
Map.of("property", MariaDbConnectorConfig.SERVER_ID.name(), "message", "The 'database.server.id' value is invalid: A value is required"),
|
|
||||||
Map.of("property", MariaDbConnectorConfig.HOSTNAME.name(), "message", "The 'database.hostname' value is invalid: A value is required")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFiltersWithEmptyFilters() {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1);
|
|
||||||
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_FILTERS_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("VALID"))
|
|
||||||
.body("validationResults.size()", is(0))
|
|
||||||
.body("matchingCollections.size()", is(6))
|
|
||||||
.body("matchingCollections",
|
|
||||||
hasItems(
|
|
||||||
Map.of("namespace", "inventory", "name", "geom", "identifier", "inventory.geom"),
|
|
||||||
Map.of("namespace", "inventory", "name", "products_on_hand", "identifier", "inventory.products_on_hand"),
|
|
||||||
Map.of("namespace", "inventory", "name", "customers", "identifier", "inventory.customers"),
|
|
||||||
Map.of("namespace", "inventory", "name", "addresses", "identifier", "inventory.addresses"),
|
|
||||||
Map.of("namespace", "inventory", "name", "orders", "identifier", "inventory.orders"),
|
|
||||||
Map.of("namespace", "inventory", "name", "products", "identifier", "inventory.products")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFiltersWithValidTableIncludeList() {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1)
|
|
||||||
.with("table.include.list", "inventory\\.product.*");
|
|
||||||
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_FILTERS_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("VALID"))
|
|
||||||
.body("validationResults.size()", is(0))
|
|
||||||
.body("matchingCollections.size()", is(2))
|
|
||||||
.body("matchingCollections",
|
|
||||||
hasItems(
|
|
||||||
Map.of("namespace", "inventory", "name", "products_on_hand", "identifier", "inventory.products_on_hand"),
|
|
||||||
Map.of("namespace", "inventory", "name", "products", "identifier", "inventory.products")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFiltersWithValidDatabaseIncludeList() {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1)
|
|
||||||
.with("database.include.list", "inventory");
|
|
||||||
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_FILTERS_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("VALID"))
|
|
||||||
.body("validationResults.size()", is(0))
|
|
||||||
.body("matchingCollections.size()", is(6))
|
|
||||||
.body("matchingCollections",
|
|
||||||
hasItems(
|
|
||||||
Map.of("namespace", "inventory", "name", "geom", "identifier", "inventory.geom"),
|
|
||||||
Map.of("namespace", "inventory", "name", "products_on_hand", "identifier", "inventory.products_on_hand"),
|
|
||||||
Map.of("namespace", "inventory", "name", "customers", "identifier", "inventory.customers"),
|
|
||||||
Map.of("namespace", "inventory", "name", "addresses", "identifier", "inventory.addresses"),
|
|
||||||
Map.of("namespace", "inventory", "name", "orders", "identifier", "inventory.orders"),
|
|
||||||
Map.of("namespace", "inventory", "name", "products", "identifier", "inventory.products")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFiltersWithInvalidDatabaseIncludeListPattern() {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1)
|
|
||||||
.with("database.include.list", "+");
|
|
||||||
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_FILTERS_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("INVALID"))
|
|
||||||
.body("matchingCollections.size()", is(0))
|
|
||||||
.body("validationResults.size()", is(1))
|
|
||||||
.rootPath("validationResults[0]")
|
|
||||||
.body("property", equalTo("database.include.list"))
|
|
||||||
.body("message", equalTo(
|
|
||||||
"The 'database.include.list' value is invalid: A comma-separated list of valid regular expressions is expected, but Dangling meta character '+' near index 0\n+\n^"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFiltersWithInvalidDatabaseExcludeListPattern() {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1)
|
|
||||||
.with("database.exclude.list", "+");
|
|
||||||
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.put(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VALIDATE_FILTERS_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.assertThat().body("status", equalTo("INVALID"))
|
|
||||||
.body("matchingCollections.size()", is(0))
|
|
||||||
.body("validationResults.size()", is(1))
|
|
||||||
.rootPath("validationResults[0]")
|
|
||||||
.body("property", equalTo("database.exclude.list"))
|
|
||||||
.body("message", equalTo(
|
|
||||||
"The 'database.exclude.list' value is invalid: A comma-separated list of valid regular expressions is expected, but Dangling meta character '+' near index 0\n+\n^"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMetricsEndpoint() throws InterruptedException {
|
|
||||||
ConnectorConfiguration config = getMariaDbConnectorConfiguration(1);
|
|
||||||
|
|
||||||
var connectorName = "my-mariadb-connector";
|
|
||||||
TestInfrastructureHelper.getDebeziumContainer().registerConnector(
|
|
||||||
connectorName,
|
|
||||||
config);
|
|
||||||
|
|
||||||
TestInfrastructureHelper.getDebeziumContainer().ensureConnectorState(connectorName, Connector.State.RUNNING);
|
|
||||||
TestInfrastructureHelper.waitForConnectorTaskStatus(connectorName, 0, Connector.State.RUNNING);
|
|
||||||
TestInfrastructureHelper.getDebeziumContainer().waitForStreamingRunning("mariadb", config.asProperties().getProperty("topic.prefix"));
|
|
||||||
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when().contentType(ContentType.JSON).accept(ContentType.JSON).body(config.toJson())
|
|
||||||
.get(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.CONNECTOR_METRICS_ENDPOINT, connectorName)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.body("name", equalTo(connectorName))
|
|
||||||
.body("connector.metrics.Connected", equalTo("true"))
|
|
||||||
.body("tasks[0].id", equalTo(0))
|
|
||||||
.body("tasks[0].namespaces[0].metrics.MilliSecondsSinceLastEvent", equalTo("0"))
|
|
||||||
.body("tasks[0].namespaces[0].metrics.TotalNumberOfEventsSeen", is(notNullValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConnectorConfiguration getMariaDbConnectorConfiguration(int id, String... options) {
|
|
||||||
final ConnectorConfiguration config = ConnectorConfiguration.forJdbcContainer(TestInfrastructureHelper.getMariaDbContainer())
|
|
||||||
.with(MariaDbConnectorConfig.USER.name(), "debezium")
|
|
||||||
.with(MariaDbConnectorConfig.PASSWORD.name(), "dbz")
|
|
||||||
.with(MariaDbConnectorConfig.SNAPSHOT_MODE.name(), "never") // temporarily disable snapshot mode globally until we can check if connectors inside testcontainers are in SNAPSHOT or STREAMING mode (wait for snapshot finished!)
|
|
||||||
.with(MariaDbConnectorConfig.TOPIC_PREFIX.name(), "dbserver" + id)
|
|
||||||
.with(KafkaSchemaHistory.BOOTSTRAP_SERVERS.name(), TestInfrastructureHelper.KAFKA_HOSTNAME + ":9092")
|
|
||||||
.with(KafkaSchemaHistory.TOPIC.name(), "dbhistory.inventory")
|
|
||||||
.with(MariaDbConnectorConfig.SERVER_ID.name(), Long.valueOf(5555 + id - 1))
|
|
||||||
// basic container does not support SSL out of the box
|
|
||||||
.with(MariaDbConnectorConfig.SSL_MODE.name(), "disabled");
|
|
||||||
|
|
||||||
if (options != null && options.length > 0) {
|
|
||||||
for (int i = 0; i < options.length; i += 2) {
|
|
||||||
config.with(options[i], options[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.rest;
|
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
|
||||||
import static org.hamcrest.Matchers.hasKey;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Assume;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.Module;
|
|
||||||
import io.debezium.testing.testcontainers.testhelper.TestInfrastructureHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class DebeziumMariaDbConnectorResourceNoDatabaseIT {
|
|
||||||
@BeforeClass
|
|
||||||
public static void checkCondition() {
|
|
||||||
Assume.assumeThat(
|
|
||||||
"Skipping DebeziumMariaDbConnectorResourceIT tests when assembly profile is not active!",
|
|
||||||
System.getProperty("isAssemblyProfileActive", "false"),
|
|
||||||
is("true"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void start() {
|
|
||||||
TestInfrastructureHelper.setupDebeziumContainer(Module.version(), DebeziumMariaDbConnectRestExtension.class.getName());
|
|
||||||
TestInfrastructureHelper.startContainers(TestInfrastructureHelper.DATABASE.NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void stop() {
|
|
||||||
TestInfrastructureHelper.stopContainers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testVersionEndpoint() {
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when()
|
|
||||||
.get(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.VERSION_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.body(is(Module.version()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSchemaEndpoint() {
|
|
||||||
given()
|
|
||||||
.port(TestInfrastructureHelper.getDebeziumContainer().getFirstMappedPort())
|
|
||||||
.when()
|
|
||||||
.get(DebeziumMariaDbConnectorResource.BASE_PATH + DebeziumMariaDbConnectorResource.SCHEMA_ENDPOINT)
|
|
||||||
.then().log().all()
|
|
||||||
.statusCode(200)
|
|
||||||
.body("components.schemas.size()", is(1))
|
|
||||||
.rootPath("components.schemas.values()[0]")
|
|
||||||
.body("title", is("Debezium MariaDB Connector"))
|
|
||||||
.body("properties.isEmpty()", is(false))
|
|
||||||
.body("x-connector-id", is("mariadb"))
|
|
||||||
.body("x-version", is(Module.version()))
|
|
||||||
.body("x-className", is(MariaDbConnector.class.getName()))
|
|
||||||
.body("properties", hasKey("topic.prefix"))
|
|
||||||
.body("properties", hasKey("database.server.id"))
|
|
||||||
.body("properties", hasKey("snapshot.mode"));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.util;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.util.BinlogTestConnection;
|
|
||||||
import io.debezium.jdbc.JdbcConfiguration;
|
|
||||||
import io.debezium.jdbc.JdbcConnection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbTestConnection extends BinlogTestConnection {
|
|
||||||
|
|
||||||
protected static ConnectionFactory FACTORY = JdbcConnection.patternBasedFactory("jdbc:mariadb://${hostname}:${port}/${dbname}");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new instance with the given configuration.
|
|
||||||
*
|
|
||||||
* @param config the configuration; may not be null
|
|
||||||
*/
|
|
||||||
public MariaDbTestConnection(JdbcConfiguration config) {
|
|
||||||
super(config, FACTORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGtidEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMariaDb() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMySQL5() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPercona() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String currentDateTimeDefaultOptional(String isoString) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBinlogCompressionOff() throws SQLException {
|
|
||||||
execute("set global log_bin_compress=OFF;");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBinlogCompressionOn() throws SQLException {
|
|
||||||
execute("set global log_bin_compress=ON;");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBinlogRowQueryEventsOff() throws SQLException {
|
|
||||||
execute("set binlog_annotate_row_events=OFF;");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBinlogRowQueryEventsOn() throws SQLException {
|
|
||||||
execute("set binlog_annotate_row_events=ON;");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCurrentDateTimeDefaultGenerated() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a connection instance to the named test database.
|
|
||||||
*
|
|
||||||
* @param databaseName the database name
|
|
||||||
* @return the connection instance; never null
|
|
||||||
*/
|
|
||||||
public static MariaDbTestConnection forTestDatabase(String databaseName) {
|
|
||||||
return new MariaDbTestConnection(getDefaultJdbcConfig(databaseName).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a connection instance to the named test database.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param databaseName the name of the test database
|
|
||||||
* @param queryTimeout the seconds to wait for query execution
|
|
||||||
* @return the connection instance; never null
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static MariaDbTestConnection forTestDatabase(String databaseName, int queryTimeout) {
|
|
||||||
return new MariaDbTestConnection(getDefaultJdbcConfig(databaseName)
|
|
||||||
.withQueryTimeoutMs(queryTimeout)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a connection instance to the named test database.
|
|
||||||
*
|
|
||||||
* @param databaseName the name of the test database
|
|
||||||
* @param urlProperties url properties
|
|
||||||
* @return the connection instance; never null
|
|
||||||
*/
|
|
||||||
public static MariaDbTestConnection forTestDatabase(String databaseName, Map<String, Object> urlProperties) {
|
|
||||||
final JdbcConfiguration.Builder builder = getDefaultJdbcConfig(databaseName);
|
|
||||||
urlProperties.forEach(builder::with);
|
|
||||||
return new MariaDbTestConnection(builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MariaDbTestConnection forTestReplicaDatabase(String databaseName) {
|
|
||||||
return new MariaDbTestConnection(getReplicaJdbcConfig(databaseName).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.util;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.util.BinlogTestConnection;
|
|
||||||
import io.debezium.connector.binlog.util.TestConnectionProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbTestConnectionProvider implements TestConnectionProvider {
|
|
||||||
@Override
|
|
||||||
public BinlogTestConnection forTestDatabase(String databaseName) {
|
|
||||||
return MariaDbTestConnection.forTestDatabase(databaseName);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.util;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.util.UniqueDatabase;
|
|
||||||
import io.debezium.jdbc.JdbcConnection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of {@link UniqueDatabase} for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbUniqueDatabase extends UniqueDatabase {
|
|
||||||
|
|
||||||
public MariaDbUniqueDatabase(String serverName, String databaseName) {
|
|
||||||
this(serverName, databaseName, Integer.toUnsignedString(new Random().nextInt(), 36), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MariaDbUniqueDatabase(String serverName, String databaseName, String identifier, String charSet) {
|
|
||||||
super(serverName, databaseName, identifier, charSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JdbcConnection forTestDatabase(String databaseName, Map<String, Object> urlProperties) {
|
|
||||||
return MariaDbTestConnection.forTestDatabase(databaseName, urlProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.util;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.util.UniqueDatabase;
|
|
||||||
import io.debezium.connector.binlog.util.UniqueDatabaseProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Java ServiceLoader contract of {@link UniqueDatabaseProvider} to supply the test suite with the class
|
|
||||||
* reference to the MariaDB connector's specific {@link UniqueDatabase} implementation.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbUniqueDatabaseProvider implements UniqueDatabaseProvider {
|
|
||||||
@Override
|
|
||||||
public Class<? extends UniqueDatabase> getUniqueDatabase() {
|
|
||||||
return MariaDbUniqueDatabase.class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.util;
|
|
||||||
|
|
||||||
import java.time.temporal.TemporalAdjuster;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.binlog.util.BinlogValueConvertersFactory;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.connector.mariadb.jdbc.MariaDbValueConverters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of {@link BinlogValueConvertersFactory} for MariaDB.
|
|
||||||
*
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MariaDbValueConvertersFactory implements BinlogValueConvertersFactory<MariaDbValueConverters> {
|
|
||||||
@Override
|
|
||||||
public MariaDbValueConverters create(Configuration configuration, TemporalAdjuster temporalAdjuster) {
|
|
||||||
final MariaDbConnectorConfig connectorConfig = new MariaDbConnectorConfig(configuration);
|
|
||||||
return new MariaDbValueConverters(
|
|
||||||
connectorConfig.getDecimalMode(),
|
|
||||||
connectorConfig.getTemporalPrecisionMode(),
|
|
||||||
connectorConfig.getBigIntUnsignedHandlingMode().asBigIntUnsignedMode(),
|
|
||||||
connectorConfig.binaryHandlingMode(),
|
|
||||||
temporalAdjuster,
|
|
||||||
connectorConfig.getEventConvertingFailureHandlingMode(),
|
|
||||||
connectorConfig.getServiceRegistry());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.connector.mariadb.zzz;
|
|
||||||
|
|
||||||
import io.debezium.connector.binlog.zzz.ZZZBinlogGtidSetIT;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbCommon;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class ZZZMariaDbGtidSetIT extends ZZZBinlogGtidSetIT<MariaDbConnector> implements MariaDbCommon {
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.relational.history;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.relational.ddl.DdlParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class FileSchemaHistoryTest extends AbstractFileSchemaHistoryTest<MariaDbConnector> {
|
|
||||||
@Override
|
|
||||||
protected DdlParser getDdlParser() {
|
|
||||||
return new MariaDbAntlrDdlParser();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.relational.history;
|
|
||||||
|
|
||||||
import io.debezium.config.Configuration;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnectorConfig;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbOffsetContext;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbPartition;
|
|
||||||
import io.debezium.connector.mariadb.MariaDbReadOnlyIncrementalSnapshotContext;
|
|
||||||
import io.debezium.connector.mariadb.SourceInfo;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.pipeline.txmetadata.TransactionContext;
|
|
||||||
import io.debezium.relational.ddl.DdlParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class KafkaSchemaHistoryTest extends AbstractKafkaSchemaHistoryTest<MariaDbPartition, MariaDbOffsetContext> {
|
|
||||||
@Override
|
|
||||||
protected MariaDbPartition createPartition(String serverName, String databaseName) {
|
|
||||||
return new MariaDbPartition(serverName, databaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MariaDbOffsetContext createOffsetContext(Configuration config) {
|
|
||||||
return new MariaDbOffsetContext(
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
new TransactionContext(),
|
|
||||||
new MariaDbReadOnlyIncrementalSnapshotContext<>(),
|
|
||||||
new SourceInfo(new MariaDbConnectorConfig(config)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DdlParser getDdlParser() {
|
|
||||||
return new MariaDbAntlrDdlParser();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.relational.history;
|
|
||||||
|
|
||||||
import io.debezium.connector.mariadb.MariaDbConnector;
|
|
||||||
import io.debezium.connector.mariadb.antlr.MariaDbAntlrDdlParser;
|
|
||||||
import io.debezium.relational.ddl.DdlParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Chris Cranford
|
|
||||||
*/
|
|
||||||
public class MemorySchemaHistoryTest extends AbstractMemorySchemaHistoryTest<MariaDbConnector> {
|
|
||||||
@Override
|
|
||||||
protected DdlParser getDdlParser() {
|
|
||||||
return new MariaDbAntlrDdlParser();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
ARG BASE_IMAGE
|
|
||||||
ARG DEBEZIUM_VERSION
|
|
||||||
FROM ${BASE_IMAGE}
|
|
||||||
ARG DEBEZIUM_VERSION
|
|
||||||
|
|
||||||
ENV CONNECTOR="mariadb"
|
|
||||||
|
|
||||||
RUN echo "Installing Debezium connectors version: ${DEBEZIUM_VERSION}" ; \
|
|
||||||
MAVEN_REPOSITORY="https://repo1.maven.org/maven2/io/debezium" ; \
|
|
||||||
if [[ "${DEBEZIUM_VERSION}" == *-SNAPSHOT ]] ; then \
|
|
||||||
MAVEN_REPOSITORY="https://s01.oss.sonatype.org/content/repositories/snapshots/io/debezium" ; \
|
|
||||||
fi ; \
|
|
||||||
CONNECTOR_VERSION="${DEBEZIUM_VERSION}" ; \
|
|
||||||
for PACKAGE in {scripting,}; do \
|
|
||||||
local CONNECTOR_VERSION="${DEBEZIUM_VERSION}" ; \
|
|
||||||
if [[ "${DEBEZIUM_VERSION}" == *-SNAPSHOT ]] ; then \
|
|
||||||
CONNECTOR_VERSION=$(curl --silent -fSL "${MAVEN_REPOSITORY}/debezium-${PACKAGE}/${DEBEZIUM_VERSION}/maven-metadata.xml" | awk -F'<[^>]+>' '/<extension>tar.gz<\/extension>/ {getline; print $2; exit}'); \
|
|
||||||
fi ; \
|
|
||||||
echo "Downloading and installing debezium-${PACKAGE}-${CONNECTOR_VERSION}.tar.gz ..." ; \
|
|
||||||
curl --silent -fSL -o /tmp/package.tar.gz "${MAVEN_REPOSITORY}/debezium-${PACKAGE}/${DEBEZIUM_VERSION}/debezium-${PACKAGE}-${CONNECTOR_VERSION}.tar.gz" && \
|
|
||||||
echo "Extracting debezium-${PACKAGE}-${CONNECTOR_VERSION}.tar.gz ..." && \
|
|
||||||
tar -xzf /tmp/package.tar.gz -C $EXTERNAL_LIBS_DIR && \
|
|
||||||
echo "Successfully installed debezium-${PACKAGE}-${CONNECTOR_VERSION}!" ; \
|
|
||||||
rm -f /tmp/package.tar.gz ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
COPY --chown=kafka:kafka debezium-connector-${CONNECTOR}-${DEBEZIUM_VERSION}-plugin.tar.gz /tmp/plugin.tar.gz
|
|
||||||
|
|
||||||
RUN tar -xvzf /tmp/plugin.tar.gz -C ${KAFKA_CONNECT_PLUGINS_DIR}/ ; rm -f /tmp/plugin.tar.gz
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.util.MariaDbTestConnectionProvider
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.util.MariaDbUniqueDatabaseProvider
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.CustomTestSnapshot
|
|
@ -1 +0,0 @@
|
|||||||
io.debezium.connector.mariadb.CustomTestSnapshot
|
|
@ -1,49 +0,0 @@
|
|||||||
# For advice on how to change settings please see
|
|
||||||
# https://dev.mysql.com/doc/refman/8.2/en/server-configuration-defaults.html
|
|
||||||
|
|
||||||
[mysqld]
|
|
||||||
#
|
|
||||||
# Remove leading # and set to the amount of RAM for the most important data
|
|
||||||
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
|
|
||||||
# innodb_buffer_pool_size = 128M
|
|
||||||
#
|
|
||||||
# Remove leading # to turn on a very important data integrity option: logging
|
|
||||||
# changes to the binary log between backups.
|
|
||||||
# log_bin
|
|
||||||
#
|
|
||||||
# Remove leading # to set options mainly useful for reporting servers.
|
|
||||||
# The server defaults are faster for transactions and fast SELECTs.
|
|
||||||
# Adjust sizes as needed, experiment to find the optimal values.
|
|
||||||
# join_buffer_size = 128M
|
|
||||||
# sort_buffer_size = 2M
|
|
||||||
# read_rnd_buffer_size = 2M
|
|
||||||
skip-host-cache
|
|
||||||
skip-name-resolve
|
|
||||||
#datadir=/var/lib/mysql
|
|
||||||
#socket=/var/lib/mysql/mysql.sock
|
|
||||||
#secure-file-priv=/var/lib/mysql-files
|
|
||||||
user=mysql
|
|
||||||
|
|
||||||
# Disabling symbolic-links is recommended to prevent assorted security risks
|
|
||||||
symbolic-links=0
|
|
||||||
|
|
||||||
#log-error=/var/log/mysqld.log
|
|
||||||
#pid-file=/var/run/mysqld/mysqld.pid
|
|
||||||
|
|
||||||
# ----------------------------------------------
|
|
||||||
# Enable the binlog for replication & CDC
|
|
||||||
# ----------------------------------------------
|
|
||||||
|
|
||||||
# Enable binary replication log and set the prefix, expiration, and log format.
|
|
||||||
# The prefix is arbitrary, expiration can be short for integration tests but would
|
|
||||||
# be longer on a production system. Row-level info is required for ingest to work.
|
|
||||||
# Server ID is required, but this will vary on production systems
|
|
||||||
server-id = 223344
|
|
||||||
log_bin = mysql-bin
|
|
||||||
binlog_format = row
|
|
||||||
|
|
||||||
# Configures the amount of table metadata added to the binary log when using row-based logging
|
|
||||||
binlog_row_metadata = FULL
|
|
||||||
|
|
||||||
default_authentication_plugin = mysql_native_password
|
|
||||||
binlog_expire_logs_seconds = 86400
|
|
@ -1,58 +0,0 @@
|
|||||||
<configuration>
|
|
||||||
|
|
||||||
<appender name="CONSOLE"
|
|
||||||
class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{ISO8601} %-5p %X{dbz.connectorType}|%X{dbz.connectorName}|%X{dbz.taskId}|%X{dbz.connectorContext}|%X{dbz.databaseName} %m [%c]%n</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root level="warn">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</root>
|
|
||||||
|
|
||||||
<!-- Set up the default logging to be INFO level, then override specific
|
|
||||||
units -->
|
|
||||||
<logger name="io.debezium" level="info" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
|
|
||||||
<!-- Reduced to manage verbosity on CI -->
|
|
||||||
<logger name="io.debezium.connector.mariadb.MariaDbSnapshotChangeEventSource" level="debug" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
<logger name="io.debezium.connector.binlog.BinlogSnapshotChangeEventSource" level="debug" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
<logger name="io.debezium.relational.RelationalSnapshotChangeEventSource" level="debug" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
<!-- This is to reduce the "context is null" error -->
|
|
||||||
<logger name="io.debezium.connector.binlog.BinlogReadOnlyIncrementalSnapshotChangeEventSource" level="error" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
|
|
||||||
<logger
|
|
||||||
name="io.debezium.embedded.EmbeddedWorkerConfig"
|
|
||||||
level="warn" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
<logger
|
|
||||||
name="org.reflections"
|
|
||||||
level="error" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
|
|
||||||
<!-- For debug purpose -->
|
|
||||||
<logger
|
|
||||||
name="io.debezium.pipeline.ChangeEventSourceCoordinator"
|
|
||||||
level="off" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
|
|
||||||
<logger
|
|
||||||
name="io.debezium.pipeline.EventDispatcher"
|
|
||||||
level="off" additivity="false">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</logger>
|
|
||||||
</configuration>
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,19 +0,0 @@
|
|||||||
This directory contains the truststore (used for validating DB server certificate) and keystore (contains the client
|
|
||||||
certificate) for running the test suite with SSL enabled and two-way authentication.
|
|
||||||
|
|
||||||
The files are generated based on the certificates in src/test/resources/ssl-certs, which in turn were taken from the
|
|
||||||
MySQL container image (which generates them by default with a validity of 10 years, see /var/lib/mysql; the currently
|
|
||||||
used certificates were created on March 8 2022, i.e. expect SSL-enabled tests to fail after March 8 2032 due to the
|
|
||||||
expired certificates). The server used for SSL authentication testing uses those pre-generated certificates (see configuration in
|
|
||||||
src/test/docker/server-ssl/my.cnf) instead of generating new ones.
|
|
||||||
|
|
||||||
To regenerate the truststore/keystore files, run the following commands:
|
|
||||||
|
|
||||||
```
|
|
||||||
keytool -importcert -alias MySQLCACert -file debezium-connector-mysql/src/test/resources/ssl-certs/ca.pem -keystore debezium-connector-mysql/src/test/resources/ssl/truststore -storepass debezium -noprompt
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
openssl pkcs12 -export -in debezium-connector-mysql/src/test/resources/ssl-certs/client-cert.pem -inkey debezium-connector-mysql/src/test/resources/ssl-certs/client-key.pem -name "mysqlclient" -passout pass:debezium -out client-keystore.p12
|
|
||||||
keytool -importkeystore -srckeystore client-keystore.p12 -srcstoretype pkcs12 -srcstorepass debezium -destkeystore debezium-connector-mysql/src/test/resources/ssl/keystore -deststoretype pkcs12 -deststorepass debezium
|
|
||||||
```
|
|
Binary file not shown.
Binary file not shown.
1
debezium-examples
Submodule
1
debezium-examples
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a2a530bc390a9334c60d9409df714c9108e3708a
|
Loading…
Reference in New Issue
Block a user