Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore.php |
— | — | @@ -29,12 +29,17 @@ |
30 | 30 | * did not match any condition. |
31 | 31 | */ |
32 | 32 | protected $m_sortfield; |
33 | | - |
34 | 33 | /** |
35 | 34 | * Global counter to prevent clashes between table aliases. |
36 | 35 | */ |
37 | | - protected $m_tablenum; |
| 36 | + static protected $m_tablenum = 0; |
| 37 | + /** |
| 38 | + * Array of names of virtual tables that hold the upper closure of certain |
| 39 | + * categories wrt. hierarchy. |
| 40 | + */ |
| 41 | + static protected $m_categorytables = array(); |
38 | 42 | |
| 43 | + |
39 | 44 | ///// Reading methods ///// |
40 | 45 | |
41 | 46 | function getSpecialValues(Title $subject, $specialprop, $requestoptions = NULL) { |
— | — | @@ -455,7 +460,7 @@ |
456 | 461 | foreach($data->getAttributes() as $attribute) { |
457 | 462 | $attributeValueArray = $data->getAttributeValues($attribute); |
458 | 463 | foreach($attributeValueArray as $value) { |
459 | | - if ($value->getXSDValue()!==false) { |
| 464 | + if ($value->isValid()) { |
460 | 465 | if ($value->getTypeID() !== 'text') { |
461 | 466 | $up_attributes[] = |
462 | 467 | array( 'subject_id' => $subject->getArticleID(), |
— | — | @@ -565,9 +570,8 @@ |
566 | 571 | */ |
567 | 572 | function getQueryResult(SMWQuery $query) { |
568 | 573 | global $smwgIQSortingEnabled; |
569 | | - |
| 574 | + |
570 | 575 | $db =& wfGetDB( DB_SLAVE ); |
571 | | - $this->m_tablenum = 0; |
572 | 576 | $prs = $query->getDescription()->getPrintrequests(); // ignore print requests at deeper levels |
573 | 577 | |
574 | 578 | // Build main query |
— | — | @@ -837,6 +841,65 @@ |
838 | 842 | } |
839 | 843 | |
840 | 844 | /** |
| 845 | + * Make a (temporary) table that contains the upper closure of the given category |
| 846 | + * wrt. the category table. |
| 847 | + */ |
| 848 | + protected function getCategoryTable($catname, &$db) { |
| 849 | + if (array_key_exists($catname, SMWSQLStore::$m_categorytables)) { |
| 850 | + return SMWSQLStore::$m_categorytables[$catname]; |
| 851 | + } |
| 852 | + |
| 853 | + global $wgDBname, $smwgIQSubcategoryInclusions; |
| 854 | + |
| 855 | + // Create multiple temporary tables for recursive computation |
| 856 | + $tablename = 'cats' . SMWSQLStore::$m_tablenum++; |
| 857 | + $db->query( 'CREATE TEMPORARY TABLE ' . $wgDBname . '.' . $tablename . |
| 858 | + '( cat_name VARCHAR(255) NOT NULL ) |
| 859 | + TYPE=MEMORY', 'SMW::getCategoryTable' ); |
| 860 | + $db->query( 'CREATE TEMPORARY TABLE smw_newcats |
| 861 | + ( cat_name VARCHAR(255) NOT NULL ) |
| 862 | + TYPE=MEMORY', 'SMW::getCategoryTable' ); |
| 863 | + $db->query( 'CREATE TEMPORARY TABLE smw_rescats |
| 864 | + ( cat_name VARCHAR(255) NOT NULL ) |
| 865 | + TYPE=MEMORY', 'SMW::getCategoryTable' ); |
| 866 | + |
| 867 | + $pagetable = $db->tableName('page'); |
| 868 | + $cltable = $db->tableName('categorylinks'); |
| 869 | + $db->insert($tablename, array('cat_name' => $catname), 'SMW::getCategoryTable'); |
| 870 | + $db->insert('smw_newcats', array('cat_name' => $catname), 'SMW::getCategoryTable'); |
| 871 | + $tmpnew='smw_newcats'; |
| 872 | + $tmpres='smw_rescats'; |
| 873 | + |
| 874 | + /// TODO: check for empty $tmpnew to abort early |
| 875 | + /// TODO: avoid duplicate results |
| 876 | + for ($i=0; $i<$smwgIQSubcategoryInclusions; $i++) { |
| 877 | + $db->insertSelect($tmpres, |
| 878 | + array($cltable,$pagetable,$tmpnew), |
| 879 | + array('cat_name' => 'page_title'), |
| 880 | + array( |
| 881 | + "$cltable.cl_to=$tmpnew.cat_name AND |
| 882 | + $pagetable.page_namespace=" . NS_CATEGORY . " AND |
| 883 | + $pagetable.page_id=$cltable.cl_from"), 'SMW::getCategoryTable'); |
| 884 | + $db->insertSelect($tablename, array($tmpnew), array('cat_name' => 'cat_name'), |
| 885 | + '*', 'SMW::getCategoryTable'); |
| 886 | + $db->insertSelect($tablename, array($tmpnew), array('cat_name' => 'cat_name'), |
| 887 | + '*', 'SMW::getCategoryTable'); |
| 888 | + $db->query('DROP TABLE ' . $tmpnew, 'SMW::getCategoryTable'); // empty "new" table |
| 889 | + $db->query( 'CREATE TEMPORARY TABLE ' . $tmpnew . ' |
| 890 | + ( cat_name VARCHAR(255) NOT NULL ) |
| 891 | + TYPE=MEMORY', 'SMW::getCategoryTable' ); |
| 892 | + $tmpname = $tmpnew; |
| 893 | + $tmpnew = $tmpres; |
| 894 | + $tmpres = $tmpname; |
| 895 | + } |
| 896 | + |
| 897 | + SMWSQLStore::$m_categorytables[$catname] = $tablename; |
| 898 | + $db->query('DROP TABLE smw_newcats', 'SMW::getCategoryTable'); |
| 899 | + $db->query('DROP TABLE smw_rescats', 'SMW::getCategoryTable'); |
| 900 | + return $tablename; |
| 901 | + } |
| 902 | + |
| 903 | + /** |
841 | 904 | * Add the table $tablename to the $from condition via an inner join, |
842 | 905 | * using the tables that are already available in $curtables (and extending |
843 | 906 | * $curtables with the new table). Return true if successful or false if it |
— | — | @@ -849,7 +912,7 @@ |
850 | 913 | } |
851 | 914 | if ($tablename == 'PAGE') { |
852 | 915 | if (array_key_exists('PREVREL', $curtables)) { // PREVREL cannot be added if not present |
853 | | - $curtables['PAGE'] = 'p' . $this->m_tablenum++; |
| 916 | + $curtables['PAGE'] = 'p' . SMWSQLStore::$m_tablenum++; |
854 | 917 | $from .= ' INNER JOIN ' . $db->tableName('page') . ' AS ' . $curtables['PAGE'] . ' ON (' . |
855 | 918 | $curtables['PAGE'] . '.page_title=' . $curtables['PREVREL'] . '.object_title AND ' . |
856 | 919 | $curtables['PAGE'] . '.page_namespace=' . $curtables['PREVREL'] . '.object_namespace)'; |
— | — | @@ -857,7 +920,7 @@ |
858 | 921 | } |
859 | 922 | } elseif ($tablename == 'CATS') { |
860 | 923 | if ($this->addInnerJoin('PAGE', $from, $db, $curtables)) { // try to add PAGE |
861 | | - $curtables['CATS'] = 'cl' . $this->m_tablenum++; |
| 924 | + $curtables['CATS'] = 'cl' . SMWSQLStore::$m_tablenum++; |
862 | 925 | $cond = $curtables['CATS'] . '.cl_from=' . $curtables['PAGE'] . '.page_id'; |
863 | 926 | // if ($smwgIQRedirectNormalization) { |
864 | 927 | // $this->addInnerJoin('REDIPAGE', $from, $db, $curtables); |
— | — | @@ -872,7 +935,7 @@ |
873 | 936 | } |
874 | 937 | } elseif ($tablename == 'RELS') { |
875 | 938 | if ($this->addInnerJoin('PAGE', $from, $db, $curtables)) { // try to add PAGE |
876 | | - $curtables['RELS'] = 'rel' . $this->m_tablenum++; |
| 939 | + $curtables['RELS'] = 'rel' . SMWSQLStore::$m_tablenum++; |
877 | 940 | $cond = $curtables['RELS'] . '.subject_id=' . $curtables['PAGE'] . '.page_id'; |
878 | 941 | // if ($smwgIQRedirectNormalization) { |
879 | 942 | // $this->addInnerJoin('REDIRECT', $from, $db, $curtables); |
— | — | @@ -886,25 +949,25 @@ |
887 | 950 | } |
888 | 951 | } elseif ($tablename == 'ATTS') { |
889 | 952 | if ($this->addInnerJoin('PAGE', $from, $db, $curtables)) { // try to add PAGE |
890 | | - $curtables['ATTS'] = 'att' . $this->m_tablenum++; |
| 953 | + $curtables['ATTS'] = 'att' . SMWSQLStore::$m_tablenum++; |
891 | 954 | $from .= ' INNER JOIN ' . $db->tableName('smw_attributes') . ' AS ' . $curtables['ATTS'] . ' ON ' . $curtables['ATTS'] . '.subject_id=' . $curtables['PAGE'] . '.page_id'; |
892 | 955 | return true; |
893 | 956 | } |
894 | 957 | } elseif ($tablename == 'TEXT') { |
895 | 958 | if ($this->addInnerJoin('PAGE', $from, $db, $curtables)) { // try to add PAGE |
896 | | - $curtables['TEXT'] = 'txt' . $this->m_tablenum++; |
| 959 | + $curtables['TEXT'] = 'txt' . SMWSQLStore::$m_tablenum++; |
897 | 960 | $from .= ' INNER JOIN ' . $db->tableName('smw_longstrings') . ' AS ' . $curtables['TEXT'] . ' ON ' . $curtables['TEXT'] . '.subject_id=' . $curtables['PAGE'] . '.page_id'; |
898 | 961 | return true; |
899 | 962 | } |
900 | 963 | } elseif ($tablename == 'REDIRECT') { |
901 | 964 | if ($this->addInnerJoin('PAGE', $from, $db, $curtables)) { // try to add PAGE |
902 | | - $curtables['REDIRECT'] = 'rd' . $this->m_tablenum++; |
| 965 | + $curtables['REDIRECT'] = 'rd' . SMWSQLStore::$m_tablenum++; |
903 | 966 | $from .= ' INNER JOIN ' . $db->tableName('redirect') . ' AS ' . $curtables['REDIRECT']; |
904 | 967 | return true; |
905 | 968 | } |
906 | 969 | } elseif ($tablename == 'REDIPAGE') { // add another copy of page for getting ids of redirect targets |
907 | 970 | if ($this->addInnerJoin('REDIRECT', $from, $db, $curtables)) { |
908 | | - $curtables['REDIPAGE'] = 'rp' . $this->m_tablenum++; |
| 971 | + $curtables['REDIPAGE'] = 'rp' . SMWSQLStore::$m_tablenum++; |
909 | 972 | $from .= ' INNER JOIN ' . $db->tableName('page') . ' AS ' . $curtables['REDIPAGE']; |
910 | 973 | return true; |
911 | 974 | } |
— | — | @@ -948,7 +1011,14 @@ |
949 | 1012 | // nothin to check |
950 | 1013 | } elseif ($description instanceof SMWClassDescription) { |
951 | 1014 | if ($this->addInnerJoin('CATS', $from, $db, $curtables)) { |
952 | | - $where .= $curtables['CATS'] . '.cl_to=' . $db->addQuotes($description->getCategory()->getDBKey()); |
| 1015 | + global $smwgIQSubcategoryInclusions; |
| 1016 | + if ($smwgIQSubcategoryInclusions > 0) { |
| 1017 | + $ct = $this->getCategoryTable($description->getCategory()->getDBKey(), $db); |
| 1018 | + $ctalias = 'cl' . SMWSQLStore::$m_tablenum++; |
| 1019 | + $from .= " INNER JOIN $ct AS $ctalias ON $ctalias.cat_name=" . $curtables['CATS'] . '.cl_to'; |
| 1020 | + } else { |
| 1021 | + $where .= $curtables['CATS'] . '.cl_to=' . $db->addQuotes($description->getCategory()->getDBKey()); |
| 1022 | + } |
953 | 1023 | } |
954 | 1024 | } elseif ($description instanceof SMWNamespaceDescription) { |
955 | 1025 | if ($this->addInnerJoin('PAGE', $from, $db, $curtables)) { |