r87992 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r87991‎ | r87992 | r87993 >
Date:15:39, 13 May 2011
Author:hashar
Status:reverted (Comments)
Tags:
Comment:
Support abstraction for 'NOT IN' SQL structure

Following a live discussion with Catrope.

When using Database::makeList() in LIST_AND or LIST_OR modes, you can now
suffix the field name with an exclamation mark. It will negate the logical
boolean.

Example:
$db->makeList( array( 'field!' => array( 1,2,3 ) );
outputs:
'field' NOT IN ('1', '2', '3' );

$db->makeList( array( 'foo!' => array( 777 ) ) );
outputs:
'foo' =! 777

(note: tests not ran, please run them and ammend them)
Modified paths:
  • /trunk/phase3/includes/db/Database.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/db/DatabaseTest.php (modified) (history)

Diff [purge]

Index: trunk/phase3/tests/phpunit/includes/db/DatabaseTest.php
@@ -90,6 +90,34 @@
9191 $sql );
9292 }
9393
 94+ function testMakeNotInList() {
 95+ $this->assertEquals(
 96+ $this->db->makeList( array(
 97+ 'field' => array( 0, 1 )
 98+ ) ),
 99+ "field IN ('0','1')"
 100+ );
 101+ $this->assertEquals(
 102+ $this->db->makeList( array(
 103+ 'field!' => array( 0, 1 )
 104+ ) ),
 105+ "field NOT IN ('0','1')"
 106+ );
 107+
 108+ // make sure an array with only one value use = or !=
 109+ $this->assertEquals(
 110+ $this->db->makeList( array(
 111+ 'field' => array( 777 )
 112+ ) ),
 113+ "field = 777"
 114+ );
 115+ $this->assertEquals(
 116+ $this->db->makeList( array(
 117+ 'field!' => array( 888 )
 118+ ) ),
 119+ "field != 888"
 120+ );
 121+ }
94122 }
95123
96124
Index: trunk/phase3/includes/db/Database.php
@@ -1382,6 +1382,13 @@
13831383 * LIST_SET - comma separated with field names, like a SET clause
13841384 * LIST_NAMES - comma separated field names
13851385 *
 1386+ * In LIST_AND or LIST_OR modes, you can suffix a field with an exclamation
 1387+ * mark to generate a 'NOT IN' structure.
 1388+ * Example:
 1389+ * $db->makeList( array( 'field!' => array( 1,2,3 ) );
 1390+ * outputs:
 1391+ * 'field' NOT IN ('1', '2', '3' );
 1392+
13861393 * @return string
13871394 */
13881395 function makeList( $a, $mode = LIST_COMMA ) {
@@ -1405,6 +1412,13 @@
14061413 $first = false;
14071414 }
14081415
 1416+ // Support 'NOT IN' by suffixing fieldname with an exclamation mark
 1417+ $not = false;
 1418+ if( substr($field,-1) == '!' ) {
 1419+ $not = true;
 1420+ $field = substr($field, 0, -1 );
 1421+ }
 1422+
14091423 if ( ( $mode == LIST_AND || $mode == LIST_OR ) && is_numeric( $field ) ) {
14101424 $list .= "($value)";
14111425 } elseif ( ( $mode == LIST_SET ) && is_numeric( $field ) ) {
@@ -1417,9 +1431,12 @@
14181432 // Don't necessarily assume the single key is 0; we don't
14191433 // enforce linear numeric ordering on other arrays here.
14201434 $value = array_values( $value );
1421 - $list .= $field . " = " . $this->addQuotes( $value[0] );
 1435+
 1436+ $operator = $not ? ' != ' : ' = ';
 1437+ $list .= $field . $operator . $this->addQuotes( $value[0] );
14221438 } else {
1423 - $list .= $field . " IN (" . $this->makeList( $value ) . ") ";
 1439+ $operator = $not ? ' NOT IN ' : ' IN ';
 1440+ $list .= $field . $operator . " (" . $this->makeList( $value ) . ") ";
14241441 }
14251442 } elseif ( $value === null ) {
14261443 if ( $mode == LIST_AND || $mode == LIST_OR ) {

Sign-offs

UserFlagDate
Platonidesinspected16:09, 13 May 2011

Follow-up revisions

RevisionCommit summaryAuthorDate
r87998bug 2429 fix up index by using IN / NOT IN instead of (!= and !=)...hashar15:56, 13 May 2011
r89028* Fix db->makeList() spacing...hashar09:03, 28 May 2011
r96930Revert r87992 and followups r87998, r89028 (Support abstraction for 'NOT IN' ...demon00:19, 13 September 2011

Comments

#Comment by Nikerabbit (talk | contribs)   16:05, 13 May 2011

Can this be extended to other operations and non-array values?

#Comment by Hashar (talk | contribs)   16:42, 13 May 2011

Maybe we can hack it together this evening ? :p

#Comment by Brion VIBBER (talk | contribs)   16:54, 13 May 2011

I'm not sure I'm a fan of this; it's not very clear or obvious syntax, and we've already got to deal with using a customized query abstraction layer that nobody else in the world uses, based on the completely unlabeled order of parameters.

If using suffixes is necessary, I might actually recommend using the full operators:

 'some_field IS NOT' => null,
 'some_value !=' => 23,
 'some_ts >=' => $db->timestamp($cutoff),
 'some_ts <' => $db->timestamp($cutoff),


Unfortunately we'd be sticking an operator right next to a '=>' which looks funky. :)

#Comment by Aaron Schulz (talk | contribs)   02:08, 24 June 2011

+1 on this. Also, if you tab it in a bit, the '=>' shouldn't be too odd.

#Comment by Catrope (talk | contribs)   23:33, 13 May 2011

I ran the tests and they're fine.

#Comment by Hashar (talk | contribs)   23:34, 13 May 2011

dankeschön!

#Comment by Hashar (talk | contribs)   20:20, 24 August 2011

That revision was hacked up during the Berlin hackaton. Catrope and Krinkle found it awesome then brion raised a concern (see above).

I have sent a Request For Comment on the wikitech-l mailing list to attract more commenters/reviewers/thought:

http://permalink.gmane.org/gmane.science.linguistics.wikipedia.technical/55179

#Comment by Reedy (talk | contribs)   16:01, 2 September 2011

This is something we want to keep in MW, but I'm thinking we should just back this out of 1.18 now, and look at resolving it in trunk later?

#Comment by Hashar (talk | contribs)   10:24, 4 September 2011

I think I have used that syntax in other commits. Will have to revert them too.

Anyway, if it does no harm we can keep it in 1.18. The RFC did not raise any objection although I suspect Brion did not have a look at it (he is probably over busy).

#Comment by Reedy (talk | contribs)   12:20, 9 September 2011

Which other commits?

#Comment by 😂 (talk | contribs)   23:39, 12 September 2011

r87998 for one.

Status & tagging log