28
28
#include < QCustomEvent>
29
29
#include < QTextOStream>
30
30
#include < QRegExp>
31
+ #include < QMap>
31
32
32
33
// for ntohl
33
34
#ifdef WIN32
@@ -1387,6 +1388,11 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
1387
1388
typedef std::map<QString, TT> columnRelationsType;
1388
1389
columnRelationsType columnRelations;
1389
1390
1391
+ // A structure to cache the query results that return the view
1392
+ // definition.
1393
+ typedef QMap<QString, QString> viewDefCache;
1394
+ viewDefCache viewDefs;
1395
+
1390
1396
PGresult* result = PQexec (connection, (const char *)(sql.utf8 ()));
1391
1397
// Store the results of the query for convenient access
1392
1398
for (int i = 0 ; i < PQntuples (result); ++i)
@@ -1407,50 +1413,57 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
1407
1413
// using 'AS'. To fix this we need to look in the view definition and
1408
1414
// adjust the view column name if necessary.
1409
1415
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'.
1412
1436
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 ())
1415
1442
{
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+)\" ?,* .*" );
1430
1446
1431
1447
#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 ' ;
1435
1451
#endif
1436
1452
1437
1453
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
+ }
1442
1458
}
1443
- else
1444
- QgsDebugMsg (" Failed to get view definition for " + temp.view_schema + " ." + temp.view_name );
1445
-
1446
1459
1447
1460
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 "
1454
1467
+ temp.column_type );
1455
1468
1456
1469
columnRelations[temp.view_schema + ' .' +
0 commit comments