QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
    , mFeatureQueueSize( sFeatureQueueSize )
{
  mConn = QgsPostgresConnPool::instance()->acquireConnection( mSource->mConnInfo );

  if ( !mConn )
  {
    mClosed = true;
    iteratorClosed();
    return;
  }

  mCursorName = mConn->uniqueCursorName();
  QString whereClause;

  if ( request.filterType() == QgsFeatureRequest::FilterRect && !mSource->mGeometryColumn.isNull() )
  {
    whereClause = whereClauseRect();
  }
  else if ( request.filterType() == QgsFeatureRequest::FilterFid )
  {
    whereClause = QgsPostgresUtils::whereClause( mRequest.filterFid(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
  }
  else if ( request.filterType() == QgsFeatureRequest::FilterFids )
  {
    whereClause = QgsPostgresUtils::whereClause( mRequest.filterFids(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
  }

  if ( !mSource->mSqlWhereClause.isEmpty() )
  {
    if ( !whereClause.isEmpty() )
      whereClause += " AND ";

    whereClause += "(" + mSource->mSqlWhereClause + ")";
  }

  if ( !declareCursor( whereClause ) )
  {
    mClosed = true;
    iteratorClosed();
    return;
  }

  mFetched = 0;
}
QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresProvider* p, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIterator( request ), P( p )
    , mFeatureQueueSize( sFeatureQueueSize )
{
  // make sure that only one iterator is active
  if ( P->mActiveIterator )
  {
    QgsMessageLog::logMessage( QObject::tr( "Already active iterator on this provider was closed." ), QObject::tr( "PostgreSQL" ) );
    P->mActiveIterator->close();
  }

  mCursorName = QString( "qgisf%1" ).arg( P->mProviderId );

  QString whereClause;

  if ( request.filterType() == QgsFeatureRequest::FilterRect && !P->mGeometryColumn.isNull() )
  {
    whereClause = whereClauseRect();
  }
  else if ( request.filterType() == QgsFeatureRequest::FilterFid )
  {
    whereClause = P->whereClause( request.filterFid() );
  }

  if ( !P->mSqlWhereClause.isEmpty() )
  {
    if ( !whereClause.isEmpty() )
      whereClause += " AND ";

    whereClause += "(" + P->mSqlWhereClause + ")";
  }

  if ( !declareCursor( whereClause ) )
  {
    mClosed = true;
    return;
  }

  P->mActiveIterator = this;

  mFetched = 0;
}
QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresProvider* p, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIterator( request ), P( p )
    , mFeatureQueueSize( sFeatureQueueSize )
{
    mCursorName = QString( "qgisf%1_%2" ).arg( P->mProviderId ).arg( P->mIteratorCounter++ );

    P->mActiveIterators << this;

    QString whereClause;

    if ( request.filterType() == QgsFeatureRequest::FilterRect && !P->mGeometryColumn.isNull() )
    {
        whereClause = whereClauseRect();
    }
    else if ( request.filterType() == QgsFeatureRequest::FilterFid )
    {
        whereClause = P->whereClause( request.filterFid() );
    }
    else if ( request.filterType() == QgsFeatureRequest::FilterFids )
    {
        whereClause = P->whereClause( request.filterFids() );
    }

    if ( !P->mSqlWhereClause.isEmpty() )
    {
        if ( !whereClause.isEmpty() )
            whereClause += " AND ";

        whereClause += "(" + P->mSqlWhereClause + ")";
    }

    if ( !declareCursor( whereClause ) )
    {
        mClosed = true;
        return;
    }

    mFetched = 0;
}
QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIteratorFromSource<QgsPostgresFeatureSource>( source, ownSource, request )
    , mFeatureQueueSize( sFeatureQueueSize )
    , mFetched( 0 )
    , mFetchGeometry( false )
    , mExpressionCompiled( false )
    , mLastFetch( false )
{
    if ( !source->mTransactionConnection )
    {
        mConn = QgsPostgresConnPool::instance()->acquireConnection( mSource->mConnInfo );
        mIsTransactionConnection = false;
    }
    else
    {
        mConn = source->mTransactionConnection;
        mConn->lock();
        mIsTransactionConnection = true;
    }

    if ( !mConn )
    {
        mClosed = true;
        iteratorClosed();
        return;
    }

    mCursorName = mConn->uniqueCursorName();
    QString whereClause;

    if ( !request.filterRect().isNull() && !mSource->mGeometryColumn.isNull() )
    {
        whereClause = whereClauseRect();
    }

    if ( request.filterType() == QgsFeatureRequest::FilterFid )
    {
        QString fidWhereClause = QgsPostgresUtils::whereClause( mRequest.filterFid(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );

        whereClause = QgsPostgresUtils::andWhereClauses( whereClause, fidWhereClause );
    }
    else if ( request.filterType() == QgsFeatureRequest::FilterFids )
    {
        QString fidsWhereClause = QgsPostgresUtils::whereClause( mRequest.filterFids(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );

        whereClause = QgsPostgresUtils::andWhereClauses( whereClause, fidsWhereClause );
    }
    else if ( request.filterType() == QgsFeatureRequest::FilterExpression
              && QSettings().value( "/qgis/compileExpressions", true ).toBool() )
    {
        QgsPostgresExpressionCompiler compiler = QgsPostgresExpressionCompiler( source );

        if ( compiler.compile( request.filterExpression() ) == QgsSqlExpressionCompiler::Complete )
        {
            whereClause = QgsPostgresUtils::andWhereClauses( whereClause, compiler.result() );
            mExpressionCompiled = true;
        }
    }

    if ( !mSource->mSqlWhereClause.isEmpty() )
    {
        if ( !whereClause.isEmpty() )
            whereClause += " AND ";

        whereClause += '(' + mSource->mSqlWhereClause + ')';
    }

    if ( !declareCursor( whereClause ) )
    {
        mClosed = true;
        iteratorClosed();
        return;
    }

    mFetched = 0;
}