QString QgsPostgresFeatureIterator::whereClauseRect()
{
  QgsRectangle rect = mRequest.filterRect();
  QString whereClause;
  if ( P->mSpatialColType == sctGeography )
  {
    rect = QgsRectangle( -180.0, -90.0, 180.0, 90.0 ).intersect( &rect );
    if ( !rect.isFinite() )
      whereClause = "false";
  }

  if ( whereClause.isEmpty() )
  {
    QString qBox;
    if ( P->mConnectionRO->majorVersion() < 2 )
    {
      qBox = QString( "setsrid('BOX3D(%1)'::box3d,%2)" )
             .arg( rect.asWktCoordinates() )
             .arg( P->mRequestedSrid.isEmpty() ? P->mDetectedSrid : P->mRequestedSrid );
    }
    else
    {
      qBox = QString( "st_makeenvelope(%1,%2,%3,%4,%5)" )
             .arg( rect.xMinimum(), 0, 'f', 16 )
             .arg( rect.yMinimum(), 0, 'f', 16 )
             .arg( rect.xMaximum(), 0, 'f', 16 )
             .arg( rect.yMaximum(), 0, 'f', 16 )
             .arg( P->mRequestedSrid.isEmpty() ? P->mDetectedSrid : P->mRequestedSrid );
    }

    whereClause = QString( "%1 && %2" )
                  .arg( P->quotedIdentifier( P->mGeometryColumn ) )
                  .arg( qBox );
    if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
    {
      whereClause += QString( " AND %1(%2%3,%4)" )
                     .arg( P->mConnectionRO->majorVersion() < 2 ? "intersects" : "st_intersects" )
                     .arg( P->quotedIdentifier( P->mGeometryColumn ) )
                     .arg( P->mSpatialColType == sctGeography ? "::geometry" : "" )
                     .arg( qBox );
    }
  }

  if ( !P->mRequestedSrid.isEmpty() && P->mRequestedSrid != P->mDetectedSrid )
  {
    whereClause += QString( " AND %1(%2%3)=%4" )
                   .arg( P->mConnectionRO->majorVersion() < 2 ? "srid" : "st_srid" )
                   .arg( P->quotedIdentifier( P->mGeometryColumn ) )
                   .arg( P->mSpatialColType == sctGeography ? "::geography" : "" )
                   .arg( P->mRequestedSrid );
  }

  if ( P->mRequestedGeomType != QGis::WKBUnknown && P->mRequestedGeomType != P->mDetectedGeomType )
  {
    whereClause += QString( " AND %1" ).arg( QgsPostgresConn::postgisTypeFilter( P->mGeometryColumn, P->mRequestedGeomType, P->mSpatialColType == sctGeography ) );
  }

  return whereClause;
}
QString QgsPostgresFeatureIterator::whereClauseRect()
{
  QgsRectangle rect = mRequest.filterRect();
  if ( mSource->mSpatialColType == sctGeography )
  {
    rect = QgsRectangle( -180.0, -90.0, 180.0, 90.0 ).intersect( &rect );
  }

  if ( !rect.isFinite() )
  {
    QgsMessageLog::logMessage( QObject::tr( "Infinite filter rectangle specified" ), QObject::tr( "PostGIS" ) );
    return "false";
  }

  QString qBox;
  if ( mConn->majorVersion() < 2 )
  {
    qBox = QString( "setsrid('BOX3D(%1)'::box3d,%2)" )
           .arg( rect.asWktCoordinates() )
           .arg( mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid );
  }
  else
  {
    qBox = QString( "st_makeenvelope(%1,%2,%3,%4,%5)" )
           .arg( qgsDoubleToString( rect.xMinimum() ) )
           .arg( qgsDoubleToString( rect.yMinimum() ) )
           .arg( qgsDoubleToString( rect.xMaximum() ) )
           .arg( qgsDoubleToString( rect.yMaximum() ) )
           .arg( mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid );
  }

  QString whereClause = QString( "%1 && %2" )
                        .arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ) )
                        .arg( qBox );
  if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
  {
    whereClause += QString( " AND %1(%2%3,%4)" )
                   .arg( mConn->majorVersion() < 2 ? "intersects" : "st_intersects" )
                   .arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ) )
                   .arg( mSource->mSpatialColType == sctGeography ? "::geometry" : "" )
                   .arg( qBox );
  }

  if ( !mSource->mRequestedSrid.isEmpty() && ( mSource->mRequestedSrid != mSource->mDetectedSrid || mSource->mRequestedSrid.toInt() == 0 ) )
  {
    whereClause += QString( " AND %1(%2%3)=%4" )
                   .arg( mConn->majorVersion() < 2 ? "srid" : "st_srid" )
                   .arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ) )
                   .arg( mSource->mSpatialColType == sctGeography ? "::geography" : "" )
                   .arg( mSource->mRequestedSrid );
  }

  if ( mSource->mRequestedGeomType != QGis::WKBUnknown && mSource->mRequestedGeomType != mSource->mDetectedGeomType )
  {
    whereClause += QString( " AND %1" ).arg( QgsPostgresConn::postgisTypeFilter( mSource->mGeometryColumn, mSource->mRequestedGeomType, mSource->mSpatialColType == sctGeography ) );
  }

  return whereClause;
}
QString QgsPostgresFeatureIterator::whereClauseRect()
{
    QgsRectangle rect = mRequest.filterRect();
    if ( mSource->mSpatialColType == sctGeography )
    {
        rect = QgsRectangle( -180.0, -90.0, 180.0, 90.0 ).intersect( &rect );
    }

    if ( !rect.isFinite() )
    {
        QgsMessageLog::logMessage( QObject::tr( "Infinite filter rectangle specified" ), QObject::tr( "PostGIS" ) );
        return "false";
    }

    QString qBox;
    if ( mConn->majorVersion() < 2 )
    {
        qBox = QString( "setsrid('BOX3D(%1)'::box3d,%2)" )
               .arg( rect.asWktCoordinates(),
                     mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid );
    }
    else
    {
        qBox = QString( "st_makeenvelope(%1,%2,%3,%4,%5)" )
               .arg( qgsDoubleToString( rect.xMinimum() ),
                     qgsDoubleToString( rect.yMinimum() ),
                     qgsDoubleToString( rect.xMaximum() ),
                     qgsDoubleToString( rect.yMaximum() ),
                     mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid );
    }

    bool castToGeometry = mSource->mSpatialColType == sctGeography ||
                          mSource->mSpatialColType == sctPcPatch;

    QString whereClause = QString( "%1%2 && %3" )
                          .arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ),
                                castToGeometry ? "::geometry" : "",
                                qBox );

    if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
    {
        QString curveToLineFn; // in postgis < 1.5 the st_curvetoline function does not exist
        if ( mConn->majorVersion() >= 2 || ( mConn->majorVersion() == 1 && mConn->minorVersion() >= 5 ) )
            curveToLineFn = "st_curvetoline"; // st_ prefix is always used
        whereClause += QString( " AND %1(%2(%3%4),%5)" )
                       .arg( mConn->majorVersion() < 2 ? "intersects" : "st_intersects",
                             curveToLineFn,
                             QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ),
                             castToGeometry ? "::geometry" : "",
                             qBox );
    }

    if ( !mSource->mRequestedSrid.isEmpty() && ( mSource->mRequestedSrid != mSource->mDetectedSrid || mSource->mRequestedSrid.toInt() == 0 ) )
    {
        whereClause += QString( " AND %1(%2%3)=%4" )
                       .arg( mConn->majorVersion() < 2 ? "srid" : "st_srid",
                             QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ),
                             castToGeometry ? "::geometry" : "",
                             mSource->mRequestedSrid );
    }

    if ( mSource->mRequestedGeomType != QGis::WKBUnknown && mSource->mRequestedGeomType != mSource->mDetectedGeomType )
    {
        whereClause += QString( " AND %1" ).arg( QgsPostgresConn::postgisTypeFilter( mSource->mGeometryColumn, ( QgsWKBTypes::Type )mSource->mRequestedGeomType, castToGeometry ) );
    }

    return whereClause;
}