/** * Generates Comparison Expression * * @param AbstractExpression $left The LHS expression. * @param AbstractExpression $right The RHS expression. * @param ExpressionToken $expressionToken The cmparision expression token. * @param boolean $isCustomExpressionProvider True if the end user is responsible * for providing the IExpressionProvider * implementation. * * @return AbstractExpression */ private static function _generateComparisonExpression($left, $right, $expressionToken, $isCustomExpressionProvider) { FunctionDescription::verifyRelationalOpArguments($expressionToken, $left, $right); //We need special handling for comparison of following types: //1. String //2. DateTime //3. Guid //4. Binary //Will make these comparison as function calls, which will // be converted to language specific function call by expression // provider $string = new OString(); if ($left->typeIs($string) && $right->typeIs($string)) { $strcmpFunctions = FunctionDescription::stringComparisionFunctions(); $left = new FunctionCallExpression($strcmpFunctions[0], array($left, $right)); $right = new ConstantExpression(0, new Int32()); } $dateTime = new DateTime(); if ($left->typeIs($dateTime) && $right->typeIs($dateTime)) { $dateTimeCmpFunctions = FunctionDescription::dateTimeComparisonFunctions(); $left = new FunctionCallExpression($dateTimeCmpFunctions[0], array($left, $right)); $right = new ConstantExpression(0, new Int32()); } $guid = new Guid(); if ($left->typeIs($guid) && $right->typeIs($guid)) { $guidEqualityFunctions = FunctionDescription::guidEqualityFunctions(); $left = new FunctionCallExpression($guidEqualityFunctions[0], array($left, $right)); $right = new ConstantExpression(true, new Boolean()); } $binary = new Binary(); if ($left->typeIs($binary) && $right->typeIs($binary)) { $binaryEqualityFunctions = FunctionDescription::binaryEqualityFunctions(); $left = new FunctionCallExpression($binaryEqualityFunctions[0], array($left, $right)); $right = new ConstantExpression(true, new Boolean()); } $null = new Null1(); if ($left->typeIs($null) || $right->typeIs($null)) { // If the end user is responsible for implementing IExpressionProvider // then the sub-tree for a nullability check would be: // // RelationalExpression(EQ/NE) // | // ------------ // | | // | | // CustomerID NULL // // Otherwise (In case of default PHPExpressionProvider): // // CustomerID eq null // ================== // // FunctionCallExpression(is_null) // | // |- Signature => bool (typeof(CustomerID)) // |- args => {CustomerID} // // // CustomerID ne null // ================== // // UnaryExpression (not) // | // FunctionCallExpression(is_null) // | // |- Signature => bool (typeof(CustomerID)) // |- args => {CustomerID} // if (!$isCustomExpressionProvider) { $arg = $left->typeIs($null) ? $right : $left; $isNullFunctionDescription = new FunctionDescription('is_null', new Boolean(), array($arg->getType())); switch ($expressionToken->Text) { case ODataConstants::KEYWORD_EQUAL: return new FunctionCallExpression($isNullFunctionDescription, array($arg)); break; case ODataConstants::KEYWORD_NOT_EQUAL: return new UnaryExpression(new FunctionCallExpression($isNullFunctionDescription, array($arg)), ExpressionType::NOT_LOGICAL, new Boolean()); break; } } } switch ($expressionToken->Text) { case ODataConstants::KEYWORD_EQUAL: return new RelationalExpression($left, $right, ExpressionType::EQUAL); case ODataConstants::KEYWORD_NOT_EQUAL: return new RelationalExpression($left, $right, ExpressionType::NOTEQUAL); case ODataConstants::KEYWORD_GREATERTHAN: return new RelationalExpression($left, $right, ExpressionType::GREATERTHAN); case ODataConstants::KEYWORD_GREATERTHAN_OR_EQUAL: return new RelationalExpression($left, $right, ExpressionType::GREATERTHAN_OR_EQUAL); case ODataConstants::KEYWORD_LESSTHAN: return new RelationalExpression($left, $right, ExpressionType::LESSTHAN); default: return new RelationalExpression($left, $right, ExpressionType::LESSTHAN_OR_EQUAL); } }
/** * Merge two null check expression trees by removing duplicate nodes. * * @param AbstractExpression $nullCheckExpTree1 First expression. * @param AbstractExpression $nullCheckExpTree2 Second expression. * * @return UnaryExpression or LogicalExpression */ private function _mergeNullableExpressionTrees($nullCheckExpTree1, $nullCheckExpTree2) { $this->_mapTable = array(); $this->_map($nullCheckExpTree1); $this->_map($nullCheckExpTree2); $expression = null; $isNullFunctionDescription = null; foreach ($this->_mapTable as $node) { if ($expression == null) { $expression = new UnaryExpression(new FunctionCallExpression(FunctionDescription::isNullCheckFunction($node->getType()), array($node)), ExpressionType::NOT_LOGICAL, new Boolean()); } else { $expression = new LogicalExpression($expression, new UnaryExpression(new FunctionCallExpression(FunctionDescription::isNullCheckFunction($node->getType()), array($node)), ExpressionType::NOT_LOGICAL, new Boolean()), ExpressionType::AND_LOGICAL); } } return $expression; }
/** * Function to create a nullable expression subtree for checking the * nullablilty of parent (and current poperty optionally) properties * * @param boolean $includeMe Boolean flag indicating whether to include null * check for this property along with parents * * @return AbstractExpression Instance of UnaryExpression, LogicalExpression * or Null * */ public function createNullableExpressionTree($includeMe) { $basePropertyExpression = $this; while ($basePropertyExpression != null && $basePropertyExpression->parent != null) { $basePropertyExpression = $basePropertyExpression->parent; } //This property is direct child of ResourceSet, no need to check //nullability for direct ResourceSet properties // ($c->CustomerID, $c->Order, $c->Address) unless $includeMe is true if ($basePropertyExpression == $this) { if ($includeMe) { return new UnaryExpression(new FunctionCallExpression(FunctionDescription::isNullCheckFunction($basePropertyExpression->getType()), array($basePropertyExpression)), ExpressionType::NOT_LOGICAL, new Boolean()); } return null; } //This property is a property of a complex type or resource reference //$c->Order->OrderID, $c->Address->LineNumber, // $c->complex1->complex2->primitveVar //($c->Order != null),($c->Address != null), // (($c->complex1 != null) && ($c->complex1->complex2 != null)) $expression = new UnaryExpression(new FunctionCallExpression(FunctionDescription::isNullCheckFunction($basePropertyExpression->getType()), array($basePropertyExpression)), ExpressionType::NOT_LOGICAL, new Boolean()); while ($basePropertyExpression->getChild() != null && $basePropertyExpression->getChild()->getChild() != null) { $basePropertyExpression = $basePropertyExpression->getChild(); $expression2 = new UnaryExpression(new FunctionCallExpression(FunctionDescription::isNullCheckFunction($basePropertyExpression->getType()), array($basePropertyExpression)), ExpressionType::NOT_LOGICAL, new Boolean()); $expression = new LogicalExpression($expression, $expression2, ExpressionType::AND_LOGICAL); } if ($includeMe) { $basePropertyExpression = $basePropertyExpression->getChild(); $expression2 = new UnaryExpression(new FunctionCallExpression(FunctionDescription::isNullCheckFunction($basePropertyExpression->getType()), array($basePropertyExpression)), ExpressionType::NOT_LOGICAL, new Boolean()); $expression = new LogicalExpression($expression, $expression2, ExpressionType::AND_LOGICAL); } return $expression; }