Skip to content

Commit c12cae2

Browse files
author
g_j_m
committed
Fix for ticket #277 (can't display data in postgres that is a view of a view)
The longstanding problem where views that renamed their column names weren't loaded is also fixed. Another problem where qgis wouldn't load a table where the table name or key column name contained capital letters is also fixed (everything is now laboriously quoted correctly). git-svn-id: http://svn.osgeo.org/qgis/trunk@5957 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent c16854a commit c12cae2

File tree

2 files changed

+89
-47
lines changed

2 files changed

+89
-47
lines changed

src/gui/qgsdbsourceselect.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,10 @@ void QgsDbSourceSelect::setLayerType(QString schema,
201201
QString QgsDbSourceSelect::makeGeomQuery(QString schema,
202202
QString table, QString column)
203203
{
204-
QString query = "select GeometryType(" + column + ") from ";
204+
QString query = "select GeometryType(\"" + column + "\") from ";
205205
if (schema.length() > 0)
206206
query += "\"" + schema + "\".";
207-
query += "\"" + table + "\" where " + column + " is not null limit 1";
207+
query += "\"" + table + "\" where \"" + column + "\" is not null limit 1";
208208
return query;
209209
}
210210

src/providers/postgres/qgspostgresprovider.cpp

+87-45
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ QgsFeature *QgsPostgresProvider::getNextFeature(bool fetchAttributes)
436436

437437
// get the value of the primary key based on type
438438

439-
int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,primaryKey));
439+
int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,"\""+primaryKey+"\""));
440440
#ifdef QGISDEBUG
441441
// std::cerr << "OID from database: " << oid << std::endl;
442442
#endif
@@ -508,7 +508,7 @@ QgsFeature* QgsPostgresProvider::getNextFeature(std::list<int> const & attlist,
508508
queryResult = PQexec(connection, (const char *)fetch);
509509

510510
int rows = PQntuples(queryResult);
511-
511+
512512
if (rows == 0)
513513
{
514514
#ifdef QGISDEBUG
@@ -521,7 +521,7 @@ QgsFeature* QgsPostgresProvider::getNextFeature(std::list<int> const & attlist,
521521

522522
for (int row = 0; row < rows; row++)
523523
{
524-
int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,primaryKey));
524+
int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,"\""+primaryKey+"\""));
525525
#ifdef QGISDEBUG
526526
// std::cerr << "Primary key type is " << primaryKeyType << std::endl;
527527
#endif
@@ -601,9 +601,9 @@ void QgsPostgresProvider::select(QgsRect * rect, bool useIntersect)
601601
std::cerr << "Selection polygon is " << rect->asPolygon().toLocal8Bit().data() << std::endl;
602602
#endif
603603

604-
QString declare = QString("declare qgisf binary cursor for select "
604+
QString declare = QString("declare qgisf binary cursor for select \""
605605
+ primaryKey
606-
+ ",asbinary(%1,'%2') as qgs_feature_geometry from %3").arg(geometryColumn).arg(endianString()).arg(mSchemaTableName);
606+
+ "\",asbinary(\"%1\",'%2') as qgs_feature_geometry from %3").arg(geometryColumn).arg(endianString()).arg(mSchemaTableName);
607607
#ifdef QGISDEBUG
608608
std::cout << "Binary cursor: " << declare.toLocal8Bit().data() << std::endl;
609609
#endif
@@ -727,7 +727,7 @@ int QgsPostgresProvider::fieldCount() const
727727
*/
728728
void QgsPostgresProvider::getFeatureAttributes(int key, int &row, QgsFeature *f) {
729729

730-
QString sql = QString("select * from %1 where %2 = %3").arg(mSchemaTableName).arg(primaryKey).arg(key);
730+
QString sql = QString("select * from %1 where \"%2\" = %3").arg(mSchemaTableName).arg(primaryKey).arg(key);
731731

732732
#ifdef QGISDEBUG
733733
std::cerr << "QgsPostgresProvider::getFeatureAttributes using: " << sql.toLocal8Bit().data() << std::endl;
@@ -756,7 +756,7 @@ void QgsPostgresProvider::getFeatureAttributes(int key, int &row,
756756
std::list<int>::const_iterator iter;
757757
for(iter=attlist.begin();iter!=attlist.end();++iter)
758758
{
759-
QString sql = QString("select %1 from %2 where %3 = %4")
759+
QString sql = QString("select \"%1\" from %2 where \"%3\" = %4")
760760
.arg(fields()[*iter].name())
761761
.arg(mSchemaTableName)
762762
.arg(primaryKey)
@@ -786,7 +786,7 @@ void QgsPostgresProvider::getFeatureGeometry(int key, QgsFeature *f)
786786
}
787787

788788
QString cursor = QString("declare qgisf binary cursor for "
789-
"select asbinary(%1,'%2') from %3 where %4 = %5")
789+
"select asbinary(\"%1\",'%2') from %3 where \"%4\" = %5")
790790
.arg(geometryColumn)
791791
.arg(endianString())
792792
.arg(mSchemaTableName)
@@ -842,9 +842,9 @@ void QgsPostgresProvider::reset()
842842
{
843843
// reset the cursor to the first record
844844
//--std::cout << "Resetting the cursor to the first record " << std::endl;
845-
QString declare = QString("declare qgisf binary cursor for select " +
845+
QString declare = QString("declare qgisf binary cursor for select \"" +
846846
primaryKey +
847-
",asbinary(%1,'%2') as qgs_feature_geometry from %3").arg(geometryColumn)
847+
"\",asbinary(\"%1\",'%2') as qgs_feature_geometry from %3").arg(geometryColumn)
848848
.arg(endianString()).arg(mSchemaTableName);
849849
if(sqlWhereClause.length() > 0)
850850
{
@@ -1028,7 +1028,6 @@ QString QgsPostgresProvider::getPrimaryKey()
10281028
}
10291029
else
10301030
{
1031-
std::cerr << col.local8Bit().data() << '\n';
10321031
sql = "select attname from pg_attribute, pg_type where "
10331032
"atttypid = pg_type.oid and attnum in (" +
10341033
col.replace(" ", ",")
@@ -1284,7 +1283,7 @@ QString QgsPostgresProvider::chooseViewColumn(const tableCols& cols)
12841283
}
12851284
else
12861285
{
1287-
log << QString(tr("Note: ") + "'" + i->first + "'"
1286+
log << QString(tr("Note: ") + "'" + i->first + "' "
12881287
+ tr("initially appeared suitable but does not "
12891288
"contain unique data, so is not suitable.\n"));
12901289
}
@@ -1320,11 +1319,12 @@ bool QgsPostgresProvider::uniqueData(QString schemaName,
13201319

13211320
bool isUnique = false;
13221321

1323-
QString sql = "select count(distinct " + colName + ") = count(" +
1324-
colName + ") from \"" + schemaName + "\".\"" + tableName + "\"";
1322+
QString sql = "select count(distinct \"" + colName + "\") = count(\"" +
1323+
colName + "\") from \"" + schemaName + "\".\"" + tableName + "\"";
13251324

13261325
PGresult* unique = PQexec(connection, (const char*) (sql.utf8()));
1327-
if (PQntuples(unique) == 1)
1326+
1327+
if (PQntuples(unique) == 1)
13281328
if (strncmp(PQgetvalue(unique, 0, 0),"t", 1) == 0)
13291329
isUnique = true;
13301330

@@ -1342,7 +1342,47 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
13421342
// This sql is derived from the one that defines the view
13431343
// 'information_schema.view_column_usage' in PostgreSQL, with a few
13441344
// mods to suit our purposes.
1345-
QString sql = "SELECT DISTINCT nv.nspname AS view_schema, v.relname AS view_name, a.attname AS view_column_name, nt.nspname AS table_schema, t.relname AS table_name, a.attname AS column_name, t.relkind as table_type, typ.typname as column_type FROM pg_namespace nv, pg_class v, pg_depend dv, pg_depend dt, pg_class t, pg_namespace nt, pg_attribute a, pg_user u, pg_type typ WHERE nv.oid = v.relnamespace AND v.relkind = 'v'::\"char\" AND v.oid = dv.refobjid AND dv.refclassid = 'pg_class'::regclass::oid AND dv.classid = 'pg_rewrite'::regclass::oid AND dv.deptype = 'i'::\"char\" AND dv.objid = dt.objid AND dv.refobjid <> dt.refobjid AND dt.classid = 'pg_rewrite'::regclass::oid AND dt.refclassid = 'pg_class'::regclass::oid AND dt.refobjid = t.oid AND t.relnamespace = nt.oid AND (t.relkind = 'r'::\"char\" OR t.relkind = 'v'::\"char\") AND t.oid = a.attrelid AND dt.refobjsubid = a.attnum AND nv.nspname NOT IN ('pg_catalog', 'information_schema' ) AND a.atttypid = typ.oid";
1345+
QString sql = ""
1346+
"SELECT DISTINCT "
1347+
" nv.nspname AS view_schema, "
1348+
" v.relname AS view_name, "
1349+
" va.attname AS view_column_name, "
1350+
" nt.nspname AS table_schema, "
1351+
" t.relname AS table_name, "
1352+
" a.attname AS column_name, "
1353+
" t.relkind as table_type, "
1354+
" typ.typname as column_type "
1355+
"FROM "
1356+
" pg_namespace nv, "
1357+
" pg_class v, "
1358+
" pg_depend dv,"
1359+
" pg_depend dt, "
1360+
" pg_class t, "
1361+
" pg_namespace nt, "
1362+
" pg_attribute a,"
1363+
" pg_attribute va,"
1364+
" pg_user u, "
1365+
" pg_type typ "
1366+
"WHERE "
1367+
" nv.oid = v.relnamespace AND "
1368+
" v.relkind = 'v'::\"char\" AND "
1369+
" v.oid = dv.refobjid AND "
1370+
" dv.refclassid = 'pg_class'::regclass::oid AND "
1371+
" dv.classid = 'pg_rewrite'::regclass::oid AND "
1372+
" dv.deptype = 'i'::\"char\" AND "
1373+
" dv.objid = dt.objid AND "
1374+
" dv.refobjid <> dt.refobjid AND "
1375+
" dt.classid = 'pg_rewrite'::regclass::oid AND "
1376+
" dt.refclassid = 'pg_class'::regclass::oid AND "
1377+
" dt.refobjid = t.oid AND "
1378+
" t.relnamespace = nt.oid AND "
1379+
" (t.relkind = 'r'::\"char\" OR t.relkind = 'v'::\"char\") AND "
1380+
" t.oid = a.attrelid AND "
1381+
" dt.refobjsubid = a.attnum AND "
1382+
" nv.nspname NOT IN ('pg_catalog', 'information_schema' ) AND "
1383+
" a.atttypid = typ.oid AND "
1384+
" v.oid = va.attrelid AND "
1385+
" va.attnum = dt.refobjsubid";
13461386

13471387
// A structure to store the results of the above sql.
13481388
typedef std::map<QString, TT> columnRelationsType;
@@ -1396,6 +1436,7 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
13961436
{
13971437
columnRelationsType::const_iterator
13981438
ii = columnRelations.find(PQgetvalue(result, i, 0));
1439+
columnRelationsType::const_iterator start_iter = ii;
13991440

14001441
if (ii == columnRelations.end())
14011442
continue;
@@ -1439,11 +1480,12 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
14391480
<< ii->second.table_name.local8Bit().data() << '.'
14401481
<< ii->second.column_name.local8Bit().data() << " failed: exceeded maximum "
14411482
<< "interation limit (" << max_loops << ").\n";
1483+
14421484
cols[ii->second.view_column_name] = SRC("","","","");
14431485
}
14441486
else if (ii != columnRelations.end())
14451487
{
1446-
cols[ii->second.view_column_name] =
1488+
cols[start_iter->second.view_column_name] =
14471489
SRC(ii->second.table_schema,
14481490
ii->second.table_name,
14491491
ii->second.column_name,
@@ -1467,11 +1509,11 @@ QString QgsPostgresProvider::minValue(int position){
14671509
QString sql;
14681510
if(sqlWhereClause.isEmpty())
14691511
{
1470-
sql = QString("select min(%1) from %2").arg(fld.name()).arg(mSchemaTableName);
1512+
sql = QString("select min(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName);
14711513
}
14721514
else
14731515
{
1474-
sql = QString("select min(%1) from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
1516+
sql = QString("select min(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
14751517
}
14761518
PGresult *rmin = PQexec(connection,(const char *)(sql.utf8()));
14771519
QString minValue = PQgetvalue(rmin,0,0);
@@ -1487,11 +1529,11 @@ QString QgsPostgresProvider::maxValue(int position){
14871529
QString sql;
14881530
if(sqlWhereClause.isEmpty())
14891531
{
1490-
sql = QString("select max(%1) from %2").arg(fld.name()).arg(mSchemaTableName);
1532+
sql = QString("select max(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName);
14911533
}
14921534
else
14931535
{
1494-
sql = QString("select max(%1) from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
1536+
sql = QString("select max(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
14951537
}
14961538
PGresult *rmax = PQexec(connection,(const char *)(sql.utf8()));
14971539
QString maxValue = PQgetvalue(rmax,0,0);
@@ -1504,7 +1546,7 @@ int QgsPostgresProvider::maxPrimaryKeyValue()
15041546
{
15051547
QString sql;
15061548

1507-
sql = QString("select max(%1) from %2")
1549+
sql = QString("select max(\"%1\") from %2")
15081550
.arg(primaryKey)
15091551
.arg(mSchemaTableName);
15101552

@@ -1557,11 +1599,11 @@ bool QgsPostgresProvider::addFeature(QgsFeature* f, int primaryKeyHighWater)
15571599
insert+=" (";
15581600

15591601
// add the name of the geometry column to the insert statement
1560-
insert += geometryColumn;
1602+
insert += "\"" + geometryColumn;
15611603

15621604
// add the name of the primary key column to the insert statement
1563-
insert += ",";
1564-
insert += primaryKey;
1605+
insert += "\",\"";
1606+
insert += primaryKey + "\"";
15651607

15661608
#ifdef QGISDEBUG
15671609
std::cout << "QgsPostgresProvider::addFeature: Constructing insert SQL, currently at: " << insert.toLocal8Bit().data()
@@ -1611,8 +1653,8 @@ bool QgsPostgresProvider::addFeature(QgsFeature* f, int primaryKeyHighWater)
16111653
(fieldInLayer)
16121654
)
16131655
{
1614-
insert+=",";
1615-
insert+=fieldname;
1656+
insert+=",\"";
1657+
insert+=fieldname +"\"";
16161658
}
16171659
}
16181660

@@ -1819,7 +1861,7 @@ QString QgsPostgresProvider::getDefaultValue(const QString& attr, QgsFeature* f)
18191861

18201862
bool QgsPostgresProvider::deleteFeature(int id)
18211863
{
1822-
QString sql("DELETE FROM "+mSchemaTableName+" WHERE "+primaryKey+" = "+QString::number(id));
1864+
QString sql("DELETE FROM "+mSchemaTableName+" WHERE \""+primaryKey+"\" = "+QString::number(id));
18231865
#ifdef QGISDEBUG
18241866
qWarning("delete sql: "+sql);
18251867
#endif
@@ -2005,7 +2047,7 @@ bool QgsPostgresProvider::changeAttributeValues(std::map<int,std::map<QString,QS
20052047
{
20062048
for(std::map<QString,QString>::const_iterator siter=(*iter).second.begin();siter!=(*iter).second.end();++siter)
20072049
{
2008-
QString sql="UPDATE "+mSchemaTableName+" SET "+(*siter).first+"='"+(*siter).second+"' WHERE " +primaryKey+"="+QString::number((*iter).first);
2050+
QString sql="UPDATE "+mSchemaTableName+" SET "+(*siter).first+"='"+(*siter).second+"' WHERE \"" +primaryKey+"\"="+QString::number((*iter).first);
20092051
#ifdef QGISDEBUG
20102052
qWarning(sql);
20112053
#endif
@@ -2095,8 +2137,8 @@ bool QgsPostgresProvider::changeGeometryValues(std::map<int, QgsGeometry> & geom
20952137
<< std::endl;
20962138
#endif
20972139

2098-
QString sql = "UPDATE "+ mSchemaTableName +" SET " +
2099-
geometryColumn + "=";
2140+
QString sql = "UPDATE "+ mSchemaTableName +" SET \"" +
2141+
geometryColumn + "\"=";
21002142

21012143
sql += "GeomFromWKB('";
21022144

@@ -2147,7 +2189,7 @@ bool QgsPostgresProvider::changeGeometryValues(std::map<int, QgsGeometry> & geom
21472189
sql += "::bytea',"+srid+")";
21482190
}
21492191

2150-
sql += " WHERE " +primaryKey+"="+QString::number(iter->first);
2192+
sql += " WHERE \"" +primaryKey+"\"="+QString::number(iter->first);
21512193

21522194
#ifdef QGISDEBUG
21532195
std::cerr << "QgsPostgresProvider::changeGeometryValues: Updating with '"
@@ -2389,7 +2431,7 @@ long QgsPostgresProvider::getFeatureCount()
23892431
std::cerr << "QgsPostgresProvider: Running SQL: " <<
23902432
sql << std::endl;
23912433
#else
2392-
QString sql = "select count(*) from " + mSchemaTableName;
2434+
QString sql = "select count(*) from " + mSchemaTableName + "";
23932435

23942436
if(sqlWhereClause.length() > 0)
23952437
{
@@ -2435,11 +2477,11 @@ void QgsPostgresProvider::calculateExtents()
24352477

24362478

24372479
#if WASTE_TIME
2438-
sql = "select xmax(extent(" + geometryColumn + ")) as xmax,"
2439-
"xmin(extent(" + geometryColumn + ")) as xmin,"
2440-
"ymax(extent(" + geometryColumn + ")) as ymax,"
2441-
"ymin(extent(" + geometryColumn + ")) as ymin"
2442-
" from " + mSchemaTableName + "";
2480+
sql = "select xmax(extent(\"" + geometryColumn + "\")) as xmax,"
2481+
"xmin(extent(\"" + geometryColumn + "\")) as xmin,"
2482+
"ymax(extent(\"" + geometryColumn + "\")) as ymax,"
2483+
"ymin(extent(\"" + geometryColumn + "\")) as ymin"
2484+
" from " + mSchemaTableName;
24432485
#endif
24442486

24452487
#ifdef QGISDEBUG
@@ -2492,18 +2534,18 @@ void QgsPostgresProvider::calculateExtents()
24922534

24932535
// get the extents
24942536

2495-
QString sql = "select extent(" + geometryColumn + ") from " +
2537+
QString sql = "select extent(\"" + geometryColumn + "\") from " +
24962538
mSchemaTableName;
24972539
if(sqlWhereClause.length() > 0)
24982540
{
24992541
sql += " where " + sqlWhereClause;
25002542
}
25012543

25022544
#if WASTE_TIME
2503-
sql = "select xmax(extent(" + geometryColumn + ")) as xmax,"
2504-
"xmin(extent(" + geometryColumn + ")) as xmin,"
2505-
"ymax(extent(" + geometryColumn + ")) as ymax,"
2506-
"ymin(extent(" + geometryColumn + ")) as ymin"
2545+
sql = "select xmax(extent(\"" + geometryColumn + "\")) as xmax,"
2546+
"xmin(extent(\"" + geometryColumn + "\")) as xmin,"
2547+
"ymax(extent(\"" + geometryColumn + "\")) as ymax,"
2548+
"ymin(extent(\"" + geometryColumn + "\")) as ymin"
25072549
" from " + mSchemaTableName;
25082550
#endif
25092551

@@ -2698,8 +2740,8 @@ bool QgsPostgresProvider::getGeometryDetails()
26982740
// fail if there is no data in the relevant table.
26992741
PQclear(result); // for the query just before the if() statement
27002742
sql = "select "
2701-
"srid(" + geometryColumn + "), "
2702-
"geometrytype(" + geometryColumn + ") from " +
2743+
"srid(\"" + geometryColumn + "\"), "
2744+
"geometrytype(\"" + geometryColumn + "\") from " +
27032745
mSchemaTableName + " limit 1";
27042746

27052747
result = executeDbCommand(connection, sql);

0 commit comments

Comments
 (0)