Skip to content

Commit aa9983b

Browse files
author
g_j_m
committed
Fix for ticket #277 (viewing views of views).
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@6267 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 6bdc552 commit aa9983b

File tree

1 file changed

+47
-34
lines changed

1 file changed

+47
-34
lines changed

src/providers/postgres/qgspostgresprovider.cpp

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <QCustomEvent>
2929
#include <QTextOStream>
3030
#include <QRegExp>
31+
#include <QMap>
3132

3233
// for ntohl
3334
#ifdef WIN32
@@ -1387,6 +1388,11 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
13871388
typedef std::map<QString, TT> columnRelationsType;
13881389
columnRelationsType columnRelations;
13891390

1391+
// A structure to cache the query results that return the view
1392+
// definition.
1393+
typedef QMap<QString, QString> viewDefCache;
1394+
viewDefCache viewDefs;
1395+
13901396
PGresult* result = PQexec(connection, (const char*)(sql.utf8()));
13911397
// Store the results of the query for convenient access
13921398
for (int i = 0; i < PQntuples(result); ++i)
@@ -1407,50 +1413,57 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
14071413
// using 'AS'. To fix this we need to look in the view definition and
14081414
// adjust the view column name if necessary.
14091415

1410-
QString view = "SELECT definition FROM pg_views WHERE schemaname = '" + temp.view_schema + "' AND "
1411-
" viewname = '" + temp.view_name + "'";
1416+
QString viewQuery = "SELECT definition FROM pg_views "
1417+
"WHERE schemaname = '" + temp.view_schema + "' AND "
1418+
"viewname = '" + temp.view_name + "'";
1419+
1420+
// Maintain a cache of the above SQL.
1421+
QString viewDef;
1422+
if (!viewDefs.contains(viewQuery))
1423+
{
1424+
PGresult* r = PQexec(connection, (const char*)(viewQuery.utf8()));
1425+
if (PQntuples(r) > 0)
1426+
viewDef = PQgetvalue(r, 0, 0);
1427+
else
1428+
QgsDebugMsg("Failed to get view definition for " + temp.view_schema + "." + temp.view_name);
1429+
viewDefs[viewQuery] = viewDef;
1430+
}
1431+
1432+
viewDef = viewDefs.value(viewQuery);
1433+
1434+
// Now pick the view definiton apart, looking for
1435+
// temp.column_name to the left of an 'AS'.
14121436

1413-
PGresult* r = PQexec(connection, (const char*)(view.utf8()));
1414-
if (PQntuples(r) > 0)
1437+
// This regular expression needs more testing. Since the view
1438+
// definition comes from postgresql and has been 'standardised', we
1439+
// don't need to deal with everything that the user could put in a view
1440+
// definition. Does the regexp have to deal with the schema??
1441+
if (!viewDef.isEmpty())
14151442
{
1416-
QString viewDef = PQgetvalue(r, 0, 0);
1417-
// Now pick the view definiton apart, looking for
1418-
// temp.column_name to the left of an 'AS'.
1419-
1420-
// This regular expression needs more work and testing. Since the view
1421-
// definition comes from postgresql and has been 'standardised', we
1422-
// don't need to deal with everything that the user could put in a view
1423-
// definition. Possible variations could include:
1424-
// - lowercase AS
1425-
// - quotes around table and column names
1426-
// - inclusion of the scheam
1427-
// - meaningful characters in the schema/table/column names (such as . ' " )
1428-
// - anything else???
1429-
QRegExp s(".* " + temp.table_name + "\\." + temp.column_name + " AS (\\w+),* .*");
1443+
QRegExp s(".* \"?" + QRegExp::escape(temp.table_name) +
1444+
"\"?\\.\"?" + QRegExp::escape(temp.column_name) +
1445+
"\"? AS \"?(\\w+)\"?,* .*");
14301446

14311447
#ifdef QGSIDEBUG
1432-
std::cerr <<__FILE__<<__LINE__ << ' ' << view.toLocal8Bit().data() << '\n'
1433-
<< viewDef.toLocal8Bit().data() << '\n'
1434-
<< s.pattern().toLocal8Bit().data() << '\n';
1448+
std::cerr <<__FILE__<<__LINE__ << ' ' << viewQuery.toLocal8Bit().data() << '\n'
1449+
<< viewDef.toLocal8Bit().data() << '\n'
1450+
<< s.pattern().toLocal8Bit().data() << '\n';
14351451
#endif
14361452

14371453
if (s.indexIn(viewDef) != -1)
1438-
{
1439-
temp.view_column_name = s.cap(1);
1440-
//std::cerr<<__FILE__<<__LINE__<<' '<<temp.view_column_name.toLocal8Bit().data()<<'\n';
1441-
}
1454+
{
1455+
temp.view_column_name = s.cap(1);
1456+
//std::cerr<<__FILE__<<__LINE__<<' '<<temp.view_column_name.toLocal8Bit().data()<<'\n';
1457+
}
14421458
}
1443-
else
1444-
QgsDebugMsg("Failed to get view definition for " + temp.view_schema + "." + temp.view_name);
1445-
14461459

14471460
QgsDebugMsg(temp.view_schema + "."
1448-
+ temp.view_name + "."
1449-
+ temp.view_column_name + " <- "
1450-
+ temp.table_schema + "."
1451-
+ temp.table_name + "."
1452-
+ temp.column_name + " is a '"
1453-
+ temp.table_type + "' of type "
1461+
+ temp.view_name + "."
1462+
+ temp.view_column_name + " <- "
1463+
+ temp.table_schema + "."
1464+
+ temp.table_name + "."
1465+
+ temp.column_name + " is a '"
1466+
+ temp.table_type + "' of type "
14541467
+ temp.column_type);
14551468

14561469
columnRelations[temp.view_schema + '.' +

0 commit comments

Comments
 (0)