58
58
const QString POSTGRES_KEY = " postgres" ;
59
59
const QString POSTGRES_DESCRIPTION = " PostgreSQL/PostGIS data provider" ;
60
60
61
+ QMap<QString, QgsPostgresProvider::Conn *> QgsPostgresProvider::connections;
62
+ int QgsPostgresProvider::providerIds=0 ;
63
+
61
64
QgsPostgresProvider::QgsPostgresProvider (QString const & uri)
62
65
: QgsVectorDataProvider(uri),
63
66
geomType(QGis::WKBUnknown),
@@ -67,10 +70,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
67
70
// assume this is a valid layer until we determine otherwise
68
71
valid = true ;
69
72
70
- // Make connection to the data source
71
- // For postgres, the connection information is passed as a space delimited
72
- // string:
73
- // host=192.168.1.5 dbname=test port=5342 user=gsherman password=xxx table=tablename
73
+ providerId=providerIds++;
74
74
75
75
QgsDebugMsg (" Postgresql Layer Creation" );
76
76
QgsDebugMsg (" URI: " + uri);
@@ -234,8 +234,6 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
234
234
QgsDebugMsg (" Main thread just dispatched mCountThread" );
235
235
#endif
236
236
237
- ready = false ; // not ready to read yet cuz the cursor hasn't been created
238
-
239
237
// fill type names into sets
240
238
mSupportedNativeTypes .insert (" double precision" );
241
239
mSupportedNativeTypes .insert (" int4" );
@@ -283,6 +281,13 @@ QgsPostgresProvider::~QgsPostgresProvider()
283
281
284
282
PGconn *QgsPostgresProvider::connectDb (const QString & conninfo)
285
283
{
284
+ if ( connections.contains (conninfo) )
285
+ {
286
+ QgsDebugMsg ( QString (" Using cached connection for %1" ).arg (conninfo) );
287
+ connections[conninfo]->ref ++;
288
+ return connections[conninfo]->conn ;
289
+ }
290
+
286
291
QgsDebugMsg (QString (" New postgres connection for " ) + conninfo);
287
292
288
293
PGconn *pd = PQconnectdb (conninfo.toLocal8Bit ()); // use what is set based on locale; after connecting, use Utf8
@@ -323,14 +328,36 @@ PGconn *QgsPostgresProvider::connectDb(const QString & conninfo)
323
328
" work properly.\n Please install PostGIS with "
324
329
" GEOS support (http://geos.refractions.net)" ));
325
330
}
326
- // --std::cout << "Connection to the database was successful\n";
331
+
332
+ QgsDebugMsg (" Connection to the database was successful" );
333
+
334
+ Conn *conn = new Conn (pd);
335
+ connections.insert ( conninfo, conn );
327
336
328
337
return pd;
329
338
}
330
339
331
340
void QgsPostgresProvider::disconnectDb ()
332
341
{
333
- PQfinish ( connection );
342
+ if (mFetching )
343
+ {
344
+ PQexecNR (connection, QString (" CLOSE qgisf%1" ).arg (providerId).toUtf8 () );
345
+ mFetching =false ;
346
+ }
347
+
348
+ QMap<QString, Conn *>::iterator i;
349
+ for (i=connections.begin (); i!=connections.end () && i.value ()->conn !=connection; i++)
350
+ ;
351
+
352
+ assert ( i.value ()->conn ==connection );
353
+ assert ( i.value ()->ref >0 );
354
+
355
+ if ( --i.value ()->ref ==0 ) {
356
+ PQfinish ( connection );
357
+ delete i.value ();
358
+ connections.remove ( i.key () );
359
+ }
360
+
334
361
connection = 0 ;
335
362
}
336
363
@@ -341,14 +368,17 @@ QString QgsPostgresProvider::storageType() const
341
368
342
369
bool QgsPostgresProvider::getNextFeature (QgsFeature& feature)
343
370
{
371
+ assert (mFetching );
372
+
344
373
if (valid)
345
374
{
346
375
347
376
// Top up our queue if it is empty
348
377
if (mFeatureQueue .empty ())
349
378
{
350
- QString fetch = QString (" fetch forward %1 from qgisf" )
351
- .arg (mFeatureQueueSize );
379
+ QString fetch = QString (" fetch forward %1 from qgisf%2" )
380
+ .arg (mFeatureQueueSize )
381
+ .arg (providerId);
352
382
353
383
if (mFirstFetch )
354
384
{
@@ -368,9 +398,7 @@ bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
368
398
QgsDebugMsg (" End of features" );
369
399
370
400
PQclear (queryResult);
371
- if (ready)
372
- PQexecNR (connection, QString (" end work" ).toUtf8 ());
373
- ready = false ;
401
+
374
402
return false ;
375
403
}
376
404
@@ -499,7 +527,7 @@ void QgsPostgresProvider::select(QgsAttributeList fetchAttributes,
499
527
QgsFieldMap attributeMap = fields ();
500
528
QgsFieldMap::const_iterator fieldIt;
501
529
for (QgsAttributeList::const_iterator it = mAttributesToFetch .constBegin ();
502
- it != mAttributesToFetch .constEnd (); ++it)
530
+ it != mAttributesToFetch .constEnd (); ++it)
503
531
{
504
532
fieldIt = attributeMap.find (*it);
505
533
if (fieldIt != attributeMap.end ())
@@ -508,14 +536,22 @@ void QgsPostgresProvider::select(QgsAttributeList fetchAttributes,
508
536
}
509
537
}
510
538
511
- QString declare = " declare qgisf binary cursor for select " + quotedIdentifier (primaryKey);
539
+ if (mFetching )
540
+ {
541
+ PQexecNR (connection, QString (" CLOSE qgisf%1" ).arg (providerId).toUtf8 () );
542
+ mFetching =false ;
543
+ }
544
+
545
+ QString declare = QString (" declare qgisf%1 binary cursor with hold for select %2" )
546
+ .arg (providerId).arg (quotedIdentifier (primaryKey));
512
547
513
548
if (fetchGeometry)
514
549
{
515
550
declare += QString (" ,asbinary(%1,'%2') as qgs_feature_geometry" )
516
- .arg ( quotedIdentifier (geometryColumn) )
517
- .arg ( endianString () );
551
+ .arg ( quotedIdentifier (geometryColumn) )
552
+ .arg ( endianString () );
518
553
}
554
+
519
555
for (std::list<QString>::const_iterator it = mFetchAttributeNames .begin (); it != mFetchAttributeNames .end (); ++it)
520
556
{
521
557
if ( (*it) != primaryKey) // no need to fetch primary key again
@@ -570,18 +606,14 @@ void QgsPostgresProvider::select(QgsAttributeList fetchAttributes,
570
606
571
607
QgsDebugMsg (" Selecting features using: " + declare);
572
608
573
- // set up the cursor
574
- if (ready){
575
- PQexecNR (connection, QString (" end work" ).toUtf8 ());
576
- }
577
- PQexecNR (connection,QString (" begin work" ).toUtf8 ());
578
- ready = true ;
579
609
PQexecNR (connection, declare.toUtf8 ());
580
-
610
+
581
611
while (!mFeatureQueue .empty ())
582
- {
583
- mFeatureQueue .pop ();
584
- }
612
+ {
613
+ mFeatureQueue .pop ();
614
+ }
615
+
616
+ mFetching = true ;
585
617
mFirstFetch = true ;
586
618
}
587
619
@@ -605,40 +637,41 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId,
605
637
}
606
638
}
607
639
608
- QString sql = " declare qgisfid binary cursor for select " + quotedIdentifier (primaryKey);
640
+ QString declare = QString (" declare qgisfid%1 binary cursor with hold for select %2" )
641
+ .arg (providerId).arg (quotedIdentifier (primaryKey));
609
642
610
643
if (fetchGeometry)
611
644
{
612
- sql += QString (" ,asbinary(%1,'%2') as qgs_feature_geometry" )
613
- .arg ( quotedIdentifier (geometryColumn) )
614
- .arg ( endianString () );
645
+ declare += QString (" ,asbinary(%1,'%2') as qgs_feature_geometry" )
646
+ .arg ( quotedIdentifier (geometryColumn) )
647
+ .arg ( endianString () );
615
648
}
649
+
616
650
for (namesIt = attributeNames.begin (); namesIt != attributeNames.end (); ++namesIt)
617
651
{
618
652
if ( (*namesIt) != primaryKey) // no need to fetch primary key again
619
653
{
620
- sql += " ," + quotedIdentifier (*namesIt) + " ::text" ;
654
+ declare += " ," + quotedIdentifier (*namesIt) + " ::text" ;
621
655
}
622
656
}
623
657
624
- sql += " " + QString (" from %1" ).arg (mSchemaTableName );
625
-
626
- sql += " where " + quotedIdentifier (primaryKey) + " =" + QString::number (featureId);
658
+ declare += QString (" from %1 where %2=%3" )
659
+ .arg (mSchemaTableName )
660
+ .arg (quotedIdentifier (primaryKey))
661
+ .arg (featureId);
627
662
628
- QgsDebugMsg (" Selecting feature using: " + sql);
629
-
630
- PQexecNR (connection,QString (" begin work" ).toUtf8 ());
663
+ QgsDebugMsg (" Selecting feature using: " + declare);
631
664
632
665
// execute query
633
- PQexecNR (connection, sql .toUtf8 ());
666
+ PQexecNR (connection, declare .toUtf8 ());
634
667
635
- PGresult *res = PQexec (connection, QString (" fetch forward 1 from qgisfid" ).toUtf8 ());
668
+ PGresult *res = PQexec (connection, QString (" fetch forward 1 from qgisfid%1 " ). arg (providerId ).toUtf8 ());
636
669
637
670
int rows = PQntuples (res);
638
671
if (rows == 0 )
639
672
{
640
673
PQclear (res);
641
- PQexecNR (connection, QString (" end work " ).toUtf8 ());
674
+ PQexecNR (connection, QString (" CLOSE qgisfid%1 " ). arg (providerId ).toUtf8 ());
642
675
QgsDebugMsg (" feature " + QString::number (featureId) + " not found" );
643
676
return FALSE ;
644
677
}
@@ -710,7 +743,7 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId,
710
743
}
711
744
712
745
PQclear (res);
713
- PQexecNR (connection, QString (" end work " ).toUtf8 ());
746
+ PQexecNR (connection, QString (" CLOSE qgisfid%1 " ). arg (providerId ).toUtf8 ());
714
747
715
748
return TRUE ;
716
749
}
@@ -770,8 +803,11 @@ QString QgsPostgresProvider::dataComment() const
770
803
771
804
void QgsPostgresProvider::reset ()
772
805
{
773
- QString move = " move 0 in qgisf" ; // move cursor to first record
774
- PQexecNR (connection, move.toUtf8 ());
806
+ if (mFetching )
807
+ {
808
+ // move cursor to first record
809
+ PQexecNR (connection, QString (" move 0 in qgisf%1" ).arg (providerId).toUtf8 ());
810
+ }
775
811
mFeatureQueue .empty ();
776
812
loadFields ();
777
813
}
@@ -852,9 +888,6 @@ void QgsPostgresProvider::loadFields()
852
888
fieldComment = QString::fromUtf8 (PQgetvalue (tresult, 0 , 0 ));
853
889
PQclear (tresult);
854
890
855
- QgsDebugMsg (" Field: " + attnum + " maps to " + QString::number (i) + " " + fieldName + " , "
856
- + fieldTypeName + " (" + QString::number (fldtyp) + " ), " + fieldSize + " , " + QString::number (fieldModifier));
857
-
858
891
if (fieldName!=geometryColumn)
859
892
{
860
893
QVariant::Type fieldType;
@@ -1906,10 +1939,8 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1906
1939
appendGeomString ( features->geometry (), geomParam);
1907
1940
1908
1941
QList<QByteArray> qparam;
1909
-
1910
1942
qparam.append ( geomParam.toUtf8 () );
1911
1943
qparam.append ( QString (" %1" ).arg ( ++primaryKeyHighWater ).toUtf8 () );
1912
-
1913
1944
param[0 ] = qparam[0 ];
1914
1945
param[1 ] = qparam[1 ];
1915
1946
@@ -2446,16 +2477,14 @@ bool QgsPostgresProvider::deduceEndian()
2446
2477
2447
2478
// get the same value using a binary cursor
2448
2479
2449
- PQexecNR (connection,QString (" begin work" ).toUtf8 ());
2450
- QString oidDeclare = " declare oidcursor binary cursor for select regclass('" + mSchemaTableName + " ')::oid" ;
2480
+ QString oidDeclare = " declare oidcursor binary cursor with hold for select regclass('" + mSchemaTableName + " ')::oid" ;
2451
2481
// set up the cursor
2452
2482
PQexecNR (connection, oidDeclare.toUtf8 ());
2453
2483
QString fetch = " fetch forward 1 from oidcursor" ;
2454
2484
2455
2485
QgsDebugMsg (" Fetching a record and attempting to get check endian-ness" );
2456
2486
2457
2487
PGresult *fResult = PQexec (connection, fetch.toUtf8 ());
2458
- PQexecNR (connection, QString (" end work" ).toUtf8 ());
2459
2488
swapEndian = true ;
2460
2489
if (PQntuples (fResult ) > 0 ){
2461
2490
// get the oid value from the binary cursor
@@ -2469,6 +2498,7 @@ bool QgsPostgresProvider::deduceEndian()
2469
2498
2470
2499
PQclear (fResult );
2471
2500
}
2501
+ PQexecNR (connection, QString (" close oidcursor" ).toUtf8 ());
2472
2502
return swapEndian;
2473
2503
}
2474
2504
@@ -2643,16 +2673,15 @@ void QgsPostgresProvider::PQexecNR(PGconn *conn, const char *query)
2643
2673
PGresult *res = PQexec (conn, query);
2644
2674
if (res)
2645
2675
{
2646
- QgsDebugMsg ( QString (" Query: %1 returned %2 [%3]" )
2647
- .arg (query)
2648
- .arg (PQresStatus (PQresultStatus (res)))
2649
- .arg (PQresultErrorMessage (res))
2650
- );
2676
+ QgsDebugMsgLevel ( QString (" Query: %1 returned %2 [%3]" )
2677
+ .arg (query)
2678
+ .arg (PQresStatus (PQresultStatus (res)))
2679
+ .arg (PQresultErrorMessage (res)), 3 );
2651
2680
PQclear (res);
2652
2681
}
2653
2682
else
2654
2683
{
2655
- QgsDebugMsg ( QString (" Query: %1 returned no result buffer" ).arg (query) );
2684
+ QgsDebugMsgLevel ( QString (" Query: %1 returned no result buffer" ).arg (query), 3 );
2656
2685
}
2657
2686
}
2658
2687
0 commit comments