00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgslogger.h"
00020 #include "qgsdistancearea.h"
00021 #include "qgsfield.h"
00022 #include "qgsgeometry.h"
00023 #include "qgssearchtreenode.h"
00024 #include <QRegExp>
00025 #include <QObject>
00026 #include <QSet>
00027 #include <QSettings>
00028
00029 #include <cmath>
00030
00031 #define EVAL_STR(x) (x.length() ? x : "(empty)")
00032
00033 QgsSearchTreeNode::QgsSearchTreeNode( QgsSearchTreeNode::Type t )
00034 {
00035 Q_ASSERT( t == tNodeList );
00036 mType = t;
00037 mLeft = NULL;
00038 mRight = NULL;
00039
00040 init();
00041 }
00042
00043 QgsSearchTreeNode::QgsSearchTreeNode( double number )
00044 {
00045 mType = tNumber;
00046 mNumber = number;
00047 mLeft = NULL;
00048 mRight = NULL;
00049
00050 init();
00051 }
00052
00053
00054 QgsSearchTreeNode::QgsSearchTreeNode( Operator op,
00055 QgsSearchTreeNode* left,
00056 QgsSearchTreeNode* right )
00057 {
00058 mType = tOperator;
00059 mOp = op;
00060 mLeft = left;
00061 mRight = right;
00062
00063 init();
00064 }
00065
00066
00067 QgsSearchTreeNode::QgsSearchTreeNode( QString text, bool isColumnRef )
00068 {
00069 mLeft = NULL;
00070 mRight = NULL;
00071
00072 if ( isColumnRef )
00073 {
00074 mType = tColumnRef;
00075 mText = text;
00076 if ( text.at( 0 ) == '\"' )
00077 {
00078
00079 stripColRef();
00080 }
00081 }
00082 else
00083 {
00084 mType = tString;
00085 mText = text;
00086 stripText();
00087 }
00088
00089 init();
00090 }
00091
00092 QgsSearchTreeNode::QgsSearchTreeNode( const QgsSearchTreeNode& node )
00093 {
00094 mType = node.mType;
00095 mOp = node.mOp;
00096 mNumber = node.mNumber;
00097 mText = node.mText;
00098
00099
00100 if ( node.mLeft )
00101 mLeft = new QgsSearchTreeNode( *node.mLeft );
00102 else
00103 mLeft = NULL;
00104
00105 if ( node.mRight )
00106 mRight = new QgsSearchTreeNode( *node.mRight );
00107 else
00108 mRight = NULL;
00109
00110 foreach( QgsSearchTreeNode * lnode, node.mNodeList )
00111 {
00112 mNodeList.append( new QgsSearchTreeNode( *lnode ) );
00113 }
00114
00115 init();
00116 }
00117
00118
00119 QgsSearchTreeNode::~QgsSearchTreeNode()
00120 {
00121
00122
00123 if ( mLeft )
00124 delete mLeft;
00125
00126 if ( mRight )
00127 delete mRight;
00128
00129 while ( !mNodeList.isEmpty() )
00130 delete mNodeList.takeFirst();
00131
00132 delete mCalc;
00133 }
00134
00135
00136 void QgsSearchTreeNode::init()
00137 {
00138 mCalc = NULL;
00139
00140 if ( mType == tOperator && ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER ) )
00141 {
00142
00143 mCalc = new QgsDistanceArea;
00144 mCalc->setProjectionsEnabled( false );
00145 QSettings settings;
00146 QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString();
00147 mCalc->setEllipsoid( ellipsoid );
00148 }
00149 else if ( mType == tOperator && mOp == opROWNUM )
00150 {
00151
00152 mNumber = 0;
00153 }
00154 }
00155
00156 void QgsSearchTreeNode::stripText()
00157 {
00158
00159 mText = mText.mid( 1, mText.length() - 2 );
00160
00161
00162 mText.replace( QRegExp( "''" ), "'" );
00163
00164
00165 int index = 0;
00166 while (( index = mText.indexOf( '\\', index ) ) != -1 )
00167 {
00168 mText.remove( index, 1 );
00169 QChar chr;
00170 switch ( mText[index].toLatin1() )
00171 {
00172 case 'n': chr = '\n'; break;
00173 case 't': chr = '\t'; break;
00174 case '\\': chr = '\\'; break;
00175 case '\'': chr = '\''; break;
00176 default: chr = '?'; break;
00177 }
00178 mText[index++] = chr;
00179 }
00180
00181 }
00182
00183 void QgsSearchTreeNode::stripColRef()
00184 {
00185
00186 mText = mText.mid( 1, mText.length() - 2 );
00187
00188
00189 mText.replace( QRegExp( "\"\"" ), "\"" );
00190 }
00191
00192 QString QgsSearchTreeNode::quotedColumnRef( QString name )
00193 {
00194 return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) );
00195 }
00196
00197
00198 QString QgsSearchTreeNode::makeSearchString()
00199 {
00200 QString str;
00201 if ( mType == tOperator )
00202 {
00203 if ( mOp == opSQRT || mOp == opSIN || mOp == opCOS || mOp == opTAN ||
00204 mOp == opASIN || mOp == opACOS || mOp == opATAN ||
00205 mOp == opTOINT || mOp == opTOREAL || mOp == opTOSTRING ||
00206 mOp == opLOWER || mOp == opUPPER || mOp == opSTRLEN ||
00207 mOp == opATAN2 || mOp == opREPLACE || mOp == opREGEXPREPLACE ||
00208 mOp == opSUBSTR || mOp == opXAT || mOp == opYAT )
00209 {
00210
00211 switch ( mOp )
00212 {
00213 case opSQRT: str += "sqrt"; break;
00214 case opSIN: str += "sin"; break;
00215 case opCOS: str += "cos"; break;
00216 case opTAN: str += "tan"; break;
00217 case opASIN: str += "asin"; break;
00218 case opACOS: str += "acos"; break;
00219 case opATAN: str += "atan"; break;
00220 case opTOINT: str += "to int"; break;
00221 case opTOREAL: str += "to real"; break;
00222 case opTOSTRING: str += "to string"; break;
00223 case opLOWER: str += "lower"; break;
00224 case opUPPER: str += "upper"; break;
00225 case opATAN2: str += "atan2"; break;
00226 case opSTRLEN: str += "length"; break;
00227 case opREPLACE: str += "replace"; break;
00228 case opREGEXPREPLACE: str += "regexp_replace"; break;
00229 case opSUBSTR: str += "substr"; break;
00230 case opXAT: str += "xat"; break;
00231 case opYAT: str += "yat"; break;
00232 default: str += "?";
00233 }
00234
00235 str += QString( "(%1)" ).arg( mLeft->makeSearchString() );
00236 }
00237 else if ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER || mOp == opROWNUM || mOp == opID || mOp == opX || mOp == opY )
00238 {
00239
00240 switch ( mOp )
00241 {
00242 case opLENGTH: str += "$length"; break;
00243 case opAREA: str += "$area"; break;
00244 case opPERIMETER: str += "$perimeter"; break;
00245 case opROWNUM: str += "$rownum"; break;
00246 case opX: str += "$x"; break;
00247 case opY: str += "$y"; break;
00248 case opID: str += "$id"; break;
00249 default: str += "?";
00250 }
00251 }
00252 else if ( mOp == opNOT )
00253 {
00254
00255 str += "(NOT " + mLeft->makeSearchString() + ")";
00256 }
00257 else
00258 {
00259
00260 str += "(";
00261 if ( mLeft )
00262 {
00263 str += mLeft->makeSearchString();
00264 }
00265 switch ( mOp )
00266 {
00267 case opAND: str += " AND "; break;
00268 case opOR: str += " OR "; break;
00269
00270 case opPLUS: str += "+"; break;
00271 case opMINUS: str += "-"; break;
00272 case opMUL: str += "*"; break;
00273 case opMOD: str += "%"; break;
00274 case opDIV: str += "/"; break;
00275 case opPOW: str += "^"; break;
00276
00277 case opEQ: str += " = "; break;
00278 case opNE: str += " != "; break;
00279 case opGT: str += " > "; break;
00280 case opLT: str += " < "; break;
00281 case opGE: str += " >= "; break;
00282 case opLE: str += " <= "; break;
00283
00284 case opISNULL: str += " IS NULL"; break;
00285 case opISNOTNULL: str += " IS NOT NULL"; break;
00286
00287 case opRegexp: str += " ~ "; break;
00288 case opLike: str += " LIKE "; break;
00289 case opILike: str += " ILIKE "; break;
00290 case opIN: str += " IN "; break;
00291 case opNOTIN: str += " NOT IN "; break;
00292
00293 case opCONCAT: str += " || "; break;
00294
00295 default: str += " ? ";
00296 }
00297
00298 if ( mRight )
00299 {
00300 str += mRight->makeSearchString();
00301 }
00302 str += ")";
00303 }
00304 }
00305 else if ( mType == tNumber )
00306 {
00307 str += QString::number( mNumber );
00308 }
00309 else if ( mType == tString || mType == tColumnRef )
00310 {
00311 str += mText;
00312 }
00313 else if ( mType == tNodeList )
00314 {
00315 QStringList items;
00316 foreach( QgsSearchTreeNode * node, mNodeList )
00317 {
00318 items << node->makeSearchString();
00319 }
00320
00321 str += "(" + items.join( "," ) + ")";
00322 }
00323 else
00324 {
00325 str += "unknown_node_type:";
00326 str += QString::number( mType );
00327 }
00328
00329 return str;
00330 }
00331
00332 QStringList QgsSearchTreeNode::referencedColumns()
00333 {
00334 QList<QgsSearchTreeNode*> columnNodeList = columnRefNodes();
00335 QSet<QString> columnStringSet;
00336
00337 QList<QgsSearchTreeNode*>::const_iterator nodeIt = columnNodeList.constBegin();
00338 for ( ; nodeIt != columnNodeList.constEnd(); ++nodeIt )
00339 {
00340 columnStringSet.insert(( *nodeIt )->columnRef() );
00341 }
00342 return columnStringSet.toList();
00343 }
00344
00345 QList<QgsSearchTreeNode*> QgsSearchTreeNode::columnRefNodes()
00346 {
00347 QList<QgsSearchTreeNode*> nodeList;
00348 if ( mType == tOperator )
00349 {
00350 if ( mLeft )
00351 {
00352 nodeList += mLeft->columnRefNodes();
00353 }
00354 if ( mRight )
00355 {
00356 nodeList += mRight->columnRefNodes();
00357 }
00358 }
00359 else if ( mType == tColumnRef )
00360 {
00361 nodeList.push_back( this );
00362 }
00363 return nodeList;
00364 }
00365
00366 bool QgsSearchTreeNode::needsGeometry()
00367 {
00368 if ( mType == tOperator )
00369 {
00370 if ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER || mOp == opX || mOp == opY || mOp == opXAT || mOp == opYAT )
00371 return true;
00372
00373 if ( mLeft && mLeft->needsGeometry() )
00374 return true;
00375
00376 if ( mRight && mRight->needsGeometry() )
00377 return true;
00378
00379 return false;
00380 }
00381 else
00382 {
00383 return false;
00384 }
00385 }
00386
00387 bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttributeMap &attributes, QgsGeometry* geom )
00388 {
00389 QgsFeature f;
00390 f.setAttributeMap( attributes );
00391 if ( geom )
00392 f.setGeometry( *geom );
00393 return checkAgainst( fields, f );
00394 }
00395
00396 bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, QgsFeature &f )
00397 {
00398 QgsDebugMsgLevel( "checkAgainst: " + makeSearchString(), 2 );
00399
00400 mError = "";
00401
00402
00403 if ( mType != tOperator )
00404 {
00405 mError = QObject::tr( "Expected operator, got scalar value!" );
00406 return false;
00407 }
00408
00409 QgsSearchTreeValue value1, value2;
00410
00411 switch ( mOp )
00412 {
00413 case opNOT:
00414 return !mLeft->checkAgainst( fields, f );
00415
00416 case opAND:
00417 if ( !mLeft->checkAgainst( fields, f ) )
00418 return false;
00419 return mRight->checkAgainst( fields, f );
00420
00421 case opOR:
00422 if ( mLeft->checkAgainst( fields, f ) )
00423 return true;
00424 return mRight->checkAgainst( fields, f );
00425
00426 case opISNULL:
00427 case opISNOTNULL:
00428 if ( !getValue( value1, mLeft, fields, f ) )
00429 return false;
00430
00431 return ( mOp == opISNULL ) == value1.isNull();
00432
00433 case opEQ:
00434 case opNE:
00435 case opGT:
00436 case opLT:
00437 case opGE:
00438 case opLE:
00439 {
00440 if ( !getValue( value1, mLeft, fields, f ) || !getValue( value2, mRight, fields, f ) )
00441 return false;
00442
00443 if ( value1.isNull() || value2.isNull() )
00444 {
00445
00446 return false;
00447 }
00448
00449 QgsSearchTreeValue res = QgsSearchTreeValue::compare( value1, value2 );
00450 if ( res.isError() )
00451 {
00452 mError = QString( "%1 [%2]" ).arg( res.string() ).arg( res.number() );
00453 return false;
00454 }
00455
00456 switch ( mOp )
00457 {
00458 case opEQ: return res.number() == 0.0;
00459 case opNE: return res.number() != 0.0;
00460 case opGT: return res.number() > 0.0;
00461 case opLT: return res.number() < 0.0;
00462 case opGE: return res.number() >= 0.0;
00463 case opLE: return res.number() <= 0.0;
00464 default:
00465 mError = QObject::tr( "Unexpected state when evaluating operator!" );
00466 return false;
00467 }
00468 }
00469 break;
00470
00471 case opIN:
00472 case opNOTIN:
00473 {
00474 if ( !getValue( value1, mLeft, fields, f ) ||
00475 !mRight || mRight->type() != tNodeList )
00476 {
00477 return false;
00478 }
00479
00480 foreach( QgsSearchTreeNode * node, mRight->mNodeList )
00481 {
00482 if ( !getValue( value2, node, fields, f ) )
00483 {
00484 mError = QObject::tr( "Could not retrieve value of list value" );
00485 return false;
00486 }
00487
00488 QgsSearchTreeValue res = QgsSearchTreeValue::compare( value1, value2 );
00489
00490 if ( res.isNumeric() && res.number() == 0.0 )
00491 {
00492
00493 return mOp == opIN;
00494 }
00495 }
00496
00497 return mOp == opNOTIN;
00498 }
00499
00500 case opRegexp:
00501 case opLike:
00502 case opILike:
00503 {
00504 if ( !getValue( value1, mLeft, fields, f ) ||
00505 !getValue( value2, mRight, fields, f ) )
00506 return false;
00507
00508
00509
00510
00511
00512
00513 if ( value1.isNumeric() || value2.isNumeric() )
00514 {
00515 mError = QObject::tr( "Regular expressions on numeric values don't make sense. Use comparison instead." );
00516 return false;
00517 }
00518
00519
00520
00521 QString str = value2.string();
00522 if ( mOp == opLike || mOp == opILike )
00523 {
00524
00525 str.replace( "%", ".*" );
00526 str.replace( "_", "." );
00527 return QRegExp( str, mOp == opLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( value1.string() );
00528 }
00529 else
00530 {
00531 return QRegExp( str ).indexIn( value1.string() ) != -1;
00532 }
00533 }
00534
00535 default:
00536 mError = QObject::tr( "Unknown operator: %1" ).arg( mOp );
00537 }
00538
00539 return false;
00540 }
00541
00542 bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value,
00543 QgsSearchTreeNode* node,
00544 const QgsFieldMap &fields,
00545 const QgsAttributeMap &attributes,
00546 QgsGeometry* geom )
00547 {
00548 QgsFeature f;
00549 f.setAttributeMap( attributes );
00550 if ( geom )
00551 f.setGeometry( *geom );
00552 return getValue( value, node, fields, f );
00553 }
00554
00555 bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value,
00556 QgsSearchTreeNode* node,
00557 const QgsFieldMap& fields,
00558 QgsFeature &f )
00559 {
00560 value = node->valueAgainst( fields, f );
00561 if ( value.isError() )
00562 {
00563 switch (( int ) value.number() )
00564 {
00565 case 1:
00566 mError = QObject::tr( "Referenced column wasn't found: %1" ).arg( value.string() );
00567 break;
00568 case 2:
00569 mError = QObject::tr( "Division by zero." );
00570 break;
00571 case 3:
00572 mError = QObject::tr( "Unknown operator: %1" ).arg( value.string() );
00573 break;
00574 case 4:
00575 mError = QObject::tr( "Unknown token: %1" ).arg( value.string() );
00576 break;
00577 case 5:
00578 mError = QObject::tr( "Expression error: %1" ).arg( value.string() );
00579 break;
00580 default:
00581 mError = QObject::tr( "Unknown error %1: %2" ).arg( value.number() ).arg( value.string() );
00582 break;
00583 }
00584 return false;
00585 }
00586 return true;
00587 }
00588
00589 QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields,
00590 const QgsAttributeMap &attributes,
00591 QgsGeometry* geom )
00592 {
00593 QgsFeature f;
00594 f.setAttributeMap( attributes );
00595 if ( geom )
00596 f.setGeometry( *geom );
00597 return valueAgainst( fields, f );
00598 }
00599
00600 QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, QgsFeature &f )
00601 {
00602 QgsDebugMsgLevel( "valueAgainst: " + makeSearchString(), 2 );
00603
00604 switch ( mType )
00605 {
00606 case tNumber:
00607 QgsDebugMsgLevel( "number: " + QString::number( mNumber ), 2 );
00608 return QgsSearchTreeValue( mNumber );
00609
00610 case tString:
00611 QgsDebugMsgLevel( "text: " + EVAL_STR( mText ), 2 );
00612 return QgsSearchTreeValue( mText );
00613
00614 case tColumnRef:
00615 {
00616 QgsDebugMsgLevel( "column (" + mText.toLower() + "): ", 2 );
00617
00618 QgsFieldMap::const_iterator it;
00619 for ( it = fields.begin(); it != fields.end(); it++ )
00620 {
00621 if ( QString::compare( it->name(), mText, Qt::CaseInsensitive ) == 0 )
00622 break;
00623 }
00624
00625 if ( it == fields.end() )
00626 {
00627
00628 QgsDebugMsgLevel( "ERROR!", 2 );
00629 return QgsSearchTreeValue( 1, mText );
00630 }
00631
00632
00633 QVariant val = f.attributeMap()[it.key()];
00634 if ( val.isNull() )
00635 {
00636 QgsDebugMsgLevel( " NULL", 2 );
00637 return QgsSearchTreeValue();
00638 }
00639 else if ( val.type() == QVariant::Bool || val.type() == QVariant::Int || val.type() == QVariant::Double )
00640 {
00641 QgsDebugMsgLevel( " number: " + QString::number( val.toDouble() ), 2 );
00642 return QgsSearchTreeValue( val.toDouble() );
00643 }
00644 else
00645 {
00646 QgsDebugMsgLevel( " text: " + EVAL_STR( val.toString() ), 2 );
00647 return QgsSearchTreeValue( val.toString() );
00648 }
00649
00650 }
00651
00652
00653 case tOperator:
00654 {
00655 QgsSearchTreeValue value1, value2, value3;
00656 if ( mLeft )
00657 {
00658 if ( mLeft->type() != tNodeList )
00659 {
00660 if ( !getValue( value1, mLeft, fields, f ) )
00661 return value1;
00662 }
00663 else
00664 {
00665 if ( mLeft->mNodeList.size() > 0 && !getValue( value1, mLeft->mNodeList[0], fields, f ) )
00666 return value1;
00667 if ( mLeft->mNodeList.size() > 1 && !getValue( value2, mLeft->mNodeList[1], fields, f ) )
00668 return value2;
00669 if ( mLeft->mNodeList.size() > 2 && !getValue( value3, mLeft->mNodeList[2], fields, f ) )
00670 return value3;
00671 }
00672 }
00673 if ( mRight )
00674 {
00675 Q_ASSERT( !mLeft || mLeft->type() != tNodeList );
00676 if ( !getValue( value2, mRight, fields, f ) )
00677 return value2;
00678 }
00679
00680 if ( mOp == opLENGTH || mOp == opAREA || mOp == opPERIMETER || mOp == opX || mOp == opY || mOp == opXAT || mOp == opYAT )
00681 {
00682 if ( !f.geometry() )
00683 {
00684 return QgsSearchTreeValue( 2, QObject::tr( "Geometry is 0" ) );
00685 }
00686
00687
00688 if ( mOp == opLENGTH && f.geometry()->type() == QGis::Line )
00689 {
00690 return QgsSearchTreeValue( mCalc->measure( f.geometry() ) );
00691 }
00692 if ( mOp == opAREA && f.geometry()->type() == QGis::Polygon )
00693 {
00694 return QgsSearchTreeValue( mCalc->measure( f.geometry() ) );
00695 }
00696 if ( mOp == opPERIMETER && f.geometry()->type() == QGis::Polygon )
00697 {
00698 return QgsSearchTreeValue( mCalc->measurePerimeter( f.geometry() ) );
00699 }
00700 if ( mOp == opX && f.geometry()->type() == QGis::Point )
00701 {
00702 return QgsSearchTreeValue( f.geometry()->asPoint().x() );
00703 }
00704 if ( mOp == opY && f.geometry()->type() == QGis::Point )
00705 {
00706 return QgsSearchTreeValue( f.geometry()->asPoint().y() );
00707 }
00708 if (( mOp == opXAT || mOp == opYAT ) && f.geometry()->type() == QGis::Line && value1.isNumeric() )
00709 {
00710 QgsPolyline p = f.geometry()->asPolyline();
00711
00712 int idx = value1.number();
00713 if ( idx < 0 )
00714 {
00715 idx += p.size();
00716 }
00717
00718 if ( idx < 0 || idx >= p.size() )
00719 {
00720 return QgsSearchTreeValue( 2, QObject::tr( "Index %1 out of range [0;%2[" ).arg( idx ).arg( p.size() ) );
00721 }
00722
00723 return QgsSearchTreeValue( mOp == opXAT ? p[idx].x() : p[idx].y() );
00724 }
00725
00726 return QgsSearchTreeValue( 0 );
00727 }
00728
00729 if ( mOp == opID )
00730 {
00731 return QgsSearchTreeValue( f.id() );
00732 }
00733
00734 if ( mOp == opROWNUM )
00735 {
00736
00737 return QgsSearchTreeValue( mNumber );
00738 }
00739
00740
00741 if ( !mRight && !value1.isNumeric() )
00742 {
00743 if ( mOp == opTOINT )
00744 {
00745 return QgsSearchTreeValue( value1.string().toInt() );
00746 }
00747 else if ( mOp == opTOREAL )
00748 {
00749 return QgsSearchTreeValue( value1.string().toDouble() );
00750 }
00751 }
00752
00753
00754 if ( mLeft && mRight && !value1.isNumeric() && !value2.isNumeric() )
00755 {
00756
00757
00758 if ( mOp == opPLUS )
00759 {
00760 return QgsSearchTreeValue( value1.string() + value2.string() );
00761 }
00762 }
00763
00764
00765 if ( mLeft && mRight && mOp == opCONCAT )
00766 {
00767 if ( value1.isNumeric() && value2.isNumeric() )
00768 {
00769 return QgsSearchTreeValue( 5, QObject::tr( "Operator doesn't match the argument types." ) );
00770 }
00771 else
00772 {
00773 QString arg1 = value1.isNumeric() ? QString::number( value1.number() ) : value1.string();
00774 QString arg2 = value2.isNumeric() ? QString::number( value2.number() ) : value2.string();
00775 return QgsSearchTreeValue( arg1 + arg2 );
00776 }
00777 }
00778
00779
00780 switch ( mOp )
00781 {
00782 case opLOWER:
00783 return QgsSearchTreeValue( value1.string().toLower() );
00784 case opUPPER:
00785 return QgsSearchTreeValue( value1.string().toUpper() );
00786 case opSTRLEN:
00787 return QgsSearchTreeValue( value1.string().length() );
00788 case opREPLACE:
00789 return QgsSearchTreeValue( value1.string().replace( value2.string(), value3.string() ) );
00790 case opREGEXPREPLACE:
00791 {
00792 QRegExp re( value2.string() );
00793 if ( !re.isValid() )
00794 {
00795 return QgsSearchTreeValue( 5, QObject::tr( "Invalid regular expression '%1': %2" ).arg( value2.string() ).arg( re.errorString() ) );
00796 }
00797
00798 return QgsSearchTreeValue( value1.string().replace( re, value3.string() ) );
00799 }
00800 case opSUBSTR:
00801 return QgsSearchTreeValue( value1.string().mid( value2.number() - 1, value3.number() ) );
00802 default:
00803 break;
00804 }
00805
00806
00807 double val1, val2;
00808 if ( value1.isNumeric() )
00809 val1 = value1.number();
00810 else
00811 val1 = value1.string().toDouble();
00812 if ( value2.isNumeric() )
00813 val2 = value2.number();
00814 else
00815 val2 = value2.string().toDouble();
00816
00817 switch ( mOp )
00818 {
00819 case opPLUS:
00820 return QgsSearchTreeValue( val1 + val2 );
00821 case opMINUS:
00822 return QgsSearchTreeValue( val1 - val2 );
00823 case opMUL:
00824 return QgsSearchTreeValue( val1 * val2 );
00825 case opMOD:
00826
00827
00828 return QgsSearchTreeValue( int( val1 ) % int( val2 ) );
00829 case opDIV:
00830 if ( val2 == 0 )
00831 return QgsSearchTreeValue( 2, "" );
00832 else
00833 return QgsSearchTreeValue( val1 / val2 );
00834 case opPOW:
00835 if (( val1 == 0 && val2 < 0 ) || ( val2 < 0 && ( val2 - floor( val2 ) ) > 0 ) )
00836 {
00837 return QgsSearchTreeValue( 4, QObject::tr( "Error in power function" ) );
00838 }
00839 return QgsSearchTreeValue( pow( val1, val2 ) );
00840 case opSQRT:
00841 return QgsSearchTreeValue( sqrt( val1 ) );
00842 case opSIN:
00843 return QgsSearchTreeValue( sin( val1 ) );
00844 case opCOS:
00845 return QgsSearchTreeValue( cos( val1 ) );
00846 case opTAN:
00847 return QgsSearchTreeValue( tan( val1 ) );
00848 case opASIN:
00849 return QgsSearchTreeValue( asin( val1 ) );
00850 case opACOS:
00851 return QgsSearchTreeValue( acos( val1 ) );
00852 case opATAN:
00853 return QgsSearchTreeValue( atan( val1 ) );
00854 case opATAN2:
00855 return QgsSearchTreeValue( atan2( val1, val2 ) );
00856 case opTOINT:
00857 return QgsSearchTreeValue( int( val1 ) );
00858 case opTOREAL:
00859 return QgsSearchTreeValue( val1 );
00860 case opTOSTRING:
00861 return QgsSearchTreeValue( QString::number( val1 ) );
00862
00863 default:
00864 return QgsSearchTreeValue( 3, QString::number( mOp ) );
00865 }
00866 }
00867
00868 default:
00869 return QgsSearchTreeValue( 4, QString::number( mType ) );
00870 }
00871 }
00872
00873
00874 void QgsSearchTreeNode::setCurrentRowNumber( int rownum )
00875 {
00876 if ( mType == tOperator )
00877 {
00878 if ( mOp == opROWNUM )
00879 mNumber = rownum;
00880 else
00881 {
00882
00883 if ( mLeft )
00884 mLeft->setCurrentRowNumber( rownum );
00885 if ( mRight )
00886 mRight->setCurrentRowNumber( rownum );
00887 }
00888 }
00889 }
00890
00891 void QgsSearchTreeNode::append( QgsSearchTreeNode *node )
00892 {
00893 Q_ASSERT( mType == tNodeList );
00894 mNodeList.append( node );
00895 }
00896
00897 void QgsSearchTreeNode::append( QList<QgsSearchTreeNode *> nodes )
00898 {
00899 foreach( QgsSearchTreeNode * node, nodes )
00900 {
00901 mNodeList.append( node );
00902 }
00903 }
00904
00905 QgsSearchTreeValue QgsSearchTreeValue::compare( QgsSearchTreeValue& value1, QgsSearchTreeValue& value2, Qt::CaseSensitivity cs )
00906 {
00907 if ( value1.isNumeric() || value2.isNumeric() )
00908 {
00909
00910
00911
00912 double val1, val2;
00913 bool ok;
00914 if ( value1.isNumeric() )
00915 {
00916 val1 = value1.number();
00917 }
00918 else
00919 {
00920 val1 = value1.string().toDouble( &ok );
00921 if ( !ok )
00922 {
00923 return QgsSearchTreeValue( 5, QObject::tr( "Value '%1' is not numeric" ).arg( value1.string() ) );
00924 }
00925 }
00926 if ( value2.isNumeric() )
00927 {
00928 val2 = value2.number();
00929 }
00930 else
00931 {
00932 val2 = value2.string().toDouble( &ok );
00933 if ( !ok )
00934 {
00935 return QgsSearchTreeValue( 5, QObject::tr( "Value '%1' is not numeric" ).arg( value2.string() ) );
00936 }
00937 }
00938
00939 QgsDebugMsgLevel( "NUM_COMP: " + QString::number( val1 ) + " ~ " + QString::number( val2 ), 2 );
00940
00941 if ( val1 < val2 )
00942 return QgsSearchTreeValue( -1.0 );
00943 else if ( val1 > val2 )
00944 return QgsSearchTreeValue( 1.0 );
00945 else
00946 return QgsSearchTreeValue( 0.0 );
00947 }
00948 else
00949 {
00950
00951 return QgsSearchTreeValue(( double ) value1.string().compare( value2.string(), cs ) );
00952 }
00953 }