147 QStringList conditions;
150 if ( dimensions.isEmpty() )
161 return QMetaType::Type::UnknownType;
168 auto refFieldCast = [ & ](
const QString &
fieldName, QMetaType::Type queryType, QMetaType::Type fieldType ) -> QString
171 const auto fieldRealType { fieldTypeFromName(
fieldName, layer ) };
172 if ( fieldRealType == QMetaType::Type::UnknownType )
179 if ( fieldRealType == QMetaType::Type::QString )
182 if ( fieldType != queryType || fieldType == QMetaType::Type::QDate )
189 .arg( queryType == QMetaType::Type::QDate ? QStringLiteral(
"to_date" ) : QStringLiteral(
"to_datetime" ) );
192 else if ( fieldType == queryType || fieldType == QMetaType::Type::QDate )
199 .arg( queryType == QMetaType::Type::QDate ? QStringLiteral(
"to_date" ) : QStringLiteral(
"to_datetime" ) );
204 auto quoteValue = [ ](
const QString & value ) -> QString
206 if ( value.length() == 10 )
217 auto makeFilter = [ "eValue ](
const QString & fieldBegin,
const QString & fieldEnd,
218 const QString & fieldBeginCasted,
const QString & fieldEndCasted,
219 const QString & queryBegin,
const QString & queryEnd ) -> QString
224 if ( ! queryBegin.isEmpty() && ! queryEnd.isEmpty() )
227 if ( ! fieldEndCasted.isEmpty() )
229 result = QStringLiteral(
"( %1 IS NULL OR %2 <= %6 ) AND ( %4 IS NULL OR %5 >= %3 )" )
232 quoteValue( queryBegin ),
235 quoteValue( queryEnd ) );
239 result = QStringLiteral(
"( %1 IS NULL OR ( %2 <= %3 AND %3 <= %4 ) )" )
241 quoteValue( queryBegin ),
243 quoteValue( queryEnd ) );
247 else if ( ! queryBegin.isEmpty() )
249 if ( ! fieldEndCasted.isEmpty() )
251 result = QStringLiteral(
"( %1 IS NULL OR %2 >= %3 )" ).arg( fieldEnd, fieldEndCasted, quoteValue( queryBegin ) );
255 result = QStringLiteral(
"( %1 IS NULL OR %2 >= %3 )" ).arg( fieldBegin, fieldBeginCasted, quoteValue( queryBegin ) );
260 result = QStringLiteral(
"( %1 IS NULL OR %2 <= %3 )" ).arg( fieldBegin, fieldBeginCasted, quoteValue( queryEnd ) );
266 QString testType { interval };
267 if ( interval.contains(
'/' ) )
269 const QStringList parts { interval.split(
'/' ) };
271 if ( testType.isEmpty() || testType == QLatin1String(
".." ) )
278 const bool inputQueryIsDateTime { testType.length() > 10 };
279 const QMetaType::Type queryType { inputQueryIsDateTime ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
282 if ( interval.contains(
'/' ) )
284 if ( ! inputQueryIsDateTime )
288 for (
const auto &dimension : std::as_const( dimensions ) )
292 const QMetaType::Type fieldType { dimension.name.toLower() == QLatin1String(
"time" ) ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
294 const auto fieldBeginCasted { refFieldCast( dimension.fieldName, queryType, fieldType ) };
295 if ( fieldBeginCasted.isEmpty() )
304 const auto fieldEndCasted { refFieldCast( dimension.endFieldName, queryType, fieldType ) };
305 if ( ! dateInterval.begin().isValid( ) && ! dateInterval.end().isValid( ) )
311 conditions.push_back( makeFilter( fieldBegin,
315 dateInterval.begin().toString( Qt::DateFormat::ISODate ),
316 dateInterval.end().toString( Qt::DateFormat::ISODate ) ) );
324 for (
const auto &dimension : std::as_const( dimensions ) )
328 const QMetaType::Type fieldType { dimension.name.toLower() == QLatin1String(
"time" ) ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
330 const auto fieldfBeginCasted { refFieldCast( dimension.fieldName, queryType, fieldType ) };
331 if ( fieldfBeginCasted.isEmpty() )
339 const auto fieldEndCasted { refFieldCast( dimension.endFieldName, queryType, fieldType ) };
340 if ( ! dateTimeInterval.begin().isValid( ) && ! dateTimeInterval.end().isValid( ) )
350 if ( fieldType == QMetaType::Type::QDate )
352 beginQuery = dateTimeInterval.begin().date().toString( Qt::DateFormat::ISODate );
353 endQuery = dateTimeInterval.end().date().toString( Qt::DateFormat::ISODate );
357 beginQuery = dateTimeInterval.begin().toString( Qt::DateFormat::ISODate );
358 endQuery = dateTimeInterval.end().toString( Qt::DateFormat::ISODate );
360 conditions.push_back( makeFilter( fieldBegin,
373 for (
const auto &dimension : std::as_const( dimensions ) )
376 const bool fieldIsDateTime { dimension.name.toLower() == QLatin1String(
"time" ) };
377 const QMetaType::Type fieldType { fieldIsDateTime ? QMetaType::Type::QDateTime : QMetaType::Type::QDate };
379 const auto fieldRefBegin { refFieldCast( dimension.fieldName, queryType, fieldType ) };
380 if ( fieldRefBegin.isEmpty() )
387 const auto fieldRefEnd { refFieldCast( dimension.endFieldName, queryType, fieldType ) };
394 if ( ! inputQueryIsDateTime || ! fieldIsDateTime )
396 QString castedInterval { interval };
398 if ( inputQueryIsDateTime )
400 castedInterval = QDate::fromString( castedInterval, Qt::DateFormat::ISODate ).toString( Qt::DateFormat::ISODate );
406 QString castedInterval { interval };
408 if ( ! inputQueryIsDateTime )
410 castedInterval = QDateTime::fromString( castedInterval, Qt::DateFormat::ISODate ).toString( Qt::DateFormat::ISODate );
415 if ( ! fieldRefEnd.isEmpty() )
417 condition = QStringLiteral(
"( %1 IS NULL OR %2 <= %3 ) AND ( %5 IS NULL OR %3 <= %4 )" ).arg(
426 condition = QStringLiteral(
"( %1 IS NULL OR %2 = %3 )" )
432 conditions.push_back( condition );
436 if ( ! conditions.isEmpty() )
438 expression.
setExpression( conditions.join( QLatin1String(
" AND " ) ) );
472 QDateTime min { minVal.toDateTime() };
473 QDateTime max { maxVal.toDateTime() };
474 if ( ! dimInfo.endFieldName.isEmpty() )
483 QDateTime minEnd { minVal.toDateTime() };
484 QDateTime maxEnd { maxVal.toDateTime() };
485 if ( minEnd.isValid() )
487 min = std::min<QDateTime>( min, minEnd );
489 if ( maxEnd.isValid() )
491 max = std::max<QDateTime>( max, maxEnd );
499 if ( dimensions.isEmpty() )
509 for (
const auto &dimension : dimensions )
514 extent = range( dimension );
519 extent.
extend( range( dimension ) );
522 json ret = json::array();
523 const QString beginVal { extent.
begin().toString( Qt::DateFormat::ISODate ) };
524 const QString endVal { extent.
end().toString( Qt::DateFormat::ISODate ) };
526 if ( beginVal.isEmpty() && endVal.isEmpty() )
528 ret.push_back( {
nullptr,
nullptr } );
530 else if ( beginVal.isEmpty() )
532 ret.push_back( {
nullptr, endVal.toStdString() } );
534 else if ( endVal.isEmpty() )
536 ret.push_back( { beginVal.toStdString(),
nullptr } );
540 ret.push_back( { beginVal.toStdString(), endVal.toStdString() } );
544 catch ( std::exception &ex )
546 const QString errorMessage { QStringLiteral(
"Error creating temporal extent: %1" ).arg( ex.what() ) };
The QgsServerApiContext class encapsulates the resources for a particular client request: the request...