Skip to content

Commit

Permalink
[FEATURE] support NULL values in search strings (fixes #2533)
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk@13023 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
jef committed Mar 8, 2010
1 parent 005205d commit 0e72bcb
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
4 changes: 4 additions & 0 deletions src/core/qgssearchstringlexer.ll
Expand Up @@ -59,6 +59,10 @@ string "'"{str_char}*"'"
"AND" { return AND; }
"OR" { return OR; }

"NULL" { return NULLVALUE; }

"IS" { return IS; }

"=" { yylval.op = QgsSearchTreeNode::opEQ; return COMPARISON; }
"!=" { yylval.op = QgsSearchTreeNode::opNE; return COMPARISON; }
"<=" { yylval.op = QgsSearchTreeNode::opLE; return COMPARISON; }
Expand Down
12 changes: 8 additions & 4 deletions src/core/qgssearchstringparser.yy
Expand Up @@ -62,8 +62,10 @@ void addToTmpNodes(QgsSearchTreeNode* node);
%token <number> NUMBER
%token <op> COMPARISON
%token <op> FUNCTION
%token IS
%token AREA
%token LENGTH
%token NULLVALUE

%token STRING
%token COLUMN_REF
Expand Down Expand Up @@ -119,12 +121,14 @@ predicate:
;

comp_predicate:
scalar_exp COMPARISON scalar_exp { $$ = new QgsSearchTreeNode($2, $1, $3); joinTmpNodes($$,$1,$3); }
scalar_exp IS NULLVALUE { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opISNULL, $1, 0); joinTmpNodes($$,$1,0); }
| scalar_exp IS NOT NULLVALUE { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opISNOTNULL, $1, 0); joinTmpNodes($$,$1,0); }
| scalar_exp COMPARISON scalar_exp { $$ = new QgsSearchTreeNode($2, $1, $3); joinTmpNodes($$,$1,$3); }
;

scalar_exp:
FUNCTION '(' scalar_exp ')' {$$ = new QgsSearchTreeNode($1, $3, 0); joinTmpNodes($$, $3, 0);}
| scalar_exp '^' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPOW, $1, $3); joinTmpNodes($$, $1, $3); }
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::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::opPLUS, $1, $3); joinTmpNodes($$,$1,$3); }
Expand All @@ -134,7 +138,7 @@ scalar_exp:
| '-' scalar_exp %prec UMINUS { $$ = $2; if ($$->type() == QgsSearchTreeNode::tNumber) $$->setNumber(- $$->number()); }
| AREA { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opAREA, 0, 0); addToTmpNodes($$); }
| LENGTH { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opLENGTH, 0, 0); addToTmpNodes($$); }
| NUMBER { $$ = new QgsSearchTreeNode($1); addToTmpNodes($$); }
| NUMBER { $$ = new QgsSearchTreeNode($1); addToTmpNodes($$); }
| STRING { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 0); addToTmpNodes($$); }
| COLUMN_REF { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 1); addToTmpNodes($$); }
;
Expand Down
27 changes: 26 additions & 1 deletion src/core/qgssearchtreenode.cpp
Expand Up @@ -237,6 +237,20 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
return true;
return mRight->checkAgainst( fields, attributes );

case opISNULL:
case opISNOTNULL:
if ( !getValue( value1, mLeft, fields, attributes ) )
return false;

if ( mOp == opISNULL )
{
return value1.isNull();
}
else if ( mOp == opISNOTNULL )
{
return !value1.isNull();
}

case opEQ:
case opNE:
case opGT:
Expand All @@ -247,6 +261,12 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
if ( !getValue( value1, mLeft, fields, attributes ) || !getValue( value2, mRight, fields, attributes ) )
return false;

if ( value1.isNull() || value2.isNull() )
{
// NULL values never match
return false;
}

res = QgsSearchTreeValue::compare( value1, value2 );

switch ( mOp )
Expand Down Expand Up @@ -365,7 +385,12 @@ QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, c

// get the value
QVariant val = attributes[it.key()];
if ( val.type() == QVariant::Bool || val.type() == QVariant::Int || val.type() == QVariant::Double )
if ( val.isNull() )
{
QgsDebugMsgLevel( " NULL", 2 );
return QgsSearchTreeValue();
}
else if ( val.type() == QVariant::Bool || val.type() == QVariant::Int || val.type() == QVariant::Double )
{
QgsDebugMsgLevel( " number: " + QString::number( val.toDouble() ), 2 );
return QgsSearchTreeValue( val.toDouble() );
Expand Down
10 changes: 7 additions & 3 deletions src/core/qgssearchtreenode.h
Expand Up @@ -78,6 +78,8 @@ class CORE_EXPORT QgsSearchTreeNode
opAREA,

// comparison
opISNULL, // IS NULL
opISNOTNULL, // IS NOT NULL
opEQ, // =
opNE, // != resp. <>
opGT, // >
Expand Down Expand Up @@ -174,11 +176,12 @@ class CORE_EXPORT QgsSearchTreeValue
{
valError,
valString,
valNumber
valNumber,
valNull
};

QgsSearchTreeValue() { }
QgsSearchTreeValue( QString string ) { mType = valString; mString = string; }
QgsSearchTreeValue() { mType = valNull; }
QgsSearchTreeValue( QString string ) { mType = string.isNull() ? valNull : valString; mString = string; }
QgsSearchTreeValue( double number ) { mType = valNumber; mNumber = number; }
QgsSearchTreeValue( int error, QString errorMsg ) { mType = valError; mNumber = error; mString = errorMsg; }

Expand All @@ -187,6 +190,7 @@ class CORE_EXPORT QgsSearchTreeValue

bool isNumeric() { return mType == valNumber; }
bool isError() { return mType == valError; }
bool isNull() { return mType == valNull; }

QString& string() { return mString; }
double number() { return mNumber; }
Expand Down

0 comments on commit 0e72bcb

Please sign in to comment.