1<?php 2require_once('strataquerytest.inc.php'); 3 4/** 5 * Tests queries. 6 * 7 * @group plugin_strata 8 * @group plugins 9 */ 10class query_test extends Strata_Query_UnitTestCase { 11 12 function setup() { 13 parent::setup(); 14 15 $this->_isPerson = array ( 16 'type' => 'triple', 17 'subject' => array ( 18 'type' => 'variable', 19 'text' => 'p' 20 ), 21 'predicate' => array ( 22 'type' => 'literal', 23 'text' => 'class' 24 ), 25 'object' => array ( 26 'type' => 'literal', 27 'text' => 'person' 28 ) 29 ); 30 $this->_personBob = array ( 31 'type' => 'triple', 32 'subject' => array ( 33 'type' => 'variable', 34 'text' => 'p' 35 ), 36 'predicate' => array ( 37 'type' => 'literal', 38 'text' => 'name' 39 ), 40 'object' => array ( 41 'type' => 'literal', 42 'text' => 'Bob' 43 ) 44 ); 45 $this->_personAlice = array ( 46 'type' => 'triple', 47 'subject' => array ( 48 'type' => 'variable', 49 'text' => 'p' 50 ), 51 'predicate' => array ( 52 'type' => 'literal', 53 'text' => 'name' 54 ), 55 'object' => array ( 56 'type' => 'literal', 57 'text' => 'Alice' 58 ) 59 ); 60 $this->_personCarol = array ( 61 'type' => 'triple', 62 'subject' => array ( 63 'type' => 'variable', 64 'text' => 'p' 65 ), 66 'predicate' => array ( 67 'type' => 'literal', 68 'text' => 'name' 69 ), 70 'object' => array ( 71 'type' => 'literal', 72 'text' => 'Carol' 73 ) 74 ); 75 $this->_bobUnionAlice = array ( 76 'type' => 'union', 77 'lhs' => $this->_personBob, 78 'rhs' => $this->_personAlice 79 ); 80 $this->_personRating = array ( 81 'type' => 'triple', 82 'subject' => array ( 83 'type' => 'variable', 84 'text' => 'p' 85 ), 86 'predicate' => array ( 87 'type' => 'literal', 88 'text' => 'is rated' 89 ), 90 'object' => array ( 91 'type' => 'variable', 92 'text' => 'rating' 93 ) 94 ); 95 $this->_personKnows = array ( 96 'type' => 'triple', 97 'subject' => array ( 98 'type' => 'variable', 99 'text' => 'p' 100 ), 101 'predicate' => array ( 102 'type' => 'literal', 103 'text' => 'knows' 104 ), 105 'object' => array ( 106 'type' => 'variable', 107 'text' => 'knows' 108 ) 109 ); 110 $this->_personLikes = array ( 111 'type' => 'triple', 112 'subject' => array ( 113 'type' => 'variable', 114 'text' => 'p' 115 ), 116 'predicate' => array ( 117 'type' => 'literal', 118 'text' => 'likes' 119 ), 120 'object' => array ( 121 'type' => 'variable', 122 'text' => 'likes' 123 ) 124 ); 125 $this->_ratingMinusCarol = array ( 126 'type' => 'minus', 127 'lhs' => $this->_personRating, 128 'rhs' => $this->_personCarol 129 ); 130 $this->_knowsOptionalLikes = array ( 131 'type' => 'optional', 132 'lhs' => $this->_personKnows, 133 'rhs' => $this->_personLikes 134 ); 135 } 136 137 function testAllPersonsOnce() { 138 $query = array ( 139 'type' => 'select', 140 'grouping'=>array(), 141 'group' => array ( 142 'type' => 'and', 143 'lhs' => array ( 144 'type' => 'and', 145 'lhs' => array ( 146 'type' => 'and', 147 'lhs' => array ( 148 'type' => 'and', 149 'lhs' => $this->_isPerson, 150 'rhs' => array ( 151 'type' => 'triple', 152 'subject' => array ( 153 'type' => 'variable', 154 'text' => 'p' 155 ), 156 'predicate' => array ( 157 'type' => 'literal', 158 'text' => 'looks like' 159 ), 160 'object' => array ( 161 'type' => 'variable', 162 'text' => 'img' 163 ) 164 ) 165 ), 166 'rhs' => $this->_personRating 167 ), 168 'rhs' => array ( 169 'type' => 'triple', 170 'subject' => array ( 171 'type' => 'variable', 172 'text' => 'p' 173 ), 174 'predicate' => array ( 175 'type' => 'literal', 176 'text' => 'has length' 177 ), 178 'object' => array ( 179 'type' => 'variable', 180 'text' => 'length' 181 ) 182 ) 183 ), 184 'rhs' => array ( 185 'type' => 'triple', 186 'subject' => array ( 187 'type' => 'variable', 188 'text' => 'p' 189 ), 190 'predicate' => array ( 191 'type' => 'literal', 192 'text' => 'tax rate' 193 ), 194 'object' => array ( 195 'type' => 'variable', 196 'text' => 'tax' 197 ) 198 ) 199 ), 200 'projection' => array ( 201 'p', 202 'img', 203 'rating', 204 'length', 205 'tax' 206 ), 207 'ordering' => array ( 208 array ( 209 'variable' => 'p', 210 'direction' => 'asc' 211 ) 212 ) 213 ); 214 215 $expected = array ( 216 array ( 217 'p' => array('person:alice'), 218 'img' => array('50:alice.svg'), 219 'rating' => array('10'), 220 'length' => array('5 ft 5 in'), 221 'tax' => array('10%') 222 ), 223 array ( 224 'p' => array('person:bob'), 225 'img' => array('50:bob.png'), 226 'rating' => array('8'), 227 'length' => array('5 ft 10 in'), 228 'tax' => array('25%') 229 ), 230 array ( 231 'p' => array('person:carol'), 232 'img' => array('50:carol.jpg'), 233 'rating' => array('1'), 234 'length' => array('4 ft 11 in'), 235 'tax' => array('2%') 236 ) 237 ); 238 239 $this->assertQueryResult($query, $expected); 240 } 241 242 function testAllPersons() { 243 $query = array ( 244 'type' => 'select', 245 'grouping'=>array(), 246 'group' => array ( 247 'type' => 'and', 248 'lhs' => array ( 249 'type' => 'and', 250 'lhs' => array ( 251 'type' => 'and', 252 'lhs' => array ( 253 'type' => 'and', 254 'lhs' => array ( 255 'type' => 'and', 256 'lhs' => $this->_isPerson, 257 'rhs' => $this->_personKnows 258 ), 259 'rhs' => array ( 260 'type' => 'triple', 261 'subject' => array ( 262 'type' => 'variable', 263 'text' => 'p' 264 ), 265 'predicate' => array ( 266 'type' => 'literal', 267 'text' => 'looks like' 268 ), 269 'object' => array ( 270 'type' => 'variable', 271 'text' => 'img' 272 ) 273 ) 274 ), 275 'rhs' => $this->_personRating 276 ), 277 'rhs' => array ( 278 'type' => 'triple', 279 'subject' => array ( 280 'type' => 'variable', 281 'text' => 'p' 282 ), 283 'predicate' => array ( 284 'type' => 'literal', 285 'text' => 'has length' 286 ), 287 'object' => array ( 288 'type' => 'variable', 289 'text' => 'length' 290 ) 291 ) 292 ), 293 'rhs' => array ( 294 'type' => 'triple', 295 'subject' => array ( 296 'type' => 'variable', 297 'text' => 'p' 298 ), 299 'predicate' => array ( 300 'type' => 'literal', 301 'text' => 'tax rate' 302 ), 303 'object' => array ( 304 'type' => 'variable', 305 'text' => 'tax' 306 ) 307 ) 308 ), 309 'projection' => array ( 310 'p', 311 'knows', 312 'img', 313 'rating', 314 'length', 315 'tax' 316 ), 317 'ordering' => array ( 318 array ( 319 'variable' => 'p', 320 'direction' => 'desc' 321 ), 322 array ( 323 'variable' => 'knows', 324 'direction' => 'asc' 325 ) 326 ) 327 ); 328 329 $expected = array ( 330 array ( 331 'p' => array('person:carol'), 332 'knows' => array('person:alice'), 333 'img' => array('50:carol.jpg'), 334 'rating' => array('1'), 335 'length' => array('4 ft 11 in'), 336 'tax' => array('2%') 337 ), 338 array ( 339 'p' => array('person:carol'), 340 'knows' => array('person:bob'), 341 'img' => array('50:carol.jpg'), 342 'rating' => array('1'), 343 'length' => array('4 ft 11 in'), 344 'tax' => array('2%') 345 ), 346 array ( 347 'p' => array('person:bob'), 348 'knows' => array('person:alice'), 349 'img' => array('50:bob.png'), 350 'rating' => array('8'), 351 'length' => array('5 ft 10 in'), 352 'tax' => array('25%') 353 ), 354 array ( 355 'p' => array('person:alice'), 356 'knows' => array('person:carol'), 357 'img' => array('50:alice.svg'), 358 'rating' => array('10'), 359 'length' => array('5 ft 5 in'), 360 'tax' => array('10%') 361 ) 362 ); 363 364 $this->assertQueryResult($query, $expected); 365 } 366 367 function testAllPersonsExceptBob() { 368 // All persons except Bob 369 $query = array ( 370 'type' => 'select', 371 'grouping'=>array(), 372 'group' => array ( 373 'type' => 'minus', 374 'lhs' => $this->_isPerson, 375 'rhs' => $this->_personBob 376 ), 377 'projection' => array ( 378 'p' 379 ), 380 'ordering' => array ( 381 array ( 382 'variable' => 'p', 383 'direction' => 'asc' 384 ) 385 ) 386 ); 387 388 $expected = array ( 389 array ( 390 'p' => array('person:alice') 391 ), 392 array ( 393 'p' => array('person:carol') 394 ) 395 ); 396 397 $this->assertQueryResult($query, $expected); 398 } 399 400 function testAllPersonsThatKnowAlice() { 401 // All persons that know Alice 402 $query = array ( 403 'type' => 'select', 404 'grouping'=>array(), 405 'group' => array ( 406 'type' => 'and', 407 'lhs' => array ( 408 'type' => 'and', 409 'lhs' => $this->_isPerson, 410 'rhs' => array ( 411 'type' => 'triple', 412 'subject' => array ( 413 'type' => 'variable', 414 'text' => 'p' 415 ), 416 'predicate' => array ( 417 'type' => 'literal', 418 'text' => 'knows' 419 ), 420 'object' => array ( 421 'type' => 'variable', 422 'text' => 'relation' 423 ) 424 ) 425 ), 426 'rhs' => array ( 427 'type' => 'triple', 428 'subject' => array ( 429 'type' => 'variable', 430 'text' => 'relation' 431 ), 432 'predicate' => array ( 433 'type' => 'literal', 434 'text' => 'name' 435 ), 436 'object' => array ( 437 'type' => 'literal', 438 'text' => 'Alice' 439 ) 440 ) 441 ), 442 'projection' => array ( 443 'p' 444 ), 445 'ordering' => array ( 446 array ( 447 'variable' => 'p', 448 'direction' => 'asc' 449 ) 450 ) 451 ); 452 453 $expected = array ( 454 array ( 455 'p' => array('person:bob') 456 ), 457 array ( 458 'p' => array('person:carol') 459 ) 460 ); 461 462 $this->assertQueryResult($query, $expected); 463 } 464 465 function testAllPersonsRelatedToAlice() { 466 // All persons having some relation with Alice 467 $query = array ( 468 'type' => 'select', 469 'grouping'=>array(), 470 'group' => array ( 471 'type' => 'and', 472 'lhs' => array ( 473 'type' => 'and', 474 'lhs' => $this->_isPerson, 475 'rhs' => array ( 476 'type' => 'triple', 477 'subject' => array ( 478 'type' => 'variable', 479 'text' => 'p' 480 ), 481 'predicate' => array ( 482 'type' => 'variable', 483 'text' => 'relationWith' 484 ), 485 'object' => array ( 486 'type' => 'variable', 487 'text' => 'relation' 488 ) 489 ) 490 ), 491 'rhs' => array ( 492 'type' => 'triple', 493 'subject' => array ( 494 'type' => 'variable', 495 'text' => 'relation' 496 ), 497 'predicate' => array ( 498 'type' => 'literal', 499 'text' => 'name' 500 ), 501 'object' => array ( 502 'type' => 'literal', 503 'text' => 'Alice' 504 ) 505 ) 506 ), 507 'projection' => array ( 508 'p', 509 'relationWith' 510 ), 511 'ordering' => array ( 512 array ( 513 'variable' => 'p', 514 'direction' => 'asc' 515 ) 516 ) 517 ); 518 519 $expected = array ( 520 array ( 521 'p' => array('person:bob'), 522 'relationWith' => array('knows') 523 ), 524 array ( 525 'p' => array('person:bob'), 526 'relationWith' => array('likes') 527 ), 528 array ( 529 'p' => array('person:carol'), 530 'relationWith' => array('knows') 531 ) 532 ); 533 534 $this->assertQueryResult($query, $expected); 535 } 536 537 function testAllPersonsAndRelationWithAlice() { 538 // All persons, including their relation with Alice 539 $query = array ( 540 'type' => 'select', 541 'grouping'=>array(), 542 'group' => array ( 543 'type' => 'optional', 544 'lhs' => $this->_isPerson, 545 'rhs' => array ( 546 'type' => 'and', 547 'lhs' => array ( 548 'type' => 'triple', 549 'subject' => array ( 550 'type' => 'variable', 551 'text' => 'p' 552 ), 553 'predicate' => array ( 554 'type' => 'variable', 555 'text' => 'relationWith' 556 ), 557 'object' => array ( 558 'type' => 'variable', 559 'text' => 'relation' 560 ) 561 ), 562 'rhs' => array ( 563 'type' => 'triple', 564 'subject' => array ( 565 'type' => 'variable', 566 'text' => 'relation' 567 ), 568 'predicate' => array ( 569 'type' => 'literal', 570 'text' => 'name' 571 ), 572 'object' => array ( 573 'type' => 'literal', 574 'text' => 'Alice' 575 ) 576 ) 577 ) 578 ), 579 'projection' => array ( 580 'p', 581 'relationWith' 582 ), 583 'ordering' => array ( 584 array ( 585 'variable' => 'p', 586 'direction' => 'asc' 587 ) 588 ) 589 ); 590 591 $expected = array ( 592 array ( 593 'p' => array('person:alice'), 594 'relationWith' => array() 595 ), 596 array ( 597 'p' => array('person:bob'), 598 'relationWith' => array('knows') 599 ), 600 array ( 601 'p' => array('person:bob'), 602 'relationWith' => array('likes') 603 ), 604 array ( 605 'p' => array('person:carol'), 606 'relationWith' => array('knows') 607 ) 608 ); 609 610 $this->assertQueryResult($query, $expected); 611 } 612 613 function testAllPersonsAndSpecialRelationWithAlice() { 614 // All persons, including their relation with Alice (unless this relation is 'knows') 615 $query = array ( 616 'type' => 'select', 617 'grouping'=>array(), 618 'group' => array ( 619 'type' => 'optional', 620 'lhs' => $this->_isPerson, 621 'rhs' => array ( 622 'type' => 'filter', 623 'lhs' => array ( 624 'type' => 'and', 625 'lhs' => array ( 626 'type' => 'triple', 627 'subject' => array ( 628 'type' => 'variable', 629 'text' => 'p' 630 ), 631 'predicate' => array ( 632 'type' => 'variable', 633 'text' => 'relationWith' 634 ), 635 'object' => array ( 636 'type' => 'variable', 637 'text' => 'relation' 638 ) 639 ), 640 'rhs' => array ( 641 'type' => 'triple', 642 'subject' => array ( 643 'type' => 'variable', 644 'text' => 'relation' 645 ), 646 'predicate' => array ( 647 'type' => 'literal', 648 'text' => 'name' 649 ), 650 'object' => array ( 651 'type' => 'literal', 652 'text' => 'Alice' 653 ) 654 ) 655 ), 656 'rhs' => array ( 657 array ( 658 'type' => 'filter', 659 'lhs' => array ( 660 'type' => 'variable', 661 'text' => 'relationWith' 662 ), 663 'operator' => '!=', 664 'rhs' => array ( 665 'type' => 'literal', 666 'text' => 'knows' 667 ) 668 ) 669 ) 670 ) 671 ), 672 'projection' => array ( 673 'p', 674 'relationWith' 675 ), 676 'ordering' => array ( 677 array ( 678 'variable' => 'p', 679 'direction' => 'asc' 680 ) 681 ) 682 ); 683 684 $expected = array ( 685 array ( 686 'p' => array('person:alice'), 687 'relationWith' => array() 688 ), 689 array ( 690 'p' => array('person:bob'), 691 'relationWith' => array('likes') 692 ), 693 array ( 694 'p' => array('person:carol'), 695 'relationWith' => array() 696 ) 697 ); 698 699 $this->assertQueryResult($query, $expected); 700 } 701 702 function testAllPersonsSpecialRelationWithAlice() { 703 // All persons having a relation with Alice that is not 'knows' 704 $query = array ( 705 'type' => 'select', 706 'grouping'=>array(), 707 'group' => array ( 708 'type' => 'filter', 709 'lhs' => array ( 710 'type' => 'and', 711 'lhs' => array ( 712 'type' => 'and', 713 'lhs' => $this->_isPerson, 714 'rhs' => array ( 715 'type' => 'triple', 716 'subject' => array ( 717 'type' => 'variable', 718 'text' => 'p' 719 ), 720 'predicate' => array ( 721 'type' => 'variable', 722 'text' => 'relationWith' 723 ), 724 'object' => array ( 725 'type' => 'variable', 726 'text' => 'relation' 727 ) 728 ) 729 ), 730 'rhs' => array ( 731 'type' => 'triple', 732 'subject' => array ( 733 'type' => 'variable', 734 'text' => 'relation' 735 ), 736 'predicate' => array ( 737 'type' => 'literal', 738 'text' => 'name' 739 ), 740 'object' => array ( 741 'type' => 'literal', 742 'text' => 'Alice' 743 ) 744 ) 745 ), 746 'rhs' => array ( 747 array ( 748 'type' => 'filter', 749 'lhs' => array ( 750 'type' => 'variable', 751 'text' => 'relationWith' 752 ), 753 'operator' => '!=', 754 'rhs' => array ( 755 'type' => 'literal', 756 'text' => 'knows' 757 ) 758 ) 759 ) 760 ), 761 'projection' => array ( 762 'p', 763 'relationWith' 764 ), 765 'ordering' => array ( 766 array ( 767 'variable' => 'p', 768 'direction' => 'asc' 769 ) 770 ) 771 ); 772 773 $expected = array ( 774 array ( 775 'p' => array('person:bob'), 776 'relationWith' => array('likes') 777 ) 778 ); 779 780 $this->assertQueryResult($query, $expected); 781 } 782 783 function testBobUnionAlice() { 784 $query = array ( 785 'type' => 'select', 786 'grouping'=>array(), 787 'group' => $this->_bobUnionAlice, 788 'projection' => array ( 789 'p' 790 ), 791 'ordering' => array ( 792 array ( 793 'variable' => 'p', 794 'direction' => 'asc' 795 ) 796 ) 797 ); 798 799 $expected = array ( 800 array ( 801 'p' => array('person:alice') 802 ), 803 array ( 804 'p' => array('person:bob') 805 ) 806 ); 807 808 $this->assertQueryResult($query, $expected); 809 } 810 811 function testBobUnionAliceWithRating() { 812 $query = array ( 813 'type' => 'select', 814 'grouping'=>array(), 815 'group' => array ( 816 'type' => 'union', 817 'lhs' => array ( 818 'type' => 'and', 819 'lhs' => $this->_personBob, 820 'rhs' => $this->_personRating 821 ), 822 'rhs' => array ( 823 'type' => 'and', 824 'lhs' => $this->_personAlice, 825 'rhs' => $this->_personRating 826 ), 827 ), 828 'projection' => array ( 829 'p', 830 'rating' 831 ), 832 'ordering' => array ( 833 array ( 834 'variable' => 'p', 835 'direction' => 'asc' 836 ) 837 ) 838 ); 839 840 $expected = array ( 841 array ( 842 'p' => array('person:alice'), 843 'rating' => array('10') 844 ), 845 array ( 846 'p' => array('person:bob'), 847 'rating' => array('8') 848 ) 849 ); 850 851 $this->assertQueryResult($query, $expected); 852 } 853 854 function testCarolUnionBobUnionAlice() { 855 $query = array ( 856 'type' => 'select', 857 'grouping'=>array(), 858 'group' => array ( 859 'type' => 'union', 860 'lhs' => $this->_personCarol, 861 'rhs' => $this->_bobUnionAlice 862 ), 863 'projection' => array ( 864 'p' 865 ), 866 'ordering' => array ( 867 array ( 868 'variable' => 'p', 869 'direction' => 'asc' 870 ) 871 ) 872 ); 873 874 $expected = array ( 875 array ( 876 'p' => array('person:alice') 877 ), 878 array ( 879 'p' => array('person:bob') 880 ), 881 array ( 882 'p' => array('person:carol') 883 ) 884 ); 885 886 $this->assertQueryResult($query, $expected); 887 } 888 889 function testBobUnionBobUnionAlice() { 890 $query = array ( 891 'type' => 'select', 892 'grouping'=>array(), 893 'group' => array ( 894 'type' => 'union', 895 'lhs' => $this->_personBob, 896 'rhs' => $this->_bobUnionAlice 897 ), 898 'projection' => array ( 899 'p' 900 ), 901 'ordering' => array ( 902 array ( 903 'variable' => 'p', 904 'direction' => 'asc' 905 ) 906 ) 907 ); 908 909 $expected = array ( 910 array ( 911 'p' => array('person:alice') 912 ), 913 array ( 914 'p' => array('person:bob') 915 ) 916 ); 917 918 $this->assertQueryResult($query, $expected); 919 } 920 921 function testCarolUnionBobUnionAliceMinusBob() { 922 $query = array ( 923 'type' => 'select', 924 'grouping'=>array(), 925 'group' => array ( 926 'type' => 'union', 927 'lhs' => $this->_personCarol, 928 'rhs' => array ( 929 'type' => 'minus', 930 'lhs' => $this->_bobUnionAlice, 931 'rhs' => $this->_personBob 932 ) 933 ), 934 'projection' => array ( 935 'p' 936 ), 937 'ordering' => array ( 938 array ( 939 'variable' => 'p', 940 'direction' => 'asc' 941 ) 942 ) 943 ); 944 945 $expected = array ( 946 array ( 947 'p' => array('person:alice') 948 ), 949 array ( 950 'p' => array('person:carol') 951 ) 952 ); 953 954 $this->assertQueryResult($query, $expected); 955 } 956 957 function testBobUnionAliceOptionalRating() { 958 $query = array ( 959 'type' => 'select', 960 'grouping'=>array(), 961 'group' => array ( 962 'type' => 'union', 963 'lhs' => $this->_personBob, 964 'rhs' => array ( 965 'type' => 'optional', 966 'lhs' => $this->_personAlice, 967 'rhs' => $this->_personRating 968 ) 969 ), 970 'projection' => array ( 971 'p', 972 'rating' 973 ), 974 'ordering' => array ( 975 array ( 976 'variable' => 'p', 977 'direction' => 'asc' 978 ) 979 ) 980 ); 981 982 $expected = array ( 983 array ( 984 'p' => array('person:alice'), 985 'rating' => array('10') 986 ), 987 array ( 988 'p' => array('person:bob'), 989 'rating' => array() 990 ) 991 ); 992 993 $this->assertQueryResult($query, $expected); 994 } 995 996 function testPersonOptionalKnowsAndLikes() { 997 $query = array ( 998 'type' => 'select', 999 'grouping'=>array(), 1000 'group' => array ( 1001 'type' => 'optional', 1002 'lhs' => $this->_isPerson, 1003 'rhs' => array ( 1004 'type' => 'and', 1005 'lhs' => $this->_personKnows, 1006 'rhs' => $this->_personLikes 1007 ) 1008 ), 1009 'projection' => array ( 1010 'p', 1011 'knows', 1012 'likes' 1013 ), 1014 'ordering' => array ( 1015 array ( 1016 'variable' => 'p', 1017 'direction' => 'asc' 1018 ) 1019 ) 1020 ); 1021 1022 $expected = array ( 1023 array ( 1024 'p' => array('person:alice'), 1025 'knows' => array(), 1026 'likes' => array() 1027 ), 1028 array ( 1029 'p' => array('person:bob'), 1030 'knows' => array('person:alice'), 1031 'likes' => array('person:alice') 1032 ), 1033 array ( 1034 'p' => array('person:carol'), 1035 'knows' => array(), 1036 'likes' => array() 1037 ) 1038 ); 1039 1040 $this->assertQueryResult($query, $expected); 1041 } 1042 1043 function testPersonOptionalKnowsOptionalLikes() { 1044 $query = array ( 1045 'type' => 'select', 1046 'grouping'=>array(), 1047 'group' => array ( 1048 'type' => 'optional', 1049 'lhs' => $this->_isPerson, 1050 'rhs' => $this->_knowsOptionalLikes 1051 ), 1052 'projection' => array ( 1053 'p', 1054 'knows', 1055 'likes' 1056 ), 1057 'ordering' => array ( 1058 array ( 1059 'variable' => 'p', 1060 'direction' => 'asc' 1061 ), 1062 array ( 1063 'variable' => 'knows', 1064 'direction' => 'asc' 1065 ) 1066 ) 1067 ); 1068 1069 $expected = array ( 1070 array ( 1071 'p' => array('person:alice'), 1072 'knows' => array('person:carol'), 1073 'likes' => array() 1074 ), 1075 array ( 1076 'p' => array('person:bob'), 1077 'knows' => array('person:alice'), 1078 'likes' => array('person:alice') 1079 ), 1080 array ( 1081 'p' => array('person:carol'), 1082 'knows' => array('person:alice'), 1083 'likes' => array() 1084 ), 1085 array ( 1086 'p' => array('person:carol'), 1087 'knows' => array('person:bob'), 1088 'likes' => array() 1089 ) 1090 ); 1091 1092 $this->assertQueryResult($query, $expected); 1093 } 1094 1095 function testPersonOptionalRatingUnionLikes() { 1096 $query = array ( 1097 'type' => 'select', 1098 'grouping'=>array(), 1099 'group' => array ( 1100 'type' => 'optional', 1101 'lhs' => $this->_isPerson, 1102 'rhs' => array ( 1103 'type' => 'union', 1104 'lhs' => $this->_personRating, 1105 'rhs' => array ( 1106 'type' => 'and', 1107 'lhs' => array ( 1108 'type' => 'triple', 1109 'subject' => array ( 1110 'type' => 'variable', 1111 'text' => 'p' 1112 ), 1113 'predicate' => array ( 1114 'type' => 'literal', 1115 'text' => 'likes' 1116 ), 1117 'object' => array ( 1118 'type' => 'variable', 1119 'text' => 'rating' 1120 ) 1121 ), 1122 'rhs' => array ( 1123 'type' => 'triple', 1124 'subject' => array ( 1125 'type' => 'variable', 1126 'text' => 'p' 1127 ), 1128 'predicate' => array ( 1129 'type' => 'literal', 1130 'text' => 'likes' 1131 ), 1132 'object' => array ( 1133 'type' => 'variable', 1134 'text' => 'likes' 1135 ) 1136 ) 1137 ) 1138 ) 1139 ), 1140 'projection' => array ( 1141 'p', 1142 'rating' 1143 ), 1144 'ordering' => array ( 1145 array ( 1146 'variable' => 'p', 1147 'direction' => 'asc' 1148 ), 1149 array ( 1150 'variable' => 'likes', 1151 'direction' => 'desc' 1152 ) 1153 ) 1154 ); 1155 1156 $expected = array ( 1157 array ( 1158 'p' => array('person:alice'), 1159 'rating' => array('10') 1160 ), 1161 array ( 1162 'p' => array('person:bob'), 1163 'rating' => array('person:alice') 1164 ), 1165 array ( 1166 'p' => array('person:bob'), 1167 'rating' => array('8') 1168 ), 1169 array ( 1170 'p' => array('person:carol'), 1171 'rating' => array('1') 1172 ) 1173 ); 1174 1175 $this->assertQueryResult($query, $expected); 1176 } 1177 1178 function testPersonOptionalRatingMinusCarol() { 1179 $query = array ( 1180 'type' => 'select', 1181 'grouping'=>array(), 1182 'group' => array ( 1183 'type' => 'optional', 1184 'lhs' => $this->_isPerson, 1185 'rhs' => $this->_ratingMinusCarol 1186 ), 1187 'projection' => array ( 1188 'p', 1189 'rating' 1190 ), 1191 'ordering' => array ( 1192 array ( 1193 'variable' => 'p', 1194 'direction' => 'asc' 1195 ) 1196 ) 1197 ); 1198 1199 $expected = array ( 1200 array ( 1201 'p' => array('person:alice'), 1202 'rating' => array('10') 1203 ), 1204 array ( 1205 'p' => array('person:bob'), 1206 'rating' => array('8') 1207 ), 1208 array ( 1209 'p' => array('person:carol'), 1210 'rating' => array() 1211 ) 1212 ); 1213 1214 $this->assertQueryResult($query, $expected); 1215 } 1216 1217 function testPersonMinusBobUnionAlice() { 1218 $query = array ( 1219 'type' => 'select', 1220 'grouping'=>array(), 1221 'group' => array ( 1222 'type' => 'minus', 1223 'lhs' => $this->_isPerson, 1224 'rhs' => $this->_bobUnionAlice 1225 ), 1226 'projection' => array ( 1227 'p' 1228 ), 1229 'ordering' => array ( 1230 array ( 1231 'variable' => 'p', 1232 'direction' => 'asc' 1233 ) 1234 ) 1235 ); 1236 1237 $expected = array ( 1238 array ( 1239 'p' => array('person:carol') 1240 ) 1241 ); 1242 1243 $this->assertQueryResult($query, $expected); 1244 } 1245 1246 function testPersonMinusRatingMinusCarol() { 1247 $query = array ( 1248 'type' => 'select', 1249 'grouping'=>array(), 1250 'group' => array ( 1251 'type' => 'minus', 1252 'lhs' => $this->_isPerson, 1253 'rhs' => $this->_ratingMinusCarol 1254 ), 1255 'projection' => array ( 1256 'p' 1257 ), 1258 'ordering' => array ( 1259 array ( 1260 'variable' => 'p', 1261 'direction' => 'asc' 1262 ) 1263 ) 1264 ); 1265 1266 $expected = array ( 1267 array ( 1268 'p' => array('person:carol') 1269 ) 1270 ); 1271 1272 $this->assertQueryResult($query, $expected); 1273 } 1274 1275 function testPersonAndRatingMinusCarol() { 1276 $query = array ( 1277 'type' => 'select', 1278 'grouping'=>array(), 1279 'group' => array ( 1280 'type' => 'and', 1281 'lhs' => $this->_isPerson, 1282 'rhs' => $this->_ratingMinusCarol 1283 ), 1284 'projection' => array ( 1285 'p', 1286 'rating' 1287 ), 1288 'ordering' => array ( 1289 array ( 1290 'variable' => 'p', 1291 'direction' => 'asc' 1292 ) 1293 ) 1294 ); 1295 1296 $expected = array ( 1297 array ( 1298 'p' => array('person:alice'), 1299 'rating' => array('10') 1300 ), 1301 array ( 1302 'p' => array('person:bob'), 1303 'rating' => array('8') 1304 ) 1305 ); 1306 1307 $this->assertQueryResult($query, $expected); 1308 } 1309 1310 function testPersonAndBobUnionAlice() { 1311 $query = array ( 1312 'type' => 'select', 1313 'grouping'=>array(), 1314 'group' => array ( 1315 'type' => 'and', 1316 'lhs' => $this->_isPerson, 1317 'rhs' => $this->_bobUnionAlice 1318 ), 1319 'projection' => array ( 1320 'p' 1321 ), 1322 'ordering' => array ( 1323 array ( 1324 'variable' => 'p', 1325 'direction' => 'asc' 1326 ) 1327 ) 1328 ); 1329 1330 $expected = array ( 1331 array ( 1332 'p' => array('person:alice') 1333 ), 1334 array ( 1335 'p' => array('person:bob') 1336 ) 1337 ); 1338 1339 $this->assertQueryResult($query, $expected); 1340 } 1341 1342 function testPersonAndKnowsOptionalLikes() { 1343 $query = array ( 1344 'type' => 'select', 1345 'grouping'=>array(), 1346 'group' => array ( 1347 'type' => 'and', 1348 'lhs' => $this->_isPerson, 1349 'rhs' => $this->_knowsOptionalLikes 1350 ), 1351 'projection' => array ( 1352 'p', 1353 'knows', 1354 'likes' 1355 ), 1356 'ordering' => array ( 1357 array ( 1358 'variable' => 'p', 1359 'direction' => 'asc' 1360 ), 1361 array ( 1362 'variable' => 'knows', 1363 'direction' => 'asc' 1364 ) 1365 ) 1366 ); 1367 1368 $expected = array ( 1369 array ( 1370 'p' => array('person:alice'), 1371 'knows' => array('person:carol'), 1372 'likes' => array() 1373 ), 1374 array ( 1375 'p' => array('person:bob'), 1376 'knows' => array('person:alice'), 1377 'likes' => array('person:alice') 1378 ), 1379 array ( 1380 'p' => array('person:carol'), 1381 'knows' => array('person:alice'), 1382 'likes' => array() 1383 ), 1384 array ( 1385 'p' => array('person:carol'), 1386 'knows' => array('person:bob'), 1387 'likes' => array() 1388 ) 1389 ); 1390 1391 $this->assertQueryResult($query, $expected); 1392 } 1393 1394 function testVariableNames() { 1395 // Strange strings as variable names 1396 $query = array ( 1397 'type' => 'select', 1398 'grouping'=>array(), 1399 'group' => array ( 1400 'type' => 'and', 1401 'lhs' => array ( 1402 'type' => 'and', 1403 'lhs' => array ( 1404 'type' => 'triple', 1405 'subject' => array ( 1406 'type' => 'variable', 1407 'text' => '_' 1408 ), 1409 'predicate' => array ( 1410 'type' => 'literal', 1411 'text' => 'class' 1412 ), 1413 'object' => array ( 1414 'type' => 'variable', 1415 'text' => '?c' 1416 ), 1417 ), 1418 'rhs' => array ( 1419 'type' => 'and', 1420 'lhs' => array ( 1421 'type' => 'triple', 1422 'subject' => array ( 1423 'type' => 'variable', 1424 'text' => '_' 1425 ), 1426 'predicate' => array ( 1427 'type' => 'literal', 1428 'text' => 'name' 1429 ), 1430 'object' => array ( 1431 'type' => 'variable', 1432 'text' => 'given name' 1433 ), 1434 ), 1435 'rhs' => array ( 1436 'type' => 'triple', 1437 'subject' => array ( 1438 'type' => 'variable', 1439 'text' => '_' 1440 ), 1441 'predicate' => array ( 1442 'type' => 'literal', 1443 'text' => 'knows' 1444 ), 1445 'object' => array ( 1446 'type' => 'variable', 1447 'text' => '2 knów \'`"' 1448 ) 1449 ) 1450 ) 1451 ), 1452 'rhs' => array ( 1453 'type' => 'and', 1454 'lhs' => array ( 1455 'type' => 'and', 1456 'lhs' => array ( 1457 'type' => 'triple', 1458 'subject' => array ( 1459 'type' => 'variable', 1460 'text' => '_' 1461 ), 1462 'predicate' => array ( 1463 'type' => 'literal', 1464 'text' => 'has length' 1465 ), 1466 'object' => array ( 1467 'type' => 'variable', 1468 'text' => ':l' 1469 ), 1470 ), 1471 'rhs' => array ( 1472 'type' => 'triple', 1473 'subject' => array ( 1474 'type' => 'variable', 1475 'text' => '_' 1476 ), 1477 'predicate' => array ( 1478 'type' => 'literal', 1479 'text' => 'tax rate' 1480 ), 1481 'object' => array ( 1482 'type' => 'variable', 1483 'text' => '%t' 1484 ) 1485 ) 1486 ), 1487 'rhs' => array ( 1488 'type' => 'and', 1489 'lhs' => array ( 1490 'type' => 'triple', 1491 'subject' => array ( 1492 'type' => 'variable', 1493 'text' => '_' 1494 ), 1495 'predicate' => array ( 1496 'type' => 'literal', 1497 'text' => 'is rated' 1498 ), 1499 'object' => array ( 1500 'type' => 'variable', 1501 'text' => '1.10' 1502 ), 1503 ), 1504 'rhs' => array ( 1505 'type' => 'triple', 1506 'subject' => array ( 1507 'type' => 'variable', 1508 'text' => '_' 1509 ), 1510 'predicate' => array ( 1511 'type' => 'literal', 1512 'text' => 'looks like' 1513 ), 1514 'object' => array ( 1515 'type' => 'variable', 1516 'text' => ' \\ like ""! ' 1517 ) 1518 ) 1519 ) 1520 ) 1521 ), 1522 'projection' => array ( 1523 '_', 1524 '?c', 1525 'given name', 1526 '2 knów \'`"', 1527 ':l', 1528 '%t', 1529 '1.10', 1530 ' \\ like ""! ' 1531 ), 1532 'ordering' => array ( 1533 array ( 1534 'variable' => '_', 1535 'direction' => 'asc' 1536 ), 1537 array ( 1538 'variable' => '2 knów \'`"', 1539 'direction' => 'asc' 1540 ) 1541 ) 1542 ); 1543 1544 $expected = array ( 1545 array ( 1546 '_' => array('person:alice'), 1547 '?c' => array('person'), 1548 'given name' => array('Alice'), 1549 '2 knów \'`"' => array('person:carol'), 1550 ':l' => array('5 ft 5 in'), 1551 '%t' => array('10%'), 1552 '1.10' => array('10'), 1553 ' \\ like ""! ' => array('50:alice.svg') 1554 ), 1555 array ( 1556 '_' => array('person:bob'), 1557 '?c' => array('person'), 1558 'given name' => array('Bob'), 1559 '2 knów \'`"' => array('person:alice'), 1560 ':l' => array('5 ft 10 in'), 1561 '%t' => array('25%'), 1562 '1.10' => array('8'), 1563 ' \\ like ""! ' => array('50:bob.png') 1564 ), 1565 array ( 1566 '_' => array('person:carol'), 1567 '?c' => array('person'), 1568 'given name' => array('Carol'), 1569 '2 knów \'`"' => array('person:alice'), 1570 ':l' => array('4 ft 11 in'), 1571 '%t' => array('2%'), 1572 '1.10' => array('1'), 1573 ' \\ like ""! ' => array('50:carol.jpg') 1574 ), 1575 array ( 1576 '_' => array('person:carol'), 1577 '?c' => array('person'), 1578 'given name' => array('Carol'), 1579 '2 knów \'`"' => array('person:bob'), 1580 ':l' => array('4 ft 11 in'), 1581 '%t' => array('2%'), 1582 '1.10' => array('1'), 1583 ' \\ like ""! ' => array('50:carol.jpg') 1584 ) 1585 ); 1586 1587 $this->assertQueryResult($query, $expected); 1588 } 1589 1590 function testGrouping() { 1591 $query = array ( 1592 'type' => 'select', 1593 'grouping' => array ( 1594 'knows', 1595 'rating' 1596 ), 1597 'group' => array ( 1598 'type' => 'and', 1599 'lhs' => array ( 1600 'type' => 'and', 1601 'lhs' => array ( 1602 'type' => 'and', 1603 'lhs' => array ( 1604 'type' => 'and', 1605 'lhs' => $this->_isPerson, 1606 'rhs' => $this->_personKnows 1607 ), 1608 'rhs' => array ( 1609 'type' => 'triple', 1610 'subject' => array ( 1611 'type' => 'variable', 1612 'text' => 'knows' 1613 ), 1614 'predicate' => array ( 1615 'type' => 'literal', 1616 'text' => 'knows' 1617 ), 1618 'object' => array ( 1619 'type' => 'variable', 1620 'text' => 'who knows' 1621 ) 1622 ) 1623 ), 1624 'rhs' => $this->_personRating 1625 ), 1626 'rhs' => array ( 1627 'type' => 'triple', 1628 'subject' => array ( 1629 'type' => 'variable', 1630 'text' => 'knows' 1631 ), 1632 'predicate' => array ( 1633 'type' => 'literal', 1634 'text' => 'identifier' 1635 ), 1636 'object' => array ( 1637 'type' => 'variable', 1638 'text' => 'knows id' 1639 ) 1640 ) 1641 ), 1642 'projection' => array ( 1643 'p', 1644 'knows id', 1645 'who knows', 1646 ), 1647 'ordering' => array ( 1648 array ( 1649 'variable' => 'rating', 1650 'direction' => 'desc' 1651 ), 1652 array ( 1653 'variable' => 'knows', 1654 'direction' => 'asc' 1655 ), 1656 array ( 1657 'variable' => 'who knows', 1658 'direction' => 'asc' 1659 ) 1660 ) 1661 ); 1662 1663 $expected = array ( 1664 array ( 1665 'p' => array('person:alice', 'person:alice'), 1666 'knows id' => array('γ', 'γ'), 1667 'who knows' => array('person:alice', 'person:bob'), 1668 ), 1669 array ( 1670 'p' => array('person:bob'), 1671 'knows id' => array('α'), 1672 'who knows' => array('person:carol'), 1673 ), 1674 array ( 1675 'p' => array('person:carol'), 1676 'knows id' => array('α'), 1677 'who knows' => array('person:carol'), 1678 ), 1679 array ( 1680 'p' => array('person:carol'), 1681 'knows id' => array('Β'), 1682 'who knows' => array('person:alice'), 1683 ) 1684 ); 1685 1686 $this->assertQueryResult($query, $expected); 1687 } 1688} 1689 1690