00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "qgsdbsourceselect.h"
00021
00022 #include "qgisapp.h"
00023 #include "qgslogger.h"
00024 #include "qgsapplication.h"
00025 #include "qgscontexthelp.h"
00026 #include "qgsnewconnection.h"
00027 #include "qgspgquerybuilder.h"
00028 #include "qgsdatasourceuri.h"
00029
00030 #include <QInputDialog>
00031 #include <QMessageBox>
00032 #include <QSettings>
00033 #include <QTextStream>
00034 #include <QTableWidgetItem>
00035 #include <QHeaderView>
00036 #include <QStringList>
00037
00038 #include <cassert>
00039 #include <iostream>
00040
00041 QgsDbSourceSelect::QgsDbSourceSelect( QWidget *parent, Qt::WFlags fl )
00042 : QDialog( parent, fl ), mColumnTypeThread( NULL ), pd( 0 )
00043 {
00044 setupUi( this );
00045 btnAdd->setEnabled( false );
00046 populateConnectionList();
00047
00048 mSearchModeComboBox->addItem( tr( "Wildcard" ) );
00049 mSearchModeComboBox->addItem( tr( "RegExp" ) );
00050
00051 mSearchColumnComboBox->addItem( tr( "All" ) );
00052 mSearchColumnComboBox->addItem( tr( "Schema" ) );
00053 mSearchColumnComboBox->addItem( tr( "Table" ) );
00054 mSearchColumnComboBox->addItem( tr( "Type" ) );
00055 mSearchColumnComboBox->addItem( tr( "Geometry column" ) );
00056 mSearchColumnComboBox->addItem( tr( "Sql" ) );
00057
00058 mProxyModel.setParent( this );
00059 mProxyModel.setFilterKeyColumn( -1 );
00060 mProxyModel.setFilterCaseSensitivity( Qt::CaseInsensitive );
00061 mProxyModel.setDynamicSortFilter( true );
00062 mProxyModel.setSourceModel( &mTableModel );
00063 mTablesTreeView->setModel( &mProxyModel );
00064 mTablesTreeView->setSortingEnabled( true );
00065
00066 mSearchGroupBox->hide();
00067 connect( mTablesTreeView, SIGNAL( doubleClicked( const QModelIndex& ) ), this, SLOT( setSql( const QModelIndex& ) ) );
00068
00069
00070
00071 mSearchColumnComboBox->setCurrentIndex( 2 );
00072 }
00074
00075 void QgsDbSourceSelect::on_btnNew_clicked()
00076 {
00077 addNewConnection();
00078 }
00079
00080 void QgsDbSourceSelect::on_btnDelete_clicked()
00081 {
00082 deleteConnection();
00083 }
00084
00085 void QgsDbSourceSelect::on_btnAdd_clicked()
00086 {
00087 addTables();
00088 }
00089
00090
00091 void QgsDbSourceSelect::on_btnEdit_clicked()
00092 {
00093 editConnection();
00094 }
00095
00096
00097 void QgsDbSourceSelect::on_btnHelp_clicked()
00098 {
00099 showHelp();
00100 }
00103
00104 void QgsDbSourceSelect::on_cmbConnections_activated( int )
00105 {
00106 dbChanged();
00107 }
00108
00109 void QgsDbSourceSelect::on_mSearchOptionsButton_clicked()
00110 {
00111 if ( mSearchGroupBox->isVisible() )
00112 {
00113 mSearchGroupBox->hide();
00114 }
00115 else
00116 {
00117 mSearchGroupBox->show();
00118 }
00119 }
00120
00121 void QgsDbSourceSelect::on_mSearchTableEdit_textChanged( const QString & text )
00122 {
00123 if ( mSearchModeComboBox->currentText() == tr( "Wildcard" ) )
00124 {
00125 mProxyModel._setFilterWildcard( text );
00126 }
00127 else if ( mSearchModeComboBox->currentText() == tr( "RegExp" ) )
00128 {
00129 mProxyModel._setFilterRegExp( text );
00130 }
00131 }
00132
00133 void QgsDbSourceSelect::on_mSearchColumnComboBox_currentIndexChanged( const QString & text )
00134 {
00135 if ( text == tr( "All" ) )
00136 {
00137 mProxyModel.setFilterKeyColumn( -1 );
00138 }
00139 else if ( text == tr( "Schema" ) )
00140 {
00141 mProxyModel.setFilterKeyColumn( 0 );
00142 }
00143 else if ( text == tr( "Table" ) )
00144 {
00145 mProxyModel.setFilterKeyColumn( 1 );
00146 }
00147 else if ( text == tr( "Type" ) )
00148 {
00149 mProxyModel.setFilterKeyColumn( 2 );
00150 }
00151 else if ( text == tr( "Geometry column" ) )
00152 {
00153 mProxyModel.setFilterKeyColumn( 3 );
00154 }
00155 else if ( text == tr( "Sql" ) )
00156 {
00157 mProxyModel.setFilterKeyColumn( 4 );
00158 }
00159 }
00160
00161 void QgsDbSourceSelect::on_mSearchModeComboBox_currentIndexChanged( const QString & text )
00162 {
00163 on_mSearchTableEdit_textChanged( mSearchTableEdit->text() );
00164 }
00165
00166 void QgsDbSourceSelect::setLayerType( QString schema,
00167 QString table, QString column,
00168 QString type )
00169 {
00170 mTableModel.setGeometryTypesForTable( schema, table, column, type );
00171 mTablesTreeView->sortByColumn( 1, Qt::AscendingOrder );
00172 mTablesTreeView->sortByColumn( 0, Qt::AscendingOrder );
00173 }
00174
00175 QString QgsDbSourceSelect::makeGeomQuery( QString schema,
00176 QString table, QString column )
00177 {
00178 return QString( "select distinct "
00179 "case"
00180 " when geometrytype(%1) IN ('POINT','MULTIPOINT') THEN 'POINT'"
00181 " when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
00182 " when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
00183 " end "
00184 "from \"%2\".\"%3\"" ).arg( "\"" + column + "\"" ).arg( schema ).arg( table );
00185 }
00186
00187 QgsDbSourceSelect::~QgsDbSourceSelect()
00188 {
00189 PQfinish( pd );
00190 }
00191 void QgsDbSourceSelect::populateConnectionList()
00192 {
00193 QSettings settings;
00194 settings.beginGroup( "/PostgreSQL/connections" );
00195 QStringList keys = settings.childGroups();
00196 QStringList::Iterator it = keys.begin();
00197 cmbConnections->clear();
00198 while ( it != keys.end() )
00199 {
00200 cmbConnections->addItem( *it );
00201 ++it;
00202 }
00203 settings.endGroup();
00204 setConnectionListPosition();
00205 }
00206 void QgsDbSourceSelect::addNewConnection()
00207 {
00208 QgsNewConnection *nc = new QgsNewConnection( this );
00209
00210 if ( nc->exec() )
00211 {
00212 populateConnectionList();
00213 }
00214 }
00215 void QgsDbSourceSelect::editConnection()
00216 {
00217 QgsNewConnection *nc = new QgsNewConnection( this, cmbConnections->currentText() );
00218
00219 if ( nc->exec() )
00220 {
00221 nc->saveConnection();
00222 }
00223 }
00224
00225 void QgsDbSourceSelect::deleteConnection()
00226 {
00227 QSettings settings;
00228 QString key = "/Postgresql/connections/" + cmbConnections->currentText();
00229 QString msg =
00230 tr( "Are you sure you want to remove the " ) + cmbConnections->currentText() + tr( " connection and all associated settings?" );
00231 QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Delete" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
00232 if ( result == QMessageBox::Ok )
00233 {
00234 settings.remove( key + "/host" );
00235 settings.remove( key + "/database" );
00236 settings.remove( key + "/username" );
00237 settings.remove( key + "/password" );
00238 settings.remove( key + "/port" );
00239 settings.remove( key + "/save" );
00240 settings.remove( key );
00241
00242
00243
00244 cmbConnections->removeItem( cmbConnections->currentIndex() );
00245 setConnectionListPosition();
00246 }
00247 }
00248 void QgsDbSourceSelect::addTables()
00249 {
00250 m_selectedTables.clear();
00251
00252 typedef QMap<int, QVector<QString> > schemaInfo;
00253 QMap<QString, schemaInfo> dbInfo;
00254
00255 QItemSelection selection = mTablesTreeView->selectionModel()->selection();
00256 QModelIndexList selectedIndices = selection.indexes();
00257 QStandardItem* currentItem = 0;
00258
00259 QModelIndexList::const_iterator selected_it = selectedIndices.constBegin();
00260 for ( ; selected_it != selectedIndices.constEnd(); ++selected_it )
00261 {
00262 if ( !selected_it->parent().isValid() )
00263 {
00264
00265 continue;
00266 }
00267 currentItem = mTableModel.itemFromIndex( mProxyModel.mapToSource( *selected_it ) );
00268 if ( !currentItem )
00269 {
00270 continue;
00271 }
00272
00273 QString currentSchemaName = currentItem->parent()->text();
00274
00275 int currentRow = currentItem->row();
00276 int currentColumn = currentItem->column();
00277
00278 if ( dbInfo[currentSchemaName][currentRow].size() == 0 )
00279 {
00280 dbInfo[currentSchemaName][currentRow].resize( 5 );
00281 }
00282
00283 dbInfo[currentSchemaName][currentRow][currentColumn] = currentItem->text();
00284 }
00285
00286
00287 QString schemaName, tableName, geomColumnName, sql;
00288 QString query;
00289
00290 QMap<QString, schemaInfo>::const_iterator schema_it = dbInfo.constBegin();
00291 for ( ; schema_it != dbInfo.constEnd(); ++schema_it )
00292 {
00293 schemaInfo scheme = schema_it.value();
00294 schemaInfo::const_iterator entry_it = scheme.constBegin();
00295 for ( ; entry_it != scheme.constEnd(); ++entry_it )
00296 {
00297 schemaName = entry_it->at( 0 );
00298 tableName = entry_it->at( 1 );
00299 geomColumnName = entry_it->at( 3 );
00300 sql = entry_it->at( 4 );
00301
00302 if ( geomColumnName.contains( " AS " ) )
00303 {
00304 int a = geomColumnName.indexOf( " AS " );
00305 QString typeName = geomColumnName.mid( a + 4 );
00306 geomColumnName = geomColumnName.mid( 0, a );
00307
00308 if ( !sql.isEmpty() )
00309 {
00310 sql += " AND ";
00311 }
00312 if ( typeName == "POINT" )
00313 {
00314 sql += QString( "GeometryType(\"%1\") IN ('POINT','MULTIPOINT')" ).arg( geomColumnName );
00315 }
00316 else if ( typeName == "LINESTRING" )
00317 {
00318 sql += QString( "GeometryType(\"%1\") IN ('LINESTRING','MULTILINESTRING')" ).arg( geomColumnName );
00319 }
00320 else if ( typeName == "POLYGON" )
00321 {
00322 sql += QString( "GeometryType(\"%1\") IN ('POLYGON','MULTIPOLYGON')" ).arg( geomColumnName );
00323 }
00324 else
00325 {
00326 continue;
00327 }
00328 }
00329
00330 query = "\"" + schemaName + "\".\"" + tableName + "\" " + "(" + geomColumnName + ") sql=" + sql;
00331
00332 m_selectedTables.push_back( query );
00333 }
00334 }
00335
00336 if ( m_selectedTables.empty() )
00337 {
00338 QMessageBox::information( this, tr( "Select Table" ), tr( "You must select a table in order to add a Layer." ) );
00339 }
00340 else
00341 {
00342 accept();
00343 }
00344 }
00345
00346 void QgsDbSourceSelect::on_btnConnect_clicked()
00347 {
00348 if ( mColumnTypeThread )
00349 {
00350 mColumnTypeThread->stop();
00351 mColumnTypeThread = 0;
00352 }
00353
00354 QModelIndex rootItemIndex = mTableModel.indexFromItem( mTableModel.invisibleRootItem() );
00355 mTableModel.removeRows( 0, mTableModel.rowCount( rootItemIndex ), rootItemIndex );
00356
00357
00358 QSettings settings;
00359
00360 bool makeConnection = true;
00361 QString key = "/PostgreSQL/connections/" + cmbConnections->currentText();
00362
00363 QString database = settings.value( key + "/database" ).toString();
00364 QString username = settings.value( key + "/username" ).toString();
00365 QString password = settings.value( key + "/password" ).toString();
00366
00367 if ( password.isEmpty() )
00368 {
00369
00370 makeConnection = false;
00371 password = QInputDialog::getText( this, tr( "Password for " ) + username,
00372 tr( "Please enter your password:" ),
00373 QLineEdit::Password, QString::null, &makeConnection );
00374
00375 }
00376
00377 QgsDataSourceURI uri;
00378 uri.setConnection( settings.value( key + "/host" ).toString(),
00379 settings.value( key + "/port" ).toString(),
00380 database,
00381 settings.value( key + "/username" ).toString(),
00382 password );
00383
00384 bool searchPublicOnly = settings.value( key + "/publicOnly" ).toBool();
00385 bool searchGeometryColumnsOnly = settings.value( key + "/geometryColumnsOnly" ).toBool();
00386
00387
00388
00389 QgsDebugMsg( "Connection info: " + uri.connectionInfo() );
00390
00391 if ( makeConnection )
00392 {
00393 m_connectionInfo = uri.connectionInfo();
00394
00395
00396 if ( pd != 0 )
00397 PQfinish( pd );
00398
00399 pd = PQconnectdb( m_connectionInfo.toLocal8Bit() );
00400 if ( PQstatus( pd ) == CONNECTION_OK )
00401 {
00402
00403
00404 PQsetClientEncoding( pd, QString( "UNICODE" ).toLocal8Bit() );
00405
00406
00407 geomCol details;
00408
00409 if ( getTableInfo( pd, searchGeometryColumnsOnly, searchPublicOnly ) )
00410 {
00411
00412
00413 if ( mColumnTypeThread != NULL )
00414 {
00415 connect( mColumnTypeThread, SIGNAL( setLayerType( QString, QString, QString, QString ) ),
00416 this, SLOT( setLayerType( QString, QString, QString, QString ) ) );
00417
00418
00419 mColumnTypeThread->start();
00420 }
00421 }
00422 else
00423 {
00424 qDebug( "Unable to get list of spatially enabled tables from the database" );
00425 qDebug( PQerrorMessage( pd ) );
00426 }
00427
00428 if ( cmbConnections->count() > 0 )
00429 btnAdd->setEnabled( true );
00430
00431 }
00432 else
00433 {
00434 QMessageBox::warning( this, tr( "Connection failed" ),
00435 tr
00436 ( "Connection to %1 on %2 failed. Either the database is down or your settings are incorrect.%3Check your username and password and try again.%4The database said:%5%6" ).
00437 arg( settings.value( key + "/database" ).toString() ).arg( settings.value( key + "/host" ).toString() ).arg( "\n\n" ).arg( "\n\n" ).arg( "\n" ).arg( QString::fromUtf8( PQerrorMessage( pd ) ) ) );
00438 }
00439 }
00440
00441 mTablesTreeView->sortByColumn( 1, Qt::AscendingOrder );
00442 mTablesTreeView->sortByColumn( 0, Qt::AscendingOrder );
00443
00444
00445 int numTopLevelItems = mTableModel.invisibleRootItem()->rowCount();
00446 if ( numTopLevelItems < 2 || mTableModel.tableCount() < 20 )
00447 {
00448
00449 for ( int i = 0; i < numTopLevelItems; ++i )
00450 {
00451 mTablesTreeView->expand( mProxyModel.mapFromSource( mTableModel.indexFromItem( mTableModel.invisibleRootItem()->child( i ) ) ) );
00452 }
00453 }
00454 }
00455
00456 QStringList QgsDbSourceSelect::selectedTables()
00457 {
00458 return m_selectedTables;
00459 }
00460
00461 QString QgsDbSourceSelect::connectionInfo()
00462 {
00463 return m_connectionInfo;
00464 }
00465
00466 void QgsDbSourceSelect::setSql( const QModelIndex& index )
00467 {
00468 if ( !index.parent().isValid() )
00469 {
00470 qWarning( "schema item found" );
00471 return;
00472 }
00473
00474 if ( pd == 0 )
00475 {
00476 return;
00477 }
00478
00479
00480 QModelIndex schemaSibling = index.sibling( index.row(), 0 );
00481 QModelIndex tableSibling = index.sibling( index.row(), 1 );
00482 if ( !schemaSibling.isValid() || !tableSibling.isValid() )
00483 {
00484 return;
00485 }
00486
00487 QString schemaName = mTableModel.itemFromIndex( mProxyModel.mapToSource( schemaSibling ) )->text();
00488 QString tableName = mTableModel.itemFromIndex( mProxyModel.mapToSource( tableSibling ) )->text();
00489 QString tableString = "\"" + schemaName + "\".\"" + tableName + "\"";
00490 qWarning( tableString.toUtf8() );
00491
00492 QString currentSql;
00493 QModelIndex sqlSibling = index.sibling( index.row(), 4 );
00494 if ( sqlSibling.isValid() )
00495 {
00496 currentSql = mTableModel.itemFromIndex( mProxyModel.mapToSource( sqlSibling ) )->text();
00497 }
00498
00499
00500 QgsPgQueryBuilder * pgb = new QgsPgQueryBuilder( tableString, pd, this );
00501
00502 pgb->setSql( currentSql );
00503
00504
00505 pgb->setConnection( pd );
00506
00507 if ( pgb->exec() )
00508 {
00509 mTableModel.setSql( mProxyModel.mapToSource( index ), pgb->sql() );
00510 }
00511 }
00512
00513 void QgsDbSourceSelect::addSearchGeometryColumn( const QString &schema, const QString &table, const QString &column )
00514 {
00515
00516 if ( mColumnTypeThread == NULL )
00517 {
00518 mColumnTypeThread = new QgsGeomColumnTypeThread();
00519 mColumnTypeThread->setConnInfo( m_connectionInfo );
00520 }
00521 mColumnTypeThread->addGeometryColumn( schema, table, column );
00522 }
00523
00524 bool QgsDbSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly )
00525 {
00526 bool ok = false;
00527 QApplication::setOverrideCursor( Qt::WaitCursor );
00528
00529
00530
00531 QString sql = "select * from geometry_columns,pg_class,pg_namespace "
00532 "where relname=f_table_name and f_table_schema=nspname "
00533 "and pg_namespace.oid = pg_class.relnamespace "
00534 "and has_schema_privilege(pg_namespace.nspname,'usage') "
00535 "and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select') "
00536 "order by f_table_schema,f_table_name";
00537
00538 PGresult *result = PQexec( pg, sql.toUtf8() );
00539 if ( result )
00540 {
00541 if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
00542 {
00543 QMessageBox::warning( this,
00544 tr( "Accessible tables could not be determined" ),
00545 QString( tr( "Database connection was successful, but the accessible tables could not be determined.\n\n"
00546 "The error message from the database was:\n%1\n" ) )
00547 .arg( QString::fromUtf8( PQresultErrorMessage( result ) ) ) );
00548 }
00549 else if ( PQntuples( result ) == 0 )
00550 {
00551 QMessageBox::warning( this, tr( "No accessible tables found" ),
00552 tr
00553 ( "Database connection was successful, but no accessible tables were found.\n\n"
00554 "Please verify that you have SELECT privilege on a table carrying PostGIS\n"
00555 "geometry." ) );
00556 }
00557 else
00558 {
00559 for ( int idx = 0; idx < PQntuples( result ); idx++ )
00560 {
00561 QString tableName = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, QString( "f_table_name" ).toUtf8() ) ) );
00562 QString schemaName = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, QString( "f_table_schema" ).toUtf8() ) ) );
00563
00564 QString column = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, QString( "f_geometry_column" ).toUtf8() ) ) );
00565 QString type = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, QString( "type" ).toUtf8() ) ) );
00566
00567 QString as = "";
00568 if ( type == "GEOMETRY" && !searchGeometryColumnsOnly )
00569 {
00570 addSearchGeometryColumn( schemaName, tableName, column );
00571 as = type = "WAITING";
00572 }
00573
00574 mTableModel.addTableEntry( type, schemaName, tableName, column, "" );
00575 }
00576 }
00577 ok = true;
00578 }
00579 PQclear( result );
00580
00581
00582 QApplication::restoreOverrideCursor();
00583 if ( searchGeometryColumnsOnly )
00584 {
00585 return ok;
00586 }
00587
00588
00589
00590
00591
00592 sql = "select pg_class.relname,pg_namespace.nspname,pg_attribute.attname,pg_class.relkind "
00593 "from pg_attribute, pg_class, pg_namespace "
00594 "where pg_namespace.oid = pg_class.relnamespace "
00595 "and pg_attribute.attrelid = pg_class.oid "
00596 "and ("
00597 "pg_attribute.atttypid = regtype('geometry')"
00598 " or "
00599 "pg_attribute.atttypid IN (select oid FROM pg_type WHERE typbasetype=regtype('geometry'))"
00600 ") "
00601 "and has_schema_privilege(pg_namespace.nspname,'usage') "
00602 "and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select') ";
00603
00604 if ( searchPublicOnly )
00605 sql += "and pg_namespace.nspname = 'public' ";
00606
00607 sql += "and not exists (select * from geometry_columns WHERE pg_namespace.nspname=f_table_schema AND pg_class.relname=f_table_name) "
00608 "and pg_class.relkind in ('v', 'r')";
00609
00610 result = PQexec( pg, sql.toUtf8() );
00611
00612 for ( int i = 0; i < PQntuples( result ); i++ )
00613 {
00614
00615
00616
00617
00618
00619
00620
00621 QString table = QString::fromUtf8( PQgetvalue( result, i, 0 ) );
00622 QString schema = QString::fromUtf8( PQgetvalue( result, i, 1 ) );
00623 QString column = QString::fromUtf8( PQgetvalue( result, i, 2 ) );
00624 QString relkind = QString::fromUtf8( PQgetvalue( result, i, 3 ) );
00625
00626 addSearchGeometryColumn( schema, table, column );
00627
00628 mTableModel.addTableEntry( "Waiting", schema, table, column, "" );
00629 }
00630 ok = true;
00631
00632 PQclear( result );
00633 return ok;
00634 }
00635
00636 #if 0 // this function is never called - smizuno
00637 bool QgsDbSourceSelect::getGeometryColumnInfo( PGconn *pg,
00638 geomCol& details, bool searchGeometryColumnsOnly,
00639 bool searchPublicOnly )
00640 {
00641 bool ok = false;
00642
00643 QApplication::setOverrideCursor( Qt::waitCursor );
00644
00645 QString sql = "select * from geometry_columns";
00646
00647 sql += " order by f_table_schema,f_table_name";
00648
00649 PGresult *result = PQexec( pg, sql.toUtf8() );
00650 if ( result )
00651 {
00652 QString msg;
00653 QTextStream( &msg ) << "Fetched " << PQntuples( result ) << " tables from database";
00654
00655 for ( int idx = 0; idx < PQntuples( result ); idx++ )
00656 {
00657
00658
00659
00660
00661
00662
00663 QString tableName = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, "f_table_name" ) ) );
00664 QString schemaName = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, "f_table_schema" ) ) );
00665 sql = "select oid from pg_class where relname = '" + tableName + "'";
00666 if ( schemaName.length() > 0 )
00667 sql += " and relnamespace = (select oid from pg_namespace where nspname = '" +
00668 schemaName + "')";
00669
00670 PGresult* exists = PQexec( pg, sql.toUtf8() );
00671 if ( PQntuples( exists ) == 1 )
00672 {
00673 QString column = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, "f_geometry_column" ) ) );
00674 QString type = QString::fromUtf8( PQgetvalue( result, idx, PQfnumber( result, "type" ) ) );
00675
00676 QString as = "";
00677 if ( type == "GEOMETRY" && !searchGeometryColumnsOnly )
00678 {
00679 addSearchGeometryColumn( schemaName, tableName, column );
00680 as = type = "WAITING";
00681 }
00682
00683 details.push_back( geomPair( fullDescription( schemaName, tableName, column, as ), type ) );
00684 }
00685 PQclear( exists );
00686 }
00687 ok = true;
00688 }
00689 PQclear( result );
00690
00691 QApplication::restoreOverrideCursor();
00692
00693 if ( searchGeometryColumnsOnly )
00694 return ok;
00695
00696
00697
00698
00699
00700 sql = "select pg_class.relname, pg_namespace.nspname, pg_attribute.attname, "
00701 "pg_class.relkind from "
00702 "pg_attribute, pg_class, pg_type, pg_namespace where pg_type.typname = 'geometry' and "
00703 "pg_attribute.atttypid = pg_type.oid and pg_attribute.attrelid = pg_class.oid ";
00704
00705 if ( searchPublicOnly )
00706 sql += "and pg_namespace.nspname = 'public' ";
00707
00708 sql += "and cast(pg_class.relname as character varying) not in "
00709 "(select f_table_name from geometry_columns) "
00710 "and pg_namespace.oid = pg_class.relnamespace "
00711 "and pg_class.relkind in ('v', 'r')";
00712
00713 result = PQexec( pg, sql.toUtf8() );
00714
00715 for ( int i = 0; i < PQntuples( result ); i++ )
00716 {
00717
00718
00719
00720
00721
00722
00723
00724 QString table = QString::fromUtf8( PQgetvalue( result, i, 0 ) );
00725 QString schema = QString::fromUtf8( PQgetvalue( result, i, 1 ) );
00726 QString column = QString::fromUtf8( PQgetvalue( result, i, 2 ) );
00727 QString relkind = QString::fromUtf8( PQgetvalue( result, i, 3 ) );
00728
00729 addSearchGeometryColumn( schema, table, column );
00730 details.push_back( geomPair( fullDescription( schema, table, column, "WAITING" ), "WAITING" ) );
00731 }
00732 ok = true;
00733
00734 PQclear( result );
00735
00736 return ok;
00737 }
00738 #endif
00739
00740 void QgsDbSourceSelect::showHelp()
00741 {
00742 QgsContextHelp::run( context_id );
00743 }
00744
00745 QString QgsDbSourceSelect::fullDescription( QString schema, QString table,
00746 QString column, QString type )
00747 {
00748 QString full_desc = "";
00749 if ( schema.length() > 0 )
00750 full_desc = '"' + schema + "\".\"";
00751 full_desc += table + "\" (" + column + ") " + type;
00752 return full_desc;
00753 }
00754
00755 void QgsDbSourceSelect::dbChanged()
00756 {
00757
00758 QSettings settings;
00759 settings.setValue( "/PostgreSQL/connections/selected",
00760 cmbConnections->currentText() );
00761 }
00762
00763 void QgsDbSourceSelect::setConnectionListPosition()
00764 {
00765 QSettings settings;
00766
00767 QString toSelect = settings.value( "/PostgreSQL/connections/selected" ).toString();
00768
00769 bool set = false;
00770 for ( int i = 0; i < cmbConnections->count(); ++i )
00771 if ( cmbConnections->itemText( i ) == toSelect )
00772 {
00773 cmbConnections->setCurrentIndex( i );
00774 set = true;
00775 break;
00776 }
00777
00778
00779
00780
00781 if ( !set && cmbConnections->count() > 0 )
00782 {
00783
00784
00785
00786
00787 if ( toSelect.isNull() )
00788 cmbConnections->setCurrentIndex( 0 );
00789 else
00790 cmbConnections->setCurrentIndex( cmbConnections->count() - 1 );
00791 }
00792 }
00793
00794 void QgsDbSourceSelect::setSearchExpression( const QString& regexp )
00795 {
00796 }
00797
00798 void QgsGeomColumnTypeThread::setConnInfo( QString s )
00799 {
00800 mConnInfo = s;
00801 }
00802
00803 void QgsGeomColumnTypeThread::addGeometryColumn( QString schema, QString table, QString column )
00804 {
00805 schemas.push_back( schema );
00806 tables.push_back( table );
00807 columns.push_back( column );
00808 }
00809
00810 void QgsGeomColumnTypeThread::stop()
00811 {
00812 mStopped = true;
00813 }
00814
00815 void QgsGeomColumnTypeThread::getLayerTypes()
00816 {
00817 mStopped = false;
00818
00819 PGconn *pd = PQconnectdb( mConnInfo.toLocal8Bit() );
00820 if ( PQstatus( pd ) == CONNECTION_OK )
00821 {
00822 PQsetClientEncoding( pd, QString( "UNICODE" ).toLocal8Bit() );
00823
00824 for ( uint i = 0; i < schemas.size(); i++ )
00825 {
00826 QString query = QgsDbSourceSelect::makeGeomQuery( schemas[i],
00827 tables[i],
00828 columns[i] );
00829 PGresult* gresult = PQexec( pd, query.toUtf8() );
00830 QString type;
00831 if ( PQresultStatus( gresult ) == PGRES_TUPLES_OK )
00832 {
00833 QStringList types;
00834
00835 for ( int j = 0; j < PQntuples( gresult ); j++ )
00836 {
00837 QString type = QString::fromUtf8( PQgetvalue( gresult, j, 0 ) );
00838 if ( type != "" )
00839 types += type;
00840 }
00841
00842 type = types.join( "," );
00843 }
00844 PQclear( gresult );
00845
00846 if ( mStopped )
00847 break;
00848
00849
00850 emit setLayerType( schemas[i], tables[i], columns[i], type );
00851 }
00852 }
00853
00854 PQfinish( pd );
00855 }