[QGIS Commit] r10940 - in trunk/qgis/src: app providers/postgres
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Wed Jun 17 05:42:25 EDT 2009
Author: mhugent
Date: 2009-06-17 05:42:24 -0400 (Wed, 17 Jun 2009)
New Revision: 10940
Modified:
trunk/qgis/src/app/qgsattributedialog.cpp
trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
trunk/qgis/src/providers/postgres/qgspostgresprovider.h
Log:
Extended enum support in postgres provider to work also with domain check constrains (at the moment only for constrain types like VALUE in ('a', 'b', 'c'))
Modified: trunk/qgis/src/app/qgsattributedialog.cpp
===================================================================
--- trunk/qgis/src/app/qgsattributedialog.cpp 2009-06-17 09:09:59 UTC (rev 10939)
+++ trunk/qgis/src/app/qgsattributedialog.cpp 2009-06-17 09:42:24 UTC (rev 10940)
@@ -143,6 +143,11 @@
{
cb->addItem(*s_it);
}
+ int idx = cb->findText( myFieldValue.toString() );
+ if ( idx >= 0 )
+ {
+ cb->setCurrentIndex( idx );
+ }
myWidget = cb;
}
break;
Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp 2009-06-17 09:09:59 UTC (rev 10939)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp 2009-06-17 09:42:24 UTC (rev 10940)
@@ -1696,7 +1696,7 @@
return;
}
- //is type an enum or a domain type?
+ //is type an enum?
QString typeSql = QString("SELECT typtype FROM pg_type where typname = %1").arg(quotedValue(typeName));
Result typeRes = connectionRO->PQexec( typeSql );
if ( PQresultStatus( typeRes ) != PGRES_TUPLES_OK || PQntuples(typeRes) < 1)
@@ -1704,40 +1704,108 @@
return;
}
+
QString typtype = PQgetvalue( typeRes, 0, 0 );
if(typtype.compare("e", Qt::CaseInsensitive) == 0)
{
- //parse enum_range
- QString enumRangeSql = QString("SELECT enum_range(%1) from %2 limit1").arg(quotedIdentifier(f_it.value().name())).arg(mSchemaTableName);
- Result enumRangeRes = connectionRO->PQexec(enumRangeSql);
- if ( PQresultStatus( enumRangeRes ) != PGRES_TUPLES_OK || PQntuples(enumRangeRes) > 0)
+ //try to read enum_range of attribute
+ if(!parseEnumRange(enumList, f_it->name()))
{
- QString enumRangeString = PQgetvalue(enumRangeRes, 0, 0);
- //strip away the brackets at begin and end
- enumRangeString.chop(1);
- enumRangeString.remove(0, 1);
- QStringList rangeSplit = enumRangeString.split(",");
- QStringList::const_iterator range_it = rangeSplit.constBegin();
- for(; range_it != rangeSplit.constEnd(); ++range_it)
+ enumList.clear();
+ }
+ }
+ else
+ {
+ //is there a domain check constraint for the attribute?
+ if(!parseDomainCheckConstraint(enumList, f_it->name()))
+ {
+ enumList.clear();
+ }
+ }
+}
+
+bool QgsPostgresProvider::parseEnumRange(QStringList& enumValues, const QString& attributeName) const
+{
+ enumValues.clear();
+ QString enumRangeSql = QString("SELECT enum_range(%1) from %2 limit1").arg(quotedIdentifier(attributeName)).arg(mSchemaTableName);
+ Result enumRangeRes = connectionRO->PQexec(enumRangeSql);
+ if ( PQresultStatus( enumRangeRes ) == PGRES_TUPLES_OK && PQntuples(enumRangeRes) > 0)
+ {
+ QString enumRangeString = PQgetvalue(enumRangeRes, 0, 0);
+ //strip away the brackets at begin and end
+ enumRangeString.chop(1);
+ enumRangeString.remove(0, 1);
+ QStringList rangeSplit = enumRangeString.split(",");
+ QStringList::const_iterator range_it = rangeSplit.constBegin();
+ for(; range_it != rangeSplit.constEnd(); ++range_it)
+ {
+ QString currentEnumValue = *range_it;
+ //remove quotes from begin and end of the value
+ if(currentEnumValue.startsWith("'") || currentEnumValue.startsWith("\""))
{
- QString currentEnumValue = *range_it;
- //remove quotes from begin and end of the value
- if(currentEnumValue.startsWith("'") || currentEnumValue.startsWith("\""))
+ currentEnumValue.remove(0, 1);
+ }
+ if(currentEnumValue.endsWith("'") || currentEnumValue.endsWith("\""))
+ {
+ currentEnumValue.chop(1);
+ }
+ enumValues << currentEnumValue;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool QgsPostgresProvider::parseDomainCheckConstraint(QStringList& enumValues, const QString& attributeName) const
+{
+ enumValues.clear();
+
+ //is it a domain type with a check constraint?
+ QString domainSql = QString("SELECT domain_name from information_schema.columns where table_name = %1 and column_name = %2").arg(quotedValue(mTableName)).arg(quotedValue(attributeName));
+ Result domainResult = connectionRO->PQexec(domainSql);
+ if ( PQresultStatus( domainResult ) == PGRES_TUPLES_OK && PQntuples(domainResult) > 0)
+ {
+ //a domain type
+ QString domainCheckDefinitionSql = QString("SELECT consrc FROM pg_constraint where conname = (SELECT constraint_name FROM information_schema.domain_constraints WHERE domain_name = %1)").arg(quotedValue(PQgetvalue(domainResult, 0, 0)));
+ Result domainCheckRes = connectionRO->PQexec(domainCheckDefinitionSql);
+ if ( PQresultStatus(domainCheckRes) == PGRES_TUPLES_OK && PQntuples(domainCheckRes) > 0)
+ {
+ QString checkDefinition = PQgetvalue(domainCheckRes, 0, 0);
+
+ //we assume that the constraint is of the following form:
+ //(VALUE = ANY (ARRAY['a'::text, 'b'::text, 'c'::text, 'd'::text]))
+ //normally, postgresql creates that if the contstraint has been specified as 'VALUE in ('a', 'b', 'c', 'd')
+
+ //todo: ANY must occure before ARRAY
+ int anyPos = checkDefinition.indexOf("VALUE = ANY");
+ int arrayPosition = checkDefinition.lastIndexOf("ARRAY[");
+ int closingBracketPos = checkDefinition.indexOf("]", arrayPosition + 6);
+
+ if(anyPos == -1 || anyPos >= arrayPosition)
+ {
+ return false; //constraint has not the required format
+ }
+
+ if(arrayPosition != -1)
+ {
+ QString valueList = checkDefinition.mid(arrayPosition + 6, closingBracketPos);
+ QStringList commaSeparation = valueList.split(",", QString::SkipEmptyParts);
+ QStringList::const_iterator cIt = commaSeparation.constBegin();
+ for(; cIt != commaSeparation.constEnd(); ++cIt)
{
- currentEnumValue.remove(0, 1);
+ //get string between ''
+ int beginQuotePos = cIt->indexOf("'");
+ int endQuotePos = cIt->lastIndexOf("'");
+ if(beginQuotePos != -1 && (endQuotePos - beginQuotePos) > 1)
+ {
+ enumValues << cIt->mid(beginQuotePos + 1, endQuotePos - beginQuotePos - 1);
+ }
}
- if(currentEnumValue.endsWith("'") || currentEnumValue.endsWith("\""))
- {
- currentEnumValue.chop(1);
- }
- enumList << currentEnumValue;
}
+ return true;
}
}
- else if (typtype.compare("d", Qt::CaseInsensitive) == 0)
- {
- //a domain type. Todo: evaluate the check constraint
- }
+ return false;
}
// Returns the maximum value of an attribute
Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.h 2009-06-17 09:09:59 UTC (rev 10939)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.h 2009-06-17 09:42:24 UTC (rev 10940)
@@ -345,6 +345,19 @@
*/
void loadFields();
+ /**Parses the enum_range of an attribute and inserts the possible values into a stringlist
+ @param enumValues the stringlist where the values are appended
+ @param attributeName the name of the enum attribute
+ @return true in case of success and fals in case of error (e.g. if the type is not an enum type)*/
+ bool parseEnumRange(QStringList& enumValues, const QString& attributeName) const;
+
+ /** Parses the possible enum values of a domain type (given in the check constraint of the domain type)
+ @param enumValues Reference to list that receives enum values
+ @param attributeName Name of the domain type attribute
+ @return true in case of success and false in case of error (e.g. if the attribute is not a domain type or does not have a check constraint)
+ */
+ bool parseDomainCheckConstraint(QStringList& enumValues, const QString& attributeName) const;
+
bool mFetching; // true if a cursor was declared
std::vector < QgsFeature > features;
QgsFieldMap attributeFields;
More information about the QGIS-commit
mailing list