r63268 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r63267‎ | r63268 | r63269 >
Date:09:57, 5 March 2010
Author:mkroetzsch
Status:deferred
Tags:
Comment:
Partly fixed geo coordinates' distance queries to not litter the core SMW store with super-slow custom SQL queries;
removed distance parameter, as its implementation was a brute force hack that violates the architecture of querying
(by making a parameter that is specific to one query condition global for the whole query, and passing it around in
partly undeclared class member variables that are then read somewhere deep within the SQL generation code) and which
thus could not be included into the cleaned-up extendible architectur implemented now. A better way for setting the
distance per query condition will be introduced in future versions, but there is no rescue for the old code.
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_GlobalFunctions.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Query.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Query.php
@@ -44,7 +44,6 @@
4545 protected $m_inline; // query used inline? (required for finding right default parameters)
4646 protected $m_concept; // query used in concept? (required for finding right default parameters)
4747 protected $m_extraprintouts = array(); // SMWPrintoutRequest objects supplied outside querystring
48 - protected $m_distance = 5; // default is 5 miles
4948
5049 /**
5150 * Constructor.
@@ -155,15 +154,6 @@
156155 return $this->m_limit;
157156 }
158157
159 - public function setDistance($distance) {
160 - $this->m_distance = $distance;
161 - return $this->m_distance;
162 - }
163 -
164 - public function getDistance() {
165 - return $this->m_distance;
166 - }
167 -
168158 /**
169159 * Apply structural restrictions to the current description.
170160 */
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php
@@ -179,7 +179,6 @@
180180 $this->m_hierarchies = array();
181181 $this->m_querylog = array();
182182 $this->m_errors = array();
183 - $this->m_distance = $query->getDistance();
184183 SMWSQLStore2Query::$qnum = 0;
185184 $this->m_sortkeys = $query->sortkeys;
186185
@@ -596,7 +595,6 @@
597596 * Given an SMWDescription that is just a conjunction or disjunction of
598597 * SMWValueDescription objects, create and return a plain WHERE condition
599598 * string for it.
600 - * @bug The geo distance code is not secure. Disabled for now.
601599 */
602600 protected function compileAttributeWhere($query, SMWDescription $description, $proptable, $valueindex, $operator = 'AND') {
603601 $where = '';
@@ -616,20 +614,16 @@
617615 case SMW_CMP_GEQ: $comp = '>='; break;
618616 case SMW_CMP_NEQ: $comp = '!='; break;
619617 case SMW_CMP_LIKE:
620 - if ($dv->getTypeID() == '_geo') { ///FIXME Insecure code that uses DB contents unescaped in SQL. Disabled for now.
621 -// $comp = '<=';
622 -// $geoarray = explode(",", $value);
623 -// if ((count($geoarray) == 2) && ($geoarray[0] != '') && ($geoarray[1] != '')) {
624 -// $field = "ROUND(((ACOS( SIN($geoarray[0] * PI()/180 ) * SIN(SUBSTRING_INDEX($field, ',',1) * PI()/180 ) + COS($geoarray[0] * PI()/180 ) * COS(SUBSTRING_INDEX($field, ',',1) * PI()/180 ) * COS(($geoarray[1] - SUBSTRING_INDEX($field, ',',-1)) * PI()/180))*180/PI())*60*1.1515),6)";
625 -// }
626 -// $value = $this->m_distance;
627 - } elseif ( ($fieldtype == 't') || ($fieldtype == 'l') ) { // string data allows pattern matches
 618+ /// TODO: explicitly excluding _geo here is a temporary workaround. Future versions will use peronalised comparators for extensions and not LIKE (requires synchronisation with SemanticMaps to work)
 619+ if ( ($dv->getTypeID() != '_geo') && ( ($fieldtype == 't') || ($fieldtype == 'l') ) ) { // string data allows pattern matches
628620 $comp = ' LIKE ';
629621 $value = str_replace(array('%', '_', '*', '?'), array('\%', '\_', '%', '_'), $value); // translate pattern
630622 }
631623 break;
632624 }
633 - if ($comp != '') {
 625+ if ($comp == '') { // allow extensions to define their own query conditions
 626+ wfRunHooks( 'smwGetSQLConditionForValue', array(&$where, $description, $query->alias, $fieldname, $this->m_dbs) );
 627+ } else {
634628 $where = "{$query->alias}.{$fieldname}{$comp}" . $this->m_dbs->addQuotes($value);
635629 }
636630 }
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php
@@ -22,27 +22,6 @@
2323 const CONCEPT_DESC = 2; // query for concept definition
2424
2525 /**
26 - * Handle the 'distance' parameter, used for location-based queries
27 - */
28 - static function setQueryDistance($distance, &$query) {
29 - $dist_components = explode(' ', $distance);
30 - if (count($dist_components) != 2) return;
31 - $dist_num = $dist_components[0]; //str_replace(",", "", $dist2[0]);
32 - if (! is_numeric($dist_num) || $dist_num < 0) return;
33 - $dist_unit = $dist_components[1];
34 - $metric_units = array("km", "kms", "kilometer", "kilometers", "kilometre", "kilometres", "KM", "KMS", "Kilometer", "Kilometers", "Kilometre", "Kilometres");
35 - $english_units = array("mile", "mi", "miles", "mis", "Mile", "Miles", "MI", "MIS");
36 - if (! in_array($dist_unit, $metric_units) && ! in_array($dist_unit, $english_units))
37 - return;
38 - // if we're still here, set the distance - it's computed as
39 - // a number of miles
40 - if (in_array($dist_unit, $metric_units)) {
41 - $dist_num *= .621371192;
42 - }
43 - $query->setDistance($dist_num);
44 - }
45 -
46 - /**
4726 * Parse a query string given in SMW's query language to create
4827 * an SMWQuery. Parameters are given as key-value-pairs in the
4928 * given array. The parameter $context defines in what context the
@@ -134,11 +113,6 @@
135114 $orders = array();
136115 }
137116 reset($orders);
138 - // get distance to search for location-based queries
139 - if ( array_key_exists('distance', $params) ) {
140 - $distance = trim($params['distance']);
141 - self::setQueryDistance( $distance, $query );
142 - }
143117
144118 if ( array_key_exists('sort', $params) ) {
145119 $query->sort = true;
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_GlobalFunctions.php
@@ -90,16 +90,15 @@
9191 // The dot tells that the domain is not complete. It will be completed
9292 // in the Export since we do not want to create a title object here when
9393 // it is not needed in many cases.
94 - if ($namespace === null)
95 - {
 94+ if ($namespace === null) {
9695 $namespace = $wgServerName;
9796 }
98 -
9997 if ( !$complete && ($smwgNamespace !== '') ) {
10098 $smwgNamespace = '.' . $namespace;
10199 } else {
102100 $smwgNamespace = $namespace;
103101 }
 102+
104103 $wgExtensionFunctions[] = 'smwfSetupExtension';
105104 // FIXME: Can be removed when new style magic words are used (introduced in r52503)
106105 $wgHooks['LanguageGetMagic'][] = 'smwfAddMagicWords'; // setup names for parser functions (needed here)
@@ -107,6 +106,8 @@
108107
109108 $wgHooks['ParserTestTables'][] = 'smwfOnParserTestTables';
110109 $wgHooks['AdminLinks'][] = 'smwfAddToAdminLinks';
 110+ // this will move to Semantic Maps in future releases:
 111+ $wgHooks['smwGetSQLConditionForValue'][] = 'smwfGetGeoProximitySQLCondition';
111112
112113 // Register special pages aliases file
113114 $wgExtensionAliasesFiles['SemanticMediaWiki'] = $smwgIP . '/languages/SMW_Aliases.php';
@@ -328,6 +329,28 @@
329330 return true;
330331 }
331332
 333+/**
 334+ * Custom SQL query extension for matching geographic coordinates.
 335+ * This hook will be moved to Semantic Maps in the next release.
 336+ * @todo Parsing latitude and longitude from the DB key of the coordinates
 337+ * value is cleary not a good approach. Instead, the geographic coordinate
 338+ * value object should provide functions to access this data directly.
 339+ */
 340+function smwfGetGeoProximitySQLCondition(&$where, $description, $tablename, $fieldname, $dbs) {
 341+ $where = '';
 342+ $dv = $description->getDatavalue();
 343+ if ( ($dv->getTypeID() != '_geo') || (!$dv->isValid()) || ($description->getComparator() != SMW_CMP_LIKE) ) return true; // only act on certain query conditions
 344+ $keys = $dv->getDBkeys();
 345+ $geoarray = explode(",", $keys[0]);
 346+ if ((count($geoarray) != 2) || ($geoarray[0] == '') || ($geoarray[1] == '')) return true; // something went wrong
 347+ $latitude = $dbs->addQuotes($geoarray[0]);
 348+ $longitude = $dbs->addQuotes($geoarray[1]);
 349+ // compute distances in miles:
 350+ $distance = "ROUND(((ACOS( SIN({$latitude} * PI()/180 ) * SIN(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) + COS({$latitude} * PI()/180 ) * COS(SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',1) * PI()/180 ) * COS(({$longitude} - SUBSTRING_INDEX({$tablename}.{$fieldname}, ',',-1)) * PI()/180))*180/PI())*60*1.1515),6)";
 351+ $where = "{$distance} <= " . $dbs->addQuotes("5");
 352+ return true;
 353+}
 354+
332355 /**********************************************/
333356 /***** namespace settings *****/
334357 /**********************************************/

Status & tagging log