Skip to content

Commit 8a5581a

Browse files
author
mhugent
committed
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'))
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@10940 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 380173a commit 8a5581a

File tree

3 files changed

+112
-26
lines changed

3 files changed

+112
-26
lines changed

src/app/qgsattributedialog.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeat
143143
{
144144
cb->addItem(*s_it);
145145
}
146+
int idx = cb->findText( myFieldValue.toString() );
147+
if ( idx >= 0 )
148+
{
149+
cb->setCurrentIndex( idx );
150+
}
146151
myWidget = cb;
147152
}
148153
break;

src/providers/postgres/qgspostgresprovider.cpp

+94-26
Original file line numberDiff line numberDiff line change
@@ -1696,48 +1696,116 @@ void QgsPostgresProvider::enumValues( int index, QStringList& enumList )
16961696
return;
16971697
}
16981698

1699-
//is type an enum or a domain type?
1699+
//is type an enum?
17001700
QString typeSql = QString("SELECT typtype FROM pg_type where typname = %1").arg(quotedValue(typeName));
17011701
Result typeRes = connectionRO->PQexec( typeSql );
17021702
if ( PQresultStatus( typeRes ) != PGRES_TUPLES_OK || PQntuples(typeRes) < 1)
17031703
{
17041704
return;
17051705
}
17061706

1707+
17071708
QString typtype = PQgetvalue( typeRes, 0, 0 );
17081709
if(typtype.compare("e", Qt::CaseInsensitive) == 0)
17091710
{
1710-
//parse enum_range
1711-
QString enumRangeSql = QString("SELECT enum_range(%1) from %2 limit1").arg(quotedIdentifier(f_it.value().name())).arg(mSchemaTableName);
1712-
Result enumRangeRes = connectionRO->PQexec(enumRangeSql);
1713-
if ( PQresultStatus( enumRangeRes ) != PGRES_TUPLES_OK || PQntuples(enumRangeRes) > 0)
1714-
{
1715-
QString enumRangeString = PQgetvalue(enumRangeRes, 0, 0);
1716-
//strip away the brackets at begin and end
1717-
enumRangeString.chop(1);
1718-
enumRangeString.remove(0, 1);
1719-
QStringList rangeSplit = enumRangeString.split(",");
1720-
QStringList::const_iterator range_it = rangeSplit.constBegin();
1721-
for(; range_it != rangeSplit.constEnd(); ++range_it)
1711+
//try to read enum_range of attribute
1712+
if(!parseEnumRange(enumList, f_it->name()))
1713+
{
1714+
enumList.clear();
1715+
}
1716+
}
1717+
else
1718+
{
1719+
//is there a domain check constraint for the attribute?
1720+
if(!parseDomainCheckConstraint(enumList, f_it->name()))
1721+
{
1722+
enumList.clear();
1723+
}
1724+
}
1725+
}
1726+
1727+
bool QgsPostgresProvider::parseEnumRange(QStringList& enumValues, const QString& attributeName) const
1728+
{
1729+
enumValues.clear();
1730+
QString enumRangeSql = QString("SELECT enum_range(%1) from %2 limit1").arg(quotedIdentifier(attributeName)).arg(mSchemaTableName);
1731+
Result enumRangeRes = connectionRO->PQexec(enumRangeSql);
1732+
if ( PQresultStatus( enumRangeRes ) == PGRES_TUPLES_OK && PQntuples(enumRangeRes) > 0)
1733+
{
1734+
QString enumRangeString = PQgetvalue(enumRangeRes, 0, 0);
1735+
//strip away the brackets at begin and end
1736+
enumRangeString.chop(1);
1737+
enumRangeString.remove(0, 1);
1738+
QStringList rangeSplit = enumRangeString.split(",");
1739+
QStringList::const_iterator range_it = rangeSplit.constBegin();
1740+
for(; range_it != rangeSplit.constEnd(); ++range_it)
1741+
{
1742+
QString currentEnumValue = *range_it;
1743+
//remove quotes from begin and end of the value
1744+
if(currentEnumValue.startsWith("'") || currentEnumValue.startsWith("\""))
17221745
{
1723-
QString currentEnumValue = *range_it;
1724-
//remove quotes from begin and end of the value
1725-
if(currentEnumValue.startsWith("'") || currentEnumValue.startsWith("\""))
1726-
{
1727-
currentEnumValue.remove(0, 1);
1728-
}
1729-
if(currentEnumValue.endsWith("'") || currentEnumValue.endsWith("\""))
1730-
{
1731-
currentEnumValue.chop(1);
1732-
}
1733-
enumList << currentEnumValue;
1746+
currentEnumValue.remove(0, 1);
17341747
}
1748+
if(currentEnumValue.endsWith("'") || currentEnumValue.endsWith("\""))
1749+
{
1750+
currentEnumValue.chop(1);
1751+
}
1752+
enumValues << currentEnumValue;
17351753
}
1754+
return true;
17361755
}
1737-
else if (typtype.compare("d", Qt::CaseInsensitive) == 0)
1756+
return false;
1757+
}
1758+
1759+
bool QgsPostgresProvider::parseDomainCheckConstraint(QStringList& enumValues, const QString& attributeName) const
1760+
{
1761+
enumValues.clear();
1762+
1763+
//is it a domain type with a check constraint?
1764+
QString domainSql = QString("SELECT domain_name from information_schema.columns where table_name = %1 and column_name = %2").arg(quotedValue(mTableName)).arg(quotedValue(attributeName));
1765+
Result domainResult = connectionRO->PQexec(domainSql);
1766+
if ( PQresultStatus( domainResult ) == PGRES_TUPLES_OK && PQntuples(domainResult) > 0)
17381767
{
1739-
//a domain type. Todo: evaluate the check constraint
1768+
//a domain type
1769+
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)));
1770+
Result domainCheckRes = connectionRO->PQexec(domainCheckDefinitionSql);
1771+
if ( PQresultStatus(domainCheckRes) == PGRES_TUPLES_OK && PQntuples(domainCheckRes) > 0)
1772+
{
1773+
QString checkDefinition = PQgetvalue(domainCheckRes, 0, 0);
1774+
1775+
//we assume that the constraint is of the following form:
1776+
//(VALUE = ANY (ARRAY['a'::text, 'b'::text, 'c'::text, 'd'::text]))
1777+
//normally, postgresql creates that if the contstraint has been specified as 'VALUE in ('a', 'b', 'c', 'd')
1778+
1779+
//todo: ANY must occure before ARRAY
1780+
int anyPos = checkDefinition.indexOf("VALUE = ANY");
1781+
int arrayPosition = checkDefinition.lastIndexOf("ARRAY[");
1782+
int closingBracketPos = checkDefinition.indexOf("]", arrayPosition + 6);
1783+
1784+
if(anyPos == -1 || anyPos >= arrayPosition)
1785+
{
1786+
return false; //constraint has not the required format
1787+
}
1788+
1789+
if(arrayPosition != -1)
1790+
{
1791+
QString valueList = checkDefinition.mid(arrayPosition + 6, closingBracketPos);
1792+
QStringList commaSeparation = valueList.split(",", QString::SkipEmptyParts);
1793+
QStringList::const_iterator cIt = commaSeparation.constBegin();
1794+
for(; cIt != commaSeparation.constEnd(); ++cIt)
1795+
{
1796+
//get string between ''
1797+
int beginQuotePos = cIt->indexOf("'");
1798+
int endQuotePos = cIt->lastIndexOf("'");
1799+
if(beginQuotePos != -1 && (endQuotePos - beginQuotePos) > 1)
1800+
{
1801+
enumValues << cIt->mid(beginQuotePos + 1, endQuotePos - beginQuotePos - 1);
1802+
}
1803+
}
1804+
}
1805+
return true;
1806+
}
17401807
}
1808+
return false;
17411809
}
17421810

17431811
// Returns the maximum value of an attribute

src/providers/postgres/qgspostgresprovider.h

+13
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,19 @@ class QgsPostgresProvider : public QgsVectorDataProvider
345345
*/
346346
void loadFields();
347347

348+
/**Parses the enum_range of an attribute and inserts the possible values into a stringlist
349+
@param enumValues the stringlist where the values are appended
350+
@param attributeName the name of the enum attribute
351+
@return true in case of success and fals in case of error (e.g. if the type is not an enum type)*/
352+
bool parseEnumRange(QStringList& enumValues, const QString& attributeName) const;
353+
354+
/** Parses the possible enum values of a domain type (given in the check constraint of the domain type)
355+
@param enumValues Reference to list that receives enum values
356+
@param attributeName Name of the domain type attribute
357+
@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)
358+
*/
359+
bool parseDomainCheckConstraint(QStringList& enumValues, const QString& attributeName) const;
360+
348361
bool mFetching; // true if a cursor was declared
349362
std::vector < QgsFeature > features;
350363
QgsFieldMap attributeFields;

0 commit comments

Comments
 (0)