@@ -56,6 +56,16 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
56
56
protected val configSchemaKey: String
57
57
get() = " schema"
58
58
59
+ /* *
60
+ * If the destination should always disable type dedupe, override this method to return true. We
61
+ * only type and dedupe if we create final tables.
62
+ *
63
+ * @return whether the destination should always disable type dedupe
64
+ */
65
+ protected open fun shouldAlwaysDisableTypeDedupe (): Boolean {
66
+ return false
67
+ }
68
+
59
69
override fun check (config : JsonNode ): AirbyteConnectionStatus ? {
60
70
val dataSource = getDataSource(config)
61
71
@@ -67,7 +77,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
67
77
val v2RawSchema =
68
78
namingResolver.getIdentifier(
69
79
getRawNamespaceOverride(RAW_SCHEMA_OVERRIDE )
70
- .orElse(JavaBaseConstants .DEFAULT_AIRBYTE_INTERNAL_NAMESPACE )
80
+ .orElse(JavaBaseConstants .DEFAULT_AIRBYTE_INTERNAL_NAMESPACE ),
71
81
)
72
82
attemptTableOperations(v2RawSchema, database, namingResolver, sqlOperations, false )
73
83
destinationSpecificTableOperations(database)
@@ -87,7 +97,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
87
97
"""
88
98
Could not connect with provided configuration.
89
99
${e.message}
90
- """ .trimIndent()
100
+ """ .trimIndent(),
91
101
)
92
102
} finally {
93
103
try {
@@ -123,7 +133,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
123
133
jdbcConfig[JdbcUtils .PASSWORD_KEY ].asText()
124
134
else null ,
125
135
driverClassName,
126
- jdbcConfig[JdbcUtils .JDBC_URL_KEY ].asText()
136
+ jdbcConfig[JdbcUtils .JDBC_URL_KEY ].asText(),
127
137
)
128
138
.withConnectionProperties(connectionProperties)
129
139
.withConnectionTimeout(getConnectionTimeout(connectionProperties))
@@ -155,8 +165,10 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
155
165
for (key in defaultParameters.keys) {
156
166
require(
157
167
! (customParameters.containsKey(key) &&
158
- customParameters[key] != defaultParameters[key])
159
- ) { " Cannot overwrite default JDBC parameter $key " }
168
+ customParameters[key] != defaultParameters[key]),
169
+ ) {
170
+ " Cannot overwrite default JDBC parameter $key "
171
+ }
160
172
}
161
173
}
162
174
@@ -191,7 +203,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
191
203
* @param config
192
204
* @return
193
205
*/
194
- protected fun getDatabaseName (config : JsonNode ): String {
206
+ protected open fun getDatabaseName (config : JsonNode ): String {
195
207
return config[JdbcUtils .DATABASE_KEY ].asText()
196
208
}
197
209
@@ -227,7 +239,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
227
239
config,
228
240
catalog,
229
241
null ,
230
- NoopTyperDeduper ()
242
+ NoopTyperDeduper (),
231
243
)
232
244
}
233
245
@@ -238,10 +250,18 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
238
250
catalog,
239
251
outputRecordCollector,
240
252
database,
241
- defaultNamespace
253
+ defaultNamespace,
242
254
)
243
255
}
244
256
257
+ private fun isTypeDedupeDisabled (config : JsonNode ): Boolean {
258
+ return shouldAlwaysDisableTypeDedupe() ||
259
+ (config.has(DISABLE_TYPE_DEDUPE ) &&
260
+ config[DISABLE_TYPE_DEDUPE ].asBoolean(
261
+ false ,
262
+ ))
263
+ }
264
+
245
265
private fun getV2MessageConsumer (
246
266
config : JsonNode ,
247
267
catalog : ConfiguredAirbyteCatalog ? ,
@@ -256,51 +276,71 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
256
276
.map { override : String -> CatalogParser (sqlGenerator, override ) }
257
277
.orElse(CatalogParser (sqlGenerator))
258
278
.parseCatalog(catalog!! )
279
+ val typerDeduper: TyperDeduper =
280
+ buildTyperDeduper(
281
+ config,
282
+ database,
283
+ parsedCatalog,
284
+ )
285
+
286
+ return JdbcBufferedConsumerFactory .createAsync(
287
+ outputRecordCollector,
288
+ database,
289
+ sqlOperations,
290
+ namingResolver,
291
+ config,
292
+ catalog,
293
+ defaultNamespace,
294
+ typerDeduper,
295
+ getDataTransformer(parsedCatalog, defaultNamespace),
296
+ )
297
+ }
298
+
299
+ private fun buildTyperDeduper (
300
+ config : JsonNode ,
301
+ database : JdbcDatabase ,
302
+ parsedCatalog : ParsedCatalog ,
303
+ ): TyperDeduper {
259
304
val databaseName = getDatabaseName(config)
260
- val migrator = JdbcV1V2Migrator (namingResolver, database, databaseName)
261
305
val v2TableMigrator = NoopV2TableMigrator ()
306
+ val migrator = JdbcV1V2Migrator (namingResolver, database, databaseName)
262
307
val destinationHandler: DestinationHandler <DestinationState > =
263
308
getDestinationHandler(
264
309
databaseName,
265
310
database,
266
- rawNamespaceOverride.orElse(JavaBaseConstants .DEFAULT_AIRBYTE_INTERNAL_NAMESPACE )
311
+ getRawNamespaceOverride(RAW_SCHEMA_OVERRIDE )
312
+ .orElse(JavaBaseConstants .DEFAULT_AIRBYTE_INTERNAL_NAMESPACE ),
267
313
)
268
- val disableTypeDedupe =
269
- config.has(DISABLE_TYPE_DEDUPE ) && config[DISABLE_TYPE_DEDUPE ].asBoolean(false )
270
- val typerDeduper: TyperDeduper
314
+ val disableTypeDedupe = isTypeDedupeDisabled(config)
271
315
val migrations = getMigrations(database, databaseName, sqlGenerator, destinationHandler)
272
- typerDeduper =
273
- if (disableTypeDedupe) {
274
- NoOpTyperDeduperWithV1V2Migrations (
275
- sqlGenerator,
276
- destinationHandler,
277
- parsedCatalog,
278
- migrator,
279
- v2TableMigrator,
280
- migrations
281
- )
282
- } else {
316
+
317
+ val typerDeduper: TyperDeduper
318
+ if (disableTypeDedupe) {
319
+ typerDeduper =
320
+ if (migrations.isEmpty()) {
321
+ NoopTyperDeduper ()
322
+ } else {
323
+ NoOpTyperDeduperWithV1V2Migrations (
324
+ sqlGenerator,
325
+ destinationHandler,
326
+ parsedCatalog,
327
+ migrator,
328
+ v2TableMigrator,
329
+ migrations,
330
+ )
331
+ }
332
+ } else {
333
+ typerDeduper =
283
334
DefaultTyperDeduper (
284
335
sqlGenerator,
285
336
destinationHandler,
286
337
parsedCatalog,
287
338
migrator,
288
339
v2TableMigrator,
289
- migrations
340
+ migrations,
290
341
)
291
- }
292
-
293
- return JdbcBufferedConsumerFactory .createAsync(
294
- outputRecordCollector,
295
- database,
296
- sqlOperations,
297
- namingResolver,
298
- config,
299
- catalog,
300
- defaultNamespace,
301
- typerDeduper,
302
- getDataTransformer(parsedCatalog, defaultNamespace)
303
- )
342
+ }
343
+ return typerDeduper
304
344
}
305
345
306
346
companion object {
@@ -361,7 +401,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
361
401
{ conn: Connection -> conn.metaData.catalogs },
362
402
{ queryContext: ResultSet ? ->
363
403
JdbcUtils .defaultSourceOperations.rowToJson(queryContext!! )
364
- }
404
+ },
365
405
)
366
406
367
407
// verify we have write permissions on the target schema by creating a table with a
@@ -370,7 +410,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
370
410
val outputTableName =
371
411
namingResolver.getIdentifier(
372
412
" _airbyte_connection_test_" +
373
- UUID .randomUUID().toString().replace(" -" .toRegex(), " " )
413
+ UUID .randomUUID().toString().replace(" -" .toRegex(), " " ),
374
414
)
375
415
sqlOps.createSchemaIfNotExists(database, outputSchema)
376
416
sqlOps.createTableIfNotExists(database, outputSchema, outputTableName)
@@ -381,7 +421,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
381
421
database,
382
422
java.util.List .of(dummyRecord),
383
423
outputSchema,
384
- outputTableName
424
+ outputTableName,
385
425
)
386
426
}
387
427
} finally {
@@ -412,7 +452,7 @@ abstract class AbstractJdbcDestination<DestinationState : MinimumDestinationStat
412
452
.withRecord(
413
453
PartialAirbyteRecordMessage ()
414
454
.withStream(" stream1" )
415
- .withEmittedAt(1602637589000L )
455
+ .withEmittedAt(1602637589000L ),
416
456
)
417
457
.withSerialized(dummyDataToInsert.toString())
418
458
}
0 commit comments