@@ -26,7 +26,7 @@ import scala.collection.mutable
26
26
import scala .util .control .NonFatal
27
27
28
28
import org .apache .spark .sql .delta ._
29
- import org .apache .spark .sql .delta .constraints . Constraints
29
+ import org .apache .spark .sql .delta .commands . DeletionVectorUtils
30
30
import org .apache .spark .sql .delta .sources .DeltaSQLConf
31
31
import org .apache .spark .sql .delta .util .JsonUtils
32
32
import com .fasterxml .jackson .annotation ._
@@ -36,11 +36,10 @@ import com.fasterxml.jackson.databind._
36
36
import com .fasterxml .jackson .databind .annotation .{JsonDeserialize , JsonSerialize }
37
37
38
38
import org .apache .spark .internal .Logging
39
- import org .apache .spark .sql .{Column , DataFrame , Dataset , Encoder , SparkSession }
39
+ import org .apache .spark .sql .{Column , Encoder , SparkSession }
40
40
import org .apache .spark .sql .catalyst .ScalaReflection
41
41
import org .apache .spark .sql .catalyst .encoders .ExpressionEncoder
42
42
import org .apache .spark .sql .catalyst .expressions .Literal
43
- import org .apache .spark .sql .internal .SQLConf
44
43
import org .apache .spark .sql .types .{DataType , StructField , StructType }
45
44
import org .apache .spark .util .Utils
46
45
@@ -339,6 +338,46 @@ object Protocol {
339
338
}
340
339
}
341
340
341
+ /**
342
+ * Verify that the table properties satisfy legality constraints. Throw an exception if not.
343
+ */
344
+ def assertTablePropertyConstraintsSatisfied (
345
+ spark : SparkSession ,
346
+ metadata : Metadata ,
347
+ snapshot : Snapshot ): Unit = {
348
+ import DeltaTablePropertyValidationFailedSubClass ._
349
+
350
+ val tableName = if (metadata.name != null ) metadata.name else metadata.id
351
+
352
+ val configs = metadata.configuration.map { case (k, v) => k.toLowerCase(Locale .ROOT ) -> v }
353
+ val dvsEnabled = {
354
+ val lowerCaseKey = DeltaConfigs .ENABLE_DELETION_VECTORS_CREATION .key.toLowerCase(Locale .ROOT )
355
+ configs.get(lowerCaseKey).exists(_.toBoolean)
356
+ }
357
+ if (dvsEnabled && metadata.format.provider != " parquet" ) {
358
+ // DVs only work with parquet-based delta tables.
359
+ throw new DeltaTablePropertyValidationFailedException (
360
+ table = tableName,
361
+ subClass = PersistentDeletionVectorsInNonParquetTable )
362
+ }
363
+ val manifestGenerationEnabled = {
364
+ val lowerCaseKey = DeltaConfigs .SYMLINK_FORMAT_MANIFEST_ENABLED .key.toLowerCase(Locale .ROOT )
365
+ configs.get(lowerCaseKey).exists(_.toBoolean)
366
+ }
367
+ if (dvsEnabled && manifestGenerationEnabled) {
368
+ throw new DeltaTablePropertyValidationFailedException (
369
+ table = tableName,
370
+ subClass = PersistentDeletionVectorsWithIncrementalManifestGeneration )
371
+ }
372
+ if (manifestGenerationEnabled) {
373
+ // Only allow enabling this, if there are no DVs present.
374
+ if (! DeletionVectorUtils .isTableDVFree(spark, snapshot)) {
375
+ throw new DeltaTablePropertyValidationFailedException (
376
+ table = tableName,
377
+ subClass = ExistingDeletionVectorsWithIncrementalManifestGeneration )
378
+ }
379
+ }
380
+ }
342
381
}
343
382
344
383
/**
@@ -406,7 +445,8 @@ case class AddFile(
406
445
// scalastyle:off
407
446
val removedFile = RemoveFile (
408
447
path, Some (timestamp), dataChange,
409
- extendedFileMetadata = Some (true ), partitionValues, Some (size), newTags
448
+ extendedFileMetadata = Some (true ), partitionValues, Some (size), newTags,
449
+ deletionVector = deletionVector
410
450
)
411
451
// scalastyle:on
412
452
removedFile
0 commit comments