Skip to content

Features and enhancements done #299

Closed
Yash0215 wants to merge 14 commits into
awslabs:masterfrom
Yash0215:master
Closed

Features and enhancements done #299
Yash0215 wants to merge 14 commits into
awslabs:masterfrom
Yash0215:master

Conversation

@Yash0215

Copy link
Copy Markdown

New Features:
1.
A Date Time Distribution analyzer for analyzing the distribution of the records based on 'DateType' or 'TimestampType' feature within fixed time intervals.
files changed/created:
DateTimeDistribution.scala
DateTimeAggregation.scala
DeequFunctions.scala
...

6 new Constraints added covering more use cases for DateTime quality checks:
files changed/created:
Check.scala
Constraint.scala

Constraint 'isContainedIn' is now supports more Scala Numeric Types
files changed/created:
Check.scala

Enahancements:

  1. Issue: Timestamp support Timestamp support #47
    New State and Metric is implemented for this enhancement since previous analyzer only support Double Metric and Standard analyzer. a new abstract analyzer for timestamp analysis is implemented.
    files changed/created:
    MinimumDateTime.scala, MaximumDateTime.scala (for new analyzer implementation)
    Analyzer.scala

  2. Analyzer for Precision and Scale of BigDecimals Analyzer for Precision and Scale of BigDecimals #46
    New State and Metric is implemented. Also new analyzers that provides precision and scale of Spark's 'DecimalType'.
    files changed/created:
    Minimum.scala, Maximum.scala, Sum.scala, Mean.scala (for new analyzer implementation)
    Analyzer.scala

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Yash0215 and others added 9 commits September 23, 2020 12:46
Features:
> Support Spark's DateType and TimestampType
> min and max analysis on date time fields
> New constraints for Spark's DateType and Timestamp Types
> BigDecimal State and Metric Support in Min, Max, Sum and Mean Analyzers
> 'isContained' is made available for all Numeric Types and Char
> Analyzer - DateTimeDistribution
  for analyzing distributions metrics (count, ratio) over some time intervals
@sscdotopen

Copy link
Copy Markdown
Contributor

Thanks! Could you look at the CI failures and fix them?

@lucene

lucene commented Oct 15, 2020

Copy link
Copy Markdown

Hi, is this feature now available?

@Yash0215

Copy link
Copy Markdown
Author

Thanks! Could you look at the CI failures and fix them?

sorry for the late reply. Ill work on it.

@lucene

lucene commented Oct 15, 2020

Copy link
Copy Markdown

This is valuable feature you've added @Yash0215. awesome. Looking forward to using it.

@lucene

lucene commented Oct 15, 2020

Copy link
Copy Markdown

Can I assist in anyway @yash021? I'm looking to utilise this functionality asap.

@Yash0215

Copy link
Copy Markdown
Author

please recommend if any changes are needed.

@aviatesk

Copy link
Copy Markdown
Contributor

So the two enhancements implemented in this PR are essentially orthogonal, right ? If so I'd recommend we split them into separate PRs and focus on each.

@sscdotopen

Copy link
Copy Markdown
Contributor

Yes, that would make a lot of sense.

@rounakdatta

Copy link
Copy Markdown

Hello @Yash0215 @sscdotopen, were there furthur developments on this work? If not, I can volunteer to take it forward.

@aviatesk

Copy link
Copy Markdown
Contributor

FWIW, I forked this project and am actively developing it afterwards.
See this changelog to see the enhancements/bugfixes.

I'm also thinking of announcing it as an active fork of this project somewhere (maybe as an issue for this repo) in the near future.

@twollnik

Copy link
Copy Markdown
Contributor

Hi, thanks so much for introducing all these changes. Unfortunately, we currently don't have availability to give this a proper review. Will keep this PR in the backlog for now. If you have the opportunity to submit a couple of smaller reviews that would be great. It's hard to find the time to do big reviews and a few smaller PRs could help us understand the main ideas and make progress on this.

@twollnik

Copy link
Copy Markdown
Contributor

@Yash0215 Please get back to us on this if you get the chance. We are considering closing this PR soon.

@RunnX

RunnX commented Jun 14, 2022

Copy link
Copy Markdown

@twollnik @Yash0215 - Will this PR be merged to improve deequ to handle timestamp/date support?

@shehzad-qureshi shehzad-qureshi added the enhancement New feature or request label Jan 31, 2023
@shehzad-qureshi shehzad-qureshi added the help wanted Extra attention is needed label Jan 31, 2023
@suadhika

Copy link
Copy Markdown

Any update on this? to improve deequ for handling of timestamp/date support?

@zeotuan

zeotuan commented Apr 18, 2024

Copy link
Copy Markdown
Contributor

This PR is quite big with multiple unrelated changes making review hard. Chunk this into multiple smaller PR should be a good start. I am interested in timestamp/date support

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Generated by AI (model: us.anthropic.claude-opus-4-6-v1, prompt: 38d3f74c) — may not be fully accurate. Reply if this doesn't help.

def metricValue(): Double
}

/** A state which produces a BigDecimalValued metric */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BigDecimalValuedState trait's metricValue() returns java.math.BigDecimal which can be null (as seen in BigDecimalMeanState.metricValue() when count is 0). This is unsafe — callers like BigDecimalScanShareableAnalyzer.computeMetricFrom wrap it in Success(theState.metricValue()), which would produce Success(null) rather than a proper Failure. Consider returning Option[BigDecimal] or handling the null/zero-count case before wrapping in Success.

@@ -52,6 +54,11 @@ trait DoubleValuedState[S <: DoubleValuedState[S]] extends State[S] {
def metricValue(): Double

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Analyzer trait has lost its extends Serializable declaration in this diff. The original code has trait Analyzer[S <: State[_], +M <: Metric[_]] extends Serializable, but the new code shows just trait Analyzer[S <: State[_], +M <: Metric[_]]. This will break serialization for Spark jobs that serialize analyzers (e.g., for broadcast or closure capture).

Seq.empty
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NumMatchesAndCount has lost its override val fullColumn: Option[Column] = None field and the FullColumn trait mixin compared to the existing code. This will break row-level results for Completeness, Compliance, PatternMatch, and other analyzers that rely on NumMatchesAndCount carrying a fullColumn.

override def aggregationFunctions(): Seq[Column] = {
sum(conditionalSelection(column, where)) ::
count(conditionalSelection(column, where)).cast(LongType) :: Nil
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BigDecimalMeanState.metricValue() returns null when count == 0L. This will result in Success(null) being stored in the metric, which will cause NPEs downstream (e.g., when flattening the metric or running assertions). Should return a failure or handle this case in computeMetricFrom.


override def filterCondition: Option[String] = where
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactored Maximum analyzer has lost the FullColumn trait on MaxState, the analyzerOptions parameter, the augmented outcome logic (criterion with conditionalSelectionWithAugmentedOutcome), and the computeMetricFrom override for the WHERE-filters-all-rows case. This is a regression that breaks row-level results and filtered-row handling for hasMax checks.


override def filterCondition: Option[String] = where
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same regression as Maximum: the refactored Minimum analyzer has lost the FullColumn trait on MinState, the analyzerOptions parameter, the augmented outcome logic, and the computeMetricFrom override. This breaks row-level results and filtered-row handling for hasMin checks.

column: String,
allowedValues: Array[String],
allowedValues: Array[T],
assertion: Double => Boolean,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isContainedIn signature has been changed from Array[String] to generic Array[T], but the existing overloads with Array[String] that take different parameter combinations still exist. After erasure, Array[T] and Array[String] both become Array[Object], which will cause compilation errors due to ambiguous overloaded methods. The generic version should be a separate method name or the existing overloads need to be removed/consolidated.



import com.amazon.deequ.analyzers.KLLSketch
import com.amazon.deequ.analyzers.catalyst.DateTimeAggregation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import import com.amazon.deequ.analyzers.catalyst.DateTimeAggregation was added but the original import import com.amazon.deequ.analyzers.KLLSketch was removed. However, KLLSketch is not used in this file (it's referenced via StatefulKLLSketch), so this removal is fine. But note that DateTimeAggregation is in the same package (com.amazon.deequ.analyzers.catalyst) — this import is unnecessary since the file is in org.apache.spark.sql package, not com.amazon.deequ.analyzers.catalyst. Actually, looking more carefully, the file declares package org.apache.spark.sql so the import IS needed. No issue here.

ifNoNullsIn(result, offset) { _ =>
DateTimeDistributionState(
DateTimeDistributionState.computeStateFromResult(Map.empty[Long, Long] ++ result.getMap(0),
DateTimeDistribution.getDateTimeAggIntervalValue(interval)))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DateTimeDistribution extends ScanShareableAnalyzer but does not extend Analyzer with Serializable. Since the base Analyzer trait lost extends Serializable in this PR's changes to Analyzer.scala, this class won't be serializable, which will cause failures when Spark tries to serialize it for distributed execution.

val data = ordersAsDataframe(session,
Order(1, new BigDecimal(213.2132), Timestamp.valueOf("2020-02-15 07:15:00")),
Order(2, new BigDecimal(43.21324432876), Timestamp.valueOf("2020-02-15 07:45:00.999")),
Order(3, new BigDecimal(56.8881238823888), Timestamp.valueOf("2020-02-15 08:15:49.786")),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new BigDecimal(213.2132) uses the BigDecimal(double) constructor which is well-known to produce unexpected results due to floating-point representation (e.g., new BigDecimal(0.1) gives 0.1000000000000000055511151231257827021181583404541015625). Use new BigDecimal("213.2132") or BigDecimal.valueOf(213.2132) instead.

@sudsali

sudsali commented May 18, 2026

Copy link
Copy Markdown
Contributor

@Yash0215 This appears to overlap with #568 (DateTimeMetric) which has a more complete implementation. Closing this one in favor of that PR. Thank you for the contribution!

@sudsali sudsali closed this May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request help wanted Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.