Skip to content

Commit

Permalink
Support more datatypes in MDP constraint evaluation in ORCA
Browse files Browse the repository at this point in the history
* Date, time & timestamp data types

  Since we don't have GPDB available in the gporca_test program, we didn't
  try to evaluate expressions on types other than integer types. For integer
  types, we just used the stats values (LINT values) to evaluate comparison
  operators.

  With this commit, we can do the same on date columns, which have a DOUBLE
  value that represents the number of microseconds since 2000-01-01
  (older dates have negative values). We could later add timestamp values
  and probably time values as well, if we want.

* float4, float8 & numeric data types

  Allow these data types in addition to int and date types for the
  "internal" expression evaluator that is used for constraints, including
  partition constraints. These float/numeric types map directly to a
  double value that can be compared.

* timeTz and timestampTz
  • Loading branch information
Hans Zeller authored and hardikar committed Feb 1, 2021
1 parent 3bb3633 commit f8990fb
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,10 @@ class CDefaultComparator : public IComparator
const IDatum *datum2,
IMDType::ECmpType cmp_type) const;

// return true iff we use built-in evaluation for integers
static BOOL
FUseBuiltinIntEvaluators()
{
return !GPOS_FTRACE(EopttraceEnableConstantExpressionEvaluation) ||
!GPOS_FTRACE(
EopttraceUseExternalConstantExpressionEvaluationForInts);
}
// return true iff we should use the internal (stats-based) evaluation
static BOOL FUseInternalEvaluator(const IDatum *datum1,
const IDatum *datum2,
BOOL *can_use_external_evaluator);

public:
CDefaultComparator(const CDefaultComparator &) = delete;
Expand Down
118 changes: 86 additions & 32 deletions src/backend/gporca/libgpopt/src/base/CDefaultComparator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,50 @@ CDefaultComparator::FEvalComparison(CMemoryPool *mp, const IDatum *datum1,
return result;
}

BOOL
CDefaultComparator::FUseInternalEvaluator(const IDatum *datum1,
const IDatum *datum2,
BOOL *can_use_external_evaluator)
{
IMDId *mdid1 = datum1->MDId();
IMDId *mdid2 = datum2->MDId();

// be conservative for now and require this extra condition that
// has been in place for a while (might be relaxed in the future)
*can_use_external_evaluator =
GPOS_FTRACE(EopttraceEnableConstantExpressionEvaluation) &&
CUtils::FConstrainableType(mdid1) && CUtils::FConstrainableType(mdid2);

if (CUtils::FIntType(mdid1) && CUtils::FIntType(mdid2) &&
!(*can_use_external_evaluator &&
GPOS_FTRACE(EopttraceUseExternalConstantExpressionEvaluationForInts)))
{
// INT types can be processed precisely by the internal evaluator
return true;
}

// For now, specifically target date and timestamp columns, since they
// are mappable to a double value that represents the number of microseconds
// since Jan 1, 2000 and therefore those can be compared precisely, just like
// integer types. Same goes for float types, since they map naturally to a
// double value
if (mdid1->Equals(datum2->MDId()) && datum1->StatsAreComparable(datum2) &&
(CMDIdGPDB::m_mdid_date.Equals(mdid1) ||
CMDIdGPDB::m_mdid_time.Equals(mdid1) ||
CMDIdGPDB::m_mdid_timestamp.Equals(mdid1) ||
CMDIdGPDB::m_mdid_float4.Equals(mdid1) ||
CMDIdGPDB::m_mdid_float8.Equals(mdid1) ||
CMDIdGPDB::m_mdid_numeric.Equals(mdid1)))
{
return true;
}

// GPDB_12_MERGE_FIXME: Throw an exception when result = false and can_use_external_evaluator = false

return false;
}


//---------------------------------------------------------------------------
// @function:
// CDefaultComparator::Equals
Expand All @@ -97,16 +141,18 @@ CDefaultComparator::FEvalComparison(CMemoryPool *mp, const IDatum *datum1,
BOOL
CDefaultComparator::Equals(const IDatum *datum1, const IDatum *datum2) const
{
if (!CUtils::FConstrainableType(datum1->MDId()) ||
!CUtils::FConstrainableType(datum2->MDId()))
BOOL can_use_external_evaluator = false;

if (FUseInternalEvaluator(datum1, datum2, &can_use_external_evaluator))
{
return false;
return datum1->StatsAreEqual(datum2);
}
if (FUseBuiltinIntEvaluators() && CUtils::FIntType(datum1->MDId()) &&
CUtils::FIntType(datum2->MDId()))

if (!can_use_external_evaluator)
{
return datum1->StatsAreEqual(datum2);
return false;
}

CAutoMemoryPool amp;

// NULL datum is a special case and is being handled here. Assumptions made are
Expand All @@ -132,16 +178,18 @@ CDefaultComparator::Equals(const IDatum *datum1, const IDatum *datum2) const
BOOL
CDefaultComparator::IsLessThan(const IDatum *datum1, const IDatum *datum2) const
{
if (!CUtils::FConstrainableType(datum1->MDId()) ||
!CUtils::FConstrainableType(datum2->MDId()))
BOOL can_use_external_evaluator = false;

if (FUseInternalEvaluator(datum1, datum2, &can_use_external_evaluator))
{
return false;
return datum1->StatsAreLessThan(datum2);
}
if (FUseBuiltinIntEvaluators() && CUtils::FIntType(datum1->MDId()) &&
CUtils::FIntType(datum2->MDId()))

if (!can_use_external_evaluator)
{
return datum1->StatsAreLessThan(datum2);
return false;
}

CAutoMemoryPool amp;

// NULL datum is a special case and is being handled here. Assumptions made are
Expand All @@ -168,17 +216,19 @@ BOOL
CDefaultComparator::IsLessThanOrEqual(const IDatum *datum1,
const IDatum *datum2) const
{
if (!CUtils::FConstrainableType(datum1->MDId()) ||
!CUtils::FConstrainableType(datum2->MDId()))
{
return false;
}
if (FUseBuiltinIntEvaluators() && CUtils::FIntType(datum1->MDId()) &&
CUtils::FIntType(datum2->MDId()))
BOOL can_use_external_evaluator = false;

if (FUseInternalEvaluator(datum1, datum2, &can_use_external_evaluator))
{
return datum1->StatsAreLessThan(datum2) ||
datum1->StatsAreEqual(datum2);
}

if (!can_use_external_evaluator)
{
return false;
}

CAutoMemoryPool amp;

// NULL datum is a special case and is being handled here. Assumptions made are
Expand Down Expand Up @@ -212,16 +262,18 @@ BOOL
CDefaultComparator::IsGreaterThan(const IDatum *datum1,
const IDatum *datum2) const
{
if (!CUtils::FConstrainableType(datum1->MDId()) ||
!CUtils::FConstrainableType(datum2->MDId()))
BOOL can_use_external_evaluator = false;

if (FUseInternalEvaluator(datum1, datum2, &can_use_external_evaluator))
{
return false;
return datum1->StatsAreGreaterThan(datum2);
}
if (FUseBuiltinIntEvaluators() && CUtils::FIntType(datum1->MDId()) &&
CUtils::FIntType(datum2->MDId()))

if (!can_use_external_evaluator)
{
return datum1->StatsAreGreaterThan(datum2);
return false;
}

CAutoMemoryPool amp;

// NULL datum is a special case and is being handled here. Assumptions made are
Expand All @@ -248,17 +300,19 @@ BOOL
CDefaultComparator::IsGreaterThanOrEqual(const IDatum *datum1,
const IDatum *datum2) const
{
if (!CUtils::FConstrainableType(datum1->MDId()) ||
!CUtils::FConstrainableType(datum2->MDId()))
{
return false;
}
if (FUseBuiltinIntEvaluators() && CUtils::FIntType(datum1->MDId()) &&
CUtils::FIntType(datum2->MDId()))
BOOL can_use_external_evaluator = false;

if (FUseInternalEvaluator(datum1, datum2, &can_use_external_evaluator))
{
return datum1->StatsAreGreaterThan(datum2) ||
datum1->StatsAreEqual(datum2);
}

if (!can_use_external_evaluator)
{
return false;
}

CAutoMemoryPool amp;

// NULL datum is a special case and is being handled here. Assumptions made are
Expand Down
23 changes: 17 additions & 6 deletions src/backend/gporca/libgpopt/src/base/CUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2987,14 +2987,25 @@ CUtils::FConstrainableType(IMDId *mdid_type)
{
return true;
}
if (!GPOS_FTRACE(EopttraceEnableConstantExpressionEvaluation))
if (GPOS_FTRACE(EopttraceEnableConstantExpressionEvaluation))
{
return false;
}
CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda();
const IMDType *pmdtype = md_accessor->RetrieveType(mdid_type);
CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda();
const IMDType *pmdtype = md_accessor->RetrieveType(mdid_type);

return FHasAllDefaultComparisons(pmdtype);
return FHasAllDefaultComparisons(pmdtype);
}
else
{
// also allow date/time/timestamp/float4/float8
return (CMDIdGPDB::m_mdid_date.Equals(mdid_type) ||
CMDIdGPDB::m_mdid_time.Equals(mdid_type) ||
CMDIdGPDB::m_mdid_timestamp.Equals(mdid_type) ||
CMDIdGPDB::m_mdid_timeTz.Equals(mdid_type) ||
CMDIdGPDB::m_mdid_timestampTz.Equals(mdid_type) ||
CMDIdGPDB::m_mdid_float4.Equals(mdid_type) ||
CMDIdGPDB::m_mdid_float8.Equals(mdid_type) ||
CMDIdGPDB::m_mdid_numeric.Equals(mdid_type));
}
}

// determine whether a type is an integer type
Expand Down

0 comments on commit f8990fb

Please sign in to comment.