jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/363178 )
Change subject: Add feature for WITHIN and HOLDS WITHIN for hierarchy fields
......................................................................
Add feature for WITHIN and HOLDS WITHIN for hierarchy fields
This commit adds support for querying data using WITHIN (for single valued
hierarchy fields)
and HOLDS WITHIN (for list hierarchy fields).
Change-Id: I35819da62c9ecc8dfdb5081188ec6269de19dbe2
---
M CargoSQLQuery.php
1 file changed, 128 insertions(+), 4 deletions(-)
Approvals:
Yaron Koren: Looks good to me, approved
jenkins-bot: Verified
diff --git a/CargoSQLQuery.php b/CargoSQLQuery.php
index 82a5337..04817bd 100644
--- a/CargoSQLQuery.php
+++ b/CargoSQLQuery.php
@@ -64,6 +64,7 @@
$sqlQuery->mGroupByStr = $sqlQuery->mOrigGroupByStr;
$sqlQuery->mHavingStr = $havingStr;
$sqlQuery->setDescriptionsForFields();
+ $sqlQuery->handleHierarchyFields();
$sqlQuery->handleVirtualFields();
$sqlQuery->handleVirtualCoordinateFields();
$sqlQuery->handleDateFields();
@@ -669,7 +670,8 @@
$virtualFields[] = array(
'fieldName' =>
$fieldName,
'tableAlias' =>
$tableAlias,
- 'tableName' =>
$tableName
+ 'tableName' =>
$tableName,
+ 'isHierarchy' =>
$fieldDescription->mIsHierarchy
);
}
}
@@ -682,6 +684,7 @@
$fieldName = $virtualField['fieldName'];
$tableAlias = $virtualField['tableAlias'];
$tableName = $virtualField['tableName'];
+ $isHierarchy = $virtualField['isHierarchy'];
$fieldTableName = $tableName . '__' . $fieldName;
$fieldTableAlias = $tableAlias . '__' . $fieldName;
@@ -727,9 +730,15 @@
$fieldReplaced);
if ( preg_match( $patternSimple[$i],
$this->mWhereStr ) ) {
- throw new MWException( "Error:
operator for the virtual field '" .
- "$tableName.$fieldName'
must be 'HOLDS', 'HOLDS NOT', '" .
- "HOLDS LIKE' or 'HOLDS
NOT LIKE'." );
+ if ( $isHierarchy ) {
+ throw new MWException(
"Error: operator for the hierarchy field '" .
+
"$tableName.$fieldName' must be 'HOLDS', 'HOLDS NOT', '" .
+ "HOLDS WITHIN',
'HOLDS LIKE' or 'HOLDS NOT LIKE'." );
+ } else {
+ throw new MWException(
"Error: operator for the virtual field '" .
+
"$tableName.$fieldName' must be 'HOLDS', 'HOLDS NOT', '" .
+ "HOLDS LIKE' or
'HOLDS NOT LIKE'." );
+ }
}
}
}
@@ -1032,6 +1041,121 @@
}
/**
+ * Handles Hierarchy fields' "WHERE" operations
+ */
+ function handleHierarchyFields() {
+ // "where" - make sure that if
+ // "WITHIN" (if not list) or "HOLDS WITHIN" (if
list)
+ // is specified, then translate the clause
accordingly.
+ // other translations in case of List fields,
+ // are handled by handleVirtualFields().
+
+ // First, create an array of the hierarchy fields in the
+ // current set of tables.
+ $hierarchyFields = array();
+ foreach ( $this->mTableSchemas as $tableName => $tableSchema ) {
+ foreach ( $tableSchema->mFieldDescriptions as
$fieldName => $fieldDescription ) {
+ if ( !$fieldDescription->mIsHierarchy ) {
+ continue;
+ }
+ foreach ( $this->mAliasedTableNames as
$tableAlias => $tableName2 ) {
+ if ( $tableName == $tableName2 ) {
+ $hierarchyFields[] = array(
+ 'fieldName' =>
$fieldName,
+ 'tableAlias' =>
$tableAlias,
+ 'tableName' =>
$tableName,
+ 'isList'=>
$fieldDescription->mIsList
+ );
+ }
+ }
+ }
+ }
+
+ // "where"
+ foreach ( $hierarchyFields as $hierarchyField ) {
+ $fieldName = $hierarchyField['fieldName'];
+ $tableName = $hierarchyField['tableName'];
+ $tableAlias = $hierarchyField['tableAlias'];
+ $fieldIsList = $hierarchyField['isList'];
+
+ $patternSimple = array(
+ CargoUtils::getSQLTableAndFieldPattern(
$tableAlias, $fieldName ),
+ CargoUtils::getSQLFieldPattern( $fieldName )
+ );
+ $patternRootArray = array(
+ CargoUtils::getSQLTableAndFieldPattern(
$tableAlias, $fieldName, false ),
+ CargoUtils::getSQLFieldPattern( $fieldName,
false )
+ );
+
+ $simpleMatch = false;
+ $completeMatch = false;
+ $patternRoot = "";
+
+ if ( preg_match( $patternSimple[0], $this->mWhereStr )
) {
+ $simpleMatch = true;
+ $patternRoot = $patternRootArray[0];
+ } elseif ( preg_match( $patternSimple[1],
$this->mWhereStr ) ) {
+ $simpleMatch = true;
+ $patternRoot = $patternRootArray[1];
+ }
+ // else we don't have current field in WHERE clause
+
+ if ( !$simpleMatch ) {
+ continue;
+ }
+ $patternSuffix = '([\'"]?[^\'"]*[\'"]?)/i'; // To
capture string in quotes or a number
+ $hierarchyTable = $this->mCargoDB->tableName(
$tableName . '__' . $fieldName . '__hierarchy' );
+ $fieldTableName = $this->mCargoDB->tableName(
$tableName . '__' . $fieldName );
+ $completeSearchPattern = "";
+ $matches = array();
+ $newWhere = "";
+
+ if ( preg_match( $patternRoot . '(\s+HOLDS WITHIN\s+)'
. $patternSuffix, $this->mWhereStr, $matches ) ) {
+ if ( !$fieldIsList ) {
+ throw new MWException( "Error: \"HOLDS
WITHIN\" cannot be used for single hierarchy field, use \"WITHIN\" instead." );
+ }
+ $completeMatch = true;
+ $completeSearchPattern = $patternRoot .
'(\s+HOLDS WITHIN\s+)' . $patternSuffix;
+ if ( count( $matches ) != 4 || $matches[3] ===
"" ) {
+ throw new MWException( "Error: Please
specify a value for \"HOLDS WITHIN\"");
+ }
+ $withinValue = $matches[3];
+ $subquery = "( SELECT _value FROM
$hierarchyTable WHERE " .
+ "_left >= ( SELECT _left FROM
$hierarchyTable WHERE _value = $withinValue ) AND " .
+ "_right <= ( SELECT _right FROM
$hierarchyTable WHERE _value = $withinValue ) " .
+ ")";
+ $subquery = "( SELECT DISTINCT( _rowID ) FROM
$fieldTableName WHERE _value IN " . $subquery . " )";
+ $newWhere = " " . $tableName . "._ID" . " IN "
. $subquery;
+ }
+
+ if ( preg_match( $patternRoot . '(\s+WITHIN\s+)' .
$patternSuffix, $this->mWhereStr, $matches ) ) {
+ if ( $fieldIsList ) {
+ throw new MWException( "Error:
\"WITHIN\" cannot be used for list hierarchy field, use \"HOLDS WITHIN\"
instead." );
+ }
+ $completeMatch = true;
+ $completeSearchPattern = $patternRoot .
'(\s+WITHIN\s+)' . $patternSuffix;
+ if ( count( $matches ) != 4 || $matches[3] ===
"" ) {
+ throw new MWException( "Error: Please
specify a value for \"WITHIN\"");
+ }
+ $withinValue = $matches[3];
+ $subquery = "( SELECT _value FROM
$hierarchyTable WHERE " .
+ "_left >= ( SELECT _left FROM
$hierarchyTable WHERE _value = $withinValue ) AND " .
+ "_right <= ( SELECT _right FROM
$hierarchyTable WHERE _value = $withinValue ) " .
+ ")";
+ $newWhere = " " . $fieldName . " IN " .
$subquery;
+ }
+
+ if ( $completeMatch ) {
+ $this->substVirtualFieldName( $this->mWhereStr,
$completeSearchPattern, $newWhere, $fieldReplaced);
+ $this->mWhereStr = preg_replace(
$completeSearchPattern, $newWhere, $this->mWhereStr );
+ }
+
+ // In case fieldIsList === true, there is a possibility
of more Query commands.
+ // like "HOLDS" and "HOLDS LIKE", that is handled by
handleVirtualFields()
+ }
+ }
+
+ /**
* Returns the number of degrees of both latitude and longitude that
* correspond to the passed-in distance (in either kilometers or
* miles), based on the passed-in latitude. (Longitude doesn't matter
--
To view, visit https://gerrit.wikimedia.org/r/363178
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I35819da62c9ecc8dfdb5081188ec6269de19dbe2
Gerrit-PatchSet: 10
Gerrit-Project: mediawiki/extensions/Cargo
Gerrit-Branch: master
Gerrit-Owner: Fz-29 <[email protected]>
Gerrit-Reviewer: Fz-29 <[email protected]>
Gerrit-Reviewer: Nischayn22 <[email protected]>
Gerrit-Reviewer: Oetterer <[email protected]>
Gerrit-Reviewer: Yaron Koren <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits