[wp-trac] [WordPress Trac] #29642: Support complex (nested, multiple relation) queries in WP_Meta_Query

WordPress Trac noreply at wordpress.org
Fri Sep 12 13:20:52 UTC 2014


#29642: Support complex (nested, multiple relation) queries in WP_Meta_Query
--------------------------------+-----------------------------
 Reporter:  boonebgorges        |      Owner:
     Type:  enhancement         |     Status:  new
 Priority:  normal              |  Milestone:  Awaiting Review
Component:  Options, Meta APIs  |    Version:
 Severity:  normal              |   Keywords:
  Focuses:                      |
--------------------------------+-----------------------------
 The syntax of `WP_Meta_Query` currently limits the kind of queries you can
 use it for. It's only possible to use a single 'relation', which means
 that you can do a string of clauses connected by OR or AND. But you can't
 group these clauses together and use a mix of relations, which makes it
 impossible to do something like, say:

 {{{
 SELECT posts WHERE (
     ( foo = bar AND foo1 = bar )
     OR
     ( foo = baz AND foo1 = baz )
     OR
     foo = barry
 )
 }}}

 I propose a restructuring of WP_Meta_Query so that it accepts arbitrary
 nested queries. For example, the pseudocode above would be represented as
 a meta_query argument that looks like this:

 {{{
 array(
     'relation' => 'OR',
     array(
         'relation' => 'AND',
         array(
             'key' => 'foo',
             'value' => 'bar',
         ),
         array(
             'key' => 'foo1',
             'value' => 'bar',
         ),
     ),
     array(
         'relation' => 'AND',
         array(
             'key' => 'foo',
             'value' => 'baz',
         ),
         array(
             'key' => 'foo1',
             'value' => 'baz',
         ),
     ),
     array(
         'key' => 'foo',
         'value' => 'barry',
     ),
 ),
 }}}

 The attached patch is a first pass at this restructuring. A few notes:

 - Syntax for current queries is unchanged, as is the SQL that's generated.
 This means that backward compatibility should be maintained in all cases
 (though see below for some very edge-case questions). I've also included
 all optimizations that have been baked into WP_Meta_Query over the years
 (such as #19729).

 - The attached patch contains simple unit tests for the new functionality.
 All existing unit tests are also passing. The extended unit test suite for
 WP_Meta_Query is also fully passing (#29560), with the exception of a
 couple very minor syntax quibbles that should not reflect any changes in
 functionality.

 - One fairly significant change in the internal SQL-building logic is that
 I've broken EXISTS queries out into their own block. Currently, EXISTS
 falls back on keyless '=' queries in a pretty opaque way; my change does
 not change the SQL that results, but I think it makes the code much
 clearer.

 - I have changed some of the codestyling of the SQL generated by the
 class. I've normalized the indentation so that the nesting is clear when
 debugging, eg

 {{{
 WHERE (
     ( meta_key = 'foo' AND meta_value = 'bar' )
     OR
     ( meta_key = 'foo1' AND meta_value = 'bar' )
 )
 }}}

 I also normalized the spaces around the parentheses in the SQL being
 generated. It's possible that these minor codestyling changes will affect
 plugins that are performing certain kinds of string operations on the
 'get_meta_sql' filter (think - `explode( "\n", $sql['where'] )` ). I can
 roll back these formatting changes to eliminate the possibility of issues
 with these sorts of plugins, but I figured that the increase in usability
 might be worth the tradeoff in this case.

 See #20312 for a related request that was closed as wontfix.

 Feedback welcome.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/29642>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list