1 /***************************************************************************
2 testqgspostgresconn.cpp
3 ---------------------
4 begin : August 2016
5 copyright : (C) 2016 by Patrick Valsecchi
6 email : patrick dot valsecchi at camptocamp dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15 #include "qgstest.h"
16 #include <QObject>
17
18 #include <qgspostgresconn.h>
19 #include <qgsfields.h>
20 #include <qgspostgresprovider.h>
21
22 // Helper function for QCOMPARE
toString(const QgsPostgresGeometryColumnType & t)23 char *toString( const QgsPostgresGeometryColumnType &t )
24 {
25 const char *ptr;
26 switch ( t )
27 {
28 case SctNone:
29 ptr = "None";
30 break;
31 case SctGeometry:
32 ptr = "Geometry";
33 break;
34 case SctGeography:
35 ptr = "Geography";
36 break;
37 case SctTopoGeometry:
38 ptr = "TopoGeometry";
39 break;
40 case SctPcPatch:
41 ptr = "PcPatch";
42 break;
43 case SctRaster:
44 ptr = "Raster";
45 break;
46 default:
47 ptr = "Unknown";
48 break;
49 }
50 char *dst = new char[16];
51 return qstrcpy( dst, ptr );
52 }
53
54 class TestQgsPostgresConn: public QObject
55 {
56 Q_OBJECT
57
58 private:
59 QgsPostgresConn *_connection;
60
getConnection()61 QgsPostgresConn *getConnection()
62 {
63 if ( ! _connection )
64 {
65 const char *connstring = getenv( "QGIS_PGTEST_DB" );
66 if ( NULL == connstring ) connstring = "service=qgis_test";
67 _connection = QgsPostgresConn::connectDb( connstring, true );
68 assert( _connection );
69 }
70 return _connection;
71 }
72
73 private slots:
initTestCase()74 void initTestCase() // will be called before the first testfunction is executed.
75 {
76 this->_connection = 0;
77 }
cleanupTestCase()78 void cleanupTestCase() // will be called after the last testfunction was executed.
79 {
80 if ( this->_connection ) this->_connection->unref();
81 }
82
quotedValueHstore()83 void quotedValueHstore()
84 {
85 QVariantMap map;
86 map[QStringLiteral( "1" )] = "2";
87 map[QStringLiteral( "a" )] = "b \"c' \\x";
88
89 const QString actual = QgsPostgresConn::quotedValue( map );
90 QCOMPARE( actual, QString( "E'\"1\"=>\"2\",\"a\"=>\"b \\\\\"c\\' \\\\\\\\x\"'::hstore" ) );
91 }
92
quotedValueString()93 void quotedValueString()
94 {
95 QCOMPARE( QgsPostgresConn::quotedValue( "b" ), QString( "'b'" ) );
96 QCOMPARE( QgsPostgresConn::quotedValue( "b's" ), QString( "'b''s'" ) );
97 QCOMPARE( QgsPostgresConn::quotedValue( "b \"c' \\x" ), QString( "E'b \"c'' \\\\x'" ) );
98 }
99
quotedValueDatetime()100 void quotedValueDatetime()
101 {
102 QCOMPARE( QgsPostgresConn::quotedValue( QDateTime::fromString( "2020-05-07 17:56:00", "yyyy-MM-dd HH:mm:ss" ) ), QString( "'2020-05-07T17:56:00.000'" ) );
103
104 QgsFields fields;
105 QgsField f;
106 f.setName( "ts" );
107 f.setType( QVariant::DateTime );
108 f.setTypeName( "timestamp" );
109 fields.append( f );
110 QgsField f2;
111 f2.setName( "pk" );
112 f2.setType( QVariant::LongLong );
113 f2.setTypeName( "serial8" );
114 fields.append( f2 );
115
116 QList<int> pkAttrs;
117 pkAttrs.append( 0 );
118 pkAttrs.append( 1 );
119
120 QgsPostgresSharedData *shared = new QgsPostgresSharedData;
121 QVariantList qvlist;
122 qvlist.append( QDateTime::fromString( "2020-05-07 17:56:00", "yyyy-MM-dd HH:mm:ss" ) );
123 qvlist.append( 123LL );
124 shared->insertFid( 1LL, qvlist );
125
126 QCOMPARE( QgsPostgresUtils::whereClause( 1LL, fields, NULL, QgsPostgresPrimaryKeyType::PktFidMap, pkAttrs, std::shared_ptr<QgsPostgresSharedData>( shared ) ), QString( "\"ts\"='2020-05-07T17:56:00.000' AND \"pk\"=123" ) );
127 }
128
quotedValueStringArray()129 void quotedValueStringArray()
130 {
131 QStringList list;
132 list << QStringLiteral( "a" ) << QStringLiteral( "b \"c' \\x" );
133 const QString actual = QgsPostgresConn::quotedValue( list );
134 QCOMPARE( actual, QString( "E'{\"a\",\"b \\\\\"c\\' \\\\\\\\x\"}'" ) );
135 }
136
quotedValueIntArray()137 void quotedValueIntArray()
138 {
139 QVariantList list;
140 list << 1 << -5;
141 const QString actual = QgsPostgresConn::quotedValue( list );
142 QCOMPARE( actual, QString( "E'{1,-5}'" ) );
143 }
144
quotedValue2DimArray()145 void quotedValue2DimArray()
146 {
147 QStringList list;
148 list << QStringLiteral( "{\"hello foo\",b}" ) << QStringLiteral( "{c,\"hello bar\"}" );
149 const QString actual = QgsPostgresConn::quotedValue( list );
150 QCOMPARE( actual, QString( "E'{{\"hello foo\",b},{c,\"hello bar\"}}'" ) );
151 }
152
supportedLayers()153 void supportedLayers()
154 {
155 QgsPostgresConn *conn = getConnection();
156 QVERIFY( conn != 0 );
157 QVector<QgsPostgresLayerProperty> layers;
158 QMap<QString, QgsPostgresLayerProperty> layersMap;
159
160 const bool success = conn->supportedLayers(
161 layers,
162 false, // searchGeometryColumnsOnly
163 false, // searchPublicOnly
164 false, // allowGeometrylessTables
165 "qgis_test" // schema
166 );
167 QVERIFY( success );
168
169 // Test no duplicates are reported by supportedLayers
170 for ( const auto &l : layers )
171 {
172 const QString key = QString( "%1.%2.%3" ).arg( l.schemaName, l.tableName, l.geometryColName );
173 const auto i = layersMap.find( key );
174 if ( i != layersMap.end() )
175 {
176 QFAIL(
177 QString(
178 "Layer %1 returned multiple times by supportedLayers"
179 ).arg( key ).toUtf8().data()
180 );
181 }
182 layersMap.insert( key, l );
183 }
184
185 // Test qgis_test.TopoLayer1.topogeom
186 const QString key = QString( "qgis_test.TopoLayer1.topogeom" );
187 const auto lit = layersMap.find( key );
188 QVERIFY2(
189 lit != layersMap.end(),
190 "Layer qgis_test.TopoLayer1.topogeom not returned by supportedLayers"
191 );
192 QCOMPARE( lit->geometryColName, "topogeom" );
193 QCOMPARE( lit->geometryColType, SctTopoGeometry );
194 // TODO: add more tests
195
196 }
197
198 };
199
200 QGSTEST_MAIN( TestQgsPostgresConn )
201 #include "testqgspostgresconn.moc"
202