add ilike, in and not in to search string

git-svn-id: http://svn.osgeo.org/qgis/trunk@14156 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
jef 2010-08-27 15:08:15 +00:00
parent d2cb8b281b
commit 1cbad87895
7 changed files with 131 additions and 25 deletions

View File

@ -112,6 +112,7 @@ class QgsQueryBuilder : public QDialog, private Ui::QgsQueryBuilderBase
*/ */
void on_btnSampleValues_clicked(); void on_btnSampleValues_clicked();
void setDatasourceDescription( QString uri ); void setDatasourceDescription( QString uri );
private: private:
/*! /*!
* Populate the field list for the selected table * Populate the field list for the selected table

View File

@ -60,14 +60,6 @@ QgsSearchQueryBuilder::QgsSearchQueryBuilder( QgsVectorLayer* layer,
pbn->setToolTip( tr( "Load query from xml file" ) ); pbn->setToolTip( tr( "Load query from xml file" ) );
connect( pbn, SIGNAL( clicked() ), this, SLOT( loadQuery() ) ); connect( pbn, SIGNAL( clicked() ), this, SLOT( loadQuery() ) );
// disable unsupported operators
btnIn->setHidden( true );
btnNotIn->setHidden( true );
btnPct->setHidden( true );
// change to ~
btnILike->setText( "~" );
lblDataUri->setText( layer->name() ); lblDataUri->setText( layer->name() );
populateFields(); populateFields();
} }
@ -281,6 +273,21 @@ void QgsSearchQueryBuilder::on_btnGreaterThan_clicked()
txtSQL->insertPlainText( " > " ); txtSQL->insertPlainText( " > " );
} }
void QgsSearchQueryBuilder::on_btnPct_clicked()
{
txtSQL->insertPlainText( "%" );
}
void QgsSearchQueryBuilder::on_btnIn_clicked()
{
txtSQL->insertPlainText( " IN " );
}
void QgsSearchQueryBuilder::on_btnNotIn_clicked()
{
txtSQL->insertPlainText( " NOT IN " );
}
void QgsSearchQueryBuilder::on_btnLike_clicked() void QgsSearchQueryBuilder::on_btnLike_clicked()
{ {
txtSQL->insertPlainText( " LIKE " ); txtSQL->insertPlainText( " LIKE " );
@ -343,8 +350,7 @@ void QgsSearchQueryBuilder::on_btnClear_clicked()
void QgsSearchQueryBuilder::on_btnILike_clicked() void QgsSearchQueryBuilder::on_btnILike_clicked()
{ {
//txtSQL->insertPlainText(" ILIKE "); txtSQL->insertPlainText( " ILIKE " );
txtSQL->insertPlainText( " ~ " );
} }
void QgsSearchQueryBuilder::saveQuery() void QgsSearchQueryBuilder::saveQuery()

View File

@ -57,6 +57,9 @@ class QgsSearchQueryBuilder : public QDialog, private Ui::QgsQueryBuilderBase
void on_btnGreaterThan_clicked(); void on_btnGreaterThan_clicked();
void on_btnLike_clicked(); void on_btnLike_clicked();
void on_btnILike_clicked(); void on_btnILike_clicked();
void on_btnPct_clicked();
void on_btnIn_clicked();
void on_btnNotIn_clicked();
void on_lstFields_doubleClicked( const QModelIndex &index ); void on_lstFields_doubleClicked( const QModelIndex &index );
void on_lstValues_doubleClicked( const QModelIndex &index ); void on_lstValues_doubleClicked( const QModelIndex &index );

View File

@ -70,6 +70,7 @@ string "'"{str_char}*"'"
"NULL" { return NULLVALUE; } "NULL" { return NULLVALUE; }
"IS" { return IS; } "IS" { return IS; }
"IN" { return IN; }
"=" { yylval.op = QgsSearchTreeNode::opEQ; return COMPARISON; } "=" { yylval.op = QgsSearchTreeNode::opEQ; return COMPARISON; }
"!=" { yylval.op = QgsSearchTreeNode::opNE; return COMPARISON; } "!=" { yylval.op = QgsSearchTreeNode::opNE; return COMPARISON; }
@ -80,6 +81,7 @@ string "'"{str_char}*"'"
">" { yylval.op = QgsSearchTreeNode::opGT; return COMPARISON; } ">" { yylval.op = QgsSearchTreeNode::opGT; return COMPARISON; }
"~" { yylval.op = QgsSearchTreeNode::opRegexp; return COMPARISON; } "~" { yylval.op = QgsSearchTreeNode::opRegexp; return COMPARISON; }
"LIKE" { yylval.op = QgsSearchTreeNode::opLike; return COMPARISON; } "LIKE" { yylval.op = QgsSearchTreeNode::opLike; return COMPARISON; }
"ILIKE" { yylval.op = QgsSearchTreeNode::opILike; return COMPARISON; }
"sqrt" { yylval.op = QgsSearchTreeNode::opSQRT; return FUNCTION;} "sqrt" { yylval.op = QgsSearchTreeNode::opSQRT; return FUNCTION;}
"sin" { yylval.op = QgsSearchTreeNode::opSIN; return FUNCTION;} "sin" { yylval.op = QgsSearchTreeNode::opSIN; return FUNCTION;}

View File

@ -64,6 +64,7 @@ void addToTmpNodes(QgsSearchTreeNode* node);
%token <op> FUNCTION %token <op> FUNCTION
%token CONCAT %token CONCAT
%token IS %token IS
%token IN
%token ROWNUM %token ROWNUM
%token AREA %token AREA
%token LENGTH %token LENGTH
@ -83,6 +84,7 @@ void addToTmpNodes(QgsSearchTreeNode* node);
%type <node> predicate %type <node> predicate
%type <node> comp_predicate %type <node> comp_predicate
%type <node> scalar_exp %type <node> scalar_exp
%type <node> scalar_exp_list
// debugging // debugging
//%error-verbose //%error-verbose
@ -130,9 +132,14 @@ comp_predicate:
| scalar_exp COMPARISON scalar_exp { $$ = new QgsSearchTreeNode($2, $1, $3); joinTmpNodes($$,$1,$3); } | scalar_exp COMPARISON scalar_exp { $$ = new QgsSearchTreeNode($2, $1, $3); joinTmpNodes($$,$1,$3); }
; ;
scalar_exp_list:
| scalar_exp_list ',' scalar_exp { $$ = $1; $1->append($3); joinTmpNodes($1,$1,$3); }
| scalar_exp { $$ = new QgsSearchTreeNode( QgsSearchTreeNode::tNodeList ); $$->append($1); joinTmpNodes($$,$$,$1); }
;
scalar_exp: scalar_exp:
FUNCTION '(' scalar_exp ')' { $$ = new QgsSearchTreeNode($1, $3, 0); joinTmpNodes($$, $3, 0);} FUNCTION '(' scalar_exp ')' { $$ = new QgsSearchTreeNode($1, $3, 0); joinTmpNodes($$, $3, 0);}
| scalar_exp '^' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPOW, $1, $3); joinTmpNodes($$, $1, $3); } | scalar_exp '^' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPOW, $1, $3); joinTmpNodes($$,$1,$3); }
| scalar_exp '*' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opMUL, $1, $3); joinTmpNodes($$,$1,$3); } | scalar_exp '*' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opMUL, $1, $3); joinTmpNodes($$,$1,$3); }
| scalar_exp '/' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opDIV, $1, $3); joinTmpNodes($$,$1,$3); } | scalar_exp '/' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opDIV, $1, $3); joinTmpNodes($$,$1,$3); }
| scalar_exp '+' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPLUS, $1, $3); joinTmpNodes($$,$1,$3); } | scalar_exp '+' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPLUS, $1, $3); joinTmpNodes($$,$1,$3); }
@ -147,6 +154,8 @@ scalar_exp:
| NUMBER { $$ = new QgsSearchTreeNode($1); addToTmpNodes($$); } | NUMBER { $$ = new QgsSearchTreeNode($1); addToTmpNodes($$); }
| STRING { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 0); addToTmpNodes($$); } | STRING { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 0); addToTmpNodes($$); }
| COLUMN_REF { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 1); addToTmpNodes($$); } | COLUMN_REF { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 1); addToTmpNodes($$); }
| scalar_exp IN '(' scalar_exp_list ')' { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opIN, $1, $4); joinTmpNodes($$,$1,$4); }
| scalar_exp NOT IN '(' scalar_exp_list ')' { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opNOTIN, $1, $5); joinTmpNodes($$,$1,$5); }
; ;
%% %%

View File

@ -38,6 +38,16 @@
#define EVAL_STR(x) (x.length() ? x : "(empty)") #define EVAL_STR(x) (x.length() ? x : "(empty)")
QgsSearchTreeNode::QgsSearchTreeNode( QgsSearchTreeNode::Type t )
{
Q_ASSERT( t == tNodeList );
mType = t;
mLeft = NULL;
mRight = NULL;
init();
}
QgsSearchTreeNode::QgsSearchTreeNode( double number ) QgsSearchTreeNode::QgsSearchTreeNode( double number )
{ {
mType = tNumber; mType = tNumber;
@ -49,7 +59,8 @@ QgsSearchTreeNode::QgsSearchTreeNode( double number )
} }
QgsSearchTreeNode::QgsSearchTreeNode( Operator op, QgsSearchTreeNode* left, QgsSearchTreeNode::QgsSearchTreeNode( Operator op,
QgsSearchTreeNode* left,
QgsSearchTreeNode* right ) QgsSearchTreeNode* right )
{ {
mType = tOperator; mType = tOperator;
@ -86,7 +97,6 @@ QgsSearchTreeNode::QgsSearchTreeNode( QString text, bool isColumnRef )
init(); init();
} }
QgsSearchTreeNode::QgsSearchTreeNode( const QgsSearchTreeNode& node ) QgsSearchTreeNode::QgsSearchTreeNode( const QgsSearchTreeNode& node )
{ {
mType = node.mType; mType = node.mType;
@ -105,6 +115,9 @@ QgsSearchTreeNode::QgsSearchTreeNode( const QgsSearchTreeNode& node )
else else
mRight = NULL; mRight = NULL;
foreach( QgsSearchTreeNode *lnode, node.mNodeList )
mNodeList.append( new QgsSearchTreeNode( *lnode ) );
init(); init();
} }
@ -119,6 +132,9 @@ QgsSearchTreeNode::~QgsSearchTreeNode()
if ( mRight ) if ( mRight )
delete mRight; delete mRight;
while ( !mNodeList.isEmpty() )
delete mNodeList.takeFirst();
delete mCalc; delete mCalc;
} }
@ -262,6 +278,9 @@ QString QgsSearchTreeNode::makeSearchString()
case opRegexp: str += " ~ "; break; case opRegexp: str += " ~ "; break;
case opLike: str += " LIKE "; break; case opLike: str += " LIKE "; break;
case opILike: str += " ILIKE "; break;
case opIN: str += " IN "; break;
case opNOTIN: str += " NOT IN "; break;
case opCONCAT: str += " || "; break; case opCONCAT: str += " || "; break;
@ -283,6 +302,16 @@ QString QgsSearchTreeNode::makeSearchString()
{ {
str += mText; str += mText;
} }
else if ( mType == tNodeList )
{
QStringList items;
foreach( QgsSearchTreeNode *node, mNodeList )
{
items << node->makeSearchString();
}
str += "(" + items.join( "," ) + ")";
}
else // unknown type else // unknown type
{ {
str += "unknown_node_type:"; str += "unknown_node_type:";
@ -422,8 +451,39 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
return false; return false;
} }
case opIN:
case opNOTIN:
{
if ( !getValue( value1, mLeft, fields, attributes, geom ) ||
!mRight || mRight->type() != tNodeList )
{
return false;
}
foreach( QgsSearchTreeNode *node, mRight->mNodeList )
{
if ( !getValue( value2, node, fields, attributes, geom ) )
{
mError = QObject::tr( "Could not retrieve value of list value" );
return false;
}
res = QgsSearchTreeValue::compare( value1, value2 );
if ( res == 0 )
{
// found
return mOp == opIN;
}
}
return mOp == opNOTIN;
}
break;
case opRegexp: case opRegexp:
case opLike: case opLike:
case opILike:
{ {
if ( !getValue( value1, mLeft, fields, attributes, geom ) || if ( !getValue( value1, mLeft, fields, attributes, geom ) ||
!getValue( value2, mRight, fields, attributes, geom ) ) !getValue( value2, mRight, fields, attributes, geom ) )
@ -443,12 +503,12 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
// TODO: reuse QRegExp // TODO: reuse QRegExp
QString str = value2.string(); QString str = value2.string();
if ( mOp == opLike ) // change from LIKE syntax to regexp if ( mOp == opLike || mOp == opILike ) // change from LIKE syntax to regexp
{ {
// XXX escape % and _ ??? // XXX escape % and _ ???
str.replace( "%", ".*" ); str.replace( "%", ".*" );
str.replace( "_", "." ); str.replace( "_", "." );
return QRegExp( str ).exactMatch( value1.string() ); return QRegExp( str, mOp == opLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( value1.string() );
} }
else else
{ {
@ -705,7 +765,17 @@ void QgsSearchTreeNode::setCurrentRowNumber( int rownum )
} }
} }
void QgsSearchTreeNode::append( QgsSearchTreeNode *node )
{
Q_ASSERT( mType == tNodeList );
mNodeList.append( node );
}
void QgsSearchTreeNode::append( QList<QgsSearchTreeNode *> nodes )
{
foreach( QgsSearchTreeNode *node, nodes )
mNodeList.append( node );
}
int QgsSearchTreeValue::compare( QgsSearchTreeValue& value1, QgsSearchTreeValue& value2, Qt::CaseSensitivity cs ) int QgsSearchTreeValue::compare( QgsSearchTreeValue& value1, QgsSearchTreeValue& value2, Qt::CaseSensitivity cs )
{ {

View File

@ -24,6 +24,7 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QVariant> #include <QVariant>
#include <QList>
#include <qgsfield.h> #include <qgsfield.h>
#include <qgsfeature.h> #include <qgsfeature.h>
@ -48,7 +49,8 @@ class CORE_EXPORT QgsSearchTreeNode
tOperator = 1, tOperator = 1,
tNumber, tNumber,
tColumnRef, tColumnRef,
tString tString,
tNodeList,
}; };
//! possible operators //! possible operators
@ -83,16 +85,19 @@ class CORE_EXPORT QgsSearchTreeNode
opAREA, opAREA,
// comparison // comparison
opISNULL, // IS NULL opISNULL, // IS NULL
opISNOTNULL, // IS NOT NULL opISNOTNULL, // IS NOT NULL
opEQ, // = opEQ, // =
opNE, // != resp. <> opNE, // != resp. <>
opGT, // > opGT, // >
opLT, // < opLT, // <
opGE, // >= opGE, // >=
opLE, // <= opLE, // <=
opRegexp, // ~ opRegexp, // ~
opLike, // LIKE opLike, // LIKE
opILike, // ILIKE
opIN, // IN
opNOTIN, // NOT IN
// string handling // string handling
opCONCAT, opCONCAT,
@ -103,6 +108,7 @@ class CORE_EXPORT QgsSearchTreeNode
}; };
//! constructors //! constructors
QgsSearchTreeNode( Type type );
QgsSearchTreeNode( double number ); QgsSearchTreeNode( double number );
QgsSearchTreeNode( Operator op, QgsSearchTreeNode* left, QgsSearchTreeNode* right ); QgsSearchTreeNode( Operator op, QgsSearchTreeNode* left, QgsSearchTreeNode* right );
QgsSearchTreeNode( QString text, bool isColumnRef ); QgsSearchTreeNode( QString text, bool isColumnRef );
@ -173,6 +179,14 @@ class CORE_EXPORT QgsSearchTreeNode
//! @note added in 1.6 //! @note added in 1.6
void setCurrentRowNumber( int rownum ); void setCurrentRowNumber( int rownum );
//! append a node to the list
//! @note added in 1.6
void append( QgsSearchTreeNode * );
//! append nodelist to the list
//! @note added in 1.6
void append( QList<QgsSearchTreeNode*> );
protected: protected:
@ -197,6 +211,7 @@ class CORE_EXPORT QgsSearchTreeNode
Operator mOp; Operator mOp;
double mNumber; double mNumber;
QString mText; QString mText;
QList<QgsSearchTreeNode *> mNodeList;
QString mError; QString mError;