@@ -207,7 +207,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
207
207
// Set the postgresql message level so that we don't get the
208
208
// 'there is no transaction in progress' warning.
209
209
#ifndef QGISDEBUG
210
- PQexec (connection, QString (" set client_min_messages to error" ).toUtf8 ());
210
+ PQexecNR (connection, QString (" set client_min_messages to error" ).toUtf8 ());
211
211
#endif
212
212
213
213
// Kick off the long running threads
@@ -369,7 +369,7 @@ bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
369
369
370
370
PQclear (queryResult);
371
371
if (ready)
372
- PQexec (connection, QString (" end work" ).toUtf8 ());
372
+ PQexecNR (connection, QString (" end work" ).toUtf8 ());
373
373
ready = false ;
374
374
return false ;
375
375
}
@@ -393,17 +393,29 @@ bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
393
393
for (; name_it != mFetchAttributeNames .end (); ++name_it, ++index_it)
394
394
{
395
395
QString val;
396
+
396
397
if ( (*name_it) == primaryKey)
397
398
{
398
399
val = QString::number (oid);
399
400
}
400
401
else
401
402
{
402
- val = QString::fromUtf8 (PQgetvalue (queryResult, row, PQfnumber (queryResult,quotedIdentifier (*name_it).toUtf8 ())));
403
+ int fn = PQfnumber (queryResult,quotedIdentifier (*name_it).toUtf8 ());
404
+
405
+ if ( !PQgetisnull (queryResult, row, fn) )
406
+ val = QString::fromUtf8 (PQgetvalue (queryResult, row, fn));
407
+ else
408
+ val = QString::null;
403
409
}
404
410
405
- switch (attributeFields[*index_it].type ())
411
+ if ( val.isNull () )
412
+ {
413
+ mFeatureQueue .back ().addAttribute (*index_it, val);
414
+ }
415
+ else
406
416
{
417
+ switch (attributeFields[*index_it].type ())
418
+ {
407
419
case QVariant::LongLong:
408
420
mFeatureQueue .back ().addAttribute (*index_it, val.toLongLong ());
409
421
break ;
@@ -418,6 +430,7 @@ bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
418
430
break ;
419
431
default :
420
432
assert (0 && " unsupported field type" );
433
+ }
421
434
}
422
435
}
423
436
@@ -559,11 +572,11 @@ void QgsPostgresProvider::select(QgsAttributeList fetchAttributes,
559
572
560
573
// set up the cursor
561
574
if (ready){
562
- PQexec (connection, QString (" end work" ).toUtf8 ());
575
+ PQexecNR (connection, QString (" end work" ).toUtf8 ());
563
576
}
564
- PQexec (connection,QString (" begin work" ).toUtf8 ());
577
+ PQexecNR (connection,QString (" begin work" ).toUtf8 ());
565
578
ready = true ;
566
- PQexec (connection, declare.toUtf8 ());
579
+ PQexecNR (connection, declare.toUtf8 ());
567
580
568
581
while (!mFeatureQueue .empty ())
569
582
{
@@ -614,18 +627,18 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId,
614
627
615
628
QgsDebugMsg (" Selecting feature using: " + sql);
616
629
617
- PQexec (connection,QString (" begin work" ).toUtf8 ());
630
+ PQexecNR (connection,QString (" begin work" ).toUtf8 ());
618
631
619
632
// execute query
620
- PQexec (connection, sql.toUtf8 ());
633
+ PQexecNR (connection, sql.toUtf8 ());
621
634
622
635
PGresult *res = PQexec (connection, QString (" fetch forward 1 from qgisfid" ).toUtf8 ());
623
636
624
637
int rows = PQntuples (res);
625
638
if (rows == 0 )
626
639
{
627
640
PQclear (res);
628
- PQexec (connection, QString (" end work" ).toUtf8 ());
641
+ PQexecNR (connection, QString (" end work" ).toUtf8 ());
629
642
QgsDebugMsg (" feature " + QString::number (featureId) + " not found" );
630
643
return FALSE ;
631
644
}
@@ -642,17 +655,29 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId,
642
655
for (namesIt = attributeNames.begin (); namesIt != attributeNames.end (); ++namesIt, ++it)
643
656
{
644
657
QString val;
658
+
645
659
if ( (*namesIt) == primaryKey)
646
660
{
647
661
val = QString::number (oid);
648
662
}
649
663
else
650
664
{
651
- val = QString::fromUtf8 (PQgetvalue (res, 0 , PQfnumber (res,quotedIdentifier (*namesIt).toUtf8 ())));
665
+ int fn = PQfnumber (res,quotedIdentifier (*namesIt).toUtf8 ());
666
+
667
+ if ( PQgetisnull (res, 0 , fn) )
668
+ val = QString::fromUtf8 (PQgetvalue (res, 0 , fn));
669
+ else
670
+ val = QString::null;
652
671
}
653
672
654
- switch (attributeFields[*it].type ())
673
+ if ( val.isNull () )
674
+ {
675
+ feature.addAttribute (*it, val);
676
+ }
677
+ else
655
678
{
679
+ switch (attributeFields[*it].type ())
680
+ {
656
681
case QVariant::LongLong:
657
682
feature.addAttribute (*it, val.toLongLong ());
658
683
break ;
@@ -667,6 +692,7 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId,
667
692
break ;
668
693
default :
669
694
assert (0 && " unsupported field type" );
695
+ }
670
696
}
671
697
}
672
698
@@ -684,7 +710,7 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId,
684
710
}
685
711
686
712
PQclear (res);
687
- PQexec (connection, QString (" end work" ).toUtf8 ());
713
+ PQexecNR (connection, QString (" end work" ).toUtf8 ());
688
714
689
715
return TRUE ;
690
716
}
@@ -745,7 +771,7 @@ QString QgsPostgresProvider::dataComment() const
745
771
void QgsPostgresProvider::reset ()
746
772
{
747
773
QString move = " move 0 in qgisf" ; // move cursor to first record
748
- PQexec (connection, move.toUtf8 ());
774
+ PQexecNR (connection, move.toUtf8 ());
749
775
mFeatureQueue .empty ();
750
776
loadFields ();
751
777
}
@@ -1660,20 +1686,22 @@ QVariant QgsPostgresProvider::getDefaultValue(int fieldId)
1660
1686
1661
1687
QString fieldName = attributeFields[fieldId].name ();
1662
1688
1663
- QString sql (" SELECT column_default FROM "
1664
- " information_schema.columns WHERE "
1665
- " column_default IS NOT NULL AND "
1666
- " table_schema = ' " + mSchemaName + " ' AND "
1667
- " table_name = ' " + mTableName + " ' AND "
1668
- " column_name = ' " + fieldName + " ' " );
1689
+ QString sql (" SELECT column_default FROM"
1690
+ " information_schema.columns WHERE"
1691
+ " column_default IS NOT NULL"
1692
+ " AND table_schema = " + quotedValue ( mSchemaName ) +
1693
+ " AND table_name = " + quotedValue ( mTableName ) +
1694
+ " AND column_name = " + quotedValue ( fieldName) );
1669
1695
1670
- QString defaultValue ( " " ) ;
1696
+ QVariant defaultValue = QString::null ;
1671
1697
1672
1698
PGresult* result = PQexec (connection, sql.toUtf8 ());
1673
1699
1674
- if (PQntuples (result) == 1 )
1700
+ if (PQntuples (result)== 1 && ! PQgetisnull (result, 0 , 0 ) )
1675
1701
defaultValue = QString::fromUtf8 (PQgetvalue (result, 0 , 0 ));
1676
1702
1703
+ QgsDebugMsg ( QString (" defaultValue for %1 is NULL: %2" ).arg (fieldId).arg ( defaultValue.isNull () ) );
1704
+
1677
1705
PQclear (result);
1678
1706
1679
1707
return defaultValue;
@@ -1735,14 +1763,20 @@ QString QgsPostgresProvider::postgisVersion(PGconn *connection)
1735
1763
1736
1764
QByteArray QgsPostgresProvider::paramValue (QString fieldValue, const QString &defaultValue) const
1737
1765
{
1738
- if ( fieldValue== " NULL " )
1739
- return 0 ;
1766
+ if ( fieldValue. isNull () )
1767
+ return QByteArray ( 0 ); // QByteArray(0).isNull() is true
1740
1768
1741
- if ( fieldValue==defaultValue && !defaultValue.isEmpty () )
1769
+ if ( fieldValue==defaultValue && !defaultValue.isNull () )
1742
1770
{
1743
1771
PGresult *result = PQexec ( connection, QString (" select %1" ).arg (defaultValue).toUtf8 () );
1744
- fieldValue = QString::fromUtf8 (PQgetvalue (result,0 ,0 ));
1745
- PQclear (result);
1772
+ if ( PQgetisnull (result, 0 , 0 ) ) {
1773
+ PQclear (result);
1774
+ return QByteArray (0 ); // QByteArray(0).isNull() is true
1775
+ } else {
1776
+ QString val = QString::fromUtf8 (PQgetvalue (result,0 ,0 ));
1777
+ PQclear (result);
1778
+ return val.toUtf8 ();
1779
+ }
1746
1780
}
1747
1781
1748
1782
return fieldValue.toUtf8 ();
@@ -1756,7 +1790,7 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1756
1790
bool returnvalue=true ;
1757
1791
1758
1792
try {
1759
- PQexec (connection,QString (" BEGIN" ).toUtf8 ());
1793
+ PQexecNR (connection,QString (" BEGIN" ).toUtf8 ());
1760
1794
1761
1795
// Prepare the INSERT statement
1762
1796
QString insert = QString (" INSERT INTO %1(%2,%3" )
@@ -1784,11 +1818,9 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1784
1818
1785
1819
QgsDebugMsg (" Checking field against: " + fieldname);
1786
1820
1787
- if ( fieldname.isEmpty () || fieldname==geometryColumn || fieldname==primaryKey || it-> isNull () )
1821
+ if ( fieldname.isEmpty () || fieldname==geometryColumn || fieldname==primaryKey )
1788
1822
continue ;
1789
1823
1790
- QString fieldvalue = it->toString ();
1791
-
1792
1824
int i;
1793
1825
for (i=1 ; i<flist.size (); i++)
1794
1826
{
@@ -1798,7 +1830,7 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1798
1830
if ( thisit == attributevec.end () )
1799
1831
break ;
1800
1832
1801
- if ( thisit-> toString () != fieldvalue )
1833
+ if ( * thisit!=*it )
1802
1834
break ;
1803
1835
}
1804
1836
@@ -1808,13 +1840,13 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1808
1840
1809
1841
if ( i==flist.size () )
1810
1842
{
1811
- if ( fieldvalue== " NULL " || (fieldvalue== defVal && ! defVal. isEmpty ()) )
1843
+ if ( ! defVal. isNull () && *it== defVal) {
1812
1844
{
1813
- values += " ," + fieldvalue ;
1845
+ values += " ," + defVal ;
1814
1846
}
1815
1847
else
1816
1848
{
1817
- values += " ," + quotedValue (fieldvalue );
1849
+ values += " ," + quotedValue ( it-> toString () );
1818
1850
}
1819
1851
}
1820
1852
else
@@ -1832,6 +1864,8 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1832
1864
if (stmt==0 || PQresultStatus (stmt)==PGRES_FATAL_ERROR)
1833
1865
throw PGException (stmt);
1834
1866
1867
+ PQclear (stmt);
1868
+
1835
1869
int primaryKeyHighWater = maxPrimaryKeyValue ();
1836
1870
const char **param = new const char *[ fieldId.size ()+2 ];
1837
1871
@@ -1853,27 +1887,30 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1853
1887
for (int i=0 ; i<fieldId.size (); i++)
1854
1888
{
1855
1889
qparam.append ( paramValue ( attributevec[ fieldId[i] ].toString (), defaultValue[i] ) );
1856
- param[i+2 ] = qparam[i+2 ];
1890
+ if ( qparam[i+2 ].isNull () )
1891
+ param[i+2 ] = 0 ;
1892
+ else
1893
+ param[i+2 ] = qparam[i+2 ];
1857
1894
}
1858
1895
1859
1896
PGresult *result = PQexecPrepared (connection, " addfeatures" , fieldId.size ()+2 , param, NULL , NULL , 0 );
1860
1897
if ( result==0 || PQresultStatus (result)==PGRES_FATAL_ERROR )
1861
1898
{
1862
- PQclear (stmt);
1863
1899
delete param;
1864
1900
throw PGException (result);
1865
1901
}
1866
1902
1867
1903
PQclear (result);
1868
1904
}
1869
1905
1870
- PQclear (stmt);
1906
+ PQexecNR (connection,QString (" COMMIT" ).toUtf8 ());
1907
+ PQexecNR (connection,QString (" DEALLOCATE addfeatures" ).toUtf8 ());
1871
1908
delete param;
1872
-
1873
- PQexec (connection,QString (" COMMIT" ).toUtf8 ());
1874
1909
} catch (PGException &e) {
1875
1910
e.showErrorMessage ( tr (" Error while adding features" ) );
1876
- PQexec (connection,QString (" ROLLBACK" ).toUtf8 ());
1911
+ PQexecNR (connection,QString (" ROLLBACK" ).toUtf8 ());
1912
+
1913
+ PQexecNR (connection,QString (" DEALLOCATE addfeatures" ).toUtf8 ());
1877
1914
returnvalue = false ;
1878
1915
}
1879
1916
@@ -1886,7 +1923,7 @@ bool QgsPostgresProvider::deleteFeatures(const QgsFeatureIds & id)
1886
1923
bool returnvalue=true ;
1887
1924
1888
1925
try {
1889
- PQexec (connection,QString (" BEGIN" ).toUtf8 ());
1926
+ PQexecNR (connection,QString (" BEGIN" ).toUtf8 ());
1890
1927
1891
1928
for (QgsFeatureIds::const_iterator it=id.begin ();it!=id.end ();++it) {
1892
1929
QString sql (" DELETE FROM " +mSchemaTableName +" WHERE " +quotedIdentifier (primaryKey)+" =" +QString::number (*it));
@@ -1900,10 +1937,10 @@ bool QgsPostgresProvider::deleteFeatures(const QgsFeatureIds & id)
1900
1937
PQclear (result);
1901
1938
}
1902
1939
1903
- PQexec (connection,QString (" COMMIT" ).toUtf8 ());
1940
+ PQexecNR (connection,QString (" COMMIT" ).toUtf8 ());
1904
1941
} catch (PGException &e) {
1905
1942
e.showErrorMessage ( tr (" Error while deleting features" ) );
1906
- PQexec (connection,QString (" ROLLBACK" ).toUtf8 ());
1943
+ PQexecNR (connection,QString (" ROLLBACK" ).toUtf8 ());
1907
1944
returnvalue = false ;
1908
1945
}
1909
1946
reset ();
@@ -1915,7 +1952,7 @@ bool QgsPostgresProvider::addAttributes(const QgsNewAttributesMap & name)
1915
1952
bool returnvalue=true ;
1916
1953
1917
1954
try {
1918
- PQexec (connection,QString (" BEGIN" ).toUtf8 ());
1955
+ PQexecNR (connection,QString (" BEGIN" ).toUtf8 ());
1919
1956
1920
1957
for (QgsNewAttributesMap::const_iterator iter=name.begin ();iter!=name.end ();++iter)
1921
1958
{
@@ -1930,10 +1967,10 @@ bool QgsPostgresProvider::addAttributes(const QgsNewAttributesMap & name)
1930
1967
PQclear (result);
1931
1968
}
1932
1969
1933
- PQexec (connection,QString (" COMMIT" ).toUtf8 ());
1970
+ PQexecNR (connection,QString (" COMMIT" ).toUtf8 ());
1934
1971
} catch (PGException &e) {
1935
1972
e.showErrorMessage ( tr (" Error while adding attributes" ) );
1936
- PQexec (connection,QString (" ROLLBACK" ).toUtf8 ());
1973
+ PQexecNR (connection,QString (" ROLLBACK" ).toUtf8 ());
1937
1974
returnvalue = false ;
1938
1975
}
1939
1976
@@ -1946,7 +1983,7 @@ bool QgsPostgresProvider::deleteAttributes(const QgsAttributeIds& ids)
1946
1983
bool returnvalue=true ;
1947
1984
1948
1985
try {
1949
- PQexec (connection,QString (" BEGIN" ).toUtf8 ());
1986
+ PQexecNR (connection,QString (" BEGIN" ).toUtf8 ());
1950
1987
1951
1988
for (QgsAttributeIds::const_iterator iter=ids.begin ();iter != ids.end ();++iter)
1952
1989
{
@@ -1967,10 +2004,10 @@ bool QgsPostgresProvider::deleteAttributes(const QgsAttributeIds& ids)
1967
2004
attributeFields.remove (*iter);
1968
2005
}
1969
2006
1970
- PQexec (connection,QString (" COMMIT" ).toUtf8 ());
2007
+ PQexecNR (connection,QString (" COMMIT" ).toUtf8 ());
1971
2008
} catch (PGException &e) {
1972
2009
e.showErrorMessage ( tr (" Error while deleting attributes" ) );
1973
- PQexec (connection,QString (" ROLLBACK" ).toUtf8 ());
2010
+ PQexecNR (connection,QString (" ROLLBACK" ).toUtf8 ());
1974
2011
returnvalue = false ;
1975
2012
}
1976
2013
@@ -1983,7 +2020,7 @@ bool QgsPostgresProvider::changeAttributeValues(const QgsChangedAttributesMap &
1983
2020
bool returnvalue=true ;
1984
2021
1985
2022
try {
1986
- PQexec (connection,QString (" BEGIN" ).toUtf8 ());
2023
+ PQexecNR (connection,QString (" BEGIN" ).toUtf8 ());
1987
2024
1988
2025
// cycle through the features
1989
2026
for (QgsChangedAttributesMap::const_iterator iter=attr_map.begin ();iter!=attr_map.end ();++iter)
@@ -2016,10 +2053,10 @@ bool QgsPostgresProvider::changeAttributeValues(const QgsChangedAttributesMap &
2016
2053
}
2017
2054
}
2018
2055
2019
- PQexec (connection,QString (" COMMIT" ).toUtf8 ());
2056
+ PQexecNR (connection,QString (" COMMIT" ).toUtf8 ());
2020
2057
} catch (PGException &e) {
2021
2058
e.showErrorMessage ( tr (" Error while changing attributes" ) );
2022
- PQexec (connection,QString (" ROLLBACK" ).toUtf8 ());
2059
+ PQexecNR (connection,QString (" ROLLBACK" ).toUtf8 ());
2023
2060
returnvalue = false ;
2024
2061
}
2025
2062
@@ -2048,7 +2085,7 @@ bool QgsPostgresProvider::changeGeometryValues(QgsGeometryMap & geometry_map)
2048
2085
2049
2086
try {
2050
2087
// Start the PostGIS transaction
2051
- PQexec (connection,QString (" BEGIN" ).toUtf8 ());
2088
+ PQexecNR (connection,QString (" BEGIN" ).toUtf8 ());
2052
2089
2053
2090
for (QgsGeometryMap::iterator iter = geometry_map.begin ();
2054
2091
iter != geometry_map.end ();
@@ -2080,10 +2117,10 @@ bool QgsPostgresProvider::changeGeometryValues(QgsGeometryMap & geometry_map)
2080
2117
} // if (*iter)
2081
2118
} // for each feature
2082
2119
2083
- PQexec (connection,QString (" COMMIT" ).toUtf8 ());
2120
+ PQexecNR (connection,QString (" COMMIT" ).toUtf8 ());
2084
2121
} catch (PGException &e) {
2085
2122
e.showErrorMessage ( tr (" Error while changing attributes" ) );
2086
- PQexec (connection,QString (" ROLLBACK" ).toUtf8 ());
2123
+ PQexecNR (connection,QString (" ROLLBACK" ).toUtf8 ());
2087
2124
returnvalue = false ;
2088
2125
}
2089
2126
@@ -2364,16 +2401,16 @@ bool QgsPostgresProvider::deduceEndian()
2364
2401
2365
2402
// get the same value using a binary cursor
2366
2403
2367
- PQexec (connection,QString (" begin work" ).toUtf8 ());
2404
+ PQexecNR (connection,QString (" begin work" ).toUtf8 ());
2368
2405
QString oidDeclare = " declare oidcursor binary cursor for select regclass('" + mSchemaTableName + " ')::oid" ;
2369
2406
// set up the cursor
2370
- PQexec (connection, oidDeclare.toUtf8 ());
2407
+ PQexecNR (connection, oidDeclare.toUtf8 ());
2371
2408
QString fetch = " fetch forward 1 from oidcursor" ;
2372
2409
2373
2410
QgsDebugMsg (" Fetching a record and attempting to get check endian-ness" );
2374
2411
2375
2412
PGresult *fResult = PQexec (connection, fetch.toUtf8 ());
2376
- PQexec (connection, QString (" end work" ).toUtf8 ());
2413
+ PQexecNR (connection, QString (" end work" ).toUtf8 ());
2377
2414
swapEndian = true ;
2378
2415
if (PQntuples (fResult ) > 0 ){
2379
2416
// get the oid value from the binary cursor
@@ -2548,11 +2585,32 @@ QString QgsPostgresProvider::quotedIdentifier( QString ident )
2548
2585
2549
2586
QString QgsPostgresProvider::quotedValue ( QString value )
2550
2587
{
2588
+ if ( value.isNull () )
2589
+ return " NULL" ;
2590
+
2551
2591
// FIXME: use PQescapeStringConn
2552
2592
value.replace (" '" , " ''" );
2553
2593
return value.prepend (" '" ).append (" '" );
2554
2594
}
2555
2595
2596
+ void QgsPostgresProvider::PQexecNR (PGconn *conn, const char *query)
2597
+ {
2598
+ PGresult *res = PQexec (conn, query);
2599
+ if (res)
2600
+ {
2601
+ QgsDebugMsg ( QString (" Query: %1 returned %2 [%3]" )
2602
+ .arg (query)
2603
+ .arg (PQresStatus (PQresultStatus (res)))
2604
+ .arg (PQresultErrorMessage (res))
2605
+ );
2606
+ PQclear (res);
2607
+ }
2608
+ else
2609
+ {
2610
+ QgsDebugMsg ( QString (" Query: %1 returned no result buffer" ).arg (query) );
2611
+ }
2612
+ }
2613
+
2556
2614
void QgsPostgresProvider::showMessageBox (const QString& title,
2557
2615
const QString& text)
2558
2616
{
0 commit comments