Skip to content

Commit

Permalink
fixes #20872 : Manage postgres multidimensionnal array
Browse files Browse the repository at this point in the history
  • Loading branch information
troopa81 committed Feb 22, 2019
1 parent fcdb4c0 commit 0753b14
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
11 changes: 10 additions & 1 deletion src/providers/postgres/qgspostgresconn.cpp
Expand Up @@ -1009,7 +1009,16 @@ static QString quotedList( const QVariantList &list )
{
ret += QLatin1String( "," );
}
ret.append( doubleQuotedMapValue( i->toString() ) );

QString inner = i->toString();
if ( inner.startsWith( "{" ) )
{
ret.append( inner );
}
else
{
ret.append( doubleQuotedMapValue( i->toString() ) );
}
}
return "E'{" + ret + "}'";
}
Expand Down
42 changes: 41 additions & 1 deletion src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -4314,6 +4314,44 @@ static QVariant parseStringArray( const QString &txt )
return result;
}

static QVariant parseMultidimensionalArray( const QString &txt )
{
QStringList result;
if ( !txt.startsWith( '{' ) || !txt.endsWith( '}' ) )
{
QgsLogger::warning( "Error parsing array, missing curly braces: " + txt );
return result;
}

QStringList values;
QString text = txt;
while ( !text.isEmpty() )
{
bool escaped = false;
int openedBrackets = 1;
int i = 0;
while ( i < text.length() && openedBrackets > 0 )
{
++i;

if ( text.at( i ) == '}' && !escaped ) openedBrackets--;
else if ( text.at( i ) == '{' && !escaped ) openedBrackets++;

escaped = !escaped ? text.at( i ) == '\\' : false;
}

values.append( text.left( ++i ) );
i = text.indexOf( ",", i );
i = i > 0 ? text.indexOf( "{", i ) : -1;
if ( i == -1 )
break;

text = text.mid( i );
}
return values;

}

static QVariant parseArray( const QString &txt, QVariant::Type type, QVariant::Type subType, const QString &typeName )
{
if ( !txt.startsWith( '{' ) || !txt.endsWith( '}' ) )
Expand All @@ -4323,7 +4361,9 @@ static QVariant parseArray( const QString &txt, QVariant::Type type, QVariant::T
return QVariant( type );
}
QString inner = txt.mid( 1, txt.length() - 2 );
if ( type == QVariant::StringList )
if ( ( type == QVariant::StringList || type == QVariant::List ) && inner.startsWith( "{" ) )
return parseMultidimensionalArray( inner );
else if ( type == QVariant::StringList )
return parseStringArray( inner );
else
return parseOtherArray( inner, subType, typeName );
Expand Down
8 changes: 8 additions & 0 deletions tests/src/providers/testqgspostgresconn.cpp
Expand Up @@ -54,6 +54,14 @@ class TestQgsPostgresConn: public QObject
QCOMPARE( actual, QString( "E'{\"1\",\"-5\"}'" ) );
}

void quotedValue2DimArray()
{
QStringList list;
list << QStringLiteral( "{\"hello foo\",b}" ) << QStringLiteral( "{c,\"hello bar\"}" );
const QString actual = QgsPostgresConn::quotedValue( list );
QCOMPARE( actual, QString( "E'{{\"hello foo\",b},{c,\"hello bar\"}}'" ) );
}

};

QGSTEST_MAIN( TestQgsPostgresConn )
Expand Down
23 changes: 23 additions & 0 deletions tests/src/providers/testqgspostgresprovider.cpp
Expand Up @@ -78,6 +78,29 @@ class TestQgsPostgresProvider: public QObject
qDebug() << "actual: " << decoded;
QCOMPARE( decoded.toList(), expected );
}

void decode2DimensionArray()
{
const QVariant decoded = QgsPostgresProvider::convertValue( QVariant::StringList, QVariant::String, QStringLiteral( "{{foo,\"escape bracket \\}\"},{\"escape bracket and backslash \\\\\\}\",\"hello bar\"}}" ), QStringLiteral( "_text" ) );
QCOMPARE( decoded.type(), QVariant::StringList );

QVariantList expected;
expected << QVariant( "{foo,\"escape bracket \\}\"}" ) << QVariant( "{\"escape bracket and backslash \\\\\\}\",\"hello bar\"}" );
qDebug() << "actual: " << decoded;
QCOMPARE( decoded.toList(), expected );
}

void decode3DimensionArray()
{
const QVariant decoded = QgsPostgresProvider::convertValue( QVariant::StringList, QVariant::String, QStringLiteral( "{{{0,1},{1,2}},{{3,4},{5,6}}}" ), QStringLiteral( "_integer" ) );
QCOMPARE( decoded.type(), QVariant::StringList );

QVariantList expected;
expected << QVariant( "{{0,1},{1,2}}" ) << QVariant( "{{3,4},{5,6}}" );
qDebug() << "actual: " << decoded;
QCOMPARE( decoded.toList(), expected );
}

void decodeJsonList()
{
const QVariant decoded = QgsPostgresProvider::convertValue( QVariant::Map, QVariant::String, QStringLiteral( "[1,2,3]" ), QStringLiteral( "json" ) );
Expand Down

0 comments on commit 0753b14

Please sign in to comment.