Skip to content

Commit c1669e2

Browse files
author
jef
committed
- add getUniqueValues method to QgsVectorDataProvider
- 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/qgis@8233 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent c9f4a71 commit c1669e2

File tree

9 files changed

+209
-36
lines changed

9 files changed

+209
-36
lines changed

python/core/qgsvectordataprovider.sip

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,15 @@ class QgsVectorDataProvider : QgsDataProvider
135135
*/
136136
virtual QVariant maxValue(int index);
137137

138+
/**
139+
* Return unique values of an attribute
140+
* @param index the index of the attribute
141+
* @param values reference to the list to fill
142+
*
143+
* Default implementation simply iterates the features
144+
*/
145+
virtual void getUniqueValues(int index, QStringList &uniqueValues);
146+
138147
/**
139148
* Adds a list of features
140149
* @return true in case of success and false in case of failure

src/app/qgsuniquevaluedialog.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -157,33 +157,26 @@ void QgsUniqueValueDialog::changeClassificationAttribute()
157157
QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider());
158158
if (provider)
159159
{
160-
QString value;
161-
QgsAttributeList attlist;
162-
163160
QgsSymbol* symbol;
164161
int nr = provider->indexFromFieldName(attributeName);
165162
if(nr == -1)
166163
{
167164
return;
168165
}
169-
attlist.append(nr);
170-
171-
provider->select(attlist, QgsRect(), false);
172-
QgsFeature feat;
173166

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

181-
if(mValues.find(value)==mValues.end())
170+
QStringList keys;
171+
provider->getUniqueValues(nr, keys);
172+
173+
QStringListIterator it(keys);
174+
while( it.hasNext() )
182175
{
176+
QString value = it.next();
183177
symbol=new QgsSymbol(mVectorLayer->vectorType(), value);
184178
mValues.insert(std::make_pair(value,symbol));
185179
}
186-
}
187180

188181
//set symbology for all QgsSiSyDialogs
189182
QColor thecolor;

src/core/qgsvectordataprovider.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,21 @@ QVariant QgsVectorDataProvider::maxValue(int index)
291291
return mCacheMaxValues[index];
292292
}
293293

294+
void QgsVectorDataProvider::getUniqueValues(int index, QStringList &values)
295+
{
296+
QgsFeature f;
297+
QgsAttributeList keys;
298+
keys.append(index);
299+
select(keys, QgsRect(), false);
300+
301+
QMap<QString,int> map;
302+
303+
while( getNextFeature(f) )
304+
map.insert( f.attributeMap()[index].toString(), 1);
305+
306+
values = map.keys();
307+
}
308+
294309
void QgsVectorDataProvider::fillMinMaxCache()
295310
{
296311
const QgsFieldMap& flds = fields();

src/core/qgsvectordataprovider.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
153153
* @param index the index of the attribute
154154
*
155155
* Default implementation walks all numeric attributes and caches minimal
156-
* and maximal values. If provider has facilities to retreive minimal
156+
* and maximal values. If provider has facilities to retrieve minimal
157157
* value directly, override this function.
158158
*/
159159
virtual QVariant minValue(int index);
@@ -163,11 +163,20 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
163163
* @param index the index of the attribute
164164
*
165165
* Default implementation walks all numeric attributes and caches minimal
166-
* and maximal values. If provider has facilities to retreive maximal
166+
* and maximal values. If provider has facilities to retrieve maximal
167167
* value directly, override this function.
168168
*/
169169
virtual QVariant maxValue(int index);
170170

171+
/**
172+
* Return unique values of an attribute
173+
* @param index the index of the attribute
174+
* @param values reference to the list to fill
175+
*
176+
* Default implementation simply iterates the features
177+
*/
178+
virtual void getUniqueValues(int index, QStringList &uniqueValues);
179+
171180
/**
172181
* Adds a list of features
173182
* @return true in case of success and false in case of failure

src/providers/grass/qgsgrassprovider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class GRASS_EXPORT QgsGrassProvider : public QgsVectorDataProvider
119119
/**
120120
* Returns the permanent storage type for this layer as a friendly name.
121121
*/
122-
QString storageType() const;
122+
virtual QString storageType() const;
123123

124124

125125
/** Select features based on a bounding rectangle. Features can be retrieved with calls to getNextFeature.

src/providers/ogr/qgsogrprovider.cpp

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ email : sherman at mrcc.com
3030

3131
#include <QtDebug>
3232
#include <QFile>
33+
#include <QDir>
3334
#include <QFileInfo>
3435
#include <QMap>
3536
#include <QString>
@@ -483,7 +484,6 @@ bool QgsOgrProvider::addFeature(QgsFeature& f)
483484
OGRFeatureH feature= OGR_F_Create(fdef);
484485
QGis::WKBTYPE ftype = f.geometry()->wkbType();
485486
unsigned char* wkb = f.geometry()->wkbBuffer();
486-
OGRErr err;
487487

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

902902

903903

904-
905-
906904
QGISEXTERN QString fileVectorFilters()
907905
{
908906
static QString myFileFilters;
@@ -1217,7 +1215,6 @@ QGISEXTERN bool createEmptyDataSource(const QString& uri,
12171215
return true;
12181216
}
12191217

1220-
12211218
QgsSpatialRefSys QgsOgrProvider::getSRS()
12221219
{
12231220
QgsDebugMsg("QgsOgrProvider::getSRS()");
@@ -1246,3 +1243,109 @@ QgsSpatialRefSys QgsOgrProvider::getSRS()
12461243

12471244
return srs;
12481245
}
1246+
1247+
void QgsOgrProvider::getUniqueValues(int index, QStringList &uniqueValues)
1248+
{
1249+
QgsField fld = mAttributeFields[index];
1250+
QFileInfo fi( dataSourceUri() );
1251+
if( !fi.exists() )
1252+
return;
1253+
1254+
QString sql = QString("SELECT DISTINCT %1 FROM %2 ORDER BY %1").arg( fld.name() ).arg( fi.baseName() );
1255+
1256+
uniqueValues.clear();
1257+
1258+
OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
1259+
if(l==0)
1260+
return;
1261+
1262+
OGRFeatureH f;
1263+
while( f=OGR_L_GetNextFeature(l) )
1264+
{
1265+
uniqueValues.append( mEncoding->toUnicode(OGR_F_GetFieldAsString(f, 0)) );
1266+
OGR_F_Destroy(f);
1267+
}
1268+
1269+
OGR_DS_ReleaseResultSet(l, ogrDataSource);
1270+
}
1271+
1272+
1273+
1274+
QVariant QgsOgrProvider::minValue(int index)
1275+
{
1276+
QgsField fld = mAttributeFields[index];
1277+
QFileInfo fi( dataSourceUri() );
1278+
if( !fi.exists() )
1279+
return QVariant();
1280+
1281+
QString sql = QString("SELECT MIN(%1) FROM %2").arg( fld.name() ).arg( fi.baseName() );
1282+
1283+
OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
1284+
1285+
if(l==0)
1286+
return QVariant();
1287+
1288+
OGRFeatureH f = OGR_L_GetNextFeature(l);
1289+
if(f==0)
1290+
{
1291+
OGR_DS_ReleaseResultSet(l, ogrDataSource);
1292+
return QVariant();
1293+
}
1294+
1295+
QString str = mEncoding->toUnicode( mEncoding->toUnicode( OGR_F_GetFieldAsString(f,0) ) );
1296+
OGR_F_Destroy(f);
1297+
1298+
QVariant value;
1299+
1300+
switch (fld.type())
1301+
{
1302+
case QVariant::String: value = QVariant(str); break;
1303+
case QVariant::Int: value = QVariant(str.toInt()); break;
1304+
case QVariant::Double: value = QVariant(str.toDouble()); break;
1305+
//case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break;
1306+
default: assert(NULL && "unsupported field type");
1307+
}
1308+
1309+
OGR_DS_ReleaseResultSet(l, ogrDataSource);
1310+
1311+
return value;
1312+
}
1313+
1314+
QVariant QgsOgrProvider::maxValue(int index)
1315+
{
1316+
QgsField fld = mAttributeFields[index];
1317+
QFileInfo fi( dataSourceUri() );
1318+
if( !fi.exists() )
1319+
return QVariant();
1320+
1321+
QString sql = QString("SELECT MAX(%1) FROM %2").arg( fld.name() ).arg( fi.baseName() );
1322+
1323+
OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
1324+
if(l==0)
1325+
return QVariant();
1326+
1327+
OGRFeatureH f = OGR_L_GetNextFeature(l);
1328+
if(f==0)
1329+
{
1330+
OGR_DS_ReleaseResultSet(l, ogrDataSource);
1331+
return QVariant();
1332+
}
1333+
1334+
QString str = mEncoding->toUnicode( mEncoding->toUnicode( OGR_F_GetFieldAsString(f,0) ) );
1335+
OGR_F_Destroy(f);
1336+
1337+
QVariant value;
1338+
1339+
switch (fld.type())
1340+
{
1341+
case QVariant::String: value = QVariant(str); break;
1342+
case QVariant::Int: value = QVariant(str.toInt()); break;
1343+
case QVariant::Double: value = QVariant(str.toDouble()); break;
1344+
//case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break;
1345+
default: assert(NULL && "unsupported field type");
1346+
}
1347+
1348+
OGR_DS_ReleaseResultSet(l, ogrDataSource);
1349+
1350+
return value;
1351+
}

src/providers/ogr/qgsogrprovider.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,18 @@ class QgsOgrProvider : public QgsVectorDataProvider
182182
*/
183183
bool isValid();
184184

185+
/** Returns the minimum value of an attribute
186+
* @param index the index of the attribute */
187+
QVariant minValue(int index);
188+
189+
/** Returns the maximum value of an attribute
190+
* @param index the index of the attribute */
191+
QVariant maxValue(int index);
192+
193+
/** Return the unique values of an attribute
194+
* @param index the index of the attribute
195+
* @param values reference to the list of unique values */
196+
virtual void getUniqueValues(int index, QStringList &uniqueValues);
185197

186198
protected:
187199
/** loads fields from input file to member attributeFields */

src/providers/postgres/qgspostgresprovider.cpp

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ void QgsPostgresProvider::disconnectDb()
334334
connection = 0;
335335
}
336336

337-
QString QgsPostgresProvider::storageType()
337+
QString QgsPostgresProvider::storageType() const
338338
{
339339
return "PostgreSQL database with PostGIS extension";
340340
}
@@ -1272,10 +1272,8 @@ bool QgsPostgresProvider::uniqueData(QString schemaName,
12721272

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

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

12801278
PQclear(unique);
12811279

@@ -1634,6 +1632,37 @@ QVariant QgsPostgresProvider::minValue(int index)
16341632
return minValue.toDouble();
16351633
}
16361634

1635+
// Returns the list of unique values of an attribute
1636+
void QgsPostgresProvider::getUniqueValues(int index, QStringList &uniqueValues)
1637+
{
1638+
// get the field name
1639+
QgsField fld = attributeFields[index];
1640+
QString sql;
1641+
if(sqlWhereClause.isEmpty())
1642+
{
1643+
sql = QString("select distinct %1 from %2 order by %1")
1644+
.arg(quotedIdentifier(fld.name()))
1645+
.arg(mSchemaTableName);
1646+
}
1647+
else
1648+
{
1649+
sql = QString("select distinct %1 from %2 where %3 order by %1")
1650+
.arg(quotedIdentifier(fld.name()))
1651+
.arg(mSchemaTableName)
1652+
.arg(sqlWhereClause);
1653+
}
1654+
1655+
uniqueValues.clear();
1656+
1657+
PGresult *res= PQexec(connection, sql.toUtf8());
1658+
if (PQresultStatus(res) == PGRES_TUPLES_OK)
1659+
{
1660+
for(int i=0; i<PQntuples(res); i++)
1661+
uniqueValues.append( QString::fromUtf8(PQgetvalue(res,i,0)) );
1662+
}
1663+
PQclear(res);
1664+
}
1665+
16371666
// Returns the maximum value of an attribute
16381667

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

1703-
QgsDebugMsg( QString("defaultValue for %1 is NULL: %2").arg(fieldId).arg( defaultValue.isNull() ) );
1732+
// QgsDebugMsg( QString("defaultValue for %1 is NULL: %2").arg(fieldId).arg( defaultValue.isNull() ) );
17041733

17051734
PQclear(result);
17061735

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

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

2580-
QString QgsPostgresProvider::quotedIdentifier( QString ident )
2609+
QString QgsPostgresProvider::quotedIdentifier( QString ident ) const
25812610
{
25822611
ident.replace('"', "\"\"");
25832612
return ident.prepend("\"").append("\"");
25842613
}
25852614

2586-
QString QgsPostgresProvider::quotedValue( QString value )
2615+
QString QgsPostgresProvider::quotedValue( QString value ) const
25872616
{
25882617
if( value.isNull() )
25892618
return "NULL";

0 commit comments

Comments
 (0)