Skip to content
Permalink
Browse files

Add support for arrays in PostgresQL

Fix parsing of PostgresQL hstore. Had problems when the key or values were
containing comas.
  • Loading branch information
pvalsecc authored and Patrick Valsecchi committed Sep 12, 2016
1 parent 93afbe1 commit abc55f4c42aee16f5cc1daaf918d3f6ef62c8886
@@ -24,13 +24,15 @@ class QgsField
* @param prec Field precision. Usually decimal places but may also be
* used in conjunction with other fields types (eg. variable character fields)
* @param comment Comment for the field
* @param subType If the field is a collection, its element's type.
*/
QgsField( const QString& name = QString(),
QVariant::Type type = QVariant::Invalid,
const QString& typeName = QString(),
int len = 0,
int prec = 0,
const QString& comment = QString() );
const QString& comment = QString(),
QVariant::Type subType = QVariant::Invalid );

/** Copy constructor
*/
@@ -59,6 +61,12 @@ class QgsField
//! Gets variant type of the field as it will be retrieved from data source
QVariant::Type type() const;

/**
* If the field is a collection, gets its element's type
* @note added in QGIS 3.0
*/
QVariant::Type subType() const;

/**
* Gets the field type. Field types vary depending on the data source. Examples
* are char, int, double, blob, geometry, etc. The type is stored exactly as
@@ -103,6 +111,12 @@ class QgsField
*/
void setType( QVariant::Type type );

/**
* If the field is a collection, set its element's type.
* @note added in QGIS 3.0
*/
void setSubType( QVariant::Type subType );

/**
* Set the field type.
* @param typeName Field type
@@ -5064,6 +5064,22 @@ QString QgsExpression::formatPreviewString( const QVariant& value )
}
return tr( "<i>&lt;map: %1&gt;</i>" ).arg( mapStr );
}
else if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
{
QString listStr;
const QVariantList list = value.toList();
for ( QVariantList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
{
if ( !listStr.isEmpty() ) listStr.append( ", " );
listStr.append( formatPreviewString( *it ) );
if ( listStr.length() > MAX_PREVIEW + 3 )
{
listStr = QString( tr( "%1..." ) ).arg( listStr.left( MAX_PREVIEW ) );
break;
}
}
return tr( "<i>&lt;list: %1&gt;</i>" ).arg( listStr );
}
else
{
return value.toString();
@@ -54,6 +54,7 @@ void QgsExpressionFieldBuffer::writeXml( QDomNode& layerNode, QDomDocument& docu
fldElem.setAttribute( "comment", fld.field.comment() );
fldElem.setAttribute( "length", fld.field.length() );
fldElem.setAttribute( "type", fld.field.type() );
fldElem.setAttribute( "subType", fld.field.subType() );
fldElem.setAttribute( "typeName", fld.field.typeName() );

expressionFieldsElem.appendChild( fldElem );
@@ -79,9 +80,10 @@ void QgsExpressionFieldBuffer::readXml( const QDomNode& layerNode )
int precision = field.attribute( "precision" ).toInt();
int length = field.attribute( "length" ).toInt();
QVariant::Type type = static_cast< QVariant::Type >( field.attribute( "type" ).toInt() );
QVariant::Type subType = static_cast< QVariant::Type >( field.attribute( "subType", 0 ).toInt() );
QString typeName = field.attribute( "typeName" );

mExpressions.append( ExpressionField( exp, QgsField( name, type, typeName, length, precision, comment ) ) );
mExpressions.append( ExpressionField( exp, QgsField( name, type, typeName, length, precision, comment, subType ) ) );
}
}
}
@@ -44,9 +44,10 @@ QgsField::QgsField( QString nam, QString typ, int len, int prec, bool num,
}
#endif
QgsField::QgsField( const QString& name, QVariant::Type type,
const QString& typeName, int len, int prec, const QString& comment )
const QString& typeName, int len, int prec, const QString& comment,
QVariant::Type subType )
{
d = new QgsFieldPrivate( name, type, typeName, len, prec, comment );
d = new QgsFieldPrivate( name, type, subType, typeName, len, prec, comment );
}

QgsField::QgsField( const QgsField &other )
@@ -99,6 +100,11 @@ QVariant::Type QgsField::type() const
return d->type;
}

QVariant::Type QgsField::subType() const
{
return d->subType;
}

QString QgsField::typeName() const
{
return d->typeName;
@@ -140,6 +146,11 @@ void QgsField::setType( QVariant::Type type )
d->type = type;
}

void QgsField::setSubType( QVariant::Type subType )
{
d->subType = subType;
}

void QgsField::setTypeName( const QString& typeName )
{
d->typeName = typeName;
@@ -292,14 +303,15 @@ QDataStream& operator<<( QDataStream& out, const QgsField& field )
out << field.comment();
out << field.alias();
out << field.defaultValueExpression();
out << static_cast< quint32 >( field.subType() );
return out;
}

QDataStream& operator>>( QDataStream& in, QgsField& field )
{
quint32 type, length, precision;
quint32 type, subType, length, precision;
QString name, typeName, comment, alias, defaultValueExpression;
in >> name >> type >> typeName >> length >> precision >> comment >> alias >> defaultValueExpression;
in >> name >> type >> typeName >> length >> precision >> comment >> alias >> defaultValueExpression >> subType;
field.setName( name );
field.setType( static_cast< QVariant::Type >( type ) );
field.setTypeName( typeName );
@@ -308,6 +320,7 @@ QDataStream& operator>>( QDataStream& in, QgsField& field )
field.setComment( comment );
field.setAlias( alias );
field.setDefaultValueExpression( defaultValueExpression );
field.setSubType( static_cast< QVariant::Type >( subType ) );
return in;
}

@@ -66,13 +66,15 @@ class CORE_EXPORT QgsField
* @param prec Field precision. Usually decimal places but may also be
* used in conjunction with other fields types (eg. variable character fields)
* @param comment Comment for the field
* @param subType If the field is a collection, its element's type
*/
QgsField( const QString& name = QString(),
QVariant::Type type = QVariant::Invalid,
const QString& typeName = QString(),
int len = 0,
int prec = 0,
const QString& comment = QString() );
const QString& comment = QString(),
QVariant::Type subType = QVariant::Invalid );

/** Copy constructor
*/
@@ -105,6 +107,12 @@ class CORE_EXPORT QgsField
//! Gets variant type of the field as it will be retrieved from data source
QVariant::Type type() const;

/**
* If the field is a collection, gets its element's type
* @note added in QGIS 3.0
*/
QVariant::Type subType() const;

/**
* Gets the field type. Field types vary depending on the data source. Examples
* are char, int, double, blob, geometry, etc. The type is stored exactly as
@@ -149,6 +157,12 @@ class CORE_EXPORT QgsField
*/
void setType( QVariant::Type type );

/**
* If the field is a collection, set its element's type.
* @note added in QGIS 3.0
*/
void setSubType( QVariant::Type subType );

/**
* Set the field type.
* @param typeName Field type
@@ -44,12 +44,14 @@ class QgsFieldPrivate : public QSharedData

QgsFieldPrivate( const QString& name = QString(),
QVariant::Type type = QVariant::Invalid,
QVariant::Type subType = QVariant::Invalid,
const QString& typeName = QString(),
int len = 0,
int prec = 0,
const QString& comment = QString() )
: name( name )
, type( type )
, subType( subType )
, typeName( typeName )
, length( len )
, precision( prec )
@@ -61,6 +63,7 @@ class QgsFieldPrivate : public QSharedData
: QSharedData( other )
, name( other.name )
, type( other.type )
, subType( other.subType )
, typeName( other.typeName )
, length( other.length )
, precision( other.precision )
@@ -74,7 +77,7 @@ class QgsFieldPrivate : public QSharedData

bool operator==( const QgsFieldPrivate& other ) const
{
return (( name == other.name ) && ( type == other.type )
return (( name == other.name ) && ( type == other.type ) && ( subType == other.subType )
&& ( length == other.length ) && ( precision == other.precision )
&& ( alias == other.alias ) && ( defaultValueExpression == other.defaultValueExpression ) );
}
@@ -85,6 +88,9 @@ class QgsFieldPrivate : public QSharedData
//! Variant type
QVariant::Type type;

//! If the variant is a collection, its element's type
QVariant::Type subType;

//! Type name from provider
QString typeName;

@@ -961,6 +961,20 @@ static QString quotedMap( const QVariantMap& map )
return "E'" + ret + "'::hstore";
}

static QString quotedList( const QVariantList& list )
{
QString ret;
for ( QVariantList::const_iterator i = list.constBegin(); i != list.constEnd(); ++i )
{
if ( !ret.isEmpty() )
{
ret += ",";
}
ret.append( doubleQuotedMapValue( i->toString() ) );
}
return "E'{" + ret + "}'";
}

QString QgsPostgresConn::quotedValue( const QVariant& value )
{
if ( value.isNull() )
@@ -979,6 +993,10 @@ QString QgsPostgresConn::quotedValue( const QVariant& value )
case QVariant::Map:
return quotedMap( value.toMap() );

case QVariant::StringList:
case QVariant::List:
return quotedList( value.toList() );

case QVariant::String:
default:
return quotedString( value.toString() );
@@ -739,7 +739,7 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
{
QgsField fld = mSource->mFields.at( idx );

QVariant v = QgsPostgresProvider::convertValue( fld.type(), queryResult.PQgetvalue( row, col ) );
QVariant v = QgsPostgresProvider::convertValue( fld.type(), fld.subType(), queryResult.PQgetvalue( row, col ) );
primaryKeyVals << v;

if ( !subsetOfAttributes || fetchAttributes.contains( idx ) )
@@ -781,7 +781,8 @@ void QgsPostgresFeatureIterator::getFeatureAttribute( int idx, QgsPostgresResult
if ( mSource->mPrimaryKeyAttrs.contains( idx ) )
return;

QVariant v = QgsPostgresProvider::convertValue( mSource->mFields.at( idx ).type(), queryResult.PQgetvalue( row, col ) );
const QgsField fld = mSource->mFields.at( idx );
QVariant v = QgsPostgresProvider::convertValue( fld.type(), fld.subType(), queryResult.PQgetvalue( row, col ) );
feature.setAttribute( idx, v );

col++;

0 comments on commit abc55f4

Please sign in to comment.
You can’t perform that action at this time.