jenkins-bot has submitted this change and it was merged. Change subject: phpunit test for XQuery generation ......................................................................
phpunit test for XQuery generation Change-Id: Ic4dfed43fb32216477b7038e5903edbd7d91e37f --- M MathQueryObject.php M MathSearch.php M XQueryGenerator.php M XQueryGeneratorDB2.php M maintenance/ExportMathTable.php M maintenance/IndexBase.php A tests/MathXQueryTest.php 7 files changed, 317 insertions(+), 47 deletions(-) Approvals: Physikerwelt: Looks good to me, approved jenkins-bot: Verified diff --git a/MathQueryObject.php b/MathQueryObject.php index d82f2e8..da8d4ac 100644 --- a/MathQueryObject.php +++ b/MathQueryObject.php @@ -185,10 +185,13 @@ public function generateContentQueryString(){ $renderer = new MathLaTeXML($this->getTexQuery()); $renderer->setLaTeXMLSettings($this->getLaTeXMLCMMLSettings()); - $renderer->setAllowedRootElments(array('query')); - $renderer->render(true); - $this->cquery = $renderer->getMathml(); - return $this->cquery; + $renderer->setAllowedRootElements(array('query')); + if ( $renderer->render(true) ){ + $this->cquery = $renderer->getMathml(); + return $this->cquery; + } else { + wfDebugLog('math', 'error during geration of query string'. $renderer->getLastError()); + } } public function generatePresentationQueryString(){ diff --git a/MathSearch.php b/MathSearch.php index 744cdfd..e2ea9e5 100644 --- a/MathSearch.php +++ b/MathSearch.php @@ -66,4 +66,4 @@ $wgGroupPermissions['user']['MathDebug'] = true; -$wgMathSearchDB2Table = 'wiki.math'; \ No newline at end of file +$wgMathSearchDB2Table = 'math'; \ No newline at end of file diff --git a/XQueryGenerator.php b/XQueryGenerator.php index 5a13aa3..47e21df 100644 --- a/XQueryGenerator.php +++ b/XQueryGenerator.php @@ -17,13 +17,13 @@ private $lengthConstraint = ''; /** @var DOMDocument the MWS XML */ private $xml ; - + /** - * + * * @param String $cmmlQueryString that contains the MathML query expression */ public function __construct( $cmmlQueryString ){ - $this->xml = new DOMDocument(); + $this->xml = new DOMDocument(); $this->xml->preserveWhiteSpace = false; $this->xml->loadXML($cmmlQueryString); } @@ -31,40 +31,55 @@ /** * @return String the XQueryExpression. */ - public function getXQuery() { - $fixedConstraints = $this->generateConstraint( $this->xml->getElementsByTagName('expr')->item(0) ); + public function getXQuery() + { + $fixedConstraints = $this->generateConstraint($this->xml->getElementsByTagName('expr')->item(0), true); $qvarConstraintString = ''; foreach ($this->qvar as $key => $value) { - $first = $value[0]; - if ($qvarConstraintString) { - $qvarConstraintString .= ' and '; - } - $qvarConstraintString .= '$x' . $first; - $second = ''; - foreach ($value as $second) { - if ($second) { - $second.=' and $x' . $first; + $addstr = ''; + $newContent = false; + if (sizeof($value) > 1) { + $first = $value[0]; + if ($qvarConstraintString) { + $addstr .= "\n and "; } - $qvarConstraintString .= ' = $x' . $second; + $lastSecond = ''; + foreach ($value as $second) { + if ($second != $first) { + if ($lastSecond) { + $addstr .= ' and '; + } + $addstr .= '$x' . $first . ' = $x' . $second; + $lastSecond = $second; + $newContent = true; + } + } + } + if ( $newContent ){ + $qvarConstraintString .= $addstr; } } - $query = 'for $x in $m//*:' . $this->xml->getElementsByTagName('expr')->item(0)->firstChild->nodeName . '[' . - $fixedConstraints . '] return - if( ' . $qvarConstraintString . $this->lengthConstraint . ')'; - return $this->getHeader().$query.$this->getFooter(); + $query = 'for $x in $m//*:' . + $this->xml->getElementsByTagName('expr')->item(0)->firstChild->localName . PHP_EOL . + $fixedConstraints . PHP_EOL . + ' where' . PHP_EOL . + $this->lengthConstraint . + $qvarConstraintString . PHP_EOL . + ' return' . PHP_EOL; + return $this->getHeader() . $query . $this->getFooter(); } /** - * + * * @param DOMNode $node * @return string */ - private function generateConstraint($node) { + private function generateConstraint($node, $isRoot=false) { $i = 0; $out = ""; $hastext = false; foreach ($node->childNodes as $child) { - $i++; if ($child->nodeName == "mws:qvar") { + $i++; $qvarname = (string) $child->textContent; if (array_key_exists($qvarname, $this->qvar)) { $this->qvar[$qvarname][] = $this->relativeXPath . "/*[" . $i . "]"; @@ -72,26 +87,54 @@ $this->qvar[$qvarname] = array($this->relativeXPath . "/*[" . $i . "]"); } } else { - if ($hastext) { - $out .= ' and '; - } - $out .= '*[' . $i . ']/name() =\'' . $child->nodeName . '\''; - $hastext = true; - if ($child->hasChildNodes()) { - $this->relativeXPath.="/*[" . $i . "]"; - $out .= ' and *[' . $i . "][\n\t" . $this->generateConstraint($child) . "\n]"; - } else { - $out .= ' and *[' . $i . "]/text()='" . $child->nodeName . "'"; + if ($child->nodeType == XML_ELEMENT_NODE) { + $i++; + //$out .= './text() = \''.$node->nodeValue . '\''; + if ($hastext) { + $out .= ' and '; + } + if(!$isRoot){ + $out .= '*[' . $i . ']/name() =\'' . $child->localName . '\''; + } + $hastext = true; + if ( $child->hasChildNodes() ) { + if(!$isRoot){ + $this->relativeXPath.="/*[" . $i . "]"; + $out .= ' and *[' . $i . "]"; + } + $out .= '['.$this->generateConstraint($child) .']'; + } + } elseif( $child->nodeType == XML_TEXT_NODE ){ + $out .= './text() = \''. $child->nodeValue. '\''; } } } - $this->lengthConstraint .=' and fn:count($x' . $this->relativeXPath . '/*) = ' . $i; + if( !$isRoot ){ + if($this->lengthConstraint == ''){ + $this->lengthConstraint .='fn:count($x' . $this->relativeXPath . '/*) = ' . $i . "\n"; + }else{ + $this->lengthConstraint .=' and fn:count($x' . $this->relativeXPath . '/*) = ' . $i . "\n"; + } + } if ($this->relativeXPath) { $this->relativeXPath = substr($this->relativeXPath, 0, strrpos($this->relativeXPath, "/")); } + /*if ($out != ""){ + $out = '['. $out . ']'; + }*/ + + return $out; } - + private function hasChild($p) { + if ($p->hasChildNodes()) { + foreach ($p->childNodes as $c) { + if ($c->nodeType == XML_ELEMENT_NODE) + return true; + } + } + return false; + } abstract protected function getHeader(); abstract protected function getFooter(); } diff --git a/XQueryGeneratorDB2.php b/XQueryGeneratorDB2.php index 0f96393..b5fd847 100644 --- a/XQueryGeneratorDB2.php +++ b/XQueryGeneratorDB2.php @@ -17,7 +17,7 @@ protected function getHeader(){ global $wgMathSearchDB2Table; return 'xquery declare default element namespace "http://www.w3.org/1998/Math/MathML";'. - "\n for \$m in db2-fn:xmlcolumn(\"$wgMathSearchDB2Table.math_mathml\") return \n"; + "\n for \$m in db2-fn:xmlcolumn(\"$wgMathSearchDB2Table.math_mathml\") return\n"; } /** @@ -25,8 +25,6 @@ * @return string */ protected function getFooter(){ - return 'then -data($m/*[1]/@alttext) - else \'\' '; + return 'data($m/*[1]/@alttext)'; } } \ No newline at end of file diff --git a/maintenance/ExportMathTable.php b/maintenance/ExportMathTable.php index 7f10d6f..71ce6d4 100644 --- a/maintenance/ExportMathTable.php +++ b/maintenance/ExportMathTable.php @@ -50,7 +50,7 @@ $out .= ','. $row->mathindex_anchor.''; $out .= ',"'.str_replace(array('"',"\n"),array('"',' '), $mo->getMathml()).'"'; $res = db2_execute($this->statment, array($mo->getMd5(),$mo->getTex(),$row->mathindex_page_id,$row->mathindex_anchor,$mo->getMathml())); - if ( $res ){ + if ( ! $res ){ echo db2_stmt_errormsg(); } return $out."\n"; @@ -73,9 +73,8 @@ $this->conn = db2_connect($wgMathSearchDB2ConnStr, '', ''); if ( $this->conn ){ if ( $this->getOption('truncate' , false ) ){ - db2_exec($this->conn,'DROP TABLE "math"'); + db2_exec( $this->conn , 'DROP TABLE "math"'); db2_exec( $this->conn , 'CREATE TABLE "math" ("math_md5" CHAR(32), "math_tex" VARCHAR(1000), "mathindex_pageid" INTEGER, "mathindex_anchord" INTEGER, "math_mathml" XML)'); - } $this->statment = db2_prepare( $this->conn ,'insert into "math" ("math_md5", "math_tex", "mathindex_pageid", "mathindex_anchord", "math_mathml") values(?, ?, ?, ?, ?)'); //db2_autocommit($this->conn , DB2_AUTOCOMMIT_OFF); diff --git a/maintenance/IndexBase.php b/maintenance/IndexBase.php index d5c9e33..b5473c5 100644 --- a/maintenance/IndexBase.php +++ b/maintenance/IndexBase.php @@ -57,7 +57,7 @@ */ protected function wFile( $fn, $min, $inc ) { $out = $this->getHead(); - $max = min( $min + $inc, $this->res->numRows() -1 ); + $max = min( $min + $inc, $this->res->numRows() ); for ( $i = $min; $i < $max; $i++ ) { $this->res->seek( $i ); $out .= $this->generateIndexString( $this->res->fetchObject() ); diff --git a/tests/MathXQueryTest.php b/tests/MathXQueryTest.php new file mode 100644 index 0000000..2ad0a0b --- /dev/null +++ b/tests/MathXQueryTest.php @@ -0,0 +1,227 @@ +<?php +/** + * Test the db2 access of MathSearch. +* +* @group MathSearch +* @group Database +*/ +class MathXQueryTest extends MediaWikiTestCase { + + private $q1 = <<<'EOT' +<?xml version="1.0"?> +<mws:query xmlns:mws="http://search.mathweb.org/ns" xmlns:m="http://www.w3.org/1998/Math/MathML" limitmin="0" answsize="30"> + <mws:expr> + <m:ci xml:id="p1.1.m1.1.1.cmml" xref="p1.1.m1.1.1">E</m:ci> + </mws:expr> +</mws:query> +EOT; + + private $q2 = <<<'EOT' +<?xml version="1.0"?> +<mws:query xmlns:mws="http://search.mathweb.org/ns" xmlns:m="http://www.w3.org/1998/Math/MathML" limitmin="0" answsize="30"> + <mws:expr> + <m:apply xml:id="p1.1.m1.1.3.cmml" xref="p1.1.m1.1.3"> + <m:csymbol cd="ambiguous" xml:id="p1.1.m1.1.3.1.cmml">superscript</m:csymbol> + <m:ci xml:id="p1.1.m1.1.1.cmml" xref="p1.1.m1.1.1">c</m:ci> + <m:cn type="integer" xml:id="p1.1.m1.1.2.1.cmml" xref="p1.1.m1.1.2.1">2</m:cn> + </m:apply> + </mws:expr> +</mws:query> +EOT; + + private $q3 = <<<'EOT' +<?xml version="1.0"?> +<mws:query xmlns:mws="http://search.mathweb.org/ns" xmlns:m="http://www.w3.org/1998/Math/MathML" limitmin="0" answsize="30"> + <mws:expr> + <m:apply xml:id="p1.1.m1.1.3.cmml" xref="p1.1.m1.1.3"> + <m:sin xml:id="p1.1.m1.1.1.cmml" xref="p1.1.m1.1.1"/> + <m:ci xml:id="p1.1.m1.1.2.cmml" xref="p1.1.m1.1.2">x</m:ci> + </m:apply> + </mws:expr> +</mws:query> +EOT; + private $qqx2 = <<<'EOT' +<?xml version="1.0"?> +<mws:query xmlns:mws="http://search.mathweb.org/ns" xmlns:m="http://www.w3.org/1998/Math/MathML" limitmin="0" answsize="30"> + <mws:expr> + <m:apply xml:id="p1.1.m1.1.3.cmml" xref="p1.1.m1.1.3"> + <m:csymbol cd="ambiguous" xml:id="p1.1.m1.1.3.1.cmml">superscript</m:csymbol> + <mws:qvar>x</mws:qvar> + <m:cn type="integer" xml:id="p1.1.m1.1.2.1.cmml" xref="p1.1.m1.1.2.1">2</m:cn> + </m:apply> + </mws:expr> +</mws:query> +EOT; + private $qqx2x = <<<'EOT' +<?xml version="1.0"?> +<mws:query xmlns:mws="http://search.mathweb.org/ns" xmlns:m="http://www.w3.org/1998/Math/MathML" limitmin="0" answsize="30"> + <mws:expr> + <m:apply xml:id="p1.1.m1.1.5.cmml" xref="p1.1.m1.1.5"> + <m:plus xml:id="p1.1.m1.1.3.cmml" xref="p1.1.m1.1.3"/> + <m:apply xml:id="p1.1.m1.1.5.1.cmml" xref="p1.1.m1.1.5.1"> + <m:csymbol cd="ambiguous" xml:id="p1.1.m1.1.5.1.1.cmml">superscript</m:csymbol> + <mws:qvar>x</mws:qvar> + <m:cn type="integer" xml:id="p1.1.m1.1.2.1.cmml" xref="p1.1.m1.1.2.1">2</m:cn> + </m:apply> + <mws:qvar>x</mws:qvar> + </m:apply> + </mws:expr> +</mws:query> +EOT; + private $r1 = <<<'EOT' +xquery declare default element namespace "http://www.w3.org/1998/Math/MathML"; + for $m in db2-fn:xmlcolumn("math.math_mathml") return +for $x in $m//*:ci +[./text() = 'E'] + where +fn:count($x/*) = 0 + + return +data($m/*[1]/@alttext) +EOT; + + private $r2 = <<<'EOT' +xquery declare default element namespace "http://www.w3.org/1998/Math/MathML"; + for $m in db2-fn:xmlcolumn("math.math_mathml") return +for $x in $m//*:apply +[*[1]/name() ='csymbol' and *[1][./text() = 'superscript'] and *[2]/name() ='ci' and *[2][./text() = 'c'] and *[3]/name() ='cn' and *[3][./text() = '2']] + where +fn:count($x/*[1]/*) = 0 + and fn:count($x/*[2]/*) = 0 + and fn:count($x/*[3]/*) = 0 + and fn:count($x/*) = 3 + + return +data($m/*[1]/@alttext) +EOT; + + private $r3 = <<<'EOT' +xquery declare default element namespace "http://www.w3.org/1998/Math/MathML"; + for $m in db2-fn:xmlcolumn("math.math_mathml") return +for $x in $m//*:apply +[*[1]/name() ='sin' and *[2]/name() ='ci' and *[2][./text() = 'x']] + where +fn:count($x/*[2]/*) = 0 + and fn:count($x/*) = 2 + + return +data($m/*[1]/@alttext) +EOT; + + + private $rqx2 = <<<'EOT' +xquery declare default element namespace "http://www.w3.org/1998/Math/MathML"; + for $m in db2-fn:xmlcolumn("math.math_mathml") return +for $x in $m//*:apply +[*[1]/name() ='csymbol' and *[1][./text() = 'superscript'] and *[3]/name() ='cn' and *[3][./text() = '2']] + where +fn:count($x/*[1]/*) = 0 + and fn:count($x/*[3]/*) = 0 + and fn:count($x/*) = 3 + + return +data($m/*[1]/@alttext) +EOT; + private $rqx2x = <<<'EOT' +xquery declare default element namespace "http://www.w3.org/1998/Math/MathML"; + for $m in db2-fn:xmlcolumn("math.math_mathml") return +for $x in $m//*:apply +[*[1]/name() ='csymbol' and *[1][./text() = 'superscript'] and *[3]/name() ='cn' and *[3][./text() = '2']] + where +fn:count($x/*[1]/*) = 0 + and fn:count($x/*[3]/*) = 0 + and fn:count($x/*) = 3 + + return +data($m/*[1]/@alttext) +EOT; + /** + * Searches for $E$ + */ + public function testE(){ + $xQuery = new XQueryGeneratorDB2($this->q1); + $this->assertEquals($this->r1,$xQuery->getXQuery()); + } + + /* + * Searches for $c^2$ + */ + public function testc2(){ + $xQuery = new XQueryGeneratorDB2($this->q2); + $this->assertEquals($this->r2,$xQuery->getXQuery()); + } + + /* + * Searches for $\sin x$ + */ + public function testsinx(){ + $xQuery = new XQueryGeneratorDB2($this->q3); + $this->assertEquals($this->r3,$xQuery->getXQuery()); + } + + /* + * Searches for $?x^2$ + */ + public function testx2(){ + $xQuery = new XQueryGeneratorDB2($this->qqx2); + $this->assertEquals($this->rqx2,$xQuery->getXQuery()); + } + /* + * Searches for $?x^2+?x$ + */ + public function testx2x(){ + $xQuery = new XQueryGeneratorDB2($this->qqx2x); + $this->assertEquals($this->rqx2x,$xQuery->getXQuery()); + } + /*public function testBasicSQL(){ + global $wgMathSearchDB2ConnStr; + $conn = db2_connect($wgMathSearchDB2ConnStr, '', ''); + $stmt = db2_exec($conn,'select "math_tex" from "math"'); + while($row = db2_fetch_object($stmt)){ + printf("$row->math_tex\n"); + } + } + public function testBasicXQuery(){ + global $wgMathSearchDB2ConnStr; + $conn = db2_connect($wgMathSearchDB2ConnStr, '', ''); + $stmt = db2_exec($conn,'xquery declare default element namespace "http://www.w3.org/1998/Math/MathML"; + for $m in db2-fn:xmlcolumn("math.math_mathml") return +for $x in $m//*:\'apply\'[*[1]/name() = \'eq\'] return +data($m/*[1]/@alttext)'); + while($row = db2_fetch_row($stmt)){ + echo db2_result($stmt,0); + + } + } + + + + + + + private function testBasic() { + $cmmlQueryString = <<<'XML' +<?xml version="1.0"?> +<mws:query xmlns:mws="http://search.mathweb.org/ns" xmlns:m="http://www.w3.org/1998/Math/MathML" limitmin="0" answsize="30"> + <mws:expr> + <m:apply xml:id="p1.1.m1.1.6.cmml" xref="p1.1.m1.1.6"> + <m:eq xml:id="p1.1.m1.1.2.cmml" xref="p1.1.m1.1.2"/> + <m:ci xml:id="p1.1.m1.1.1.cmml" xref="p1.1.m1.1.1">E</m:ci> + <m:apply xml:id="p1.1.m1.1.6.1.cmml" xref="p1.1.m1.1.6.1"> + <m:times xml:id="p1.1.m1.1.6.1.1.cmml" xref="p1.1.m1.1.6.1.1"/> + <m:ci xml:id="p1.1.m1.1.3.cmml" xref="p1.1.m1.1.3">m</m:ci> + <m:apply xml:id="p1.1.m1.1.6.1.2.cmml" xref="p1.1.m1.1.6.1.2"> + <m:csymbol cd="ambiguous" xml:id="p1.1.m1.1.6.1.2.1.cmml">superscript</m:csymbol> + <m:ci xml:id="p1.1.m1.1.4.cmml" xref="p1.1.m1.1.4">c</m:ci> + <m:cn type="integer" xml:id="p1.1.m1.1.5.1.cmml" xref="p1.1.m1.1.5.1">2</m:cn> + </m:apply> + </m:apply> + </m:apply> + </mws:expr> +</mws:query> +XML; + //TODO: fix test + $xqueryTest = new XQueryGeneratorDB2($cmmlQueryString); + echo $xqueryTest->getXQuery(); + }*/ +} \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/111468 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ic4dfed43fb32216477b7038e5903edbd7d91e37f Gerrit-PatchSet: 8 Gerrit-Project: mediawiki/extensions/MathSearch Gerrit-Branch: master Gerrit-Owner: Etienne <etienne-m...@web.de> Gerrit-Reviewer: Physikerwelt <w...@physikerwelt.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits