290 changes: 0 additions & 290 deletions src/core/qgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,36 +207,11 @@ const char* QgsExpression::BinaryOperatorText[] =
"||"
};

const char* QgsExpression::BinaryOgcOperatorText[] =
{
"Or", "And",
"PropertyIsEqualTo", "PropertyIsNotEqualTo",
"PropertyIsLessThanOrEqualTo", "PropertyIsGreaterThanOrEqualTo",
"PropertyIsLessThan", "PropertyIsGreaterThan",
"", "PropertyIsLike", "", "", "",
"Add", "Sub", "Mul", "Div", "", "",
""
};

const char* QgsExpression::UnaryOperatorText[] =
{
"NOT", "-"
};

const char* QgsExpression::UnaryOgcOperatorText[] =
{
"Not", ""
};

const char* QgsExpression::SpatialOgcOperatorText[] =
{
"BBOX", "Intersects",
"Contians", "Crosses",
"Equals", "Disjoint",
"Overlaps", "Touches",
"Within"
};

///////////////////////////////////////////////
// functions

Expand Down Expand Up @@ -1318,15 +1293,6 @@ QString QgsExpression::dump() const
return mRootNode->dump();
}

void QgsExpression::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
if ( !mRootNode )
return;

mRootNode->toOgcFilter( doc, element );
}


void QgsExpression::acceptVisitor( QgsExpression::Visitor& v ) const
{
if ( mRootNode )
Expand Down Expand Up @@ -1430,13 +1396,6 @@ QString QgsExpression::NodeList::dump() const
return msg;
}

void QgsExpression::NodeList::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
foreach ( Node* n, mList )
{
n->toOgcFilter( doc, element );
}
}

//

Expand Down Expand Up @@ -1478,28 +1437,6 @@ QString QgsExpression::NodeUnaryOperator::dump() const
return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() );
}

void QgsExpression::NodeUnaryOperator::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
QDomElement uoElem;
switch ( mOp )
{
case uoMinus:
uoElem = doc.createElement( "ogc:Literal" );
uoElem.appendChild( doc.createTextNode( "-" ) );
break;
case uoNot:
uoElem = doc.createElement( "ogc:Not" );
break;

default:
element.appendChild( doc.createComment( QString( "Unary operator %1 not implemented yet" ).arg( UnaryOperatorText[mOp] ) ) );
return;
}
mOperand->toOgcFilter( doc, uoElem );
element.appendChild( uoElem );
}


//

QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression* parent, QgsFeature* f )
Expand Down Expand Up @@ -1736,104 +1673,6 @@ QString QgsExpression::NodeBinaryOperator::dump() const
return QString( "%1 %2 %3" ).arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
}

void QgsExpression::NodeBinaryOperator::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
if ( mOp == boConcat )
{
// the concat binary operator must only convert its operands
mOpLeft->toOgcFilter( doc, element );
mOpRight->toOgcFilter( doc, element );
return;
}

if ( mOp == boIs || mOp == boIsNot )
{
// check if one of the operands is NULL
QgsExpression::NodeLiteral *opLeftLiteral = dynamic_cast<QgsExpression::NodeLiteral *>( mOpLeft );
QgsExpression::NodeLiteral *opRightLiteral = dynamic_cast<QgsExpression::NodeLiteral *>( mOpRight );

if ( opLeftLiteral && opLeftLiteral->value().isNull() &&
opRightLiteral && opRightLiteral->value().isNull() )
{
// why could anybody find useful to use NULL IS NULL???
// BTW avoid issues by converting it to 1 = 1
QDomElement eqElem = doc.createElement( "ogc:PropertyIsEqual" );

QDomElement literalElem = doc.createElement( "ogc:Literal" );
literalElem.appendChild( doc.createTextNode( "1" ) );
eqElem.appendChild( literalElem );

literalElem = doc.createElement( "ogc:Literal" );
literalElem.appendChild( doc.createTextNode( "1" ) );
eqElem.appendChild( literalElem );

element.appendChild( eqElem );
}
else if (( opLeftLiteral && opLeftLiteral->value().isNull() ) ||
( opRightLiteral && opRightLiteral->value().isNull() ) )
{
// at least one operand is NULL, use <ogc:PropertyIsNull> element
QDomElement isNullElem = doc.createElement( "ogc:PropertyIsNull" );
QgsExpression::Node *operand = opLeftLiteral->value().isNull() ? mOpRight : mOpLeft;
operand->toOgcFilter( doc, isNullElem );

if ( mOp == boIsNot )
{
// append to <ogc:Not> element if IS NOT operator was required
QDomElement notOpElem = doc.createElement( "ogc:Not" );
notOpElem.appendChild( isNullElem );
element.appendChild( notOpElem );
}
else
{
element.appendChild( isNullElem );
}
}
else
{
// both operands are not null, use <ogc:PropertyIsEqual> element
QDomElement eqElem = doc.createElement( "ogc:PropertyIsEqual" );
mOpLeft->toOgcFilter( doc, eqElem );
mOpRight->toOgcFilter( doc, eqElem );
element.appendChild( eqElem );
}
return;
}

if ( mOp == boILike )
{
// XXX why ogc:PropertyIsLikeType extends ogc:ComparisonOpsType
// which has no matchCase attribute? Shouldn't it be better if
// would extend BinaryComparisonOpType which has that attribute
// and doesn't require to have a ogc:PropertyName as first parameter?
QgsExpression ilikeExpr( QString( "upper( %1 ) LIKE upper( %2 )" ).arg( mOpLeft->dump() ).arg( mOpRight->dump() ) );
ilikeExpr.toOgcFilter( doc, element );
return;
}

QString opText = BinaryOgcOperatorText[mOp];
if ( opText.isEmpty() )
{
// not implemented binary operators
// TODO: regex, % (mod), ^ (pow) are not supported yet
element.appendChild( doc.createComment( QString( "Binary operator %1 not implemented yet" ).arg( BinaryOperatorText[mOp] ) ) );
return;
}

QDomElement boElem = doc.createElement( "ogc:" + opText );
if ( mOp == boLike )
{
// setup wildcards to <ogc:PropertyIsLike>
boElem.setAttribute( "wildCard", "%" );
boElem.setAttribute( "singleChar", "?" );
boElem.setAttribute( "escapeChar", "!" );
}

mOpLeft->toOgcFilter( doc, boElem );
mOpRight->toOgcFilter( doc, boElem );
element.appendChild( boElem );
}

//

QVariant QgsExpression::NodeInOperator::eval( QgsExpression* parent, QgsFeature* f )
Expand Down Expand Up @@ -1897,31 +1736,6 @@ QString QgsExpression::NodeInOperator::dump() const
return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() );
}

void QgsExpression::NodeInOperator::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
// XXX use a function instead of multiple comparations?

QDomElement *parent = &element;

QDomElement orElem;
if ( mList->list().size() > 1 )
{
orElem = doc.createElement( "ogc:Or" );
element.appendChild( orElem );

parent = &orElem;
}

foreach ( Node* n, mList->list() )
{
QDomElement eqElem = doc.createElement( "ogc:PropertyIsEqualTo" );
mNode->toOgcFilter( doc, eqElem );
n->toOgcFilter( doc, eqElem );

parent->appendChild( eqElem );
}
}

//

QVariant QgsExpression::NodeFunction::eval( QgsExpression* parent, QgsFeature* f )
Expand Down Expand Up @@ -1972,70 +1786,6 @@ QString QgsExpression::NodeFunction::dump() const
return QString( "%1(%2)" ).arg( fd->name() ).arg( mArgs ? mArgs->dump() : QString() ); // function
}

void QgsExpression::NodeFunction::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
Function* fd = Functions()[mFnIndex];
if ( fd->params() == 0 )
return; // TODO: special column

bool isSpatial = false;
// check for spatial operators
int spatialOpCount = sizeof( SpatialOgcOperatorText ) / sizeof( SpatialOgcOperatorText[0] );
for ( int i = 0; i < spatialOpCount; i++ )
{
QString ogcOperatorName = SpatialOgcOperatorText[ i ];
if ( ogcOperatorName.isEmpty() )
continue;

if ( fd->name() == ogcOperatorName.toLower() )
{
isSpatial = true;
QDomElement funcElem = doc.createElement( "ogc:" + ogcOperatorName );
QDomElement geomProperty = doc.createElement( "ogc:PropertyName" );
geomProperty.appendChild( doc.createTextNode( "geometry" ) );
funcElem.appendChild( geomProperty );

QDomDocument tmpDoc;
QDomElement tmpElem = tmpDoc.createElement( "tmp" );
mArgs->toOgcFilter( tmpDoc, tmpElem );
QDomElement childElem = funcElem.firstChildElement();
while ( !childElem.isNull() )
{
if ( childElem.tagName() == "Function" )
{
if ( childElem.attribute( "name" ) == "geomFromWKT" )
{
QgsGeometry* geom = QgsGeometry::fromWkt( childElem.firstChildElement().text() );
if ( geom )
funcElem.appendChild( QgsOgcUtils::geometryToGML( geom, doc ) );
delete geom;
}
else if ( childElem.attribute( "name" ) == "geomFromGML2" )
{
QDomDocument geomDoc;
QString errorMsg;
QString gml = childElem.firstChildElement().text();
if ( geomDoc.setContent( gml, true, &errorMsg ) )
funcElem.appendChild( doc.documentElement() );
}
}
childElem = childElem.nextSiblingElement();
}

element.appendChild( funcElem );
}
}

if ( !isSpatial )
{
QDomElement funcElem = doc.createElement( "ogc:Function" );
funcElem.setAttribute( "name", fd->name() );
mArgs->toOgcFilter( doc, funcElem );
element.appendChild( funcElem );
}
}


//

QVariant QgsExpression::NodeLiteral::eval( QgsExpression* , QgsFeature* )
Expand Down Expand Up @@ -2063,32 +1813,6 @@ QString QgsExpression::NodeLiteral::dump() const
}
}

void QgsExpression::NodeLiteral::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
QString value;
if ( !mValue.isNull() )
{
switch ( mValue.type() )
{
case QVariant::Int:
value = QString::number( mValue.toInt() );
break;
case QVariant::Double:
value = QString::number( mValue.toDouble() );
break;
case QVariant::String:
value = mValue.toString();
break;
default:
break;
}
}
QDomElement litElem = doc.createElement( "ogc:Literal" );
litElem.appendChild( doc.createTextNode( value ) );
element.appendChild( litElem );
}


//

QVariant QgsExpression::NodeColumnRef::eval( QgsExpression* /*parent*/, QgsFeature* f )
Expand Down Expand Up @@ -2120,14 +1844,6 @@ QString QgsExpression::NodeColumnRef::dump() const
return mName;
}

void QgsExpression::NodeColumnRef::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
QDomElement propElem = doc.createElement( "ogc:PropertyName" );
propElem.appendChild( doc.createTextNode( mName ) );
element.appendChild( propElem );
}


//

QVariant QgsExpression::NodeCondition::eval( QgsExpression* parent, QgsFeature* f )
Expand Down Expand Up @@ -2184,12 +1900,6 @@ QString QgsExpression::NodeCondition::dump() const
return msg;
}

void QgsExpression::NodeCondition::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
{
// TODO: if(cond) ... [else if (cond2) ...]* [else ...]
element.appendChild( doc.createComment( "CASE operator not implemented yet" ) );
}

QStringList QgsExpression::NodeCondition::referencedColumns() const
{
QStringList lst;
Expand Down
48 changes: 24 additions & 24 deletions src/core/qgsexpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class CORE_EXPORT QgsExpression
//! Returns parser error
QString parserErrorString() const { return mParserErrorString; }

class Node;

//! Returns root node of the expression. Root node is null is parsing has failed
const Node* rootNode() const { return mRootNode; }

//! Get the expression ready for evaluation - find out column indexes.
bool prepare( const QgsFields& fields );

Expand Down Expand Up @@ -216,10 +221,6 @@ class CORE_EXPORT QgsExpression
static const char* BinaryOperatorText[];
static const char* UnaryOperatorText[];

static const char* BinaryOgcOperatorText[];
static const char* UnaryOgcOperatorText[];
static const char* SpatialOgcOperatorText[];

typedef QVariant( *FcnEval )( const QVariantList& values, QgsFeature* f, QgsExpression* parent );


Expand Down Expand Up @@ -309,10 +310,22 @@ class CORE_EXPORT QgsExpression

class Visitor; // visitor interface is defined below

enum NodeType
{
ntUnaryOperator,
ntBinaryOperator,
ntInOperator,
ntFunction,
ntLiteral,
ntColumnRef,
ntCondition
};

class CORE_EXPORT Node
{
public:
virtual ~Node() {}
virtual NodeType nodeType() const = 0;
// abstract virtual eval function
// errors are reported to the parent
virtual QVariant eval( QgsExpression* parent, QgsFeature* f ) = 0;
Expand All @@ -323,8 +336,6 @@ class CORE_EXPORT QgsExpression

virtual QString dump() const = 0;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const { Q_UNUSED( doc ); Q_UNUSED( element ); }

virtual QStringList referencedColumns() const = 0;
virtual bool needsGeometry() const = 0;

Expand All @@ -342,7 +353,6 @@ class CORE_EXPORT QgsExpression
QList<Node*> list() { return mList; }

virtual QString dump() const;
virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

protected:
QList<Node*> mList;
Expand Down Expand Up @@ -387,12 +397,11 @@ class CORE_EXPORT QgsExpression
UnaryOperator op() const { return mOp; }
Node* operand() const { return mOperand; }

virtual NodeType nodeType() const { return ntUnaryOperator; }
virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
virtual QString dump() const;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
virtual void accept( Visitor& v ) const { v.visit( *this ); }
Expand All @@ -412,12 +421,11 @@ class CORE_EXPORT QgsExpression
Node* opLeft() const { return mOpLeft; }
Node* opRight() const { return mOpRight; }

virtual NodeType nodeType() const { return ntBinaryOperator; }
virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
virtual QString dump() const;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
virtual void accept( Visitor& v ) const { v.visit( *this ); }
Expand All @@ -443,12 +451,11 @@ class CORE_EXPORT QgsExpression
bool isNotIn() const { return mNotIn; }
NodeList* list() const { return mList; }

virtual NodeType nodeType() const { return ntInOperator; }
virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
virtual QString dump() const;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
virtual bool needsGeometry() const { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
virtual void accept( Visitor& v ) const { v.visit( *this ); }
Expand All @@ -469,12 +476,11 @@ class CORE_EXPORT QgsExpression
int fnIndex() const { return mFnIndex; }
NodeList* args() const { return mArgs; }

virtual NodeType nodeType() const { return ntFunction; }
virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
virtual QString dump() const;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

virtual QStringList referencedColumns() const { QStringList lst; if ( !mArgs ) return lst; foreach ( Node* n, mArgs->list() ) lst.append( n->referencedColumns() ); return lst; }
virtual bool needsGeometry() const { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
virtual void accept( Visitor& v ) const { v.visit( *this ); }
Expand All @@ -492,12 +498,11 @@ class CORE_EXPORT QgsExpression

QVariant value() const { return mValue; }

virtual NodeType nodeType() const { return ntLiteral; }
virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
virtual QString dump() const;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

virtual QStringList referencedColumns() const { return QStringList(); }
virtual bool needsGeometry() const { return false; }
virtual void accept( Visitor& v ) const { v.visit( *this ); }
Expand All @@ -513,12 +518,11 @@ class CORE_EXPORT QgsExpression

QString name() const { return mName; }

virtual NodeType nodeType() const { return ntColumnRef; }
virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
virtual QString dump() const;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

virtual QStringList referencedColumns() const { return QStringList( mName ); }
virtual bool needsGeometry() const { return false; }
virtual void accept( Visitor& v ) const { v.visit( *this ); }
Expand Down Expand Up @@ -546,12 +550,11 @@ class CORE_EXPORT QgsExpression
NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
~NodeCondition() { delete mElseExp; foreach ( WhenThen* cond, mConditions ) delete cond; }

virtual NodeType nodeType() const { return ntCondition; }
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
virtual QString dump() const;

virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

virtual QStringList referencedColumns() const;
virtual bool needsGeometry() const;
virtual void accept( Visitor& v ) const { v.visit( *this ); }
Expand Down Expand Up @@ -581,9 +584,6 @@ class CORE_EXPORT QgsExpression
/** entry function for the visitor pattern */
void acceptVisitor( Visitor& v ) const;

// convert from/to OGC Filter
void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;

protected:
// internally used to create an empty expression
QgsExpression() : mRootNode( NULL ), mRowNumber( 0 ) {}
Expand Down
402 changes: 322 additions & 80 deletions src/core/qgsogcutils.cpp

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion src/core/qgsogcutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class CORE_EXPORT QgsOgcUtils
/** Creates OGC filter XML element. Supports minimum standard filter according to the OGC filter specs (=,!=,<,>,<=,>=,AND,OR,NOT)
@return valid <Filter> QDomElement on success, otherwise null QDomElement
*/
static QDomElement expressionToOgcFilter( const QgsExpression& exp, QDomDocument& doc );
static QDomElement expressionToOgcFilter( const QgsExpression& exp, QDomDocument& doc, QString* errorMessage = 0 );

private:
/** static method that creates geometry from GML Point */
Expand Down Expand Up @@ -129,6 +129,15 @@ class CORE_EXPORT QgsOgcUtils
static QgsExpression::Node* nodeIsBetweenFromOgcFilter( QDomElement& element, QString& errorMessage );
//! handles <PropertyIsNull> tag
static QgsExpression::NodeBinaryOperator* nodePropertyIsNullFromOgcFilter( QDomElement& element, QString& errorMessage );

static QDomElement expressionNodeToOgcFilter( const QgsExpression::Node* node, QDomDocument& doc, QString& errorMessage );
static QDomElement expressionUnaryOperatorToOgcFilter( const QgsExpression::NodeUnaryOperator* node, QDomDocument& doc, QString& errorMessage );
static QDomElement expressionBinaryOperatorToOgcFilter( const QgsExpression::NodeBinaryOperator* node, QDomDocument& doc, QString& errorMessage );
static QDomElement expressionLiteralToOgcFilter( const QgsExpression::NodeLiteral* node, QDomDocument& doc, QString& errorMessage );
static QDomElement expressionColumnRefToOgcFilter( const QgsExpression::NodeColumnRef* node, QDomDocument& doc, QString& errorMessage );
static QDomElement expressionInOperatorToOgcFilter( const QgsExpression::NodeInOperator* node, QDomDocument& doc, QString& errorMessage );
static QDomElement expressionFunctionToOgcFilter( const QgsExpression::NodeFunction* node, QDomDocument& doc, QString& errorMessage );

};

#endif // QGSOGCUTILS_H
4 changes: 3 additions & 1 deletion src/core/symbology-ng/qgssymbollayerv2utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2231,7 +2231,9 @@ bool QgsSymbolLayerV2Utils::createFunctionElement( QDomDocument &doc, QDomElemen
element.appendChild( doc.createComment( "Parser Error: " + expr.parserErrorString() + " - Expression was: " + function ) );
return false;
}
expr.toOgcFilter( doc, element );
QDomElement filterElem = QgsOgcUtils::expressionToOgcFilter( expr, doc );
if ( !filterElem.isNull() )
element.appendChild( filterElem );
return true;
}

Expand Down
109 changes: 94 additions & 15 deletions tests/src/core/testqgsogcutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,13 @@ void TestQgsOgcUtils::testExpressionToOgcFilter()
QgsExpression exp( exprText );
QVERIFY( !exp.hasParserError() );

QString errorMsg;
QDomDocument doc;
QDomElement filterElem = QgsOgcUtils::expressionToOgcFilter( exp, doc );
QDomElement filterElem = QgsOgcUtils::expressionToOgcFilter( exp, doc, &errorMsg );

if ( !errorMsg.isEmpty() )
qDebug( "ERROR: %s", errorMsg.toAscii().data() );

QVERIFY( !filterElem.isNull() );

doc.appendChild( filterElem );
Expand All @@ -241,24 +246,98 @@ void TestQgsOgcUtils::testExpressionToOgcFilter_data()
QTest::addColumn<QString>( "xmlText" );

QTest::newRow( "=" ) << QString( "NAME = 'New York'" ) << QString(
"<Filter><PropertyIsEqualTo>"
"<PropertyName>NAME</PropertyName>"
"<Literal>New York</Literal>"
"</PropertyIsEqualTo></Filter>" );
"<ogc:Filter><ogc:PropertyIsEqualTo>"
"<ogc:PropertyName>NAME</ogc:PropertyName>"
"<ogc:Literal>New York</ogc:Literal>"
"</ogc:PropertyIsEqualTo></ogc:Filter>" );

QTest::newRow( ">" ) << QString( "COUNT > 3" ) << QString(
"<Filter><PropertyIsGreaterThan>"
"<PropertyName>COUNT</PropertyName>"
"<Literal>3</Literal>"
"</PropertyIsGreaterThan></Filter>" );
"<ogc:Filter><ogc:PropertyIsGreaterThan>"
"<ogc:PropertyName>COUNT</ogc:PropertyName>"
"<ogc:Literal>3</ogc:Literal>"
"</ogc:PropertyIsGreaterThan></ogc:Filter>" );

QTest::newRow( "and+or" ) << QString( "(FIELD1 = 10 OR FIELD1 = 20) AND STATUS = 'VALID'" ) << QString(
"<ogc:Filter>"
"<ogc:And>"
"<ogc:Or>"
"<ogc:PropertyIsEqualTo>"
"<ogc:PropertyName>FIELD1</ogc:PropertyName>"
"<ogc:Literal>10</ogc:Literal>"
"</ogc:PropertyIsEqualTo>"
"<ogc:PropertyIsEqualTo>"
"<ogc:PropertyName>FIELD1</ogc:PropertyName>"
"<ogc:Literal>20</ogc:Literal>"
"</ogc:PropertyIsEqualTo>"
"</ogc:Or>"
"<ogc:PropertyIsEqualTo>"
"<ogc:PropertyName>STATUS</ogc:PropertyName>"
"<ogc:Literal>VALID</ogc:Literal>"
"</ogc:PropertyIsEqualTo>"
"</ogc:And>"
"</ogc:Filter>" );

QTest::newRow( "is null" ) << QString( "X IS NULL" ) << QString(
"<ogc:Filter>"
"<ogc:PropertyIsNull>"
"<ogc:PropertyName>X</ogc:PropertyName>"
"</ogc:PropertyIsNull>"
"</ogc:Filter>" );

QTest::newRow( "is not null" ) << QString( "X IS NOT NULL" ) << QString(
"<ogc:Filter>"
"<ogc:Not>"
"<ogc:PropertyIsNull>"
"<ogc:PropertyName>X</ogc:PropertyName>"
"</ogc:PropertyIsNull>"
"</ogc:Not>"
"</ogc:Filter>" );

QTest::newRow( "in" ) << QString( "A IN (10,20,30)" ) << QString(
"<ogc:Filter>"
"<ogc:Or>"
"<ogc:PropertyIsEqualTo>"
"<ogc:PropertyName>A</ogc:PropertyName>"
"<ogc:Literal>10</ogc:Literal>"
"</ogc:PropertyIsEqualTo>"
"<ogc:PropertyIsEqualTo>"
"<ogc:PropertyName>A</ogc:PropertyName>"
"<ogc:Literal>20</ogc:Literal>"
"</ogc:PropertyIsEqualTo>"
"<ogc:PropertyIsEqualTo>"
"<ogc:PropertyName>A</ogc:PropertyName>"
"<ogc:Literal>30</ogc:Literal>"
"</ogc:PropertyIsEqualTo>"
"</ogc:Or>"
"</ogc:Filter>" );

QTest::newRow( "intersects + wkt" ) << QString( "intersects($geometry, geomFromWKT('POINT (5 6)'))" ) << QString(
"<ogc:Filter>"
"<ogc:Intersects>"
"<ogc:PropertyName>geometry</ogc:PropertyName>"
"<gml:Point><gml:coordinates cs=\",\" ts=\" \">5.0,6.0</gml:coordinates></gml:Point>"
"</ogc:Intersects>"
"</ogc:Filter>" );

QTest::newRow( "contains + gml" ) << QString( "contains($geometry, geomFromGML2('<Point><coordinates cs=\",\" ts=\" \">5.0,6.0</coordinates></Point>'))" ) << QString(
"<ogc:Filter>"
"<ogc:Contains>"
"<ogc:PropertyName>geometry</ogc:PropertyName>"
"<Point><coordinates cs=\",\" ts=\" \">5.0,6.0</coordinates></Point>"
"</ogc:Contains>"
"</ogc:Filter>" );

/*
QTest::newRow( "is null" ) << QString( "FIRST_NAME IS NULL" ) << QString(
"<Filter>"
"<PropertyIsNull>"
"<PropertyName>FIRST_NAME</ogc:PropertyName>"
"</PropertyIsNull>"
"</Filter>" );
QTest::newRow( "bbox" ) << QString( "bbox(13.0983, )") << QString(
"<ogc:Filter>"
"<ogc:BBOX>"
"<ogc:PropertyName>Geometry</ogc:PropertyName>"
"<gml:Envelope>"
"<gml:lowerCorner>13.0983 31.5899</gml:lowerCorner>"
"<gml:upperCorner>35.5472 42.8143</gml:upperCorner>"
"</gml:Envelope>"
"</ogc:BBOX>"
"</ogc:Filter>" );
*/
}

Expand Down