diff --git a/src/qgspgquerybuilder.cpp b/src/qgspgquerybuilder.cpp index 3865acfc292..8f728d77180 100644 --- a/src/qgspgquerybuilder.cpp +++ b/src/qgspgquerybuilder.cpp @@ -1,9 +1,9 @@ /*************************************************************************** - qgspgquerybuilder.cpp - PostgreSQL Query Builder - -------------------------------------- - Date : 2004-11-19 - Copyright : (C) 2004 by Gary E.Sherman - Email : sherman at mrcc.com + qgspgquerybuilder.cpp - PostgreSQL Query Builder + -------------------------------------- + Date : 2004-11-19 + Copyright : (C) 2004 by Gary E.Sherman + Email : sherman at mrcc.com /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * @@ -16,11 +16,12 @@ #include #include #include +#include #include "qgsfield.h" #include "qgspgquerybuilder.h" -QgsPgQueryBuilder::QgsPgQueryBuilder(QWidget *parent, const char *name) - : QgsPgQueryBuilderBase(parent, name) + QgsPgQueryBuilder::QgsPgQueryBuilder(QWidget *parent, const char *name) +: QgsPgQueryBuilderBase(parent, name) { } @@ -28,6 +29,13 @@ QgsPgQueryBuilder::QgsPgQueryBuilder(QString tableName, PGconn *con, QWidget *parent, const char *name) : QgsPgQueryBuilderBase(parent, name), mTableName(tableName), mPgConnection(con) { + QString datasource = QString(tr("Table %1 in database %2 on host %3, user %4")) + .arg(mTableName) + .arg(PQdb(mPgConnection)) + .arg(PQhost(mPgConnection)) + .arg(PQuser(mPgConnection)); + + lblDataUri->setText(datasource); populateFields(); } QgsPgQueryBuilder::~QgsPgQueryBuilder() @@ -43,56 +51,47 @@ void QgsPgQueryBuilder::populateFields() qWarning("Query executed: " + sql); if (PQresultStatus(result) == PGRES_TUPLES_OK) { - //--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl; - for (int i = 0; i < PQnfields(result); i++) { + //--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl; + for (int i = 0; i < PQnfields(result); i++) { - QString fieldName = PQfname(result, i); - int fldtyp = PQftype(result, i); - QString typOid = QString().setNum(fldtyp); - std::cerr << "typOid is: " << typOid << std::endl; - int fieldModifier = PQfmod(result, i); - QString sql = "select typelem from pg_type where typelem = " + typOid + " and typlen = -1"; - // //--std::cout << sql << std::endl; - PGresult *oidResult = PQexec(mPgConnection, (const char *) sql); - if (PQresultStatus(oidResult) == PGRES_TUPLES_OK) - std::cerr << "Ok fetching typelem using\n" << sql << std::endl; + QString fieldName = PQfname(result, i); + int fldtyp = PQftype(result, i); + QString typOid = QString().setNum(fldtyp); + std::cerr << "typOid is: " << typOid << std::endl; + int fieldModifier = PQfmod(result, i); + QString sql = "select typelem from pg_type where typelem = " + typOid + " and typlen = -1"; + // //--std::cout << sql << std::endl; + PGresult *oidResult = PQexec(mPgConnection, (const char *) sql); + if (PQresultStatus(oidResult) == PGRES_TUPLES_OK) + std::cerr << "Ok fetching typelem using\n" << sql << std::endl; - // get the oid of the "real" type - QString poid = PQgetvalue(oidResult, 0, PQfnumber(oidResult, "typelem")); - std::cerr << "poid is: " << poid << std::endl; - PQclear(oidResult); - sql = "select typname, typlen from pg_type where oid = " + poid; - // //--std::cout << sql << std::endl; - oidResult = PQexec(mPgConnection, (const char *) sql); - if (PQresultStatus(oidResult) == PGRES_TUPLES_OK) - std::cerr << "Ok fetching typenam,etc\n"; + // get the oid of the "real" type + QString poid = PQgetvalue(oidResult, 0, PQfnumber(oidResult, "typelem")); + std::cerr << "poid is: " << poid << std::endl; + PQclear(oidResult); + sql = "select typname, typlen from pg_type where oid = " + poid; + // //--std::cout << sql << std::endl; + oidResult = PQexec(mPgConnection, (const char *) sql); + if (PQresultStatus(oidResult) == PGRES_TUPLES_OK) + std::cerr << "Ok fetching typenam,etc\n"; - QString fieldType = PQgetvalue(oidResult, 0, 0); - QString fieldSize = PQgetvalue(oidResult, 0, 1); - PQclear(oidResult); - /* - sql = "select oid from pg_class where relname = '" + mTableName + "'"; - PGresult *tresult= PQexec(mPgConnection, (const char *)sql); - QString tableoid = PQgetvalue(tresult, 0, 0); - PQclear(tresult); - sql = "select attnum from pg_attribute where attrelid = " + tableoid + " and attname = '" + fieldName + "'"; - tresult = PQexec(mPgConnection, (const char *)sql); - QString attnum = PQgetvalue(tresult, 0, 0); - PQclear(tresult); + QString fieldType = PQgetvalue(oidResult, 0, 0); + QString fieldSize = PQgetvalue(oidResult, 0, 1); + PQclear(oidResult); #ifdef QGISDEBUG - std::cerr << "Field: " << attnum << " maps to " << i << " " << fieldName << ", " - << fieldType << " (" << fldtyp << "), " << fieldSize << ", " - << fieldModifier << std::endl; + std::cerr << "Field parms: Name = " + fieldName + + ", Type = " + fieldType << std::endl; #endif -*/ - std::cerr << "Field parms: Name = " + fieldName + ", Type = " + fieldType << std::endl; - mFieldMap[fieldName] = QgsField(fieldName, fieldType, fieldSize.toInt(), fieldModifier); - lstFields->insertItem(fieldName); + mFieldMap[fieldName] = QgsField(fieldName, fieldType, + fieldSize.toInt(), fieldModifier); + lstFields->insertItem(fieldName); + } + }else + { +#ifdef QGISDEBUG + std::cerr << "Error fetching a row from " + mTableName << std::endl; +#endif } -}else -{ - std::cerr << "Error fetching a row from " + mTableName << std::endl; -} PQclear(result); } @@ -138,7 +137,7 @@ void QgsPgQueryBuilder::getAllValues() + " from " + mTableName + " order by " + lstFields->currentText(); // clear the values list lstValues->clear(); - // determine the field type + // determine the field type QgsField field = mFieldMap[lstFields->currentText()]; bool isCharField = field.type().find("char") > -1; @@ -151,7 +150,7 @@ void QgsPgQueryBuilder::getAllValues() { QString value = PQgetvalue(result, i, 0); - if(isCharField) + if(isCharField) { lstValues->insertItem("'" + value + "'"); } @@ -181,18 +180,19 @@ void QgsPgQueryBuilder::testSql() { QString numRows = PQgetvalue(result, 0, 0); //numRows.setNum(rowCount); - QMessageBox::information(this, "Query Result", "The where clause returned " + numRows + " rows."); + QMessageBox::information(this, tr("Query Result"), tr("The where clause returned ") + numRows + tr(" rows.")); } else { - QMessageBox::warning(this, "Query Failed", "An error occurred when executing the query:\n" + QString(PQresultErrorMessage(result))); + QMessageBox::warning(this, tr("Query Failed"), tr("An error occurred when executing the query:") + "\n" + QString(PQresultErrorMessage(result))); } -// free the result set -PQclear(result); + // free the result set + PQclear(result); } void QgsPgQueryBuilder::setConnection(PGconn *con) { + // store the connection mPgConnection = con; } diff --git a/src/qgspgquerybuilder.h b/src/qgspgquerybuilder.h index 6ea978a54de..a2f7f85aa73 100644 --- a/src/qgspgquerybuilder.h +++ b/src/qgspgquerybuilder.h @@ -27,39 +27,66 @@ extern "C" #include "qgspgquerybuilderbase.uic.h" #endif class QgsField; -class QgsPgQueryBuilder : public QgsPgQueryBuilderBase -{ - Q_OBJECT - public: - //! Default constructor - QgsPgQueryBuilder(QWidget *parent = 0, const char *name=0); - //! Constructor which also takes the table name and PG connection - // pointer - QgsPgQueryBuilder(QString tableName, PGconn *con, - QWidget *parent = 0, const char *name=0); - ~QgsPgQueryBuilder(); - void setConnection(PGconn *con); - private: - //! Populate the field list for the selected table - void populateFields(); - //! Get sample distinct values for the selected field. The sample size - // is limited to an arbitrary value - void getSampleValues(); - //! Get all distinct values for the field - void getAllValues(); - //! Test the constructed sql statement to see if the database likes it - void testSql(); +/*! + * \class QgsPgQueryBuider + * \brief Query Builder for PostgreSQL layers. + * + * The query builder allows interactive creation of a SQL for limiting the + * features displayed in a database layer. The fields in the table are + * displayed and sample values (or all values) can be viewed to aid in + * constructing the query. A test function returns the number of features that + * will be returned. + * + */ +class QgsPgQueryBuilder : public QgsPgQueryBuilderBase { Q_OBJECT public: + //! Default constructor - not very useful + QgsPgQueryBuilder(QWidget *parent = 0, const char *name=0); - // private members - - //! PostgreSQL conneciton - PGconn *mPgConnection; - //! Table name - QString mTableName; - //! Vector of QgsField objects - std::vector mFields; - //! Map that holds field information - std::map mFieldMap; + /*! Constructor which also takes the table name and PG connection pointer + * @param tableName Name of the table being queried + * @param con PostgreSQL connection from the Add PostGIS Layer dialog + * @param parent Parent widget + * @param name Name of the widget + */ + QgsPgQueryBuilder(QString tableName, PGconn *con, QWidget *parent = 0, + const char *name=0); ~QgsPgQueryBuilder(); void setConnection(PGconn + *con); + private: + /*! + * Populate the field list for the selected table + */ + void populateFields(); + + /*! + * Get sample distinct values for the selected field. The sample size is + * limited to an arbitrary value (currently set to 25). The fields + * are inserted into the field list box. + */ + void getSampleValues(); + + /*! + * Get all distinct values for the field. Values are inserted + * into the value list box + */ + void getAllValues(); + + /*! Test the constructed sql statement to see if the database likes it. + * The number of rows that would be returned is displayed in a message box. + * The test uses a "select count(*) from ..." query to test the SQL + * statement. + */ + void testSql(); + + // private members + + //! PostgreSQL connection object + PGconn *mPgConnection; + //! Table name + QString mTableName; + //! Vector of QgsField objects + std::vector mFields; + //! Map that holds field information, keyed by field name + std::map mFieldMap; }; #endif //QGSPGQUERYBUILDER_H diff --git a/src/qgspgquerybuilderbase.ui b/src/qgspgquerybuilderbase.ui index 62df1d7ebec..8fee91311b5 100644 --- a/src/qgspgquerybuilderbase.ui +++ b/src/qgspgquerybuilderbase.ui @@ -1,4 +1,4 @@ - + QgsPgQueryBuilderBase Query builder for PostgreSQL layers (using PostGIS) Gary Sherman @@ -24,7 +24,92 @@ unnamed - + + + layout5 + + + + unnamed + + + + spacer2_2 + + + Horizontal + + + Fixed + + + + 30 + 21 + + + + + + btnClear + + + Clear + + + false + + + + + btnTest + + + Test + + + false + + + + + btnOk + + + Ok + + + true + + + + + Cancel + + + Cancel + + + + + spacer2 + + + Horizontal + + + Fixed + + + + 30 + 21 + + + + + + groupBox3 @@ -42,7 +127,7 @@ - + groupBox4 @@ -193,7 +278,7 @@ LIKE - + btnAnd @@ -207,7 +292,21 @@ AND - + + + btnILike + + + + 50 + 25 + + + + ILIKE + + + btnOr @@ -221,7 +320,7 @@ OR - + btnNot @@ -237,25 +336,7 @@ - - - groupBox1 - - - Fields - - - - unnamed - - - - lstFields - - - - - + groupBox2 @@ -297,90 +378,31 @@ - + - layout5 + groupBox1 - + + Fields + + unnamed - + - spacer2_2 - - - Horizontal - - - Fixed - - - - 30 - 21 - - - - - - btnClear - - - Clear - - - false + lstFields - - - btnTest - - - Test - - - false - - - - - btnOk - - - Ok - - - true - - - - - Cancel - - - Cancel - - - - - spacer2 - - - Horizontal - - - Fixed - - - - 30 - 21 - - - - + + + + + lblDataUri + + + Datasource: + @@ -516,6 +538,12 @@ QgsPgQueryBuilderBase clearSQL() + + btnILike + clicked() + QgsPgQueryBuilderBase + insIlike() + qgspgquerybuilderbase.ui.h @@ -542,6 +570,8 @@ insNot() insOr() clearSQL() + insIlike() + setDatasourceDescription( QString uri ) diff --git a/src/qgspgquerybuilderbase.ui.h b/src/qgspgquerybuilderbase.ui.h index 1c75efc1948..829a299026b 100644 --- a/src/qgspgquerybuilderbase.ui.h +++ b/src/qgspgquerybuilderbase.ui.h @@ -116,3 +116,13 @@ void QgsPgQueryBuilderBase::clearSQL() { txtSQL->clear(); } + + +void QgsPgQueryBuilderBase::insIlike() +{ + txtSQL->insert(" ILIKE "); +} +void QgsPgQueryBuilderBase::setDatasourceDescription(QString uri) +{ + lblDataUri->setText(uri); +}