Skip to content

Commit 9487036

Browse files
author
morb_au
committed
In the PostGIS provider, restored the ability to save added and
changed geometries to pre-1.0 PostGIS servers (pre-r3907). This also now includes the ability to sniff the PostGIS version. git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@5549 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 3d8060f commit 9487036

File tree

2 files changed

+155
-37
lines changed

2 files changed

+155
-37
lines changed

src/providers/postgres/qgspostgresprovider.cpp

+146-37
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ const QString POSTGRES_DESCRIPTION = "PostgreSQL/PostGIS data provider";
6363

6464

6565
QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
66-
: QgsVectorDataProvider(uri), geomType(QGis::WKBUnknown)
66+
: QgsVectorDataProvider(uri),
67+
geomType(QGis::WKBUnknown),
68+
gotPostgisVersion(FALSE)
6769
{
6870
// assume this is a valid layer until we determine otherwise
6971
valid = true;
@@ -1457,8 +1459,31 @@ bool QgsPostgresProvider::addFeature(QgsFeature* f, int primaryKeyHighWater)
14571459
<< "." << std::endl;
14581460
#endif
14591461

1460-
if(f)
1462+
if (f)
14611463
{
1464+
// Determine which insertion method to use for WKB
1465+
// PostGIS 1.0+ uses BYTEA
1466+
// earlier versions use HEX
1467+
bool useWkbHex(FALSE);
1468+
1469+
if (!gotPostgisVersion)
1470+
{
1471+
postgisVersion(connection);
1472+
}
1473+
1474+
#ifdef QGISDEBUG
1475+
std::cout << "QgsPostgresProvider::addFeature: PostGIS version is "
1476+
<< " major: " << postgisVersionMajor
1477+
<< ", minor: " << postgisVersionMinor
1478+
<< "." << std::endl;
1479+
#endif
1480+
1481+
if (postgisVersionMajor < 1)
1482+
{
1483+
useWkbHex = TRUE;
1484+
}
1485+
1486+
// Start building insert string
14621487
QString insert("INSERT INTO ");
14631488
insert+=mSchemaTableName;
14641489
insert+=" (";
@@ -1524,12 +1549,27 @@ bool QgsPostgresProvider::addFeature(QgsFeature* f, int primaryKeyHighWater)
15241549

15251550
insert+=") VALUES (GeomFromWKB('";
15261551

1527-
//add the wkb geometry to the insert statement
1528-
unsigned char* geom=f->getGeometry();
1529-
for(int i=0;i<f->getGeometrySize();++i)
1552+
// Add the WKB geometry to the INSERT statement
1553+
unsigned char* geom = f->getGeometry();
1554+
for (int i=0; i < f->getGeometrySize(); ++i)
15301555
{
1531-
//Postgis 1.0 wants bytea instead of hex
1532-
QString oct = QString::number((int)geom[i], 8);
1556+
if (useWkbHex)
1557+
{
1558+
// PostGIS < 1.0 wants hex
1559+
QString hex = QString::number((int) geom[i], 16).upper();
1560+
1561+
if (hex.length() == 1)
1562+
{
1563+
hex = "0" + hex;
1564+
}
1565+
1566+
insert += hex;
1567+
}
1568+
else
1569+
{
1570+
// Postgis 1.0 wants bytea
1571+
QString oct = QString::number((int) geom[i], 8);
1572+
15331573
if(oct.length()==3)
15341574
{
15351575
oct="\\\\"+oct;
@@ -1542,9 +1582,19 @@ bool QgsPostgresProvider::addFeature(QgsFeature* f, int primaryKeyHighWater)
15421582
{
15431583
oct="\\\\0"+oct;
15441584
}
1545-
insert+=oct;
1585+
1586+
insert += oct;
1587+
}
1588+
}
1589+
1590+
if (useWkbHex)
1591+
{
1592+
insert += "',"+srid+")";
1593+
}
1594+
else
1595+
{
1596+
insert += "::bytea',"+srid+")";
15461597
}
1547-
insert+="::bytea',"+srid+")";
15481598

15491599
//add the primary key value to the insert statement
15501600
insert += ",";
@@ -1695,20 +1745,31 @@ bool QgsPostgresProvider::hasGEOS(PGconn *connection){
16951745
// get geos capability
16961746
return geosAvailable;
16971747
}
1748+
16981749
/* Functions for determining available features in postGIS */
1699-
QString QgsPostgresProvider::postgisVersion(PGconn *connection){
1750+
QString QgsPostgresProvider::postgisVersion(PGconn *connection)
1751+
{
17001752
PGresult *result = PQexec(connection, "select postgis_version()");
17011753
postgisVersionInfo = PQgetvalue(result,0,0);
17021754
#ifdef QGISDEBUG
17031755
std::cerr << "PostGIS version info: " << postgisVersionInfo.toLocal8Bit().data() << std::endl;
17041756
#endif
17051757
PQclear(result);
1758+
1759+
QStringList postgisParts = QStringList::split(" ", postgisVersionInfo);
1760+
1761+
// Get major and minor version
1762+
QStringList postgisVersionParts = QStringList::split(".", postgisParts[0]);
1763+
1764+
postgisVersionMajor = postgisVersionParts[0].toInt();
1765+
postgisVersionMinor = postgisVersionParts[1].toInt();
1766+
17061767
// assume no capabilities
17071768
geosAvailable = false;
17081769
gistAvailable = false;
17091770
projAvailable = false;
1771+
17101772
// parse out the capabilities and store them
1711-
QStringList postgisParts = QStringList::split(" ", postgisVersionInfo);
17121773
QStringList geos = postgisParts.grep("GEOS");
17131774
if(geos.size() == 1){
17141775
geosAvailable = (geos[0].find("=1") > -1);
@@ -1721,6 +1782,9 @@ QString QgsPostgresProvider::postgisVersion(PGconn *connection){
17211782
if(proj.size() == 1){
17221783
projAvailable = (proj[0].find("=1") > -1);
17231784
}
1785+
1786+
gotPostgisVersion = TRUE;
1787+
17241788
return postgisVersionInfo;
17251789
}
17261790

@@ -1882,9 +1946,33 @@ bool QgsPostgresProvider::changeGeometryValues(std::map<int, QgsGeometry> & geom
18821946
std::cerr << "QgsPostgresProvider::changeGeometryValues: entering."
18831947
<< std::endl;
18841948
#endif
1885-
1886-
bool returnvalue=true;
1887-
1949+
1950+
bool returnvalue = true;
1951+
1952+
// Determine which insertion method to use for WKB
1953+
// PostGIS 1.0+ uses BYTEA
1954+
// earlier versions use HEX
1955+
bool useWkbHex(FALSE);
1956+
1957+
if (!gotPostgisVersion)
1958+
{
1959+
postgisVersion(connection);
1960+
}
1961+
1962+
#ifdef QGISDEBUG
1963+
std::cout << "QgsPostgresProvider::addFeature: PostGIS version is "
1964+
<< " major: " << postgisVersionMajor
1965+
<< ", minor: " << postgisVersionMinor
1966+
<< "." << std::endl;
1967+
#endif
1968+
1969+
if (postgisVersionMajor < 1)
1970+
{
1971+
useWkbHex = TRUE;
1972+
}
1973+
1974+
// Start the PostGIS transaction
1975+
18881976
PQexec(connection,"BEGIN");
18891977

18901978
for(std::map<int, QgsGeometry>::const_iterator iter = geometry_map.begin();
@@ -1907,36 +1995,57 @@ bool QgsPostgresProvider::changeGeometryValues(std::map<int, QgsGeometry> & geom
19071995

19081996
QString sql = "UPDATE "+ mSchemaTableName +" SET " +
19091997
geometryColumn + "=";
1910-
1998+
19111999
sql += "GeomFromWKB('";
19122000

1913-
//add the wkb geometry to the insert statement
2001+
// Add the WKB geometry to the UPDATE statement
19142002
unsigned char* geom = iter->second.wkbBuffer();
1915-
19162003
for (int i=0; i < iter->second.wkbSize(); ++i)
19172004
{
1918-
//Postgis 1.0 wants bytea instead of hex
1919-
QString oct = QString::number((int)geom[i], 8);
1920-
if(oct.length()==3)
1921-
{
1922-
oct="\\\\"+oct;
1923-
}
1924-
else if(oct.length()==1)
1925-
{
1926-
oct="\\\\00"+oct;
1927-
}
1928-
else if(oct.length()==2)
1929-
{
1930-
oct="\\\\0"+oct;
1931-
}
1932-
sql += oct;
2005+
if (useWkbHex)
2006+
{
2007+
// PostGIS < 1.0 wants hex
2008+
QString hex = QString::number((int) geom[i], 16).upper();
2009+
2010+
if (hex.length() == 1)
2011+
{
2012+
hex = "0" + hex;
2013+
}
2014+
2015+
sql += hex;
2016+
}
2017+
else
2018+
{
2019+
// Postgis 1.0 wants bytea
2020+
QString oct = QString::number((int) geom[i], 8);
2021+
2022+
if(oct.length()==3)
2023+
{
2024+
oct="\\\\"+oct;
2025+
}
2026+
else if(oct.length()==1)
2027+
{
2028+
oct="\\\\00"+oct;
2029+
}
2030+
else if(oct.length()==2)
2031+
{
2032+
oct="\\\\0"+oct;
2033+
}
2034+
2035+
sql += oct;
2036+
}
19332037
}
1934-
sql+="::bytea',"+srid+")";
1935-
sql+=" WHERE " +primaryKey+"="+QString::number(iter->first);
19362038

1937-
#ifdef QGISDEBUG
1938-
qWarning(sql);
1939-
#endif
2039+
if (useWkbHex)
2040+
{
2041+
sql += "',"+srid+")";
2042+
}
2043+
else
2044+
{
2045+
sql += "::bytea',"+srid+")";
2046+
}
2047+
2048+
sql += " WHERE " +primaryKey+"="+QString::number(iter->first);
19402049

19412050
#ifdef QGISDEBUG
19422051
std::cerr << "QgsPostgresProvider::changeGeometryValues: Updating with '"

src/providers/postgres/qgspostgresprovider.h

+9
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,15 @@ class QgsPostgresProvider:public QgsVectorDataProvider
500500
//! PostGIS version string
501501
QString postgisVersionInfo;
502502

503+
//! Are postgisVersionMajor, postgisVersionMinor, geosAvailable, gistAvailable, projAvailable valid?
504+
bool gotPostgisVersion;
505+
506+
//! PostGIS major version
507+
int postgisVersionMajor;
508+
509+
//! PostGIS minor version
510+
int postgisVersionMinor;
511+
503512
//! GEOS capability
504513
bool geosAvailable;
505514

0 commit comments

Comments
 (0)