summaryrefslogtreecommitdiff
path: root/tests/test_xpath_paths.cpp
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2014-10-26 09:37:18 -0700
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2014-10-26 09:37:18 -0700
commitd5e29292c67c24b5cd7ac4f6afce2f8ec293144a (patch)
tree9e454ea5ac1c27697aecbb4dac5d4f542d6c9ceb /tests/test_xpath_paths.cpp
parentf31c14e1fdcbd6e406e7e2bea21b303853e028e3 (diff)
XPath: Optimize constant filters/predicates
If a filter/predicate expression is a constant, we don't need to evaluate it for every nodeset element - we can evaluate it once and pick the right element or keep/discard the entire collection. If the expression is 1, we can early out on first node when evaluating the node set - queries like following::item[1] are now significantly faster. Additionally this change refactors filters/predicates to have additional metadata describing the expression type in _test field that is filled during optimization. Note that predicate_constant selection right now is very simple (but captures most common use cases except for maybe [last()]).
Diffstat (limited to 'tests/test_xpath_paths.cpp')
-rw-r--r--tests/test_xpath_paths.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/tests/test_xpath_paths.cpp b/tests/test_xpath_paths.cpp
index ee2401a..046592a 100644
--- a/tests/test_xpath_paths.cpp
+++ b/tests/test_xpath_paths.cpp
@@ -437,6 +437,44 @@ TEST_XML(xpath_paths_predicate_number, "<node><chapter/><chapter/><chapter/><cha
CHECK_XPATH_NODESET(n, STR("preceding-sibling::chapter[2]")) % 3;
}
+TEST_XML(xpath_paths_predicate_number_boundary, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
+{
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[0.999999999999999]"));
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[1]")) % 3;
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[1.000000000000001]"));
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[1.999999999999999]"));
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[2]")) % 4;
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[2.000000000000001]"));
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[4.999999999999999]"));
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[5]")) % 7;
+ CHECK_XPATH_NODESET(doc, STR("node/chapter[5.000000000000001]"));
+}
+
+TEST_XML(xpath_paths_predicate_number_out_of_range, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
+{
+ xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
+
+ CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[0]"));
+ CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[-1]"));
+ CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[-1000000000000]"));
+ CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[-1 div 0]"));
+ CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[1000000000000]"));
+ CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[1 div 0]"));
+ CHECK_XPATH_NODESET(n, STR("following-sibling::chapter[0 div 0]"));
+}
+
+TEST_XML(xpath_paths_predicate_constant_boolean, "<node><chapter/><chapter/><chapter/><chapter/><chapter/></node>")
+{
+ xml_node n = doc.child(STR("node")).child(STR("chapter")).next_sibling().next_sibling();
+
+ xpath_variable_set set;
+ set.set(STR("true"), true);
+ set.set(STR("false"), false);
+
+ CHECK_XPATH_NODESET_VAR(n, STR("following-sibling::chapter[$false]"), &set);
+ CHECK_XPATH_NODESET_VAR(n, STR("following-sibling::chapter[$true]"), &set) % 6 % 7;
+}
+
TEST_XML(xpath_paths_predicate_several, "<node><employee/><employee secretary=''/><employee assistant=''/><employee secretary='' assistant=''/><employee assistant='' secretary=''/></node>")
{
xml_node n = doc.child(STR("node"));