⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qgspostgresprovider.cpp

📁 一个非常好的GIS开源新版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    return PQexecNR(connection, declare.toUtf8());  }  catch(PGFieldNotFound)  {    return false;  }}bool QgsPostgresProvider::getFeature(PGresult *queryResult, int row, bool fetchGeometry,                                     QgsFeature &feature,                                     const QgsAttributeList &fetchAttributes){    try  {    int oid = *(int *)PQgetvalue(queryResult, row, 0);    if (swapEndian)      oid = ntohl(oid); // convert oid to opposite endian    feature.setFeatureId(oid);    int col;  // first attribute column after geometry    if (fetchGeometry)    {      int returnedLength = PQgetlength(queryResult, row, 1);       if(returnedLength > 0)      {        unsigned char *featureGeom = new unsigned char[returnedLength + 1];        memset(featureGeom, '\0', returnedLength + 1);        memcpy(featureGeom, PQgetvalue(queryResult, row, 1), returnedLength);         feature.setGeometryAndOwnership(featureGeom, returnedLength + 1);      }      else      {        feature.setGeometryAndOwnership(0, 0);        QgsDebugMsg("Couldn't get the feature geometry in binary form");      }      col = 2;    }    else    {      col = 1;    }    // iterate attributes    for(QgsAttributeList::const_iterator it=fetchAttributes.constBegin(); it!=fetchAttributes.constEnd(); it++)    {      const QgsField &fld = field(*it);      if( fld.name() == primaryKey )      {        // primary key was already processed        feature.addAttribute(*it, QString::number(oid) );        continue;      }      if( !PQgetisnull(queryResult, row, col) )      {        QString val = QString::fromUtf8(PQgetvalue(queryResult, row, col));        switch (fld.type())        {        case QVariant::LongLong:          feature.addAttribute(*it, val.toLongLong());          break;        case QVariant::Int:          feature.addAttribute(*it, val.toInt());          break;        case QVariant::Double:          feature.addAttribute(*it, val.toDouble());          break;        case QVariant::String:          feature.addAttribute(*it, val);          break;        default:          QgsDebugMsg( QString("feature %1, field %2, value '%3': unexpected variant type %4 considered as NULL")                         .arg( oid )                         .arg( fld.name() )                         .arg( val )                         .arg( fld.type() ) );          feature.addAttribute(*it, QVariant(QString::null));        }      }      else      {        feature.addAttribute(*it, QVariant(QString::null));      }      col++;    }    return true;  }  catch(PGFieldNotFound)  {    return false;  }}void QgsPostgresProvider::select(QgsAttributeList fetchAttributes, QgsRect rect, bool fetchGeometry, bool useIntersect){  QString cursorName = QString("qgisf%1").arg(providerId);    if(mFetching)   {    PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8() );    mFetching=false;      while(!mFeatureQueue.empty())    {      mFeatureQueue.pop();    }  }  QString whereClause;  if(!rect.isEmpty())  {    if(useIntersect)    {       // Contributed by #qgis irc "creeping"      // This version actually invokes PostGIS's use of spatial indexes      whereClause = QString("%1 && setsrid('BOX3D(%2)'::box3d,%3) and intersects(%1,setsrid('BOX3D(%2)'::box3d,%3))")                      .arg( quotedIdentifier(geometryColumn) )                      .arg( rect.asWKTCoords() )                      .arg( srid );    }    else    {      whereClause = QString("%1 && setsrid('BOX3D(%2)'::box3d,%3)")                      .arg( quotedIdentifier(geometryColumn) )                      .arg( rect.asWKTCoords() )                      .arg( srid );    }  }  if( !sqlWhereClause.isEmpty() )  {    if (!whereClause.isEmpty())      whereClause += " and ";    whereClause += "(" + sqlWhereClause + ")";  }  mFetchGeom = fetchGeometry;  mAttributesToFetch = fetchAttributes;  if( !declareCursor( cursorName, fetchAttributes, fetchGeometry, whereClause ) )    return;    mFetching = true;}bool QgsPostgresProvider::getNextFeature(QgsFeature& feature){  QString cursorName = QString("qgisf%1").arg(providerId);  if (!valid)  {    QgsDebugMsg("Read attempt on an invalid postgresql data source");    return false;  }  if( mFeatureQueue.empty() )  {    QString fetch = QString("fetch forward %1 from %2").arg(mFeatureQueueSize).arg(cursorName);    if(PQsendQuery(connection, fetch.toUtf8()) == 0) //fetch features in asynchronously    {      qWarning("PQsendQuery failed (1)");    }    PGresult *queryResult;    while( (queryResult = PQgetResult(connection)) )    {      int rows = PQntuples(queryResult);      if (rows == 0)        continue;      for (int row = 0; row < rows; row++)      {        mFeatureQueue.push(QgsFeature());        getFeature(queryResult, row, mFetchGeom, mFeatureQueue.back(), mAttributesToFetch);      } // for each row in queue      PQclear(queryResult);    }  }  if( mFeatureQueue.empty() )  {    QgsDebugMsg("End of features");    return false;  }   // Now return the next feature from the queue  if(mFetchGeom)  {    QgsGeometry* featureGeom = mFeatureQueue.front().geometryAndOwnership();    feature.setGeometry(featureGeom);  }  else  {    feature.setGeometryAndOwnership(0, 0);  }  feature.setFeatureId(mFeatureQueue.front().featureId());  feature.setAttributeMap(mFeatureQueue.front().attributeMap());  mFeatureQueue.pop();  return true;}bool QgsPostgresProvider::getFeatureAtId(int featureId, QgsFeature& feature, bool fetchGeometry, QgsAttributeList fetchAttributes){  QString cursorName = QString("qgisfid%1").arg(providerId);  if( !declareCursor( cursorName, fetchAttributes, fetchGeometry, QString("%2=%3").arg(quotedIdentifier(primaryKey)).arg(featureId) ) )    return false;  PGresult *queryResult = PQexec(connection, QString("fetch forward 1 from %1").arg(cursorName).toUtf8());  if(queryResult==0)    return false;  int rows = PQntuples(queryResult);  if (rows == 0)  {    QgsDebugMsg("feature " + QString::number(featureId) + " not found");    PQclear(queryResult);    PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8());    return false;  }  else if(rows != 1)  {    QgsDebugMsg( QString("found %1 features instead of just one.").arg(rows) );  }  bool gotit = getFeature(queryResult, 0, fetchGeometry, feature, fetchAttributes);  PQclear(queryResult);  PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8());  return gotit;}QgsDataSourceURI& QgsPostgresProvider::getURI(){  return mUri;}void QgsPostgresProvider::setExtent( QgsRect& newExtent ){  layerExtent.setXmax( newExtent.xMax() );  layerExtent.setXmin( newExtent.xMin() );  layerExtent.setYmax( newExtent.yMax() );  layerExtent.setYmin( newExtent.yMin() );}// TODO - make this function return the real extent_QgsRect QgsPostgresProvider::extent(){  return layerExtent;      //extent_->MinX, extent_->MinY, extent_->MaxX, extent_->MaxY);}/**  * Return the feature type */QGis::WKBTYPE QgsPostgresProvider::geometryType() const{  return geomType;}/**  * Return the feature type */long QgsPostgresProvider::featureCount() const{  return numberFeatures;}const QgsField &QgsPostgresProvider::field(int index) const{  QgsFieldMap::const_iterator it = attributeFields.find(index);  if( it==attributeFields.constEnd() ) {    QgsDebugMsg("Field " + QString::number(index) + " not found.");    throw PGFieldNotFound();  }  return it.value();}/** * Return the number of fields */uint QgsPostgresProvider::fieldCount() const{  return attributeFields.size();}const QgsFieldMap & QgsPostgresProvider::fields() const{  return attributeFields;}QString QgsPostgresProvider::dataComment() const{  return mDataComment;}void QgsPostgresProvider::reset(){  if(mFetching)  {     //move cursor to first record    PQexecNR(connection, QString("move 0 in qgisf%1").arg(providerId).toUtf8());  }  mFeatureQueue.empty();  loadFields();}/** @todo XXX Perhaps this should be promoted to QgsDataProvider? */QString QgsPostgresProvider::endianString(){  switch ( QgsApplication::endian() )  {    case QgsApplication::NDR :       return QString("NDR");      break;    case QgsApplication::XDR :       return QString("XDR");      break;    default :      return QString("UNKNOWN");  }}void QgsPostgresProvider::loadFields(){  QgsDebugMsg("Loading fields for table " + mTableName);  // Get the relation oid for use in later queries  QString sql = QString("SELECT regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );  PGresult *tresult= PQexec(connection, sql.toUtf8());  QString tableoid = QString::fromUtf8(PQgetvalue(tresult, 0, 0));  PQclear(tresult);  // Get the table description  sql = QString("SELECT description FROM pg_description WHERE objoid=%1 AND objsubid=0").arg( tableoid );  tresult = PQexec(connection, sql.toUtf8());  if (PQntuples(tresult) > 0)    mDataComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));  PQclear(tresult);  // Populate the field vector for this layer. The field vector contains  // field name, type, length, and precision (if numeric)  sql = QString("select * from %1 limit 0").arg ( mSchemaTableName );  PGresult *result = PQexec(connection, sql.toUtf8());  //--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;  // The queries inside this loop could possibly be combined into one  // single query - this would make the code run faster.  attributeFields.clear();  for (int i = 0; i < PQnfields(result); i++)  {    QString fieldName = QString::fromUtf8(PQfname(result, i));    int fldtyp = PQftype(result, i);    QString typOid = QString().setNum(fldtyp);    int fieldModifier = PQfmod(result, i);    QString fieldComment("");    sql = QString("SELECT typname,typlen FROM pg_type WHERE oid=%1").arg(typOid);    // just oid; needs more work to support array type    //      "oid = (SELECT Distinct typelem FROM pg_type WHERE "	//needs DISTINCT to guard against 2 or more rows on int2    //      "typelem = " + typOid + " AND typlen = -1)";    PGresult* oidResult = PQexec(connection, sql.toUtf8());    QString fieldTypeName = QString::fromUtf8(PQgetvalue(oidResult, 0, 0));    QString fieldSize = QString::fromUtf8(PQgetvalue(oidResult, 0, 1));    PQclear(oidResult);    sql = QString("SELECT attnum FROM pg_attribute WHERE attrelid=%1 AND attname=%2")            .arg( tableoid ).arg( quotedValue(fieldName) );          PGresult *tresult = PQexec(connection, sql.toUtf8());    QString attnum = QString::fromUtf8(PQgetvalue(tresult, 0, 0));    PQclear(tresult);    sql = QString("SELECT description FROM pg_description WHERE objoid=%1 AND objsubid=%2")            .arg( tableoid ).arg( attnum );    tresult = PQexec(connection, sql.toUtf8());    if (PQntuples(tresult) > 0)      fieldComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));    PQclear(tresult);    if(fieldName!=geometryColumn)    {      QVariant::Type fieldType;      bool isArray = fieldTypeName.startsWith("_");       if(isArray)        fieldTypeName = fieldTypeName.mid(1);      if (fieldTypeName == "int8" )        fieldType = QVariant::LongLong;      else if (fieldTypeName.startsWith("int") || fieldTypeName=="serial" )        fieldType = QVariant::Int;      else if (fieldTypeName == "real" || fieldTypeName == "double precision" || fieldTypeName.startsWith("float") || fieldTypeName == "numeric" )        fieldType = QVariant::Double;      else if (fieldTypeName == "text" || 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -