@@ -1696,48 +1696,116 @@ void QgsPostgresProvider::enumValues( int index, QStringList& enumList )
1696
1696
return ;
1697
1697
}
1698
1698
1699
- // is type an enum or a domain type ?
1699
+ // is type an enum?
1700
1700
QString typeSql = QString (" SELECT typtype FROM pg_type where typname = %1" ).arg (quotedValue (typeName));
1701
1701
Result typeRes = connectionRO->PQexec ( typeSql );
1702
1702
if ( PQresultStatus ( typeRes ) != PGRES_TUPLES_OK || PQntuples (typeRes) < 1 )
1703
1703
{
1704
1704
return ;
1705
1705
}
1706
1706
1707
+
1707
1708
QString typtype = PQgetvalue ( typeRes, 0 , 0 );
1708
1709
if (typtype.compare (" e" , Qt::CaseInsensitive) == 0 )
1709
1710
{
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 (" \" " ))
1722
1745
{
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 );
1734
1747
}
1748
+ if (currentEnumValue.endsWith (" '" ) || currentEnumValue.endsWith (" \" " ))
1749
+ {
1750
+ currentEnumValue.chop (1 );
1751
+ }
1752
+ enumValues << currentEnumValue;
1735
1753
}
1754
+ return true ;
1736
1755
}
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 )
1738
1767
{
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
+ }
1740
1807
}
1808
+ return false ;
1741
1809
}
1742
1810
1743
1811
// Returns the maximum value of an attribute
0 commit comments