138  QStringList conditions;
 
  141  if ( dimensions.isEmpty() )
 
  151      return QMetaType::Type::UnknownType;
 
  158  auto refFieldCast = [&]( 
const QString &
fieldName, QMetaType::Type queryType, QMetaType::Type fieldType ) -> QString {
 
  159    const auto fieldRealType { fieldTypeFromName( 
fieldName, layer ) };
 
  160    if ( fieldRealType == QMetaType::Type::UnknownType )
 
  167    if ( fieldRealType == QMetaType::Type::QString )
 
  170      if ( fieldType != queryType || fieldType == QMetaType::Type::QDate )
 
  176        return QStringLiteral( 
"%2( %1 )" ).arg( 
QgsExpression::quotedColumnRef( 
fieldName ) ).arg( queryType == QMetaType::Type::QDate ? QStringLiteral( 
"to_date" ) : QStringLiteral( 
"to_datetime" ) );
 
  179    else if ( fieldType == queryType || fieldType == QMetaType::Type::QDate )
 
  185      return QStringLiteral( 
"%2( %1 )" ).arg( 
QgsExpression::quotedColumnRef( 
fieldName ) ).arg( queryType == QMetaType::Type::QDate ? QStringLiteral( 
"to_date" ) : QStringLiteral( 
"to_datetime" ) );
 
  190  auto quoteValue = []( 
const QString &value ) -> QString {
 
  191    if ( value.length() == 10 )
 
  202  auto makeFilter = ["eValue]( 
const QString &fieldBegin, 
const QString &fieldEnd, 
const QString &fieldBeginCasted, 
const QString &fieldEndCasted, 
const QString &queryBegin, 
const QString &queryEnd ) -> QString {
 
  206    if ( !queryBegin.isEmpty() && !queryEnd.isEmpty() )
 
  209      if ( !fieldEndCasted.isEmpty() )
 
  211        result = QStringLiteral( 
"( %1 IS NULL OR %2 <= %6 ) AND ( %4 IS NULL OR %5 >= %3 )" )
 
  212                   .arg( fieldBegin, fieldBeginCasted, quoteValue( queryBegin ), fieldEnd, fieldEndCasted, quoteValue( queryEnd ) );
 
  216        result = QStringLiteral( 
"( %1 IS NULL OR ( %2 <= %3 AND %3 <= %4 ) )" )
 
  217                   .arg( fieldBegin, quoteValue( queryBegin ), fieldBeginCasted, quoteValue( queryEnd ) );
 
  220    else if ( !queryBegin.isEmpty() ) 
 
  222      if ( !fieldEndCasted.isEmpty() )
 
  224        result = QStringLiteral( 
"( %1 IS NULL OR %2 >= %3 )" ).arg( fieldEnd, fieldEndCasted, quoteValue( queryBegin ) );
 
  228        result = QStringLiteral( 
"( %1 IS NULL OR %2 >= %3 )" ).arg( fieldBegin, fieldBeginCasted, quoteValue( queryBegin ) );
 
  233      result = QStringLiteral( 
"( %1 IS NULL OR %2 <= %3 )" ).arg( fieldBegin, fieldBeginCasted, quoteValue( queryEnd ) );
 
  239  QString testType { interval };
 
  240  if ( interval.contains( 
'/' ) )
 
  242    const QStringList parts { interval.split( 
'/' ) };
 
  244    if ( testType.isEmpty() || testType == QLatin1String( 
".." ) )
 
  251  const bool inputQueryIsDateTime { testType.length() > 10 };
 
  252  const QMetaType::Type queryType { inputQueryIsDateTime ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
 
  255  if ( interval.contains( 
'/' ) )
 
  257    if ( !inputQueryIsDateTime )
 
  261      for ( 
const auto &dimension : std::as_const( dimensions ) )
 
  264        const QMetaType::Type fieldType { dimension.name.toLower() == QLatin1String( 
"time" ) ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
 
  266        const auto fieldBeginCasted { refFieldCast( dimension.fieldName, queryType, fieldType ) };
 
  267        if ( fieldBeginCasted.isEmpty() )
 
  276        const auto fieldEndCasted { refFieldCast( dimension.endFieldName, queryType, fieldType ) };
 
  277        if ( !dateInterval.begin().isValid() && !dateInterval.end().isValid() )
 
  283          conditions.push_back( makeFilter( fieldBegin, fieldEnd, fieldBeginCasted, fieldEndCasted, dateInterval.begin().toString( Qt::DateFormat::ISODate ), dateInterval.end().toString( Qt::DateFormat::ISODate ) ) );
 
  290      for ( 
const auto &dimension : std::as_const( dimensions ) )
 
  293        const QMetaType::Type fieldType { dimension.name.toLower() == QLatin1String( 
"time" ) ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
 
  295        const auto fieldfBeginCasted { refFieldCast( dimension.fieldName, queryType, fieldType ) };
 
  296        if ( fieldfBeginCasted.isEmpty() )
 
  304        const auto fieldEndCasted { refFieldCast( dimension.endFieldName, queryType, fieldType ) };
 
  305        if ( !dateTimeInterval.begin().isValid() && !dateTimeInterval.end().isValid() )
 
  315          if ( fieldType == QMetaType::Type::QDate )
 
  317            beginQuery = dateTimeInterval.begin().date().toString( Qt::DateFormat::ISODate );
 
  318            endQuery = dateTimeInterval.end().date().toString( Qt::DateFormat::ISODate );
 
  322            beginQuery = dateTimeInterval.begin().toString( Qt::DateFormat::ISODate );
 
  323            endQuery = dateTimeInterval.end().toString( Qt::DateFormat::ISODate );
 
  325          conditions.push_back( makeFilter( fieldBegin, fieldEnd, fieldfBeginCasted, fieldEndCasted, beginQuery, endQuery ) );
 
  332    for ( 
const auto &dimension : std::as_const( dimensions ) )
 
  335      const bool fieldIsDateTime { dimension.name.toLower() == QLatin1String( 
"time" ) };
 
  336      const QMetaType::Type fieldType { fieldIsDateTime ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
 
  338      const auto fieldRefBegin { refFieldCast( dimension.fieldName, queryType, fieldType ) };
 
  339      if ( fieldRefBegin.isEmpty() )
 
  346      const auto fieldRefEnd { refFieldCast( dimension.endFieldName, queryType, fieldType ) };
 
  353      if ( !inputQueryIsDateTime || !fieldIsDateTime )
 
  355        QString castedInterval { interval };
 
  357        if ( inputQueryIsDateTime )
 
  359          castedInterval = QDate::fromString( castedInterval, Qt::DateFormat::ISODate ).toString( Qt::DateFormat::ISODate );
 
  365        QString castedInterval { interval };
 
  367        if ( !inputQueryIsDateTime )
 
  369          castedInterval = QDateTime::fromString( castedInterval, Qt::DateFormat::ISODate ).toString( Qt::DateFormat::ISODate );
 
  374      if ( !fieldRefEnd.isEmpty() )
 
  376        condition = QStringLiteral( 
"( %1 IS NULL OR %2 <= %3 ) AND ( %5 IS NULL OR %3 <= %4 )" ).arg( fieldBegin, fieldRefBegin, castedValue, fieldRefEnd, fieldEnd );
 
  380        condition = QStringLiteral( 
"( %1 IS NULL OR %2 = %3 )" )
 
  381                      .arg( fieldBegin, fieldRefBegin, castedValue );
 
  383      conditions.push_back( condition );
 
  386  if ( !conditions.isEmpty() )
 
  388    expression.
setExpression( conditions.join( QLatin1String( 
" AND " ) ) );
 
 
  421    QDateTime min { minVal.toDateTime() };
 
  422    QDateTime max { maxVal.toDateTime() };
 
  423    if ( !dimInfo.endFieldName.isEmpty() )
 
  432        QDateTime minEnd { minVal.toDateTime() };
 
  433        QDateTime maxEnd { maxVal.toDateTime() };
 
  434        if ( minEnd.isValid() )
 
  436          min = std::min<QDateTime>( min, minEnd );
 
  438        if ( maxEnd.isValid() )
 
  440          max = std::max<QDateTime>( max, maxEnd );
 
  448  if ( dimensions.isEmpty() )
 
  458      for ( 
const auto &dimension : dimensions )
 
  463          extent = range( dimension );
 
  468          extent.
extend( range( dimension ) );
 
  471      json ret = json::array();
 
  472      const QString beginVal { extent.
begin().toString( Qt::DateFormat::ISODate ) };
 
  473      const QString endVal { extent.
end().toString( Qt::DateFormat::ISODate ) };
 
  475      if ( beginVal.isEmpty() && endVal.isEmpty() )
 
  477        ret.push_back( { 
nullptr, 
nullptr } );
 
  479      else if ( beginVal.isEmpty() )
 
  481        ret.push_back( { 
nullptr, endVal.toStdString() } );
 
  483      else if ( endVal.isEmpty() )
 
  485        ret.push_back( { beginVal.toStdString(), 
nullptr } );
 
  489        ret.push_back( { beginVal.toStdString(), endVal.toStdString() } );
 
  493    catch ( std::exception &ex )
 
  495      const QString errorMessage { QStringLiteral( 
"Error creating temporal extent: %1" ).arg( ex.what() ) };