@@ -97,7 +97,6 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
97
97
else
98
98
mSchemaTableName = " \" " + mTableName + " \" " ;
99
99
100
-
101
100
QgsDebugMsg (" Table name is " + mTableName );
102
101
QgsDebugMsg (" SQL is " + sqlWhereClause);
103
102
QgsDebugMsg (" Connection info is " + mUri .connInfo );
@@ -110,37 +109,18 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
110
109
// pLog.open((const char *)logFile);
111
110
// QgsDebugMsg("Opened log file for " + mTableName);
112
111
113
- PGconn *pd = PQconnectdb ((const char *) mUri .connInfo );
114
- // check the connection status
115
- if (PQstatus (pd) != CONNECTION_OK)
116
- {
117
- QgsDebugMsg (" Connection to database failed" );
118
- valid = false ;
119
- return ;
120
- }
121
-
122
- // store the connection for future use
123
- connection = pd;
124
-
125
- // set client encoding to unicode because QString uses UTF-8 anyway
126
- QgsDebugMsg (" setting client encoding to UNICODE" );
127
-
128
- int errcode=PQsetClientEncoding (connection, " UNICODE" );
129
-
130
- if (errcode==0 ) {
131
- QgsDebugMsg (" encoding successfully set" );
132
- } else if (errcode==-1 ) {
133
- QgsDebugMsg (" error in setting encoding" );
134
- } else {
135
- QgsDebugMsg (" undefined return value from encoding setting" );
112
+ connection = connectDb ( (const char *)mUri .connInfo );
113
+ if ( connection==NULL ) {
114
+ valid = false ;
115
+ return ;
136
116
}
137
117
138
118
QgsDebugMsg (" Checking for select permission on the relation\n " );
139
119
140
120
// Check that we can read from the table (i.e., we have
141
121
// select permission).
142
122
QString sql = " select * from " + mSchemaTableName + " limit 1" ;
143
- PGresult* testAccess = PQexec (pd , (const char *)(sql.utf8 ()));
123
+ PGresult* testAccess = PQexec (connection , (const char *)(sql.utf8 ()));
144
124
if (PQresultStatus (testAccess) != PGRES_TUPLES_OK)
145
125
{
146
126
showMessageBox (tr (" Unable to access relation" ),
@@ -150,33 +130,19 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
150
130
" SQL: " + sql);
151
131
PQclear (testAccess);
152
132
valid = false ;
153
- PQfinish (connection );
133
+ disconnectDb ( );
154
134
return ;
155
135
}
156
136
PQclear (testAccess);
157
137
158
- /* Check to see if we have GEOS support and if not, warn the user about
159
- the problems they will see :) */
160
- QgsDebugMsg (" Checking for GEOS support" );
161
-
162
- if (!hasGEOS (pd))
163
- {
164
- showMessageBox (tr (" No GEOS Support!" ),
165
- tr (" Your PostGIS installation has no GEOS support.\n "
166
- " Feature selection and identification will not "
167
- " work properly.\n Please install PostGIS with "
168
- " GEOS support (http://geos.refractions.net)" ));
169
- }
170
- // --std::cout << "Connection to the database was successful\n";
171
-
172
138
if (!getGeometryDetails ()) // gets srid and geometry type
173
139
{
174
140
// the table is not a geometry table
175
141
numberFeatures = 0 ;
176
142
valid = false ;
177
143
178
144
QgsDebugMsg (" Invalid Postgres layer" );
179
- PQfinish (connection );
145
+ disconnectDb ( );
180
146
return ;
181
147
}
182
148
@@ -187,14 +153,14 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
187
153
// Get the relation oid for use in later queries
188
154
sql = " SELECT oid FROM pg_class WHERE relname = '" + mTableName + " ' AND relnamespace = ("
189
155
" SELECT oid FROM pg_namespace WHERE nspname = '" + mSchemaName + " ')" ;
190
- PGresult *tresult= PQexec (pd , (const char *)(sql.utf8 ()));
156
+ PGresult *tresult= PQexec (connection , (const char *)(sql.utf8 ()));
191
157
QString tableoid = PQgetvalue (tresult, 0 , 0 );
192
158
PQclear (tresult);
193
159
194
160
// Get the table description
195
161
sql = " SELECT description FROM pg_description WHERE "
196
162
" objoid = " + tableoid + " AND objsubid = 0" ;
197
- tresult = PQexec (pd , (const char *) sql.utf8 ());
163
+ tresult = PQexec (connection , (const char *) sql.utf8 ());
198
164
if (PQntuples (tresult) > 0 )
199
165
mDataComment = PQgetvalue (tresult, 0 , 0 );
200
166
PQclear (tresult);
@@ -203,7 +169,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
203
169
// field name, type, length, and precision (if numeric)
204
170
sql = " select * from " + mSchemaTableName + " limit 0" ;
205
171
206
- PGresult *result = PQexec (pd , (const char *) (sql.utf8 ()));
172
+ PGresult *result = PQexec (connection , (const char *) (sql.utf8 ()));
207
173
// --std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
208
174
209
175
// The queries inside this loop could possibly be combined into one
@@ -221,20 +187,20 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
221
187
" oid = (SELECT typelem FROM pg_type WHERE "
222
188
" typelem = " + typOid + " AND typlen = -1)" ;
223
189
224
- PGresult* oidResult = PQexec (pd , (const char *) sql);
190
+ PGresult* oidResult = PQexec (connection , (const char *) sql);
225
191
QString fieldTypeName = PQgetvalue (oidResult, 0 , 0 );
226
192
QString fieldSize = PQgetvalue (oidResult, 0 , 1 );
227
193
PQclear (oidResult);
228
194
229
195
sql = " SELECT attnum FROM pg_attribute WHERE "
230
196
" attrelid = " + tableoid + " AND attname = '" + fieldName + " '" ;
231
- PGresult *tresult = PQexec (pd , (const char *)(sql.utf8 ()));
197
+ PGresult *tresult = PQexec (connection , (const char *)(sql.utf8 ()));
232
198
QString attnum = PQgetvalue (tresult, 0 , 0 );
233
199
PQclear (tresult);
234
200
235
201
sql = " SELECT description FROM pg_description WHERE "
236
202
" objoid = " + tableoid + " AND objsubid = " + attnum;
237
- tresult = PQexec (pd , (const char *)(sql.utf8 ()));
203
+ tresult = PQexec (connection , (const char *)(sql.utf8 ()));
238
204
if (PQntuples (tresult) > 0 )
239
205
fieldComment = PQgetvalue (tresult, 0 , 0 );
240
206
PQclear (tresult);
@@ -306,7 +272,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
306
272
307
273
// Close the database connection if the layer isn't going to be loaded.
308
274
if (!valid)
309
- PQfinish (connection );
275
+ disconnectDb ( );
310
276
}
311
277
312
278
QgsPostgresProvider::~QgsPostgresProvider ()
@@ -329,13 +295,93 @@ QgsPostgresProvider::~QgsPostgresProvider()
329
295
QApplication::sendPostedEvents (this , QGis::ProviderExtentCalcEvent);
330
296
QApplication::sendPostedEvents (this , QGis::ProviderCountCalcEvent);
331
297
#endif
332
- PQfinish (connection);
298
+
299
+ disconnectDb ();
333
300
334
301
QgsDebugMsg (" deconstructing." );
335
302
336
303
// pLog.flush();
337
304
}
338
305
306
+ PGconn *QgsPostgresProvider::connectDb (const char *conninfo)
307
+ {
308
+ if ( connections.contains (conninfo) )
309
+ {
310
+ QgsDebugMsg (QString (" Using cached connection for " ) + conninfo);
311
+ connections[conninfo]->ref ++;
312
+ return connections[conninfo]->conn ;
313
+ }
314
+
315
+ QgsDebugMsg (QString (" New postgres connection for " ) + conninfo);
316
+
317
+ PGconn *pd = PQconnectdb (conninfo);
318
+ // check the connection status
319
+ if (PQstatus (pd) != CONNECTION_OK)
320
+ {
321
+ QgsDebugMsg (" Connection to database failed" );
322
+ return NULL ;
323
+ }
324
+
325
+ // set client encoding to unicode because QString uses UTF-8 anyway
326
+ QgsDebugMsg (" setting client encoding to UNICODE" );
327
+
328
+ int errcode=PQsetClientEncoding (pd, " UNICODE" );
329
+
330
+ if (errcode==0 )
331
+ {
332
+ QgsDebugMsg (" encoding successfully set" );
333
+ }
334
+ else if (errcode==-1 )
335
+ {
336
+ QgsDebugMsg (" error in setting encoding" );
337
+ }
338
+ else
339
+ {
340
+ QgsDebugMsg (" undefined return value from encoding setting" );
341
+ }
342
+
343
+ /* Check to see if we have GEOS support and if not, warn the user about
344
+ the problems they will see :) */
345
+ QgsDebugMsg (" Checking for GEOS support" );
346
+
347
+ if (!hasGEOS (pd))
348
+ {
349
+ showMessageBox (tr (" No GEOS Support!" ),
350
+ tr (" Your PostGIS installation has no GEOS support.\n "
351
+ " Feature selection and identification will not "
352
+ " work properly.\n Please install PostGIS with "
353
+ " GEOS support (http://geos.refractions.net)" ));
354
+ }
355
+ // --std::cout << "Connection to the database was successful\n";
356
+
357
+ Conn *conn = new Conn (pd);
358
+ connections.insert ( conninfo, conn );
359
+
360
+ return pd;
361
+ }
362
+
363
+ void QgsPostgresProvider::disconnectDb ()
364
+ {
365
+ QMapIterator <QString, Conn *> i (connections);
366
+ while ( i.hasNext () )
367
+ {
368
+ i.next ();
369
+
370
+ if ( i.value ()->conn == connection )
371
+ break ;
372
+ }
373
+
374
+ assert ( i.value ()->conn ==connection );
375
+ assert ( i.value ()->ref >0 );
376
+
377
+ if ( --i.value ()->ref ==0 )
378
+ {
379
+ PQfinish ( i.value ()->conn );
380
+ delete (i.value ());
381
+ connections.remove ( i.key () );
382
+ }
383
+ }
384
+
339
385
QString QgsPostgresProvider::storageType ()
340
386
{
341
387
return " PostgreSQL database with PostGIS extension" ;
@@ -434,7 +480,6 @@ bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
434
480
} // if new queue is required
435
481
436
482
// Now return the next feature from the queue
437
-
438
483
feature = mFeatureQueue .front ();
439
484
mFeatureQueue .pop ();
440
485
@@ -2609,3 +2654,4 @@ QGISEXTERN bool isProvider(){
2609
2654
return true ;
2610
2655
}
2611
2656
2657
+ QMap<QString, QgsPostgresProvider::Conn *> QgsPostgresProvider::connections;
0 commit comments