TEST(QueryPlannerTest, createTripleGraph) { try { { ParsedQuery pq = SparqlParser::parse( "PREFIX : <http://rdf.myprefix.com/>\n" "PREFIX ns: <http://rdf.myprefix.com/ns/>\n" "PREFIX xxx: <http://rdf.myprefix.com/xxx/>\n" "SELECT ?x ?z \n " "WHERE \t {?x :myrel ?y. ?y ns:myrel ?z.?y xxx:rel2 " "<http://abc.de>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: <http://rdf.myprefix.com/myrel>, o: ?y} : (1, 2)\n" "1 {s: ?y, p: <http://rdf.myprefix.com/ns/myrel>, o: ?z} : (0, 2)\n" "2 {s: ?y, p: <http://rdf.myprefix.com/xxx/rel2>, o: " "<http://abc.de>} : (0, 1)", tg.asString()); } { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {?x ?p <X>. ?x ?p2 <Y>. <X> ?p <Y>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: ?p, o: <X>} : (1, 2)\n" "1 {s: ?x, p: ?p2, o: <Y>} : (0)\n" "2 {s: <X>, p: ?p, o: <Y>} : (0)", tg.asString()); } { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE { ?x <is-a> <Book> . \n" "?x <Author> <Anthony_Newman_(Author)> }"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: <is-a>, o: <Book>} : (1)\n" "1 {s: ?x, p: <Author>, o: <Anthony_Newman_(Author)>} : (0)", tg.asString()); } } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryPlannerTest, testBFSLeaveOut) { try { { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {?x ?p <X>. ?x ?p2 <Y>. <X> ?p <Y>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ(3u, tg._adjLists.size()); ad_utility::HashSet<size_t> lo; auto out = tg.bfsLeaveOut(0, lo); ASSERT_EQ(3u, out.size()); lo.insert(1); out = tg.bfsLeaveOut(0, lo); ASSERT_EQ(2u, out.size()); lo.insert(2); out = tg.bfsLeaveOut(0, lo); ASSERT_EQ(1u, out.size()); lo.clear(); lo.insert(0); out = tg.bfsLeaveOut(1, lo); ASSERT_EQ(1u, out.size()); } { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {<A> <B> ?x. ?x <C> ?y. ?y <X> <Y>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ad_utility::HashSet<size_t> lo; auto out = tg.bfsLeaveOut(0, lo); ASSERT_EQ(3u, out.size()); lo.insert(1); out = tg.bfsLeaveOut(0, lo); ASSERT_EQ(1u, out.size()); lo.insert(2); out = tg.bfsLeaveOut(0, lo); ASSERT_EQ(1u, out.size()); lo.clear(); lo.insert(0); out = tg.bfsLeaveOut(1, lo); ASSERT_EQ(2u, out.size()); } } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testBornInEuropeOwCocaine) { try { ParsedQuery pq = SparqlParser::parse( "PREFIX : <>\n" "SELECT ?x ?y TEXT(?c)\n " "WHERE \t {" "?x :Place_of_birth ?y ." "?y :Contained_by :Europe ." "?c ql:contains-entity ?x ." "?c ql:contains-word \"cocaine\" ." "}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n TEXT OPERATION WITH FILTER: co-occurrence with words: " "\"cocaine\" and 1 variables with textLimit = 1 filtered by\n " "{\n JOIN\n {\n SCAN POS with P = \"<Contained_by>\", " "O = \"<Europe>\"\n qet-width: 1 \n } join-column: [0]\n" " |X|\n {\n SCAN POS with P = \"<Place_of_birth>\"\n" " qet-width: 2 \n } join-column: [0]\n qet-width: 2 \n" " }\n filtered on column 1\n qet-width: 4 \n}", qet.asString()); ASSERT_EQ(0u, qet.getVariableColumn("?c")); ASSERT_EQ(1u, qet.getVariableColumn("SCORE(?c)")); ASSERT_EQ(2u, qet.getVariableColumn("?y")); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testCoOccFreeVar) { try { ParsedQuery pq = SparqlParser::parse( "PREFIX : <>" "SELECT ?x ?y WHERE {" "?x :is-a :Politician ." "?c ql:contains-entity ?x ." "?c ql:contains-word \"friend*\" ." "?c ql:contains-entity ?y ." "}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n TEXT OPERATION WITH FILTER: co-occurrence with words: " "\"friend*\" and 2 variables with textLimit = 1 filtered by\n" " {\n SCAN POS with P = \"<is-a>\", O = \"<Politician>" "\"\n qet-width: 1 \n }\n filtered on column 0\n " " qet-width: 4 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryPlannerTest, testStarTwoFree) { try { { ParsedQuery pq = SparqlParser::parse( "PREFIX : <http://rdf.myprefix.com/>\n" "PREFIX ns: <http://rdf.myprefix.com/ns/>\n" "PREFIX xxx: <http://rdf.myprefix.com/xxx/>\n" "SELECT ?x ?z \n " "WHERE \t {?x :myrel ?y. ?y ns:myrel ?z. ?y xxx:rel2 " "<http://abc.de>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n JOIN\n {\n JOIN\n {\n SCAN POS with P = \"" "<http://rdf.myprefix.com/myrel>\"\n qet-width: 2 \n " " } join-column: [0]\n |X|\n {\n SCAN PSO wit" "h P = \"<http://rdf.myprefix.com/ns/myrel>\"\n qet-" "width: 2 \n } join-column: [0]\n qet-width: 3 \n " "} join-column: [0]\n |X|\n {\n SCAN POS with P = " "\"<http://rdf.myprefix.com/xxx/rel2>\", O = \"<http://a" "bc.de>\"\n qet-width: 1 \n } join-column: [0]\n qet" "-width: 3 \n}", qet.asString()); } } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryPlannerTest, testActorsBornInEurope) { try { ParsedQuery pq = SparqlParser::parse( "PREFIX : <pre/>\n" "SELECT ?a \n " "WHERE {?a :profession :Actor . ?a :born-in ?c. ?c :in :Europe}\n" "ORDER BY ?a"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n JOIN\n {\n SCAN POS with P = \"<pre/profession>\", " "O = \"<pre/Actor>\"\n qet-width: 1 \n } join-column:" " [0]\n |X|\n {\n SORT on column:1\n {\n " "JOIN\n {\n SCAN POS with P = \"<pre/born-i" "n>\"\n qet-width: 2 \n } join-column: [0]\n " " |X|\n {\n SCAN POS with P = \"<pre/in>\"" ", O = \"<pre/Europe>\"\n qet-width: 1 \n }" " join-column: [0]\n qet-width: 2 \n }\n " "qet-width: 2 \n } join-column: [1]\n qet-width: 2 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testCyclicQuery) { try { ParsedQuery pq = SparqlParser::parse( "SELECT ?x ?y ?m WHERE { ?x <Spouse_(or_domestic_partner)> ?y . " "?x <Film_performance> ?m . ?y <Film_performance> ?m }"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n TWO_COLUMN_JOIN\n {\n ORDER_BY\n {\n JOIN\n" " {\n SCAN PSO with P = \"<Film_performance>\"\n" " qet-width: 2 \n } join-column: [0]\n |X|\n" " {\n " "SCAN PSO with P = \"<Spouse_(or_domestic_partner)>\"\n " " qet-width: 2 \n } join-column: [0]\n " " qet-width: 3 \n } order on asc(2) asc(1) \n" " qet-width: 3 \n }\n join-columns: [2 & 1]\n |X|\n" " {\n SCAN PSO with P = \"<Film_performance>\"\n" " qet-width: 2 \n }\n join-columns: [0 & 1]\n" " qet-width: 3 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testFormerSegfaultTriFilter) { try { ParsedQuery pq = SparqlParser::parse( "PREFIX fb: <http://rdf.freebase.com/ns/>\n" "SELECT DISTINCT ?1 ?0 WHERE {\n" "fb:m.0fkvn fb:government.government_office_category.officeholders ?0 " ".\n" "?0 fb:government.government_position_held.jurisdiction_of_office " "fb:m.0vmt .\n" "?0 fb:government.government_position_held.office_holder ?1 .\n" "FILTER (?1 != fb:m.0fkvn) .\n" "FILTER (?1 != fb:m.0vmt) .\n" "FILTER (?1 != fb:m.018mts)" "} LIMIT 300"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_TRUE(qet.varCovered("?1")); ASSERT_TRUE(qet.varCovered("?0")); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testPlantsEdibleLeaves) { try { ParsedQuery pq = SparqlParser::parse( "SELECT ?a \n " "WHERE {?a <is-a> <Plant> . ?c ql:contains-entity ?a. " "?c ql:contains-word \"edible leaves\"} TEXTLIMIT 5"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryPlanner::TripleGraph tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ(1u, tg._nodeMap.find(0)->second->_variables.size()); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n TEXT OPERATION WITH FILTER: co-occurrence with words: " "\"edible leaves\" and 1 variables with textLimit = 5 " "filtered by\n {\n SCAN POS with P = \"<is-a>\", " "O = \"<Plant>\"\n qet-width: 1 \n }\n filtered on " "column 0\n qet-width: 3 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(ParserTest, testExpandPrefixes) { ParsedQuery pq = SparqlParser::parse( "PREFIX : <http://rdf.myprefix.com/>\n" "PREFIX ns: <http://rdf.myprefix.com/ns/>\n" "PREFIX xxx: <http://rdf.myprefix.com/xxx/>\n" "SELECT ?x ?z \n " "WHERE \t {?x :myrel ?y. ?y ns:myrel ?z.?y nsx:rel2 <http://abc.de>}"); pq.expandPrefixes(); ASSERT_EQ(3, pq._prefixes.size()); ASSERT_EQ(2, pq._selectedVariables.size()); ASSERT_EQ(3, pq._whereClauseTriples.size()); ASSERT_EQ("", pq._prefixes[0]._prefix); ASSERT_EQ("<http://rdf.myprefix.com/>", pq._prefixes[0]._uri); ASSERT_EQ("ns", pq._prefixes[1]._prefix); ASSERT_EQ("<http://rdf.myprefix.com/ns/>", pq._prefixes[1]._uri); ASSERT_EQ("?x", pq._selectedVariables[0]); ASSERT_EQ("?z", pq._selectedVariables[1]); ASSERT_EQ("?x", pq._whereClauseTriples[0]._s); ASSERT_EQ("<http://rdf.myprefix.com/myrel>", pq._whereClauseTriples[0]._p); ASSERT_EQ("?y", pq._whereClauseTriples[0]._o); ASSERT_EQ("?y", pq._whereClauseTriples[1]._s); ASSERT_EQ("<http://rdf.myprefix.com/ns/myrel>", pq._whereClauseTriples[1] ._p); ASSERT_EQ("?z", pq._whereClauseTriples[1]._o); ASSERT_EQ("?y", pq._whereClauseTriples[2]._s); ASSERT_EQ("nsx:rel2", pq._whereClauseTriples[2]._p); ASSERT_EQ("<http://abc.de>", pq._whereClauseTriples[2]._o); ASSERT_EQ("", pq._limit); ASSERT_EQ("", pq._offset); }
TEST(QueryPlannerTest, testSimpleOptional) { try { QueryPlanner qp(nullptr); ParsedQuery pq = SparqlParser::parse( "SELECT ?a ?b \n " "WHERE {?a <rel1> ?b . OPTIONAL { ?a <rel2> ?c }}"); pq.expandPrefixes(); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n" " OPTIONAL_JOIN\n" " {\n" " SCAN PSO with P = \"<rel1>\"\n" " qet-width: 2 \n" " } join-columns: [0]\n" " |X|\n" " {\n" " SCAN PSO with P = \"<rel2>\"\n" " qet-width: 2 \n" " } join-columns: [0]\n" " qet-width: 3 \n" "}", qet.asString()); ParsedQuery pq2 = SparqlParser::parse( "SELECT ?a ?b \n " "WHERE {?a <rel1> ?b . " "OPTIONAL { ?a <rel2> ?c }} ORDER BY ?b"); pq2.expandPrefixes(); QueryExecutionTree qet2 = qp.createExecutionTree(pq2); ASSERT_EQ( "{\n" " SORT on column:1\n" " {\n" " OPTIONAL_JOIN\n" " {\n" " SCAN PSO with P = \"<rel1>\"\n" " qet-width: 2 \n" " } join-columns: [0]\n" " |X|\n" " {\n" " SCAN PSO with P = \"<rel2>\"\n" " qet-width: 2 \n" " } join-columns: [0]\n" " qet-width: 3 \n" " }\n" " qet-width: 3 \n" "}", qet2.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
// _____________________________________________________________________________ void Server::process(Socket *client, QueryExecutionContext *qec) const { string request; string response; string query; string contentType; client->recieve(&request); size_t indexOfGET = request.find("GET"); size_t indexOfHTTP = request.find("HTTP"); size_t upper = indexOfHTTP; if (indexOfGET != request.npos && indexOfHTTP != request.npos) { size_t indexOfQuest = request.find("?", indexOfGET); if (indexOfQuest != string::npos && indexOfQuest < indexOfHTTP) { upper = indexOfQuest + 1; } string file = request.substr(indexOfGET + 5, upper - (indexOfGET + 5) - 1); // Use hardcoded white-listing for index.html and style.css // can be changed if more should ever be needed, for now keep it simple. LOG(DEBUG) << "file: " << file << '\n'; if (file == "index.html" || file == "style.css" || file == "script.js") { serveFile(client, file); return; } if (indexOfQuest == string::npos) { LOG(INFO) << "Ignoring request for file " << file << '\n'; return; } try { ParamValueMap params = parseHttpRequest(request); if (ad_utility::getLowercase(params["cmd"]) == "clearcache") { qec->clearCache(); } query = createQueryFromHttpParams(params); LOG(INFO) << "Query: " << query << '\n'; ParsedQuery pq = SparqlParser::parse(query); pq.expandPrefixes(); QueryGraph qg(qec); qg.createFromParsedQuery(pq); const QueryExecutionTree& qet = qg.getExecutionTree(); response = composeResponseJson(pq, qet); contentType = "application/json"; } catch (const ad_semsearch::Exception& e) { response = composeResponseJson(query, e); } catch (const ParseException& e) { response = composeResponseJson(query, e); } string httpResponse = createHttpResponse(response, contentType); client->send(httpResponse); } else { LOG(INFO) << "Ignoring invalid request " << request << '\n'; } }
TEST(QueryPlannerTest, testSP_free_) { ParsedQuery pq = SparqlParser::parse( "PREFIX : <http://rdf.myprefix.com/>\n" "SELECT ?x \n " "WHERE \t {?x :myrel ?y}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n SCAN PSO with P = \"<http://rdf.myprefix.com/myrel>\"\n " "qet-width: 2 \n}", qet.asString()); }
TEST(QueryExecutionTreeTest, testBooksGermanAwardNomAuth) { try { ParsedQuery pq = SparqlParser::parse( "SELECT ?x ?y WHERE { " "?x <is-a> <Person> . " "?x <Country_of_nationality> <Germany> . " "?x <Author> ?y . " "?y <is-a> <Award-Nominated_Work> }"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_GT(qet.asString().size(), 0u); // Just check that ther is no exception, here. } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testTextQuerySE) { try { ParsedQuery pq = SparqlParser::parse( "SELECT TEXT(?c) \n " "WHERE {?c ql:contains-word \"search engine\"}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n TEXT OPERATION WITHOUT FILTER: co-occurrence with words:" " \"search engine\" and 0 variables with textLimit = 1\n" " qet-width: 2 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryPlannerTest, test_free_PX__free_PX) { try { ParsedQuery pq = SparqlParser::parse( "PREFIX : <pre/>\n" "SELECT ?x ?y ?z \n " "WHERE {?y :r ?x. ?z :r ?x}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n JOIN\n {\n SCAN POS with P = \"<pre/r>\"\n " "qet-width: 2 \n } join-column: [0]\n |X|\n {\n " "SCAN POS with P = \"<pre/r>\"\n qet-width: 2 \n" " } join-column: [0]\n qet-width: 3 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testBooksbyNewman) { try { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE { ?x <is-a> <Book> . " "?x <Author> <Anthony_Newman_(Author)> }"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n JOIN\n {\n SCAN POS with " "P = \"<Author>\", O = \"<Anthony_Newman_(Author)>\"\n " " qet-width: 1 \n } join-column: [0]\n |X|\n {\n " " SCAN POS with P = \"<is-a>\", O = \"<Book>\"\n " " qet-width: 1 \n } join-column: [0]\n qet-width: 1 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryExecutionTreeTest, testPoliticiansFriendWithScieManHatProj) { try { ParsedQuery pq = SparqlParser::parse( "SELECT ?p ?s \n " "WHERE {" "?a <is-a> <Politician> . " "?c ql:contains-entity ?a ." "?c ql:contains-word \"friend*\" ." "?c ql:contains-entity ?s ." "?s <is-a> <Scientist> ." "?c2 ql:contains-entity ?s ." "?c2 ql:contains-word \"manhattan project\"}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); QueryExecutionTree qet = qp.createExecutionTree(pq); ASSERT_EQ( "{\n JOIN\n {\n SCAN POS with P = \"<is-a>\", O = " "\"<Scientist>\"\n qet-width: 1 \n } join-column: [0]\n |X|\n " "{\n SORT on column:4\n {\n TEXT OPERATION WITH FILTER: " "co-occurrence with words: \"manhattan project\" and 1 variables with " "textLimit = 1 filtered by\n {\n TEXT OPERATION WITH " "FILTER: co-occurrence with words: \"friend*\" and 2 variables with " "textLimit = 1 filtered by\n {\n SCAN POS with P = " "\"<is-a>\", O = \"<Politician>\"\n qet-width: 1 \n " "}\n filtered on column 0\n qet-width: 4 \n }\n " " filtered on column 2\n qet-width: 6 \n }\n qet-width: 6 " "\n } join-column: [4]\n qet-width: 6 \n}", qet.asString()); } catch (const ad_semsearch::Exception& e) { std::cout << "Caught: " << e.getFullErrorMessage() << std::endl; FAIL() << e.getFullErrorMessage(); } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
// Main function. int main(int argc, char** argv) { cout.sync_with_stdio(false); std::cout << std::endl << EMPH_ON << "WriteIndexListsMain, version " << __DATE__ << " " << __TIME__ << EMPH_OFF << std::endl << std::endl; char* locale = setlocale(LC_CTYPE, ""); cout << "Set locale LC_CTYPE to: " << locale << endl; std::locale loc; ad_utility::ReadableNumberFacet facet(1); std::locale locWithNumberGrouping(loc, &facet); ad_utility::Log::imbue(locWithNumberGrouping); string indexName = ""; bool freebase = false; optind = 1; // Process command line arguments. while (true) { int c = getopt_long(argc, argv, "i:f", options, NULL); if (c == -1) break; switch (c) { case 'i': indexName = optarg; break; case 'f': freebase = true; break; default: cout << endl << "! ERROR in processing options (getopt returned '" << c << "' = 0x" << std::setbase(16) << c << ")" << endl << endl; exit(1); } } if (indexName.size() == 0) { cout << "Missing required argument --index (-i)..." << endl; exit(1); } try { Index index; index.createFromOnDiskIndex(indexName); index.addTextFromOnDiskIndex(); vector<string> lists; lists.push_back("algo*"); bool decodeGapsAndFrequency = true; index.dumpAsciiLists(lists, decodeGapsAndFrequency); Engine engine; QueryExecutionContext qec(index, engine); ParsedQuery q; if (!freebase) { q = SparqlParser::parse("SELECT ?x WHERE {?x <is-a> <Scientist>}"); } else { q = SparqlParser::parse( "PREFIX fb: <http://rdf.freebase.com/ns/> SELECT ?p WHERE {?p " "fb:people.person.profession fb:m.06q2q}"); q.expandPrefixes(); } QueryPlanner queryPlanner(&qec); auto qet = queryPlanner.createExecutionTree(q); const auto res = qet.getResult(); AD_CHECK(res->size() > 0); AD_CHECK(res->_data.cols() == 1); string personlistFile = indexName + ".list.scientists"; std::ofstream f(personlistFile.c_str()); const IdTable& ids = res->_data; for (size_t i = 0; i < ids.size(); ++i) { f << ids(i, 0) << ' '; } f.close(); } catch (const std::exception& e) { cout << e.what() << std::endl; } return 0; }
TEST(ParserTest, testParse) { try { ParsedQuery pq = SparqlParser::parse("SELECT ?x WHERE {?x ?y ?z}"); ASSERT_GT(pq.asString().size(), 0); ASSERT_EQ(0, pq._prefixes.size()); ASSERT_EQ(1, pq._selectedVariables.size()); ASSERT_EQ(1, pq._whereClauseTriples.size()); pq = SparqlParser::parse( "PREFIX : <http://rdf.myprefix.com/>\n" "PREFIX ns: <http://rdf.myprefix.com/ns/>\n" "PREFIX xxx: <http://rdf.myprefix.com/xxx/>\n" "SELECT ?x ?z \n " "WHERE \t {?x :myrel ?y. ?y ns:myrel ?z.?y nsx:rel2 <http://abc.de>}"); ASSERT_EQ(3, pq._prefixes.size()); ASSERT_EQ(2, pq._selectedVariables.size()); ASSERT_EQ(3, pq._whereClauseTriples.size()); ASSERT_EQ("", pq._prefixes[0]._prefix); ASSERT_EQ("<http://rdf.myprefix.com/>", pq._prefixes[0]._uri); ASSERT_EQ("ns", pq._prefixes[1]._prefix); ASSERT_EQ("<http://rdf.myprefix.com/ns/>", pq._prefixes[1]._uri); ASSERT_EQ("?x", pq._selectedVariables[0]); ASSERT_EQ("?z", pq._selectedVariables[1]); ASSERT_EQ("?x", pq._whereClauseTriples[0]._s); ASSERT_EQ(":myrel", pq._whereClauseTriples[0]._p); ASSERT_EQ("?y", pq._whereClauseTriples[0]._o); ASSERT_EQ("?y", pq._whereClauseTriples[1]._s); ASSERT_EQ("ns:myrel", pq._whereClauseTriples[1]._p); ASSERT_EQ("?z", pq._whereClauseTriples[1]._o); ASSERT_EQ("?y", pq._whereClauseTriples[2]._s); ASSERT_EQ("nsx:rel2", pq._whereClauseTriples[2]._p); ASSERT_EQ("<http://abc.de>", pq._whereClauseTriples[2]._o); ASSERT_EQ("", pq._limit); ASSERT_EQ("", pq._offset); pq = SparqlParser::parse( "PREFIX : <http://rdf.myprefix.com/>\n" "PREFIX ns: <http://rdf.myprefix.com/ns/>\n" "PREFIX xxx: <http://rdf.myprefix.com/xxx/>\n" "SELECT ?x ?z \n " "WHERE \t {\n?x :myrel ?y. ?y ns:myrel ?z.\n?y nsx:rel2 <http://abc.de>\n}"); ASSERT_EQ(3, pq._prefixes.size()); ASSERT_EQ(2, pq._selectedVariables.size()); ASSERT_EQ(3, pq._whereClauseTriples.size()); ASSERT_EQ("", pq._prefixes[0]._prefix); ASSERT_EQ("<http://rdf.myprefix.com/>", pq._prefixes[0]._uri); ASSERT_EQ("ns", pq._prefixes[1]._prefix); ASSERT_EQ("<http://rdf.myprefix.com/ns/>", pq._prefixes[1]._uri); ASSERT_EQ("?x", pq._selectedVariables[0]); ASSERT_EQ("?z", pq._selectedVariables[1]); ASSERT_EQ("?x", pq._whereClauseTriples[0]._s); ASSERT_EQ(":myrel", pq._whereClauseTriples[0]._p); ASSERT_EQ("?y", pq._whereClauseTriples[0]._o); ASSERT_EQ("?y", pq._whereClauseTriples[1]._s); ASSERT_EQ("ns:myrel", pq._whereClauseTriples[1]._p); ASSERT_EQ("?z", pq._whereClauseTriples[1]._o); ASSERT_EQ("?y", pq._whereClauseTriples[2]._s); ASSERT_EQ("nsx:rel2", pq._whereClauseTriples[2]._p); ASSERT_EQ("<http://abc.de>", pq._whereClauseTriples[2]._o); ASSERT_EQ("", pq._limit); ASSERT_EQ("", pq._offset); pq = SparqlParser::parse( "PREFIX ns: <http://ns/>" "SELECT ?x ?z \n " "WHERE \t {\n?x <Directed_by> ?y. ?y ns:myrel.extend ?z.\n" "?y nsx:rel2 \"Hello... World\"}"); ASSERT_EQ(1, pq._prefixes.size()); ASSERT_EQ(2, pq._selectedVariables.size()); ASSERT_EQ(3, pq._whereClauseTriples.size()); pq.expandPrefixes(); ASSERT_EQ("?x", pq._selectedVariables[0]); ASSERT_EQ("?z", pq._selectedVariables[1]); ASSERT_EQ("?x", pq._whereClauseTriples[0]._s); ASSERT_EQ("<Directed_by>", pq._whereClauseTriples[0]._p); ASSERT_EQ("?y", pq._whereClauseTriples[0]._o); ASSERT_EQ("?y", pq._whereClauseTriples[1]._s); ASSERT_EQ("<http://ns/myrel.extend>", pq._whereClauseTriples[1]._p); ASSERT_EQ("?z", pq._whereClauseTriples[1]._o); ASSERT_EQ("?y", pq._whereClauseTriples[2]._s); ASSERT_EQ("nsx:rel2", pq._whereClauseTriples[2]._p); ASSERT_EQ("\"Hello... World\"", pq._whereClauseTriples[2]._o); ASSERT_EQ("", pq._limit); ASSERT_EQ("", pq._offset); pq = SparqlParser::parse( "SELECT ?x ?y WHERE {?x is-a Actor . FILTER(?x != ?y)." "?y is-a Actor . FILTER(?y < ?x)} LIMIT 10"); pq.expandPrefixes(); ASSERT_EQ(2, pq._filters.size()); ASSERT_EQ("?x", pq._filters[0]._lhs); ASSERT_EQ("?y", pq._filters[0]._rhs); ASSERT_EQ(SparqlFilter::FilterType::NE, pq._filters[0]._type); ASSERT_EQ("?y", pq._filters[1]._lhs); ASSERT_EQ("?x", pq._filters[1]._rhs); ASSERT_EQ(SparqlFilter::FilterType::LT, pq._filters[1]._type); ASSERT_EQ(2, pq._whereClauseTriples.size()); pq = SparqlParser::parse( "SELECT ?x ?y WHERE {?x is-a Actor . FILTER(?x != ?y)." "?y is-a Actor} LIMIT 10"); pq.expandPrefixes(); ASSERT_EQ(1, pq._filters.size()); ASSERT_EQ("?x", pq._filters[0]._lhs); ASSERT_EQ("?y", pq._filters[0]._rhs); ASSERT_EQ(SparqlFilter::FilterType::NE, pq._filters[0]._type); ASSERT_EQ(2, pq._whereClauseTriples.size()); pq = SparqlParser::parse( "SELECT ?x ?y WHERE {?x is-a Actor . FILTER(?x != ?y)." "?y is-a Actor. ?x <in-context> ?c." "?c <in-context> coca* abuse} LIMIT 10"); pq.expandPrefixes(); ASSERT_EQ(1, pq._filters.size()); ASSERT_EQ("?x", pq._filters[0]._lhs); ASSERT_EQ("?y", pq._filters[0]._rhs); ASSERT_EQ(SparqlFilter::FilterType::NE, pq._filters[0]._type); ASSERT_EQ(4, pq._whereClauseTriples.size()); ASSERT_EQ("?x", pq._whereClauseTriples[2]._s); ASSERT_EQ("<in-context>", pq._whereClauseTriples[2]._p); ASSERT_EQ("?c", pq._whereClauseTriples[2]._o); ASSERT_EQ("?c", pq._whereClauseTriples[3]._s); ASSERT_EQ("<in-context>", pq._whereClauseTriples[3]._p); ASSERT_EQ("coca* abuse", pq._whereClauseTriples[3]._o); pq = SparqlParser::parse( "PREFIX : <>\n" "SELECT ?x ?y ?z TEXT(?c) SCORE(?c) ?c WHERE {\n" "?x :is-a :Politician .\n" "?x :in-context ?c .\n" "?c :in-context friend .\n" "?c :in-context ?y .\n" "?y :is-a :Scientist .\n" "FILTER(?x != ?y) .\n" "} ORDER BY ?c"); pq.expandPrefixes(); ASSERT_EQ(1, pq._filters.size()); } catch (const ad_semsearch::Exception& e) { FAIL() << e.getFullErrorMessage(); } };
TEST(QueryPlannerTest, testcollapseTextCliques) { try { { { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {?x <p> <X>. ?c ql:contains-entity ?x. ?c " "ql:contains-word abc}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: <p>, o: <X>} : (1)\n" "1 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?x} : " "(0, 2)\n" "2 {s: ?c, p: <QLever-internal-function/contains-word>, o: abc} : " "(1)", tg.asString()); tg.collapseTextCliques(); ASSERT_EQ( "0 {TextOP for ?c, wordPart: \"abc\"} : (1)\n" "1 {s: ?x, p: <p>, o: <X>} : (0)", tg.asString()); ASSERT_EQ(2ul, tg._nodeMap[0]->_variables.size()); ASSERT_EQ(1ul, tg._nodeMap[1]->_variables.size()); } { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {?x <p> <X>. ?c " "<QLever-internal-function/contains-entity> ?x. ?c " "<QLever-internal-function/contains-word> abc . ?c " "ql:contains-entity ?y}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: <p>, o: <X>} : (1)\n" "1 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?x} : " "(0, 2, 3)\n" "2 {s: ?c, p: <QLever-internal-function/contains-word>, o: abc} : " "(1, 3)\n" "3 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?y} : " "(1, 2)", tg.asString()); tg.collapseTextCliques(); ASSERT_EQ( "0 {TextOP for ?c, wordPart: \"abc\"} : (1)\n" "1 {s: ?x, p: <p>, o: <X>} : (0)", tg.asString()); ASSERT_EQ(3ul, tg._nodeMap[0]->_variables.size()); ASSERT_EQ(1ul, tg._nodeMap[1]->_variables.size()); } { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {?x <p> <X>. ?c ql:contains-entity ?x. ?c " "ql:contains-word abc . ?c ql:contains-entity ?y. ?y <P2> <X2>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: <p>, o: <X>} : (1)\n" "1 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?x} : " "(0, 2, 3)\n" "2 {s: ?c, p: <QLever-internal-function/contains-word>, o: abc} : " "(1, 3)\n" "3 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?y} : " "(1, 2, 4)\n" "4 {s: ?y, p: <P2>, o: <X2>} : (3)", tg.asString()); tg.collapseTextCliques(); ASSERT_EQ( "0 {TextOP for ?c, wordPart: \"abc\"} : (1, 2)\n" "1 {s: ?x, p: <p>, o: <X>} : (0)\n" "2 {s: ?y, p: <P2>, o: <X2>} : (0)", tg.asString()); ASSERT_EQ(3ul, tg._nodeMap[0]->_variables.size()); ASSERT_EQ(1ul, tg._nodeMap[1]->_variables.size()); ASSERT_EQ(1ul, tg._nodeMap[2]->_variables.size()); } { ParsedQuery pq = SparqlParser::parse( "(SELECT ?x WHERE {?x <p> <X>. ?c ql:contains-entity ?x. ?c " "ql:contains-word \"abc\" . ?c ql:contains-entity ?y. ?c2 " "ql:contains-entity ?y. ?c2 ql:contains-word \"xx\"})"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: <p>, o: <X>} : (1)\n" "1 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?x} : " "(0, 2, 3)\n" "2 {s: ?c, p: <QLever-internal-function/contains-word>, o: abc} : " "(1, 3)\n" "3 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?y} : " "(1, 2, 4)\n" "4 {s: ?c2, p: <QLever-internal-function/contains-entity>, o: ?y} " ": (3, 5)\n" "5 {s: ?c2, p: <QLever-internal-function/contains-word>, o: xx} : " "(4)", tg.asString()); tg.collapseTextCliques(); ASSERT_EQ( "0 {TextOP for ?c, wordPart: \"abc\"} : (1, 2)\n" "1 {TextOP for ?c2, wordPart: \"xx\"} : (0)\n" "2 {s: ?x, p: <p>, o: <X>} : (0)", tg.asString()); ASSERT_EQ(3ul, tg._nodeMap[0]->_variables.size()); ASSERT_EQ(2ul, tg._nodeMap[1]->_variables.size()); ASSERT_EQ(1ul, tg._nodeMap[2]->_variables.size()); } { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {?x <p> <X>. ?c ql:contains-entity ?x. ?c " "ql:contains-word abc . ?c ql:contains-entity ?y. ?c2 " "ql:contains-entity ?y. ?c2 ql:contains-word xx. ?y <P2> <X2>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ( "0 {s: ?x, p: <p>, o: <X>} : (1)\n" "1 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?x} : " "(0, 2, 3)\n" "2 {s: ?c, p: <QLever-internal-function/contains-word>, o: abc} : " "(1, 3)\n" "3 {s: ?c, p: <QLever-internal-function/contains-entity>, o: ?y} : " "(1, 2, 4, 6)\n" "4 {s: ?c2, p: <QLever-internal-function/contains-entity>, o: ?y} " ": (3, 5, 6)\n" "5 {s: ?c2, p: <QLever-internal-function/contains-word>, o: xx} : " "(4)\n" "6 {s: ?y, p: <P2>, o: <X2>} : (3, 4)", tg.asString()); tg.collapseTextCliques(); ASSERT_EQ( "0 {TextOP for ?c, wordPart: \"abc\"} : (1, 2, 3)\n" "1 {TextOP for ?c2, wordPart: \"xx\"} : (0, 3)\n" "2 {s: ?x, p: <p>, o: <X>} : (0)\n" "3 {s: ?y, p: <P2>, o: <X2>} : (0, 1)", tg.asString()); ASSERT_EQ(3ul, tg._nodeMap[0]->_variables.size()); ASSERT_EQ(2ul, tg._nodeMap[1]->_variables.size()); ASSERT_EQ(1ul, tg._nodeMap[2]->_variables.size()); ASSERT_EQ(1ul, tg._nodeMap[3]->_variables.size()); } } } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(QueryPlannerTest, testCpyCtorWithKeepNodes) { try { { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE {?x ?p <X>. ?x ?p2 <Y>. <X> ?p <Y>}"); pq.expandPrefixes(); QueryPlanner qp(nullptr); auto tg = qp.createTripleGraph(&pq._rootGraphPattern); ASSERT_EQ(2u, tg._nodeMap.find(0)->second->_variables.size()); ASSERT_EQ(2u, tg._nodeMap.find(1)->second->_variables.size()); ASSERT_EQ(1u, tg._nodeMap.find(2)->second->_variables.size()); ASSERT_EQ( "0 {s: ?x, p: ?p, o: <X>} : (1, 2)\n" "1 {s: ?x, p: ?p2, o: <Y>} : (0)\n" "2 {s: <X>, p: ?p, o: <Y>} : (0)", tg.asString()); { vector<size_t> keep; QueryPlanner::TripleGraph tgnew(tg, keep); ASSERT_EQ("", tgnew.asString()); } { vector<size_t> keep; keep.push_back(0); keep.push_back(1); keep.push_back(2); QueryPlanner::TripleGraph tgnew(tg, keep); ASSERT_EQ( "0 {s: ?x, p: ?p, o: <X>} : (1, 2)\n" "1 {s: ?x, p: ?p2, o: <Y>} : (0)\n" "2 {s: <X>, p: ?p, o: <Y>} : (0)", tgnew.asString()); ASSERT_EQ(2u, tgnew._nodeMap.find(0)->second->_variables.size()); ASSERT_EQ(2u, tgnew._nodeMap.find(1)->second->_variables.size()); ASSERT_EQ(1u, tgnew._nodeMap.find(2)->second->_variables.size()); } { vector<size_t> keep; keep.push_back(0); QueryPlanner::TripleGraph tgnew(tg, keep); ASSERT_EQ("0 {s: ?x, p: ?p, o: <X>} : ()", tgnew.asString()); ASSERT_EQ(2u, tgnew._nodeMap.find(0)->second->_variables.size()); } { vector<size_t> keep; keep.push_back(0); keep.push_back(1); QueryPlanner::TripleGraph tgnew(tg, keep); ASSERT_EQ( "0 {s: ?x, p: ?p, o: <X>} : (1)\n" "1 {s: ?x, p: ?p2, o: <Y>} : (0)", tgnew.asString()); ASSERT_EQ(2u, tgnew._nodeMap.find(0)->second->_variables.size()); ASSERT_EQ(2u, tgnew._nodeMap.find(1)->second->_variables.size()); } } } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; FAIL() << e.what(); } }
TEST(ParserTest, testSolutionModifiers) { ParsedQuery pq = SparqlParser::parse( "SELECT ?x WHERE \t {?x :myrel ?y}"); pq.expandPrefixes(); ASSERT_EQ(0, pq._prefixes.size()); ASSERT_EQ(1, pq._selectedVariables.size()); ASSERT_EQ(1, pq._whereClauseTriples.size()); ASSERT_EQ("", pq._limit); ASSERT_EQ("", pq._offset); ASSERT_EQ(size_t(0), pq._orderBy.size()); ASSERT_FALSE(pq._distinct); ASSERT_FALSE(pq._reduced); pq = SparqlParser::parse( "SELECT ?x WHERE \t {?x :myrel ?y} LIMIT 10"); pq.expandPrefixes(); ASSERT_EQ(0, pq._prefixes.size()); ASSERT_EQ(1, pq._selectedVariables.size()); ASSERT_EQ(1, pq._whereClauseTriples.size()); ASSERT_EQ("10", pq._limit); ASSERT_EQ("", pq._offset); ASSERT_EQ(size_t(0), pq._orderBy.size()); ASSERT_FALSE(pq._distinct); ASSERT_FALSE(pq._reduced); pq = SparqlParser::parse( "SELECT ?x WHERE \t {?x :myrel ?y}\n" "LIMIT 10 OFFSET 15"); pq.expandPrefixes(); ASSERT_EQ(0, pq._prefixes.size()); ASSERT_EQ(1, pq._selectedVariables.size()); ASSERT_EQ(1, pq._whereClauseTriples.size()); ASSERT_EQ("10", pq._limit); ASSERT_EQ("15", pq._offset); ASSERT_EQ(size_t(0), pq._orderBy.size()); ASSERT_FALSE(pq._distinct); ASSERT_FALSE(pq._reduced); pq = SparqlParser::parse( "SELECT DISTINCT ?x ?y WHERE \t {?x :myrel ?y}\n" "ORDER BY ?y LIMIT 10 OFFSET 15"); pq.expandPrefixes(); ASSERT_EQ(0, pq._prefixes.size()); ASSERT_EQ(2, pq._selectedVariables.size()); ASSERT_EQ(1, pq._whereClauseTriples.size()); ASSERT_EQ("10", pq._limit); ASSERT_EQ("15", pq._offset); ASSERT_EQ(size_t(1), pq._orderBy.size()); ASSERT_EQ("?y", pq._orderBy[0]._key); ASSERT_FALSE(pq._orderBy[0]._desc); ASSERT_TRUE(pq._distinct); ASSERT_FALSE(pq._reduced); pq = SparqlParser::parse( "SELECT DISTINCT ?x SCORE(?x|?c) ?y WHERE \t {?x :myrel ?y}\n" "ORDER BY ASC(?y) DESC(SCORE(?x|?c)) LIMIT 10 OFFSET 15"); pq.expandPrefixes(); ASSERT_EQ(0, pq._prefixes.size()); ASSERT_EQ(3, pq._selectedVariables.size()); ASSERT_EQ("SCORE(?x|?c)", pq._selectedVariables[1]); ASSERT_EQ(1, pq._whereClauseTriples.size()); ASSERT_EQ("10", pq._limit); ASSERT_EQ("15", pq._offset); ASSERT_EQ(size_t(2), pq._orderBy.size()); ASSERT_EQ("?y", pq._orderBy[0]._key); ASSERT_FALSE(pq._orderBy[0]._desc); ASSERT_EQ("SCORE(?x|?c)", pq._orderBy[1]._key); ASSERT_TRUE(pq._orderBy[1]._desc); ASSERT_TRUE(pq._distinct); ASSERT_FALSE(pq._reduced); pq = SparqlParser::parse( "SELECT REDUCED ?x ?y WHERE \t {?x :myrel ?y}\n" "ORDER BY DESC(?x) ASC(?y) LIMIT 10 OFFSET 15"); pq.expandPrefixes(); ASSERT_EQ(0, pq._prefixes.size()); ASSERT_EQ(2, pq._selectedVariables.size()); ASSERT_EQ(1, pq._whereClauseTriples.size()); ASSERT_EQ("10", pq._limit); ASSERT_EQ("15", pq._offset); ASSERT_EQ(size_t(2), pq._orderBy.size()); ASSERT_EQ("?x", pq._orderBy[0]._key); ASSERT_TRUE(pq._orderBy[0]._desc); ASSERT_EQ("?y", pq._orderBy[1]._key); ASSERT_FALSE(pq._orderBy[1]._desc); ASSERT_FALSE(pq._distinct); ASSERT_TRUE(pq._reduced); pq = SparqlParser::parse( "SELECT ?x ?y WHERE {?x is-a Actor} LIMIT 10"); pq.expandPrefixes(); ASSERT_EQ("10", pq._limit); }