PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/PHPCR/Util/QOM/QomToSql2QueryConverter.php

https://github.com/lyrixx/phpcr-utils
PHP | 268 lines | 132 code | 21 blank | 115 comment | 19 complexity | e16fa0cfa6826a19a4154d49384b382c MD5 | raw file
  1. <?php
  2. namespace PHPCR\Util\QOM;
  3. use PHPCR\Query\QOM;
  4. /**
  5. * Convert a QOM query into an SQL2 statement
  6. */
  7. class QomToSql2QueryConverter extends BaseQomToSqlQueryConverter
  8. {
  9. /**
  10. * Source ::= Selector | Join
  11. *
  12. * @param QOM\SourceInterface $source
  13. * @return string
  14. */
  15. protected function convertSource(QOM\SourceInterface $source)
  16. {
  17. if ($source instanceof QOM\SelectorInterface) {
  18. return $this->convertSelector($source);
  19. }
  20. if ($source instanceof QOM\JoinInterface) {
  21. return $this->convertJoin($source);
  22. }
  23. throw new \InvalidArgumentException("Invalid Source");
  24. }
  25. /**
  26. * Join ::= left [JoinType] 'JOIN' right 'ON' JoinCondition
  27. * // If JoinType is omitted INNER is assumed.
  28. * left ::= Source
  29. * right ::= Source
  30. *
  31. * JoinType ::= Inner | LeftOuter | RightOuter
  32. * Inner ::= 'INNER'
  33. * LeftOuter ::= 'LEFT OUTER'
  34. * RightOuter ::= 'RIGHT OUTER'
  35. *
  36. * @param QOM\JoinInterface $join
  37. * @return string
  38. */
  39. protected function convertJoin(QOM\JoinInterface $join)
  40. {
  41. $left = $this->convertSource($join->getLeft());
  42. $right = $this->convertSource($join->getRight());
  43. $condition = $this->convertJoinCondition($join->getJoinCondition());
  44. return $this->generator->evalJoin($left, $right, $condition, $this->generator->evalJoinType($join->getJoinType()));
  45. }
  46. /**
  47. * JoinCondition ::= EquiJoinCondition |
  48. * SameNodeJoinCondition |
  49. * ChildNodeJoinCondition |
  50. * DescendantNodeJoinCondition
  51. *
  52. * @param QOM\JoinConditionInterface $condition
  53. * @return string
  54. */
  55. protected function convertJoinCondition(QOM\JoinConditionInterface $condition)
  56. {
  57. if ($condition instanceof QOM\EquiJoinConditionInterface) {
  58. $sql2 = $this->convertEquiJoinCondition($condition);
  59. } elseif ($condition instanceof QOM\SameNodeJoinConditionInterface) {
  60. $sql2 = $this->convertSameNodeJoinCondition($condition);
  61. } elseif ($condition instanceof QOM\ChildNodeJoinConditionInterface) {
  62. $sql2 = $this->convertChildNodeJoinCondition($condition);
  63. } elseif ($condition instanceof QOM\DescendantNodeJoinConditionInterface) {
  64. $sql2 = $this->convertDescendantNodeJoinCondition($condition);
  65. } else {
  66. // This should not happen, but who knows...
  67. throw new \InvalidArgumentException("Invalid operand");
  68. }
  69. return $sql2;
  70. }
  71. /**
  72. * EquiJoinCondition ::= selector1Name'.'property1Name '='
  73. * selector2Name'.'property2Name
  74. * selector1Name ::= selectorName
  75. * selector2Name ::= selectorName
  76. * property1Name ::= propertyName
  77. * property2Name ::= propertyName
  78. *
  79. * @param QOM\EquiJoinConditionInterface $condition
  80. * @return string
  81. */
  82. protected function convertEquiJoinCondition(QOM\EquiJoinConditionInterface $condition)
  83. {
  84. return $this->generator->evalEquiJoinCondition(
  85. $condition->getSelector1Name(),
  86. $condition->getProperty1Name(),
  87. $condition->getSelector2Name(),
  88. $condition->getProperty2Name());
  89. }
  90. /**
  91. * SameNodeJoinCondition ::=
  92. * 'ISSAMENODE(' selector1Name ','
  93. * selector2Name
  94. * [',' selector2Path] ')'
  95. * selector2Path ::= Path
  96. *
  97. * @param QOM\SameNodeJoinConditionInterface $condition
  98. * @return string
  99. */
  100. protected function convertSameNodeJoinCondition(QOM\SameNodeJoinConditionInterface $condition)
  101. {
  102. return $this->generator->evalSameNodeJoinCondition(
  103. $condition->getSelector1Name(),
  104. $condition->getSelector2Name(),
  105. ! is_null($condition->getSelector2Path()) ? $this->convertPath($condition->getSelector2Path()) : null);
  106. }
  107. /**
  108. * ChildNodeJoinCondition ::=
  109. * 'ISCHILDNODE(' childSelectorName ','
  110. * parentSelectorName ')'
  111. * childSelectorName ::= selectorName
  112. * parentSelectorName ::= selectorName
  113. *
  114. * @param QOM\ChildNodeJoinConditionInterface $condition
  115. * @return string
  116. */
  117. protected function convertChildNodeJoinCondition(QOM\ChildNodeJoinConditionInterface $condition)
  118. {
  119. return $this->generator->evalChildNodeJoinCondition(
  120. $condition->getChildSelectorName(),
  121. $condition->getParentSelectorName());
  122. }
  123. /**
  124. * DescendantNodeJoinCondition ::=
  125. * 'ISDESCENDANTNODE(' descendantSelectorName ','
  126. * ancestorSelectorName ')'
  127. * descendantSelectorName ::= selectorName
  128. * ancestorSelectorName ::= selectorName
  129. *
  130. * @param QOM\DescendantNodeJoinConditionInterface $condition
  131. * @return string
  132. */
  133. protected function convertDescendantNodeJoinCondition(QOM\DescendantNodeJoinConditionInterface $condition)
  134. {
  135. return $this->generator->evalDescendantNodeJoinCondition(
  136. $condition->getDescendantSelectorName(),
  137. $condition->getAncestorSelectorName());
  138. }
  139. /**
  140. * Constraint ::= And | Or | Not | Comparison |
  141. * PropertyExistence | FullTextSearch |
  142. * SameNode | ChildNode | DescendantNode
  143. *
  144. * And ::= constraint1 'AND' constraint2
  145. * Or ::= constraint1 'OR' constraint2
  146. * Not ::= 'NOT' Constraint
  147. *
  148. * SameNode ::= 'ISSAMENODE(' [selectorName ','] Path ')'
  149. * // If only one selector exists in this query, explicit
  150. * specification of the selectorName is optional
  151. *
  152. * ChildNode ::= 'ISCHILDNODE(' [selectorName ','] Path ')'
  153. * // If only one selector exists in this query, explicit
  154. * specification of the selectorName is optional
  155. *
  156. * DescendantNode ::= 'ISDESCENDANTNODE(' [selectorName ','] Path ')'
  157. * // If only one selector exists in this query, explicit
  158. * specification of the selectorName is optional
  159. *
  160. * @param QOM\ConstraintInterface $constraint
  161. * @return string
  162. */
  163. protected function convertConstraint(QOM\ConstraintInterface $constraint)
  164. {
  165. if ($constraint instanceof QOM\AndInterface) {
  166. return $this->generator->evalAnd(
  167. $this->convertConstraint($constraint->getConstraint1()),
  168. $this->convertConstraint($constraint->getConstraint2()));
  169. }
  170. if ($constraint instanceof QOM\OrInterface) {
  171. return $this->generator->evalOr(
  172. $this->convertConstraint($constraint->getConstraint1()),
  173. $this->convertConstraint($constraint->getConstraint2()));
  174. }
  175. if ($constraint instanceof QOM\NotInterface) {
  176. return $this->generator->evalNot($this->convertConstraint($constraint->getConstraint()));
  177. }
  178. if ($constraint instanceof QOM\ComparisonInterface) {
  179. return $this->convertComparison($constraint);
  180. }
  181. if ($constraint instanceof QOM\PropertyExistenceInterface) {
  182. return $this->convertPropertyExistence($constraint);
  183. } elseif ($constraint instanceof QOM\FullTextSearchInterface) {
  184. return $this->convertFullTextSearch($constraint);
  185. }
  186. if ($constraint instanceof QOM\SameNodeInterface) {
  187. return $this->generator->evalSameNode(
  188. $this->convertPath($constraint->getPath()),
  189. $constraint->getSelectorName());
  190. }
  191. if ($constraint instanceof QOM\ChildNodeInterface) {
  192. return $this->generator->evalChildNode(
  193. $this->convertPath($constraint->getParentPath()),
  194. $constraint->getSelectorName());
  195. }
  196. if ($constraint instanceof QOM\DescendantNodeInterface) {
  197. return $this->generator->evalDescendantNode(
  198. $this->convertPath($constraint->getAncestorPath()),
  199. $constraint->getSelectorName());
  200. }
  201. // This should not happen, but who knows...
  202. throw new \InvalidArgumentException("Invalid operand: " . get_class($constraint));
  203. }
  204. /**
  205. * DynamicOperand ::= PropertyValue | Length | NodeName |
  206. * NodeLocalName | FullTextSearchScore |
  207. * LowerCase | UpperCase
  208. *
  209. * Length ::= 'LENGTH(' PropertyValue ')'
  210. * NodeName ::= 'NAME(' [selectorName] ')' // If only one selector exists
  211. * NodeLocalName ::= 'LOCALNAME(' [selectorName] ')' // If only one selector exists
  212. * FullTextSearchScore ::= 'SCORE(' [selectorName] ')' // If only one selector exists
  213. * LowerCase ::= 'LOWER(' DynamicOperand ')'
  214. * UpperCase ::= 'UPPER(' DynamicOperand ')'
  215. *
  216. * @param QOM\DynamicOperandInterface $operand
  217. * @return string
  218. */
  219. protected function convertDynamicOperand(QOM\DynamicOperandInterface $operand)
  220. {
  221. if ($operand instanceof QOM\PropertyValueInterface) {
  222. return $this->convertPropertyValue($operand);
  223. }
  224. if ($operand instanceof QOM\LengthInterface) {
  225. return $this->generator->evalLength($this->convertPropertyValue($operand->getPropertyValue()));
  226. }
  227. if ($operand instanceof QOM\NodeNameInterface) {
  228. return $this->generator->evalNodeName($operand->getSelectorName());
  229. }
  230. if ($operand instanceof QOM\NodeLocalNameInterface) {
  231. return $this->generator->evalNodeLocalName($operand->getSelectorName());
  232. }
  233. if ($operand instanceof QOM\FullTextSearchScoreInterface) {
  234. return $this->generator->evalFullTextSearchScore($operand->getSelectorName());
  235. }
  236. if ($operand instanceof QOM\LowerCaseInterface) {
  237. $operand = $this->convertDynamicOperand($operand->getOperand());
  238. return $this->generator->evalLower($operand);
  239. }
  240. if ($operand instanceof QOM\UpperCaseInterface) {
  241. $operand = $this->convertDynamicOperand($operand->getOperand());
  242. return $this->generator->evalUpper($operand);
  243. }
  244. // This should not happen, but who knows...
  245. throw new \InvalidArgumentException("Invalid operand");
  246. }
  247. }