-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
destination: add implementation for mysql as destination #3242
Changes from 5 commits
f1b070f
1aa3314
d0ff264
d77b1eb
a4cb890
775210c
ea4ca83
ecaad3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,7 @@ | |
import io.airbyte.protocol.models.ConfiguredAirbyteStream; | ||
import io.airbyte.protocol.models.DestinationSyncMode; | ||
import java.time.Instant; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.function.Function; | ||
|
@@ -66,7 +67,7 @@ public static AirbyteMessageConsumer create(JdbcDatabase database, | |
NamingConventionTransformer namingResolver, | ||
JsonNode config, | ||
ConfiguredAirbyteCatalog catalog) { | ||
final List<WriteConfig> writeConfigs = createWriteConfigs(namingResolver, config, catalog); | ||
final List<WriteConfig> writeConfigs = createWriteConfigs(namingResolver, config, catalog, sqlOperations.isSchemaRequired()); | ||
|
||
return new BufferedStreamConsumer( | ||
onStartFunction(database, sqlOperations, writeConfigs), | ||
|
@@ -77,25 +78,41 @@ public static AirbyteMessageConsumer create(JdbcDatabase database, | |
sqlOperations::isValidData); | ||
} | ||
|
||
private static List<WriteConfig> createWriteConfigs(NamingConventionTransformer namingResolver, JsonNode config, ConfiguredAirbyteCatalog catalog) { | ||
Preconditions.checkState(config.has("schema"), "jdbc destinations must specify a schema."); | ||
private static List<WriteConfig> createWriteConfigs(NamingConventionTransformer namingResolver, | ||
JsonNode config, | ||
ConfiguredAirbyteCatalog catalog, | ||
boolean schemaRequired) { | ||
if (schemaRequired) { | ||
Preconditions.checkState(config.has("schema"), "jdbc destinations must specify a schema."); | ||
} | ||
final Instant now = Instant.now(); | ||
return catalog.getStreams().stream().map(toWriteConfig(namingResolver, config, now)).collect(Collectors.toList()); | ||
return catalog.getStreams().stream().map(toWriteConfig(namingResolver, config, now, schemaRequired)).collect(Collectors.toList()); | ||
} | ||
|
||
private static Function<ConfiguredAirbyteStream, WriteConfig> toWriteConfig(NamingConventionTransformer namingResolver, | ||
private static Function<ConfiguredAirbyteStream, WriteConfig> toWriteConfig( | ||
NamingConventionTransformer namingResolver, | ||
JsonNode config, | ||
Instant now) { | ||
Instant now, | ||
boolean schemaRequired) { | ||
return stream -> { | ||
Preconditions.checkNotNull(stream.getDestinationSyncMode(), "Undefined destination sync mode"); | ||
final AirbyteStream abStream = stream.getStream(); | ||
|
||
final String defaultSchemaName = namingResolver.getIdentifier(config.get("schema").asText()); | ||
final String defaultSchemaName = schemaRequired ? namingResolver.getIdentifier(config.get("schema").asText()) | ||
: namingResolver.getIdentifier(config.get("database").asText()); | ||
final String outputSchema = getOutputSchema(abStream, defaultSchemaName); | ||
|
||
final String streamName = abStream.getName(); | ||
final String tableName = Names.concatQuotedNames("_airbyte_raw_", namingResolver.getIdentifier(streamName)); | ||
final String tmpTableName = Names.concatQuotedNames("_airbyte_" + now.toEpochMilli() + "_", tableName); | ||
String tmpTableName = Names.concatQuotedNames("_airbyte_" + now.toEpochMilli() + "_", tableName); | ||
|
||
// This is for MySQL destination, the table names can't have more than 64 characters. | ||
if (tmpTableName.length() > 64) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs collision handling in case the 0-31 and 32-63 are the same for different tables. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually @ChristopheDuong mentioned that this is a more general problem. Beyond the scope of this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeap. Discussed this with Subodh. Will create a follow up ticket to track this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, a related issue on Postgres is here: We'd probably need to handle these table name truncations and collisions in a common class, maybe in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, Subodh, can you leave a TODO here and reference the issue? e.g.
or something of the sort so we remember when we get to this. |
||
String prefix = tmpTableName.substring(0, 31); // 31 | ||
String suffix = tmpTableName.substring(32, 63); // 31 | ||
tmpTableName = prefix + "__" + suffix; | ||
} | ||
|
||
final DestinationSyncMode syncMode = stream.getDestinationSyncMode(); | ||
|
||
return new WriteConfig(streamName, abStream.getNamespace(), outputSchema, tmpTableName, tableName, syncMode); | ||
|
@@ -155,7 +172,7 @@ private static OnCloseFunction onCloseFunction(JdbcDatabase database, SqlOperati | |
return (hasFailed) -> { | ||
// copy data | ||
if (!hasFailed) { | ||
final StringBuilder queries = new StringBuilder(); | ||
List<String> queryList = new ArrayList<>(); | ||
LOGGER.info("Finalizing tables in destination started for {} streams", writeConfigs.size()); | ||
for (WriteConfig writeConfig : writeConfigs) { | ||
final String schemaName = writeConfig.getOutputSchemaName(); | ||
|
@@ -166,16 +183,16 @@ private static OnCloseFunction onCloseFunction(JdbcDatabase database, SqlOperati | |
|
||
sqlOperations.createTableIfNotExists(database, schemaName, dstTableName); | ||
switch (writeConfig.getSyncMode()) { | ||
case OVERWRITE -> queries.append(sqlOperations.truncateTableQuery(schemaName, dstTableName)); | ||
case OVERWRITE -> queryList.add(sqlOperations.truncateTableQuery(schemaName, dstTableName)); | ||
case APPEND -> {} | ||
case APPEND_DEDUP -> {} | ||
default -> throw new IllegalStateException("Unrecognized sync mode: " + writeConfig.getSyncMode()); | ||
} | ||
queries.append(sqlOperations.copyTableQuery(schemaName, srcTableName, dstTableName)); | ||
queryList.add(sqlOperations.copyTableQuery(schemaName, srcTableName, dstTableName)); | ||
} | ||
|
||
LOGGER.info("Executing finalization of tables."); | ||
sqlOperations.executeTransaction(database, queries.toString()); | ||
sqlOperations.executeTransaction(database, queryList); | ||
LOGGER.info("Finalizing tables in destination completed."); | ||
} | ||
// clean up | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
* | ||
!Dockerfile | ||
!build |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FROM airbyte/integration-base-java:dev | ||
|
||
WORKDIR /airbyte | ||
|
||
ENV APPLICATION destination-mysql | ||
|
||
COPY build/distributions/${APPLICATION}*.tar ${APPLICATION}.tar | ||
|
||
RUN tar xf ${APPLICATION}.tar --strip-components=1 | ||
|
||
LABEL io.airbyte.version=0.1.0 | ||
LABEL io.airbyte.name=airbyte/destination-mysql |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
plugins { | ||
id 'application' | ||
id 'airbyte-docker' | ||
id 'airbyte-integration-test-java' | ||
} | ||
|
||
application { | ||
mainClass = 'io.airbyte.integrations.destination.mysql.MySQLDestination' | ||
} | ||
|
||
dependencies { | ||
implementation project(':airbyte-db') | ||
implementation project(':airbyte-integrations:bases:base-java') | ||
implementation project(':airbyte-protocol:models') | ||
implementation project(':airbyte-integrations:connectors:destination-jdbc') | ||
|
||
implementation 'mysql:mysql-connector-java:8.0.22' | ||
|
||
integrationTestJavaImplementation project(':airbyte-integrations:bases:standard-destination-test') | ||
integrationTestJavaImplementation project(':airbyte-integrations:connectors:destination-mysql') | ||
integrationTestJavaImplementation "org.testcontainers:mysql:1.15.1" | ||
|
||
implementation files(project(':airbyte-integrations:bases:base-java').airbyteDocker.outputs) | ||
integrationTestJavaImplementation files(project(':airbyte-integrations:bases:base-normalization').airbyteDocker.outputs) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this cleans things up a lot 👍