Skip to content

Commit

Permalink
- add getUniqueValues method to QgsVectorDataProvider
Browse files Browse the repository at this point in the history
 - implement getUniqueValues in QgsPostgresProvider (fixes #399)
 - implement getUniqueValues, minValue and maxValue in OgsOgrProvider
 - use getUniqueValues in QgsUniqueValueDialog
- update QgsPostgresProvider::storageType interface (fixes #995)
  (applied patch from Steven Mizuno, thanks again)


git-svn-id: http://svn.osgeo.org/qgis/trunk@8233 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
jef committed Mar 16, 2008
1 parent 95c8c42 commit d846010
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 36 deletions.
9 changes: 9 additions & 0 deletions python/core/qgsvectordataprovider.sip
Expand Up @@ -135,6 +135,15 @@ class QgsVectorDataProvider : QgsDataProvider
*/
virtual QVariant maxValue(int index);

/**
* Return unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list to fill
*
* Default implementation simply iterates the features
*/
virtual void getUniqueValues(int index, QStringList &uniqueValues);

/**
* Adds a list of features
* @return true in case of success and false in case of failure
Expand Down
19 changes: 6 additions & 13 deletions src/app/qgsuniquevaluedialog.cpp
Expand Up @@ -157,33 +157,26 @@ void QgsUniqueValueDialog::changeClassificationAttribute()
QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider());
if (provider)
{
QString value;
QgsAttributeList attlist;

QgsSymbol* symbol;
int nr = provider->indexFromFieldName(attributeName);
if(nr == -1)
{
return;
}
attlist.append(nr);

provider->select(attlist, QgsRect(), false);
QgsFeature feat;

//go through all the features and insert their value into the map and into mClassListWidget
mClassListWidget->clear();
while(provider->getNextFeature(feat))
{
const QgsAttributeMap& attrs = feat.attributeMap();
value = attrs[nr].toString();

if(mValues.find(value)==mValues.end())
QStringList keys;
provider->getUniqueValues(nr, keys);

QStringListIterator it(keys);
while( it.hasNext() )
{
QString value = it.next();
symbol=new QgsSymbol(mVectorLayer->vectorType(), value);
mValues.insert(std::make_pair(value,symbol));
}
}

//set symbology for all QgsSiSyDialogs
QColor thecolor;
Expand Down
15 changes: 15 additions & 0 deletions src/core/qgsvectordataprovider.cpp
Expand Up @@ -291,6 +291,21 @@ QVariant QgsVectorDataProvider::maxValue(int index)
return mCacheMaxValues[index];
}

void QgsVectorDataProvider::getUniqueValues(int index, QStringList &values)
{
QgsFeature f;
QgsAttributeList keys;
keys.append(index);
select(keys, QgsRect(), false);

QMap<QString,int> map;

while( getNextFeature(f) )
map.insert( f.attributeMap()[index].toString(), 1);

values = map.keys();
}

void QgsVectorDataProvider::fillMinMaxCache()
{
const QgsFieldMap& flds = fields();
Expand Down
13 changes: 11 additions & 2 deletions src/core/qgsvectordataprovider.h
Expand Up @@ -153,7 +153,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
* @param index the index of the attribute
*
* Default implementation walks all numeric attributes and caches minimal
* and maximal values. If provider has facilities to retreive minimal
* and maximal values. If provider has facilities to retrieve minimal
* value directly, override this function.
*/
virtual QVariant minValue(int index);
Expand All @@ -163,11 +163,20 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
* @param index the index of the attribute
*
* Default implementation walks all numeric attributes and caches minimal
* and maximal values. If provider has facilities to retreive maximal
* and maximal values. If provider has facilities to retrieve maximal
* value directly, override this function.
*/
virtual QVariant maxValue(int index);

/**
* Return unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list to fill
*
* Default implementation simply iterates the features
*/
virtual void getUniqueValues(int index, QStringList &uniqueValues);

/**
* Adds a list of features
* @return true in case of success and false in case of failure
Expand Down
2 changes: 1 addition & 1 deletion src/providers/grass/qgsgrassprovider.h
Expand Up @@ -119,7 +119,7 @@ class GRASS_EXPORT QgsGrassProvider : public QgsVectorDataProvider
/**
* Returns the permanent storage type for this layer as a friendly name.
*/
QString storageType() const;
virtual QString storageType() const;


/** Select features based on a bounding rectangle. Features can be retrieved with calls to getNextFeature.
Expand Down
111 changes: 107 additions & 4 deletions src/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -30,6 +30,7 @@ email : sherman at mrcc.com

#include <QtDebug>
#include <QFile>
#include <QDir>
#include <QFileInfo>
#include <QMap>
#include <QString>
Expand Down Expand Up @@ -483,7 +484,6 @@ bool QgsOgrProvider::addFeature(QgsFeature& f)
OGRFeatureH feature= OGR_F_Create(fdef);
QGis::WKBTYPE ftype = f.geometry()->wkbType();
unsigned char* wkb = f.geometry()->wkbBuffer();
OGRErr err;

if( f.geometry()->wkbSize() > 0 )
{
Expand Down Expand Up @@ -901,8 +901,6 @@ static QString createFileFilter_(QString const &longName, QString const &glob)





QGISEXTERN QString fileVectorFilters()
{
static QString myFileFilters;
Expand Down Expand Up @@ -1217,7 +1215,6 @@ QGISEXTERN bool createEmptyDataSource(const QString& uri,
return true;
}


QgsSpatialRefSys QgsOgrProvider::getSRS()
{
QgsDebugMsg("QgsOgrProvider::getSRS()");
Expand Down Expand Up @@ -1246,3 +1243,109 @@ QgsSpatialRefSys QgsOgrProvider::getSRS()

return srs;
}

void QgsOgrProvider::getUniqueValues(int index, QStringList &uniqueValues)
{
QgsField fld = mAttributeFields[index];
QFileInfo fi( dataSourceUri() );
if( !fi.exists() )
return;

QString sql = QString("SELECT DISTINCT %1 FROM %2 ORDER BY %1").arg( fld.name() ).arg( fi.baseName() );

uniqueValues.clear();

OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
if(l==0)
return;

OGRFeatureH f;
while( f=OGR_L_GetNextFeature(l) )
{
uniqueValues.append( mEncoding->toUnicode(OGR_F_GetFieldAsString(f, 0)) );
OGR_F_Destroy(f);
}

OGR_DS_ReleaseResultSet(l, ogrDataSource);
}



QVariant QgsOgrProvider::minValue(int index)
{
QgsField fld = mAttributeFields[index];
QFileInfo fi( dataSourceUri() );
if( !fi.exists() )
return QVariant();

QString sql = QString("SELECT MIN(%1) FROM %2").arg( fld.name() ).arg( fi.baseName() );

OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");

if(l==0)
return QVariant();

OGRFeatureH f = OGR_L_GetNextFeature(l);
if(f==0)
{
OGR_DS_ReleaseResultSet(l, ogrDataSource);
return QVariant();
}

QString str = mEncoding->toUnicode( mEncoding->toUnicode( OGR_F_GetFieldAsString(f,0) ) );
OGR_F_Destroy(f);

QVariant value;

switch (fld.type())
{
case QVariant::String: value = QVariant(str); break;
case QVariant::Int: value = QVariant(str.toInt()); break;
case QVariant::Double: value = QVariant(str.toDouble()); break;
//case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break;
default: assert(NULL && "unsupported field type");
}

OGR_DS_ReleaseResultSet(l, ogrDataSource);

return value;
}

QVariant QgsOgrProvider::maxValue(int index)
{
QgsField fld = mAttributeFields[index];
QFileInfo fi( dataSourceUri() );
if( !fi.exists() )
return QVariant();

QString sql = QString("SELECT MAX(%1) FROM %2").arg( fld.name() ).arg( fi.baseName() );

OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
if(l==0)
return QVariant();

OGRFeatureH f = OGR_L_GetNextFeature(l);
if(f==0)
{
OGR_DS_ReleaseResultSet(l, ogrDataSource);
return QVariant();
}

QString str = mEncoding->toUnicode( mEncoding->toUnicode( OGR_F_GetFieldAsString(f,0) ) );
OGR_F_Destroy(f);

QVariant value;

switch (fld.type())
{
case QVariant::String: value = QVariant(str); break;
case QVariant::Int: value = QVariant(str.toInt()); break;
case QVariant::Double: value = QVariant(str.toDouble()); break;
//case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break;
default: assert(NULL && "unsupported field type");
}

OGR_DS_ReleaseResultSet(l, ogrDataSource);

return value;
}
12 changes: 12 additions & 0 deletions src/providers/ogr/qgsogrprovider.h
Expand Up @@ -182,6 +182,18 @@ class QgsOgrProvider : public QgsVectorDataProvider
*/
bool isValid();

/** Returns the minimum value of an attribute
* @param index the index of the attribute */
QVariant minValue(int index);

/** Returns the maximum value of an attribute
* @param index the index of the attribute */
QVariant maxValue(int index);

/** Return the unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list of unique values */
virtual void getUniqueValues(int index, QStringList &uniqueValues);

protected:
/** loads fields from input file to member attributeFields */
Expand Down
47 changes: 38 additions & 9 deletions src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -334,7 +334,7 @@ void QgsPostgresProvider::disconnectDb()
connection = 0;
}

QString QgsPostgresProvider::storageType()
QString QgsPostgresProvider::storageType() const
{
return "PostgreSQL database with PostGIS extension";
}
Expand Down Expand Up @@ -1272,10 +1272,8 @@ bool QgsPostgresProvider::uniqueData(QString schemaName,

PGresult* unique = PQexec(connection, sql.toUtf8());

if (PQntuples(unique) == 1)
// if (strncmp(PQgetvalue(unique, 0, 0),"t", 1) == 0)
if (QString::fromUtf8(PQgetvalue(unique, 0, 0)).compare("t") == 0) //really should compare just first character as original did
isUnique = true;
if (PQntuples(unique)==1 && QString::fromUtf8(PQgetvalue(unique, 0, 0)).startsWith("t") == 0)
isUnique = true;

PQclear(unique);

Expand Down Expand Up @@ -1634,6 +1632,37 @@ QVariant QgsPostgresProvider::minValue(int index)
return minValue.toDouble();
}

// Returns the list of unique values of an attribute
void QgsPostgresProvider::getUniqueValues(int index, QStringList &uniqueValues)
{
// get the field name
QgsField fld = attributeFields[index];
QString sql;
if(sqlWhereClause.isEmpty())
{
sql = QString("select distinct %1 from %2 order by %1")
.arg(quotedIdentifier(fld.name()))
.arg(mSchemaTableName);
}
else
{
sql = QString("select distinct %1 from %2 where %3 order by %1")
.arg(quotedIdentifier(fld.name()))
.arg(mSchemaTableName)
.arg(sqlWhereClause);
}

uniqueValues.clear();

PGresult *res= PQexec(connection, sql.toUtf8());
if (PQresultStatus(res) == PGRES_TUPLES_OK)
{
for(int i=0; i<PQntuples(res); i++)
uniqueValues.append( QString::fromUtf8(PQgetvalue(res,i,0)) );
}
PQclear(res);
}

// Returns the maximum value of an attribute

QVariant QgsPostgresProvider::maxValue(int index)
Expand Down Expand Up @@ -1700,7 +1729,7 @@ QVariant QgsPostgresProvider::getDefaultValue(int fieldId)
if (PQntuples(result)==1 && !PQgetisnull(result, 0, 0) )
defaultValue = QString::fromUtf8(PQgetvalue(result, 0, 0));

QgsDebugMsg( QString("defaultValue for %1 is NULL: %2").arg(fieldId).arg( defaultValue.isNull() ) );
// QgsDebugMsg( QString("defaultValue for %1 is NULL: %2").arg(fieldId).arg( defaultValue.isNull() ) );

PQclear(result);

Expand Down Expand Up @@ -2391,7 +2420,7 @@ bool QgsPostgresProvider::deduceEndian()
// version 7.4, binary cursors return data in XDR whereas previous versions
// return data in the endian of the server

QString firstOid = "select regclass('" + mSchemaTableName + "')::oid";
QString firstOid = "select regclass(" + quotedValue(mSchemaTableName) + ")::oid";
PGresult * oidResult = PQexec(connection, firstOid.toUtf8());
// get the int value from a "normal" select
QString oidValue = QString::fromUtf8(PQgetvalue(oidResult,0,0));
Expand Down Expand Up @@ -2577,13 +2606,13 @@ PGresult* QgsPostgresProvider::executeDbCommand(PGconn* connection,
return result;
}

QString QgsPostgresProvider::quotedIdentifier( QString ident )
QString QgsPostgresProvider::quotedIdentifier( QString ident ) const
{
ident.replace('"', "\"\"");
return ident.prepend("\"").append("\"");
}

QString QgsPostgresProvider::quotedValue( QString value )
QString QgsPostgresProvider::quotedValue( QString value ) const
{
if( value.isNull() )
return "NULL";
Expand Down

0 comments on commit d846010

Please sign in to comment.