Ed Hoo has uploaded a new change for review. https://gerrit.wikimedia.org/r/260951
Change subject: Fix HOLDS operator parsing and adds corresponding NOT functionality ...................................................................... Fix HOLDS operator parsing and adds corresponding NOT functionality The expanded functionality enables HOLDS to be used as follows: Author HOLDS "John Smith" Author HOLDS NOT "Jane Smith" Author HOLDS LIKE "% Smith" Author HOLDS NOT LIKE "% Johnson" Book.Author HOLDS "John Smith" Book.Author HOLDS NOT "Jane Smith" Book.Author HOLDS LIKE "% Smith" Book.Author HOLDS NOT LIKE "% Johnson" Change-Id: I46f3e052901420f0c6d68c6291b16b52299d43f5 --- M CargoSQLQuery.php 1 file changed, 62 insertions(+), 41 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Cargo refs/changes/51/260951/1 diff --git a/CargoSQLQuery.php b/CargoSQLQuery.php index 23722ee..c892f2e 100644 --- a/CargoSQLQuery.php +++ b/CargoSQLQuery.php @@ -558,6 +558,22 @@ return false; } + /* + * Provides HOLDS functionality to WHERE clause by replacing $pattern + * in $subject with $replacement and setting $found to true if + * successful (leaves it untouched otehrwise). Includes modifying + * the regex beginning from a non-valid identifier character to word + * boundary. + */ + function substVirtualFieldName( &$subject, $pattern, $replacement, &$found ) { + if ( preg_match( $pattern, $subject ) ) { + $pattern = str_replace( '([^\w$]|^)', '\b', $pattern); + $pattern = str_replace( '([^\w$.]|^)', '\b', $pattern); + $subject = preg_replace( $pattern, $replacement, $subject ); + $found = true; + } + } + function handleVirtualFields() { // The array-field alias can be found in a number of different // clauses. Handling depends on which clause it is: @@ -592,38 +608,57 @@ foreach ( $virtualFields as $virtualField ) { $fieldName = $virtualField['fieldName']; $tableName = $virtualField['tableName']; - $foundLikeMatch1 = $foundMatch1 = $foundLikeMatch2 = $foundMatch2 = false; - $likePattern1 = $likePattern2 = ''; - $patternSuffix = '\s+(HOLDS)\s+(LIKE)?/i'; + $fieldTableName = $tableName . '__' . $fieldName; + $replacementFieldName = $fieldTableName . '._value'; + $patternSuffix = '\b\s*/i'; + $fieldReplaced = false; $throwException = false; - $simplePattern1 = CargoUtils::getSQLTableAndFieldPattern( $tableName, $fieldName ); - if ( preg_match( $simplePattern1, $this->mWhereStr ) ) { - $likePattern1 = CargoUtils::getSQLTableAndFieldPattern( $tableName, $fieldName, false ). - $patternSuffix; - if ( preg_match( $likePattern1, $this->mWhereStr, $matches ) ) { - $foundMatch1 = count( $matches ) == 3; - $foundLikeMatch1 = count( $matches ) == 4; + $patternSimple = array( + CargoUtils::getSQLTableAndFieldPattern( $tableName, $fieldName ), + CargoUtils::getSQLFieldPattern( $fieldName ) + ); + $patternRoot = array( + CargoUtils::getSQLTableAndFieldPattern( $tableName, $fieldName, false ) . '\s+', + CargoUtils::getSQLFieldPattern( $fieldName, false ) . '\s+' + ); + + for ( $i = 0 ; $i < 2 ; $i++ ) { + if ( preg_match( $patternSimple[$i], $this->mWhereStr ) ) { + + $this->substVirtualFieldName( + $this->mWhereStr, + $patternRoot[$i] . 'HOLDS\s+NOT\s+LIKE' . $patternSuffix, + "$replacementFieldName NOT LIKE ", + $fieldReplaced); + + $this->substVirtualFieldName( + $this->mWhereStr, + $patternRoot[$i] . 'HOLDS\s+LIKE' . $patternSuffix, + "$replacementFieldName LIKE ", + $fieldReplaced); + + $this->substVirtualFieldName( + $this->mWhereStr, + $patternRoot[$i] . 'HOLDS\s+NOT' . $patternSuffix, + "$replacementFieldName!=", + $fieldReplaced); + + $this->substVirtualFieldName( + $this->mWhereStr, + $patternRoot[$i] . 'HOLDS' . $patternSuffix, + "$replacementFieldName=", + $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'." ); + } } - $throwException = $throwException || (! $foundMatch1 && ! $foundLikeMatch1); - } - $simplePattern2 = CargoUtils::getSQLFieldPattern( $fieldName ); - if ( preg_match( $simplePattern2, $this->mWhereStr ) ) { - $likePattern2 = CargoUtils::getSQLFieldPattern( $fieldName, false ). - $patternSuffix; - if ( preg_match( $likePattern2, $this->mWhereStr, $matches ) ) { - $foundMatch2 = count( $matches ) == 3; - $foundLikeMatch2 = count( $matches ) == 4; - } - $throwException = $throwException || (! $foundMatch2 && ! $foundLikeMatch2); - } - if ( $throwException ) { - throw new MWException( "Error: operator for the virtual field '" . - "$tableName.$fieldName' must be 'HOLDS' or 'HOLDS LIKE'." ); } - if ( $foundLikeMatch1 || $foundLikeMatch2 || $foundMatch1 || $foundMatch2 ) { - $fieldTableName = $tableName . '__' . $fieldName; + if ( $fieldReplaced ) { $this->addFieldTableToTableNames( $fieldTableName, $tableName ); $this->mCargoJoinConds[] = array( 'joinType' => 'LEFT OUTER JOIN', @@ -632,20 +667,6 @@ 'table2' => $fieldTableName, 'field2' => '_rowID' ); - $likePattern1 = str_replace( '([^\w$.]|^)', '\b', $likePattern1); - $likePattern2 = str_replace( '([^\w$.]|^)', '\b', $likePattern2); - - if ( $foundLikeMatch1 ) { - $this->mWhereStr = preg_replace( $likePattern1, "$fieldTableName._value LIKE ", - $this->mWhereStr ); - } elseif ( $foundLikeMatch2 ) { - $this->mWhereStr = preg_replace( $likePattern2, "$fieldTableName._value LIKE ", - $this->mWhereStr ); - } elseif ( $foundMatch1 ) { - $this->mWhereStr = preg_replace( $likePattern1, "$fieldTableName._value=", $this->mWhereStr ); - } elseif ( $foundMatch2 ) { - $this->mWhereStr = preg_replace( $likePattern2, "$fieldTableName._value=", $this->mWhereStr ); - } } } -- To view, visit https://gerrit.wikimedia.org/r/260951 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I46f3e052901420f0c6d68c6291b16b52299d43f5 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Cargo Gerrit-Branch: master Gerrit-Owner: Ed Hoo <edward....@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits