@@ -65,7 +65,8 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
65
65
: QgsVectorDataProvider(uri),
66
66
geomType(QGis::WKBUnknown),
67
67
mFeatureQueueSize(200 ),
68
- gotPostgisVersion(FALSE )
68
+ gotPostgisVersion(false ),
69
+ mFetching(false )
69
70
{
70
71
// assume this is a valid layer until we determine otherwise
71
72
valid = true ;
@@ -366,388 +367,294 @@ QString QgsPostgresProvider::storageType() const
366
367
return " PostgreSQL database with PostGIS extension" ;
367
368
}
368
369
369
- bool QgsPostgresProvider::getNextFeature (QgsFeature& feature)
370
+ void QgsPostgresProvider::declareCursor (const QString &cursorName,
371
+ const QgsAttributeList &fetchAttributes,
372
+ bool fetchGeometry,
373
+ QString whereClause,
374
+ QStringList &attributeNames)
370
375
{
371
- assert (mFetching );
376
+ QString declare = QString (" declare %1 binary cursor with hold for select %2" )
377
+ .arg (cursorName).arg (quotedIdentifier (primaryKey));
372
378
373
- if (valid )
379
+ if (fetchGeometry )
374
380
{
381
+ declare += QString (" ,asbinary(%1,'%2') as qgs_feature_geometry" )
382
+ .arg ( quotedIdentifier (geometryColumn) )
383
+ .arg ( endianString () );
384
+ }
375
385
376
- // Top up our queue if it is empty
377
- if (mFeatureQueue .empty ())
386
+ QgsFieldMap attributeMap = fields ();
387
+ for (QgsAttributeList::const_iterator it = fetchAttributes.constBegin (); it != fetchAttributes.constEnd (); ++it)
388
+ {
389
+ QgsFieldMap::const_iterator fieldIt = attributeMap.find (*it);
390
+ if (fieldIt != attributeMap.end ())
378
391
{
379
- QString fetch = QString (" fetch forward %1 from qgisf%2" )
380
- .arg (mFeatureQueueSize )
381
- .arg (providerId);
392
+ const QString &fieldname = fieldIt.value ().name ();
382
393
383
- if (mFirstFetch )
394
+ if ( fieldname != primaryKey )
384
395
{
385
- if (PQsendQuery (connection, fetch. toUtf8 () ) == 0 ) // fetch features in asynchronously
396
+ if ( fieldIt. value (). typeName ( ) == " money " || fieldIt. value (). typeName (). startsWith ( " _ " ) )
386
397
{
387
- qWarning (" PQsendQuery failed (1)" );
398
+ // money and arrays don't support cast to text, but return text
399
+ // TODO: check other types
400
+ declare += " ," + quotedIdentifier ( fieldname );
401
+ }
402
+ else if ( fieldIt.value ().typeName () == " bool" )
403
+ {
404
+ // bool doesn't support cast to text either and even doesn't return text.
405
+ // (even text() doesn't work with binary cursors)
406
+ declare += QString (" ,CASE WHEN %1 THEN 't' WHEN NOT %1 THEN 'f' ELSE NULL END AS %1" )
407
+ .arg ( quotedIdentifier (fieldname) );
408
+ }
409
+ else
410
+ {
411
+ declare += " ," + quotedIdentifier ( fieldname ) + " ::text" ;
388
412
}
389
- }
390
- mFirstFetch = false ;
391
- queryResult = PQgetResult (connection);
392
- PQgetResult (connection); // just to get the 0 pointer...
393
-
394
- int rows = PQntuples (queryResult);
395
-
396
- if (rows == 0 )
397
- {
398
- QgsDebugMsg (" End of features" );
399
-
400
- PQclear (queryResult);
401
-
402
- return false ;
403
413
}
404
414
405
- for ( int row = 0 ; row < rows; row++)
406
- {
407
- int oid = *( int *) PQgetvalue (queryResult, row, PQfnumber (queryResult, quotedIdentifier (primaryKey). toUtf8 ()));
415
+ attributeNames << fieldname;
416
+ }
417
+ }
408
418
409
- if (swapEndian)
410
- oid = ntohl (oid); // convert oid to opposite endian
411
-
412
- mFeatureQueue . push ( QgsFeature () );
419
+ declare += " from " + mSchemaTableName ;
420
+
421
+ if ( !whereClause. isEmpty () )
422
+ declare += QString ( " where %1 " ). arg (whereClause );
413
423
414
- // set ID
415
- mFeatureQueue .back ().setFeatureId (oid);
424
+ QgsDebugMsg (" Binary cursor: " + declare);
416
425
417
- // fetch attributes
418
- std::list<QString>::const_iterator name_it = mFetchAttributeNames .begin ();
419
- QgsAttributeList::const_iterator index_it = mAttributesToFetch .constBegin ();
426
+ PQexecNR (connection, declare.toUtf8 ());
427
+ }
420
428
421
- for (; name_it != mFetchAttributeNames .end (); ++name_it, ++index_it)
422
- {
423
- QString val;
429
+ void QgsPostgresProvider::getFeature (PGresult *queryResult, int row, bool fetchGeometry,
430
+ QgsFeature &feature,
431
+ const QStringList &attributeNames,
432
+ const QgsAttributeList &fetchAttributes)
433
+ {
434
+ int oid = *(int *)PQgetvalue (queryResult, row, PQfnumber (queryResult,quotedIdentifier (primaryKey).toUtf8 ()));
435
+ if (swapEndian)
436
+ oid = ntohl (oid); // convert oid to opposite endian
424
437
425
- if ( (*name_it) == primaryKey)
426
- {
427
- val = QString::number (oid);
428
- }
429
- else
430
- {
431
- int fn = PQfnumber (queryResult,quotedIdentifier (*name_it).toUtf8 ());
432
-
433
- if ( !PQgetisnull (queryResult, row, fn) )
434
- val = QString::fromUtf8 (PQgetvalue (queryResult, row, fn));
435
- else
436
- val = QString::null;
437
- }
438
-
439
- if ( val.isNull () )
440
- {
441
- mFeatureQueue .back ().addAttribute (*index_it, val);
442
- }
443
- else
444
- {
445
- switch (attributeFields[*index_it].type ())
446
- {
447
- case QVariant::LongLong:
448
- mFeatureQueue .back ().addAttribute (*index_it, val.toLongLong ());
449
- break ;
450
- case QVariant::Int:
451
- mFeatureQueue .back ().addAttribute (*index_it, val.toInt ());
452
- break ;
453
- case QVariant::Double:
454
- mFeatureQueue .back ().addAttribute (*index_it, val.toDouble ());
455
- break ;
456
- case QVariant::String:
457
- mFeatureQueue .back ().addAttribute (*index_it, val);
458
- break ;
459
- default :
460
- assert (0 && " unsupported field type" );
461
- }
462
- }
463
- }
438
+ feature.setFeatureId (oid);
464
439
465
- // fetch geometry
466
- if (mFetchGeom )
467
- {
468
- int returnedLength = PQgetlength (queryResult, row, PQfnumber (queryResult," qgs_feature_geometry" ));
469
- if (returnedLength > 0 )
470
- {
471
- unsigned char *featureGeom = new unsigned char [returnedLength + 1 ];
472
- memset (featureGeom, ' \0 ' , returnedLength + 1 );
473
- memcpy (featureGeom, PQgetvalue (queryResult, row, PQfnumber (queryResult,QString (" qgs_feature_geometry" ).toUtf8 ())), returnedLength);
474
- mFeatureQueue .back ().setGeometryAndOwnership (featureGeom, returnedLength + 1 );
475
- }
476
- else
477
- {
478
- mFeatureQueue .back ().setGeometryAndOwnership (0 , 0 );
479
- QgsDebugMsg (" Couldn't get the feature geometry in binary form" );
480
- }
481
- }
482
- } // for each row in queue
440
+ // fetch attributes
441
+ QgsAttributeList::const_iterator it = fetchAttributes.constBegin ();
442
+ for (QStringList::const_iterator namesIt = attributeNames.begin (); namesIt != attributeNames.end (); ++namesIt, ++it)
443
+ {
444
+ QString val;
483
445
484
- PQclear (queryResult);
446
+ if ( (*namesIt) == primaryKey)
447
+ {
448
+ val = QString::number (oid);
449
+ }
450
+ else
451
+ {
452
+ int fn = PQfnumber (queryResult,quotedIdentifier (*namesIt).toUtf8 ());
485
453
486
- if (PQsendQuery (connection, fetch. toUtf8 ()) == 0 ) // already fetch the next couple of features asynchronously
454
+ if ( ! PQgetisnull (queryResult, row, fn) )
487
455
{
488
- qWarning ( " PQsendQuery failed (2) " );
456
+ val = QString::fromUtf8 ( PQgetvalue (queryResult, row, fn) );
489
457
}
458
+ else
459
+ {
460
+ val = QString::null;
461
+ }
462
+ }
490
463
491
- } // if new queue is required
492
-
493
- // Now return the next feature from the queue
494
- if (mFetchGeom )
464
+ if ( val.isNull () )
495
465
{
496
- QgsGeometry* featureGeom = mFeatureQueue .front ().geometryAndOwnership ();
497
- feature.setGeometry (featureGeom);
466
+ feature.addAttribute (*it, val);
498
467
}
499
468
else
500
469
{
501
- feature.setGeometryAndOwnership (0 , 0 );
470
+ switch (attributeFields[*it].type ())
471
+ {
472
+ case QVariant::LongLong:
473
+ feature.addAttribute (*it, val.toLongLong ());
474
+ break ;
475
+ case QVariant::Int:
476
+ feature.addAttribute (*it, val.toInt ());
477
+ break ;
478
+ case QVariant::Double:
479
+ feature.addAttribute (*it, val.toDouble ());
480
+ break ;
481
+ case QVariant::String:
482
+ feature.addAttribute (*it, val);
483
+ break ;
484
+ default :
485
+ assert (0 && " unsupported field type" );
486
+ }
502
487
}
503
- feature.setFeatureId (mFeatureQueue .front ().featureId ());
504
- feature.setAttributeMap (mFeatureQueue .front ().attributeMap ());
505
-
506
- mFeatureQueue .pop ();
507
-
508
- }
509
- else
510
- {
511
- QgsDebugMsg (" Read attempt on an invalid postgresql data source" );
512
- return false ;
513
488
}
514
489
515
- return true ;
516
- }
517
-
518
- void QgsPostgresProvider::select (QgsAttributeList fetchAttributes,
519
- QgsRect rect,
520
- bool fetchGeometry,
521
- bool useIntersect)
522
- {
523
- mFetchGeom = fetchGeometry;
524
- mAttributesToFetch = fetchAttributes;
525
-
526
- mFetchAttributeNames .clear ();
527
- QgsFieldMap attributeMap = fields ();
528
- QgsFieldMap::const_iterator fieldIt;
529
- for (QgsAttributeList::const_iterator it = mAttributesToFetch .constBegin ();
530
- it != mAttributesToFetch .constEnd (); ++it)
490
+ if (fetchGeometry)
531
491
{
532
- fieldIt = attributeMap. find (*it);
533
- if (fieldIt != attributeMap. end () )
492
+ int returnedLength = PQgetlength (queryResult, row, PQfnumber (queryResult, " qgs_feature_geometry " ));
493
+ if (returnedLength > 0 )
534
494
{
535
- mFetchAttributeNames .push_back (fieldIt.value ().name ());
495
+ unsigned char *featureGeom = new unsigned char [returnedLength + 1 ];
496
+ memset (featureGeom, ' \0 ' , returnedLength + 1 );
497
+ memcpy (featureGeom, PQgetvalue (queryResult, row, PQfnumber (queryResult,QString (" qgs_feature_geometry" ).toUtf8 ())), returnedLength);
498
+ feature.setGeometryAndOwnership (featureGeom, returnedLength + 1 );
536
499
}
537
- }
500
+ else
501
+ {
502
+ feature.setGeometryAndOwnership (0 , 0 );
503
+ QgsDebugMsg (" Couldn't get the feature geometry in binary form" );
504
+ }
505
+ }
506
+ }
538
507
508
+ void QgsPostgresProvider::select (QgsAttributeList fetchAttributes, QgsRect rect, bool fetchGeometry, bool useIntersect)
509
+ {
510
+ QString cursorName = QString (" qgisf%1" ).arg (providerId);
511
+
539
512
if (mFetching )
540
513
{
541
- PQexecNR (connection, QString (" CLOSE qgisf %1" ).arg (providerId ).toUtf8 () );
514
+ PQexecNR (connection, QString (" CLOSE %1" ).arg (cursorName ).toUtf8 () );
542
515
mFetching =false ;
543
- }
544
-
545
- QString declare = QString (" declare qgisf%1 binary cursor with hold for select %2" )
546
- .arg (providerId).arg (quotedIdentifier (primaryKey));
547
-
548
- if (fetchGeometry)
549
- {
550
- declare += QString (" ,asbinary(%1,'%2') as qgs_feature_geometry" )
551
- .arg ( quotedIdentifier (geometryColumn) )
552
- .arg ( endianString () );
553
- }
554
-
555
- for (std::list<QString>::const_iterator it = mFetchAttributeNames .begin (); it != mFetchAttributeNames .end (); ++it)
556
- {
557
- if ( (*it) != primaryKey) // no need to fetch primary key again
516
+
517
+ while (!mFeatureQueue .empty ())
558
518
{
559
- declare += " , " + quotedIdentifier (*it) + " ::text " ;
519
+ mFeatureQueue . pop () ;
560
520
}
561
521
}
562
522
563
- declare += QString (" from %1" ).arg (mSchemaTableName );
564
-
565
- QgsDebugMsg (" Binary cursor: " + declare);
566
-
567
- bool hasWhere = FALSE ;
523
+ QString whereClause;
568
524
569
525
if (!rect.isEmpty ())
570
526
{
571
527
if (useIntersect)
572
528
{
573
529
// Contributed by #qgis irc "creeping"
574
530
// This version actually invokes PostGIS's use of spatial indexes
575
- declare += " where " + quotedIdentifier (geometryColumn);
576
- declare += " && setsrid('BOX3D(" + rect.asWKTCoords ();
577
- declare += " )'::box3d," ;
578
- declare += srid;
579
- declare += " )" ;
580
- declare += " and intersects(" + quotedIdentifier (geometryColumn);
581
- declare += " , setsrid('BOX3D(" + rect.asWKTCoords ();
582
- declare += " )'::box3d," ;
583
- declare += srid;
584
- declare += " ))" ;
531
+ whereClause = QString (" %1 && setsrid('BOX3D(%2)'::box3d,%3) and intersects(%1,setsrid('BOX3D(%2)'::box3d,%3))" )
532
+ .arg ( quotedIdentifier (geometryColumn) )
533
+ .arg ( rect.asWKTCoords () )
534
+ .arg ( srid );
585
535
}
586
536
else
587
537
{
588
- declare += " where " + quotedIdentifier (geometryColumn);
589
- declare += " && setsrid('BOX3D(" + rect.asWKTCoords ();
590
- declare += " )'::box3d," ;
591
- declare += srid;
592
- declare += " )" ;
538
+ whereClause = QString (" %1 && setsrid('BOX3D(%2)'::box3d,%3)" )
539
+ .arg ( quotedIdentifier (geometryColumn) )
540
+ .arg ( rect.asWKTCoords () )
541
+ .arg ( srid );
593
542
}
594
- hasWhere = TRUE ;
595
543
}
596
544
597
- if (sqlWhereClause.length () > 0 )
545
+ if ( ! sqlWhereClause.isEmpty () )
598
546
{
599
- if (hasWhere)
600
- declare += " and " ;
601
- else
602
- declare += " where " ;
603
- declare += " (" + sqlWhereClause + " )" ;
604
- hasWhere = TRUE ;
605
- }
547
+ if (!whereClause.isEmpty ())
548
+ whereClause += " and " ;
606
549
607
- QgsDebugMsg (" Selecting features using: " + declare);
608
-
609
- PQexecNR (connection, declare.toUtf8 ());
610
-
611
- while (!mFeatureQueue .empty ())
612
- {
613
- mFeatureQueue .pop ();
550
+ whereClause += " (" + sqlWhereClause + " )" ;
614
551
}
615
552
553
+ mFetchGeom = fetchGeometry;
554
+ mAttributesToFetch = fetchAttributes;
555
+ declareCursor ( cursorName, fetchAttributes, fetchGeometry, whereClause, mFetchAttributeNames );
556
+
616
557
mFetching = true ;
617
558
mFirstFetch = true ;
618
559
}
619
560
620
- bool QgsPostgresProvider::getFeatureAtId (int featureId,
621
- QgsFeature& feature,
622
- bool fetchGeometry,
623
- QgsAttributeList fetchAttributes)
561
+ bool QgsPostgresProvider::getNextFeature (QgsFeature& feature)
624
562
{
625
- std::list<QString> attributeNames;
626
- QgsFieldMap fldMap = fields ();
627
- QgsFieldMap::const_iterator fieldIt;
628
- QgsAttributeList::const_iterator it;
629
- std::list<QString>::const_iterator namesIt;
563
+ QString cursorName = QString (" qgisf%1" ).arg (providerId);
630
564
631
- for (it = fetchAttributes. constBegin (); it != fetchAttributes. constEnd (); ++it )
565
+ if (!valid )
632
566
{
633
- fieldIt = fldMap.find (*it);
634
- if (fieldIt != fldMap.end ())
635
- {
636
- attributeNames.push_back (fieldIt.value ().name ());
637
- }
567
+ QgsDebugMsg (" Read attempt on an invalid postgresql data source" );
568
+ return false ;
638
569
}
639
570
640
- QString declare = QString (" declare qgisfid%1 binary cursor with hold for select %2" )
641
- .arg (providerId).arg (quotedIdentifier (primaryKey));
642
-
643
- if (fetchGeometry)
571
+ // Top up our queue if it is empty
572
+ if (mFeatureQueue .empty ())
644
573
{
645
- declare += QString (" ,asbinary(%1,'%2') as qgs_feature_geometry" )
646
- .arg ( quotedIdentifier (geometryColumn) )
647
- .arg ( endianString () );
648
- }
574
+ QString fetch = QString (" fetch forward %1 from %2" ).arg (mFeatureQueueSize ).arg (cursorName);
575
+ if (mFirstFetch )
576
+ {
577
+ if (PQsendQuery (connection, fetch.toUtf8 ()) == 0 ) // fetch features in asynchronously
578
+ {
579
+ qWarning (" PQsendQuery failed (1)" );
580
+ }
581
+ }
582
+ mFirstFetch = false ;
583
+ queryResult = PQgetResult (connection);
584
+ PQgetResult (connection); // just to get the 0 pointer...
649
585
650
- for (namesIt = attributeNames.begin (); namesIt != attributeNames.end (); ++namesIt)
651
- {
652
- if ( (*namesIt) != primaryKey) // no need to fetch primary key again
586
+ int rows = PQntuples (queryResult);
587
+ if (rows == 0 )
653
588
{
654
- declare += " ," + quotedIdentifier (*namesIt) + " ::text" ;
589
+ QgsDebugMsg (" End of features" );
590
+ PQclear (queryResult);
591
+ return false ;
655
592
}
656
- }
657
593
658
- declare += QString (" from %1 where %2=%3" )
659
- .arg (mSchemaTableName )
660
- .arg (quotedIdentifier (primaryKey))
661
- .arg (featureId);
594
+ for (int row = 0 ; row < rows; row++)
595
+ {
596
+ mFeatureQueue .push (QgsFeature ());
597
+ getFeature (queryResult, row, mFetchGeom , mFeatureQueue .back (), mFetchAttributeNames , mAttributesToFetch );
598
+ } // for each row in queue
662
599
663
- QgsDebugMsg ( " Selecting feature using: " + declare );
600
+ PQclear (queryResult );
664
601
665
- // execute query
666
- PQexecNR (connection, declare.toUtf8 ());
667
-
668
- PGresult *res = PQexec (connection, QString (" fetch forward 1 from qgisfid%1" ).arg (providerId).toUtf8 ());
602
+ if (PQsendQuery (connection, fetch.toUtf8 ()) == 0 ) // already fetch the next couple of features asynchronously
603
+ {
604
+ qWarning (" PQsendQuery failed (2)" );
605
+ }
606
+ } // if new queue is required
669
607
670
- int rows = PQntuples (res);
671
- if (rows == 0 )
608
+ // Now return the next feature from the queue
609
+ if ( mFetchGeom )
672
610
{
673
- PQclear (res);
674
- PQexecNR (connection, QString (" CLOSE qgisfid%1" ).arg (providerId).toUtf8 ());
675
- QgsDebugMsg (" feature " + QString::number (featureId) + " not found" );
676
- return FALSE ;
611
+ QgsGeometry* featureGeom = mFeatureQueue .front ().geometryAndOwnership ();
612
+ feature.setGeometry (featureGeom);
677
613
}
614
+ else
615
+ {
616
+ feature.setGeometryAndOwnership (0 , 0 );
617
+ }
618
+ feature.setFeatureId (mFeatureQueue .front ().featureId ());
619
+ feature.setAttributeMap (mFeatureQueue .front ().attributeMap ());
678
620
679
- // set ID
680
- int oid = *(int *)PQgetvalue (res, 0 , PQfnumber (res,quotedIdentifier (primaryKey).toUtf8 ()));
681
- if (swapEndian)
682
- oid = ntohl (oid); // convert oid to opposite endian
683
- feature.setFeatureId (oid);
684
-
685
- // fetch attributes
686
- it = fetchAttributes.constBegin ();
621
+ mFeatureQueue .pop ();
687
622
688
- for (namesIt = attributeNames.begin (); namesIt != attributeNames.end (); ++namesIt, ++it)
689
- {
690
- QString val;
623
+ return true ;
624
+ }
691
625
692
- if ( (*namesIt) == primaryKey)
693
- {
694
- val = QString::number (oid);
695
- }
696
- else
697
- {
698
- int fn = PQfnumber (res,quotedIdentifier (*namesIt).toUtf8 ());
626
+ bool QgsPostgresProvider::getFeatureAtId (int featureId, QgsFeature& feature, bool fetchGeometry, QgsAttributeList fetchAttributes)
627
+ {
628
+ QStringList attributeNames;
629
+ QString cursorName = QString (" qgisfid%1" ).arg (providerId);
630
+ declareCursor ( cursorName, fetchAttributes, fetchGeometry, QString (" %2=%3" ).arg (quotedIdentifier (primaryKey)).arg (featureId), attributeNames );
699
631
700
- if ( PQgetisnull (res, 0 , fn) )
701
- val = QString::fromUtf8 (PQgetvalue (res, 0 , fn));
702
- else
703
- val = QString::null;
704
- }
632
+ PGresult *queryResult = PQexec (connection, QString (" fetch forward 1 from %1" ).arg (cursorName).toUtf8 ());
633
+ if (queryResult==0 )
634
+ return false ;
705
635
706
- if ( val.isNull () )
707
- {
708
- feature.addAttribute (*it, val);
709
- }
710
- else
711
- {
712
- switch (attributeFields[*it].type ())
713
- {
714
- case QVariant::LongLong:
715
- feature.addAttribute (*it, val.toLongLong ());
716
- break ;
717
- case QVariant::Int:
718
- feature.addAttribute (*it, val.toInt ());
719
- break ;
720
- case QVariant::Double:
721
- feature.addAttribute (*it, val.toDouble ());
722
- break ;
723
- case QVariant::String:
724
- feature.addAttribute (*it, val);
725
- break ;
726
- default :
727
- assert (0 && " unsupported field type" );
728
- }
729
- }
636
+ int rows = PQntuples (queryResult);
637
+ if (rows == 0 )
638
+ {
639
+ QgsDebugMsg (" feature " + QString::number (featureId) + " not found" );
640
+ PQclear (queryResult);
641
+ PQexecNR (connection, QString (" CLOSE %1" ).arg (cursorName).toUtf8 ());
642
+ return false ;
730
643
}
731
-
732
- // fetch geometry
733
- if (fetchGeometry)
644
+ else if (rows != 1 )
734
645
{
735
- int returnedLength = PQgetlength (res, 0 , PQfnumber (res," qgs_feature_geometry" ));
736
- if (returnedLength > 0 )
737
- {
738
- unsigned char *featureGeom = new unsigned char [returnedLength + 1 ];
739
- memset (featureGeom, ' \0 ' , returnedLength + 1 );
740
- memcpy (featureGeom, PQgetvalue (res, 0 , PQfnumber (res,QString (" qgs_feature_geometry" ).toUtf8 ())), returnedLength);
741
- feature.setGeometryAndOwnership (featureGeom, returnedLength + 1 );
742
- }
646
+ QgsDebugMsg ( QString (" found %1 features instead of just one." ).arg (rows) );
743
647
}
744
648
745
- PQclear (res);
746
- PQexecNR (connection, QString (" CLOSE qgisfid%1" ).arg (providerId).toUtf8 ());
649
+ getFeature (queryResult, 0 , fetchGeometry, feature, attributeNames, fetchAttributes);
650
+
651
+ PQclear (queryResult);
747
652
748
- return TRUE ;
653
+ PQexecNR (connection, QString (" CLOSE %1" ).arg (cursorName).toUtf8 ());
654
+ return true ;
749
655
}
750
656
657
+
751
658
QgsDataSourceURI& QgsPostgresProvider::getURI ()
752
659
{
753
660
return mUri ;
@@ -891,16 +798,38 @@ void QgsPostgresProvider::loadFields()
891
798
if (fieldName!=geometryColumn)
892
799
{
893
800
QVariant::Type fieldType;
894
- if (fieldTypeName.find (" int8" ) != -1 )
801
+ bool isArray = fieldTypeName.startsWith (" _" );
802
+
803
+ if (isArray)
804
+ fieldTypeName = fieldTypeName.mid (1 );
805
+
806
+ if (fieldTypeName == " int8" )
895
807
fieldType = QVariant::LongLong;
896
- else if (fieldTypeName.find (" int" ) != - 1 || fieldTypeName. find ( " serial" ) != - 1 )
808
+ else if (fieldTypeName.startsWith (" int" ) || fieldTypeName== " serial" )
897
809
fieldType = QVariant::Int;
898
- else if (fieldTypeName == " real" || fieldTypeName == " double precision" || fieldTypeName.find (" float" ) != - 1 )
810
+ else if (fieldTypeName == " real" || fieldTypeName == " double precision" || fieldTypeName.startsWith (" float" ) || fieldTypeName == " numeric " )
899
811
fieldType = QVariant::Double;
900
- else if (fieldTypeName == " bytea" )
901
- continue ;
812
+ else if (fieldTypeName == " text" ||
813
+ fieldTypeName == " char" ||
814
+ fieldTypeName == " bpchar" ||
815
+ fieldTypeName == " varchar" ||
816
+ fieldTypeName == " bool" ||
817
+ fieldTypeName == " money" ||
818
+ fieldTypeName.startsWith (" time" ) ||
819
+ fieldTypeName.startsWith (" date" ) )
820
+ fieldType = QVariant::String;
902
821
else
822
+ {
823
+ QgsDebugMsg ( " Field " + fieldName + " ignored, because of unsupported type " + fieldTypeName);
824
+ continue ;
825
+ }
826
+
827
+ if (isArray)
828
+ {
829
+ fieldTypeName = " _" + fieldTypeName;
903
830
fieldType = QVariant::String;
831
+ }
832
+
904
833
attributeFields.insert (i, QgsField (fieldName, fieldType, fieldTypeName, fieldSize.toInt (), fieldModifier, fieldComment));
905
834
}
906
835
}
@@ -1653,11 +1582,16 @@ QVariant QgsPostgresProvider::minValue(int index)
1653
1582
QString sql;
1654
1583
if (sqlWhereClause.isEmpty ())
1655
1584
{
1656
- sql = QString (" select min(%1) from %2" ).arg (quotedIdentifier (fld.name ())).arg (mSchemaTableName );
1585
+ sql = QString (" select min(%1) from %2" )
1586
+ .arg (quotedIdentifier (fld.name ()))
1587
+ .arg (mSchemaTableName );
1657
1588
}
1658
1589
else
1659
1590
{
1660
- sql = QString (" select min(%1) from %2" ).arg (quotedIdentifier (fld.name ())).arg (mSchemaTableName )+" where " +sqlWhereClause;
1591
+ sql = QString (" select min(%1) from %2 where %3" )
1592
+ .arg (quotedIdentifier (fld.name ()))
1593
+ .arg (mSchemaTableName )
1594
+ .arg (sqlWhereClause);
1661
1595
}
1662
1596
PGresult *rmin = PQexec (connection, sql.toUtf8 ());
1663
1597
QString minValue = QString::fromUtf8 (PQgetvalue (rmin,0 ,0 ));
@@ -1705,11 +1639,16 @@ QVariant QgsPostgresProvider::maxValue(int index)
1705
1639
QString sql;
1706
1640
if (sqlWhereClause.isEmpty ())
1707
1641
{
1708
- sql = QString (" select max(%1) from %2" ).arg (quotedIdentifier (fld.name ())).arg (mSchemaTableName );
1642
+ sql = QString (" select max(%1) from %2" )
1643
+ .arg (quotedIdentifier (fld.name ()))
1644
+ .arg (mSchemaTableName );
1709
1645
}
1710
1646
else
1711
1647
{
1712
- sql = QString (" select max(%1) from %2" ).arg (quotedIdentifier (fld.name ())).arg (mSchemaTableName )+" where " +sqlWhereClause;
1648
+ sql = QString (" select max(%1) from %2 where %3" )
1649
+ .arg (quotedIdentifier (fld.name ()))
1650
+ .arg (mSchemaTableName )
1651
+ .arg (sqlWhereClause);
1713
1652
}
1714
1653
PGresult *rmax = PQexec (connection, sql.toUtf8 ());
1715
1654
QString maxValue = QString::fromUtf8 (PQgetvalue (rmax,0 ,0 ));
@@ -1818,7 +1757,7 @@ QString QgsPostgresProvider::postgisVersion(PGconn *connection)
1818
1757
1819
1758
useWkbHex = postgisVersionMajor < 1 ;
1820
1759
1821
- gotPostgisVersion = TRUE ;
1760
+ gotPostgisVersion = true ;
1822
1761
1823
1762
return postgisVersionInfo;
1824
1763
}
@@ -1872,7 +1811,7 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1872
1811
// e.g. for defaults
1873
1812
for (QgsAttributeMap::const_iterator it = attributevec.begin (); it != attributevec.end (); it++)
1874
1813
{
1875
- QgsFieldMap::const_iterator fit = attributeFields.find ( it.key () );
1814
+ QgsFieldMap::const_iterator fit = attributeFields.find ( it.key () );
1876
1815
if (fit == attributeFields.end () )
1877
1816
continue ;
1878
1817
@@ -1897,7 +1836,7 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1897
1836
}
1898
1837
1899
1838
insert += " ," + quotedIdentifier (fieldname);
1900
-
1839
+
1901
1840
QString defVal = getDefaultValue ( it.key () ).toString ();
1902
1841
1903
1842
if ( i==flist.size () )
@@ -2685,8 +2624,7 @@ void QgsPostgresProvider::PQexecNR(PGconn *conn, const char *query)
2685
2624
}
2686
2625
}
2687
2626
2688
- void QgsPostgresProvider::showMessageBox (const QString& title,
2689
- const QString& text)
2627
+ void QgsPostgresProvider::showMessageBox (const QString& title, const QString& text)
2690
2628
{
2691
2629
QgsMessageOutput* message = QgsMessageOutput::createMessageOutput ();
2692
2630
message->setTitle (title);
0 commit comments