@@ -31,13 +31,9 @@ email : sherman at mrcc.com
31
31
#include < QMessageBox>
32
32
#include < QSettings>
33
33
#include < QTextStream>
34
- #include < QTableWidgetItem>
35
34
#include < QHeaderView>
36
35
#include < QStringList>
37
36
38
- #include < cassert>
39
- #include < iostream>
40
-
41
37
#ifdef HAVE_PGCONFIG
42
38
#include < pg_config.h>
43
39
#endif
@@ -57,6 +53,7 @@ QgsDbSourceSelect::QgsDbSourceSelect( QWidget *parent, Qt::WFlags fl )
57
53
mSearchColumnComboBox ->addItem ( tr ( " Table" ) );
58
54
mSearchColumnComboBox ->addItem ( tr ( " Type" ) );
59
55
mSearchColumnComboBox ->addItem ( tr ( " Geometry column" ) );
56
+ mSearchColumnComboBox ->addItem ( tr ( " Primary key column" ) );
60
57
mSearchColumnComboBox ->addItem ( tr ( " Sql" ) );
61
58
62
59
mProxyModel .setParent ( this );
@@ -67,6 +64,10 @@ QgsDbSourceSelect::QgsDbSourceSelect( QWidget *parent, Qt::WFlags fl )
67
64
mTablesTreeView ->setModel ( &mProxyModel );
68
65
mTablesTreeView ->setSortingEnabled ( true );
69
66
67
+ mTablesTreeView ->setEditTriggers ( QAbstractItemView::CurrentChanged );
68
+
69
+ mTablesTreeView ->setItemDelegateForColumn ( QgsDbTableModel::dbtmPkCol, new QgsDbSourceSelectDelegate ( this ) );
70
+
70
71
QSettings settings;
71
72
mTablesTreeView ->setSelectionMode ( settings.value ( " /qgis/addPostgisDC" , false ).toBool () ?
72
73
QAbstractItemView::ExtendedSelection :
@@ -169,23 +170,27 @@ void QgsDbSourceSelect::on_mSearchColumnComboBox_currentIndexChanged( const QStr
169
170
}
170
171
else if ( text == tr ( " Schema" ) )
171
172
{
172
- mProxyModel .setFilterKeyColumn ( 0 );
173
+ mProxyModel .setFilterKeyColumn ( QgsDbTableModel::dbtmSchema );
173
174
}
174
175
else if ( text == tr ( " Table" ) )
175
176
{
176
- mProxyModel .setFilterKeyColumn ( 1 );
177
+ mProxyModel .setFilterKeyColumn ( QgsDbTableModel::dbtmTable );
177
178
}
178
179
else if ( text == tr ( " Type" ) )
179
180
{
180
- mProxyModel .setFilterKeyColumn ( 2 );
181
+ mProxyModel .setFilterKeyColumn ( QgsDbTableModel::dbtmType );
181
182
}
182
183
else if ( text == tr ( " Geometry column" ) )
183
184
{
184
- mProxyModel .setFilterKeyColumn ( 3 );
185
+ mProxyModel .setFilterKeyColumn ( QgsDbTableModel::dbtmGeomCol );
186
+ }
187
+ else if ( text == tr ( " Primay key column" ) )
188
+ {
189
+ mProxyModel .setFilterKeyColumn ( QgsDbTableModel::dbtmPkCol );
185
190
}
186
191
else if ( text == tr ( " Sql" ) )
187
192
{
188
- mProxyModel .setFilterKeyColumn ( 4 );
193
+ mProxyModel .setFilterKeyColumn ( QgsDbTableModel::dbtmSql );
189
194
}
190
195
}
191
196
@@ -199,26 +204,15 @@ void QgsDbSourceSelect::setLayerType( QString schema,
199
204
QString type )
200
205
{
201
206
mTableModel .setGeometryTypesForTable ( schema, table, column, type );
202
- mTablesTreeView ->sortByColumn ( 1 , Qt::AscendingOrder );
203
- mTablesTreeView ->sortByColumn ( 0 , Qt::AscendingOrder );
204
- }
205
-
206
- QString QgsDbSourceSelect::makeGeomQuery ( QString schema,
207
- QString table, QString column )
208
- {
209
- return QString ( " select distinct "
210
- " case"
211
- " when geometrytype(%1) IN ('POINT','MULTIPOINT') THEN 'POINT'"
212
- " when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
213
- " when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
214
- " end "
215
- " from \" %2\" .\" %3\" " ).arg ( " \" " + column + " \" " ).arg ( schema ).arg ( table );
207
+ mTablesTreeView ->sortByColumn ( QgsDbTableModel::dbtmTable, Qt::AscendingOrder );
208
+ mTablesTreeView ->sortByColumn ( QgsDbTableModel::dbtmSchema, Qt::AscendingOrder );
216
209
}
217
210
218
211
QgsDbSourceSelect::~QgsDbSourceSelect ()
219
212
{
220
213
PQfinish ( pd );
221
214
}
215
+
222
216
void QgsDbSourceSelect::populateConnectionList ()
223
217
{
224
218
QSettings settings;
@@ -234,6 +228,7 @@ void QgsDbSourceSelect::populateConnectionList()
234
228
settings.endGroup ();
235
229
setConnectionListPosition ();
236
230
}
231
+
237
232
void QgsDbSourceSelect::addNewConnection ()
238
233
{
239
234
QgsNewConnection *nc = new QgsNewConnection ( this );
@@ -243,6 +238,7 @@ void QgsDbSourceSelect::addNewConnection()
243
238
populateConnectionList ();
244
239
}
245
240
}
241
+
246
242
void QgsDbSourceSelect::editConnection ()
247
243
{
248
244
QgsNewConnection *nc = new QgsNewConnection ( this , cmbConnections->currentText () );
@@ -278,6 +274,7 @@ void QgsDbSourceSelect::deleteConnection()
278
274
setConnectionListPosition ();
279
275
}
280
276
}
277
+
281
278
void QgsDbSourceSelect::addTables ()
282
279
{
283
280
m_selectedTables.clear ();
@@ -310,33 +307,31 @@ void QgsDbSourceSelect::addTables()
310
307
311
308
if ( dbInfo[currentSchemaName][currentRow].size () == 0 )
312
309
{
313
- dbInfo[currentSchemaName][currentRow].resize ( 5 );
310
+ dbInfo[currentSchemaName][currentRow].resize ( QgsDbTableModel::dbtmColumns );
314
311
}
315
312
316
313
dbInfo[currentSchemaName][currentRow][currentColumn] = currentItem->text ();
317
314
}
318
315
319
316
// now traverse all the schemas and table infos
320
- QString schemaName, tableName, geomColumnName, sql;
321
- QString query;
322
-
323
317
QMap<QString, schemaInfo>::const_iterator schema_it = dbInfo.constBegin ();
324
318
for ( ; schema_it != dbInfo.constEnd (); ++schema_it )
325
319
{
326
320
schemaInfo scheme = schema_it.value ();
327
321
schemaInfo::const_iterator entry_it = scheme.constBegin ();
328
322
for ( ; entry_it != scheme.constEnd (); ++entry_it )
329
323
{
330
- schemaName = entry_it->at ( 0 );
331
- tableName = entry_it->at ( 1 );
332
- geomColumnName = entry_it->at ( 3 );
333
- sql = entry_it->at ( 4 );
324
+ QString schemaName = entry_it->at ( QgsDbTableModel::dbtmSchema );
325
+ QString tableName = entry_it->at ( QgsDbTableModel::dbtmTable );
326
+ QString geomColumnName = entry_it->at ( QgsDbTableModel::dbtmGeomCol );
327
+ QString pkColumnName = entry_it->at ( QgsDbTableModel::dbtmPkCol );
328
+ QString sql = entry_it->at ( QgsDbTableModel::dbtmSql );
334
329
335
330
if ( geomColumnName.contains ( " AS " ) )
336
331
{
337
332
int a = geomColumnName.indexOf ( " AS " );
338
333
QString typeName = geomColumnName.mid ( a + 4 ); // only the type name
339
- geomColumnName = geomColumnName.mid ( 0 , a ); // only the geom column name
334
+ geomColumnName = geomColumnName.left ( a ); // only the geom column name
340
335
341
336
if ( !sql.isEmpty () )
342
337
{
@@ -360,7 +355,16 @@ void QgsDbSourceSelect::addTables()
360
355
}
361
356
}
362
357
363
- query = " \" " + schemaName + " \" .\" " + tableName + " \" " + " (" + geomColumnName + " ) sql=" + sql;
358
+ QString query;
359
+ if ( !pkColumnName.isEmpty () )
360
+ {
361
+ query += QString ( " key=\" %1\" " ).arg ( pkColumnName );
362
+ }
363
+
364
+ query += QString ( " table=\" %1\" .\" %2\" (%3) sql=%4" )
365
+ .arg ( schemaName ).arg ( tableName )
366
+ .arg ( geomColumnName )
367
+ .arg ( sql );
364
368
365
369
m_selectedTables.push_back ( query );
366
370
}
@@ -493,8 +497,8 @@ void QgsDbSourceSelect::on_btnConnect_clicked()
493
497
.arg ( QString::fromUtf8 ( PQerrorMessage ( pd ) ) ) );
494
498
}
495
499
496
- mTablesTreeView ->sortByColumn ( 1 , Qt::AscendingOrder );
497
- mTablesTreeView ->sortByColumn ( 0 , Qt::AscendingOrder );
500
+ mTablesTreeView ->sortByColumn ( QgsDbTableModel::dbtmTable , Qt::AscendingOrder );
501
+ mTablesTreeView ->sortByColumn ( QgsDbTableModel::dbtmSchema , Qt::AscendingOrder );
498
502
499
503
// if we have only one schema item, expand it by default
500
504
int numTopLevelItems = mTableModel .invisibleRootItem ()->rowCount ();
@@ -532,8 +536,8 @@ void QgsDbSourceSelect::setSql( const QModelIndex& index )
532
536
}
533
537
534
538
// create "Schema"."Table" and find out existing sql string
535
- QModelIndex schemaSibling = index .sibling ( index .row (), 0 );
536
- QModelIndex tableSibling = index .sibling ( index .row (), 1 );
539
+ QModelIndex schemaSibling = index .sibling ( index .row (), QgsDbTableModel::dbtmSchema );
540
+ QModelIndex tableSibling = index .sibling ( index .row (), QgsDbTableModel::dbtmTable );
537
541
if ( !schemaSibling.isValid () || !tableSibling.isValid () )
538
542
{
539
543
return ;
@@ -545,7 +549,7 @@ void QgsDbSourceSelect::setSql( const QModelIndex& index )
545
549
QgsDebugMsg ( tableString );
546
550
547
551
QString currentSql;
548
- QModelIndex sqlSibling = index .sibling ( index .row (), 4 );
552
+ QModelIndex sqlSibling = index .sibling ( index .row (), QgsDbTableModel::dbtmSql );
549
553
if ( sqlSibling.isValid () )
550
554
{
551
555
currentSql = mTableModel .itemFromIndex ( mProxyModel .mapToSource ( sqlSibling ) )->text ();
@@ -576,19 +580,57 @@ void QgsDbSourceSelect::addSearchGeometryColumn( const QString &schema, const QS
576
580
mColumnTypeThread ->addGeometryColumn ( schema, table, column );
577
581
}
578
582
583
+ QStringList QgsDbSourceSelect::pkCandidates ( PGconn *pg, QString schemaName, QString tableName )
584
+ {
585
+ QStringList cols;
586
+ cols << QString::null;
587
+
588
+ QString sql = QString ( " select attname from pg_attribute join pg_type on atttypid=pg_type.oid WHERE pg_type.typname='int4' AND attrelid=regclass('\" %1\" .\" %2\" ')" ).arg ( schemaName ).arg ( tableName );
589
+ QgsDebugMsg ( sql );
590
+ PGresult *colRes = PQexec ( pg, sql.toUtf8 () );
591
+
592
+ if ( PQresultStatus ( colRes ) == PGRES_TUPLES_OK )
593
+ {
594
+ for ( int i = 0 ; i < PQntuples ( colRes ); i++ )
595
+ {
596
+ QgsDebugMsg ( PQgetvalue ( colRes, i, 0 ) );
597
+ cols << QString::fromUtf8 ( PQgetvalue ( colRes, i, 0 ) );
598
+ }
599
+ }
600
+ else
601
+ {
602
+ QgsDebugMsg ( QString ( " SQL:%1\n result:%2\n error:%3\n " ).arg ( sql ).arg ( PQresultStatus ( colRes ) ).arg ( PQerrorMessage ( pg ) ) );
603
+ }
604
+
605
+ PQclear ( colRes );
606
+
607
+ return cols;
608
+ }
609
+
579
610
bool QgsDbSourceSelect::getTableInfo ( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly )
580
611
{
581
612
int n = 0 ;
582
613
QApplication::setOverrideCursor ( Qt::WaitCursor );
583
614
584
615
// The following query returns only tables that exist and the user has SELECT privilege on.
585
616
// Can't use regclass here because table must exist, else error occurs.
586
- QString sql = " select * from geometry_columns,pg_class,pg_namespace "
587
- " where relname=f_table_name and f_table_schema=nspname "
588
- " and pg_namespace.oid = pg_class.relnamespace "
589
- " and has_schema_privilege(pg_namespace.nspname,'usage') "
590
- " and has_table_privilege('\" '||pg_namespace.nspname||'\" .\" '||pg_class.relname||'\" ','select') " // user has select privilege
591
- " order by f_table_schema,f_table_name,f_geometry_column" ;
617
+ QString sql = " select "
618
+ " f_table_name,"
619
+ " f_table_schema,"
620
+ " f_geometry_column,"
621
+ " type"
622
+ " from "
623
+ " geometry_columns,"
624
+ " pg_class,"
625
+ " pg_namespace"
626
+ " where "
627
+ " relname=f_table_name"
628
+ " and f_table_schema=nspname"
629
+ " and pg_namespace.oid=pg_class.relnamespace"
630
+ " and has_schema_privilege(pg_namespace.nspname,'usage')"
631
+ " and has_table_privilege('\" '||pg_namespace.nspname||'\" .\" '||pg_class.relname||'\" ','select')" // user has select privilege
632
+ " order by "
633
+ " f_table_schema,f_table_name,f_geometry_column" ;
592
634
593
635
PGresult *result = PQexec ( pg, sql.toUtf8 () );
594
636
if ( result )
@@ -606,11 +648,10 @@ bool QgsDbSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly
606
648
{
607
649
for ( int idx = 0 ; idx < PQntuples ( result ); idx++ )
608
650
{
609
- QString tableName = QString::fromUtf8 ( PQgetvalue ( result, idx, PQfnumber ( result, QString ( " f_table_name" ).toUtf8 () ) ) );
610
- QString schemaName = QString::fromUtf8 ( PQgetvalue ( result, idx, PQfnumber ( result, QString ( " f_table_schema" ).toUtf8 () ) ) );
611
-
612
- QString column = QString::fromUtf8 ( PQgetvalue ( result, idx, PQfnumber ( result, QString ( " f_geometry_column" ).toUtf8 () ) ) );
613
- QString type = QString::fromUtf8 ( PQgetvalue ( result, idx, PQfnumber ( result, QString ( " type" ).toUtf8 () ) ) );
651
+ QString tableName = QString::fromUtf8 ( PQgetvalue ( result, idx, 0 ) );
652
+ QString schemaName = QString::fromUtf8 ( PQgetvalue ( result, idx, 1 ) );
653
+ QString column = QString::fromUtf8 ( PQgetvalue ( result, idx, 2 ) );
654
+ QString type = QString::fromUtf8 ( PQgetvalue ( result, idx, 3 ) );
614
655
615
656
QString as = " " ;
616
657
if ( type == " GEOMETRY" && !searchGeometryColumnsOnly )
@@ -619,7 +660,7 @@ bool QgsDbSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly
619
660
as = type = " WAITING" ;
620
661
}
621
662
622
- mTableModel .addTableEntry ( type, schemaName, tableName, column, " " );
663
+ mTableModel .addTableEntry ( type, schemaName, tableName, column, pkCandidates ( pg, schemaName, tableName ), " " );
623
664
n++;
624
665
}
625
666
}
@@ -636,31 +677,38 @@ bool QgsDbSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly
636
677
// geometry_columns table. This code is specific to postgresql,
637
678
// but an equivalent query should be possible in other
638
679
// databases.
639
- sql = " select pg_class.relname,pg_namespace.nspname,pg_attribute.attname,pg_class.relkind "
640
- " from pg_attribute, pg_class, pg_namespace "
641
- " where pg_namespace.oid = pg_class.relnamespace "
642
- " and pg_attribute.attrelid = pg_class.oid "
643
- " and ("
680
+ sql = " select "
681
+ " pg_class.relname,"
682
+ " pg_namespace.nspname,"
683
+ " pg_attribute.attname,"
684
+ " pg_class.relkind"
685
+ " from "
686
+ " pg_attribute,"
687
+ " pg_class,"
688
+ " pg_namespace"
689
+ " where "
690
+ " pg_namespace.oid = pg_class.relnamespace"
691
+ " and pg_attribute.attrelid = pg_class.oid "
692
+ " and ("
644
693
" pg_attribute.atttypid = regtype('geometry')"
645
- " or "
646
- " pg_attribute.atttypid IN (select oid FROM pg_type WHERE typbasetype=regtype('geometry'))"
647
- " ) "
648
- " and has_schema_privilege(pg_namespace.nspname,'usage') "
649
- " and has_table_privilege('\" '||pg_namespace.nspname||'\" .\" '||pg_class.relname||'\" ','select') " ;
694
+ " or pg_attribute.atttypid IN (select oid FROM pg_type WHERE typbasetype=regtype('geometry'))"
695
+ " )"
696
+ " and has_schema_privilege(pg_namespace.nspname,'usage')"
697
+ " and has_table_privilege('\" '||pg_namespace.nspname||'\" .\" '||pg_class.relname||'\" ','select')" ;
650
698
// user has select privilege
651
699
if ( searchPublicOnly )
652
- sql += " and pg_namespace.nspname = 'public' " ;
700
+ sql += " and pg_namespace.nspname = 'public'" ;
653
701
654
702
if ( n > 0 )
655
703
{
656
- sql += " and not exists (select * from geometry_columns WHERE pg_namespace.nspname=f_table_schema AND pg_class.relname=f_table_name) " ;
704
+ sql += " and not exists (select * from geometry_columns WHERE pg_namespace.nspname=f_table_schema AND pg_class.relname=f_table_name)" ;
657
705
}
658
706
else
659
707
{
660
708
n = 0 ;
661
709
}
662
710
663
- sql += " and pg_class.relkind in ('v', 'r')" ; // only from views and relations (tables)
711
+ sql += " and pg_class.relkind in ('v', 'r')" ; // only from views and relations (tables)
664
712
665
713
result = PQexec ( pg, sql.toUtf8 () );
666
714
@@ -692,7 +740,7 @@ bool QgsDbSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly
692
740
693
741
addSearchGeometryColumn ( schema, table, column );
694
742
// details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
695
- mTableModel .addTableEntry ( " Waiting" , schema, table, column, " " );
743
+ mTableModel .addTableEntry ( " Waiting" , schema, table, column, pkCandidates ( pg, schema, table ), " " );
696
744
n++;
697
745
}
698
746
}
@@ -798,9 +846,14 @@ void QgsGeomColumnTypeThread::getLayerTypes()
798
846
799
847
for ( uint i = 0 ; i < schemas.size (); i++ )
800
848
{
801
- QString query = QgsDbSourceSelect::makeGeomQuery ( schemas[i],
802
- tables[i],
803
- columns[i] );
849
+ QString query = QString ( " select distinct "
850
+ " case"
851
+ " when geometrytype(%1) IN ('POINT','MULTIPOINT') THEN 'POINT'"
852
+ " when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
853
+ " when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
854
+ " end "
855
+ " from "
856
+ " \" %2\" .\" %3\" " ).arg ( " \" " + columns[i] + " \" " ).arg ( schemas[i] ).arg ( tables[i] );
804
857
PGresult* gresult = PQexec ( pd, query.toUtf8 () );
805
858
QString type;
806
859
if ( PQresultStatus ( gresult ) == PGRES_TUPLES_OK )
0 commit comments