This can be used everywhere in an SQL query where boolean operations are used.
Currently, this can only be used in the WHERE and the JOINs' ON clause.
Initially, I'm intending on trying it just on the WHERE clause.
The main and general use-cases are:
- To flexibly the build of the WHERE clause in SQL queries
- To ease, simplify and prevent errors when doing SQL query editing by phpBB's extensions
- Doctrine dbal -> The issue with Doctrine dbal is that it's query builder is not ready for the 2nd major use case listed above. There is no way of altering an SQL query. If you want to alter something, you have to rebuild the whole SQL query. I also didn't find a way to know the currently build query except for getting the query built so far as a string.
- Linq -> I didn't know the assistance of Linq until today. From what I searched, not only it has the same issue as Doctrine, while also its interface is unnecessarily complex for the common folk who just wants to change a small amount of information.
Quick guide on how to use
This builder uses a tree-like information organization for the boolean comparisons.
Now, there are 3 types of arrays:
- A
- B
- C
The A type contains 3 elements:
Left hand, operator, right hand.
E.g.
Code: Select all
array('f.forum_id', '=', 1)
array('f.forum_id', '<>', 1)
array('f.forum_id', 'IN', array())
array('f.forum_id', 'IN', array(1,2,5,6,7))
array('f.forum_id', 'NOT_IN', array(1,2,5,6,7))
array('f.forum_id', 'IS', NULL)
Left hand, operator, sub query operator, sub query SELECT type, the sub query.
This is essentially a recursive call to sql_build_query() to parse that sub-tree which is the sub query.
Code: Select all
array('f.forum_id', '=', 'ANY', 'SELECT', array(
'SELECT' => array(/*...*/),
'FROM' => array(/*...*/),
)
)
array('f.forum_id', '', 'IN', 'SELECT', array(
'SELECT' => array(/*...*/),
'FROM' => array(/*...*/),
)
)
The C type which contains a boolean operator to apply to all other elements which are either A or B or C type:
Code: Select all
array('OR',
array('t.forum_id', '=', 3),
array('t.topic_type', '=', 0),
)
array('AND',
array('t.forum_id', '=', 3),
array('t.topic_type', '=', 0),
array('t.topic_id', '>', 5),
array('t.topic_poster', '<>', 5),
),
array('AND',
array('t.forum_id', '=', 3),
array('NOT',
array('t.topic_type', '=', 0),
),
array('t.topic_id', '>', 5),
array('t.topic_poster', '<>', 5),
),
Code: Select all
t.forum_id = 3
AND NOT ( t.topic_type = 0 )
AND t.topic_id > 5
AND t.topic_poster <> 5
Comparison examples
Here are some code examples of the "before" and "after" in order to fully use this feature.
Code: Select all
// Original
sql_build_query('SELECT',
array(
'SELECT' => "COUNT(topic_id) AS num_topics",
'FROM' => array("phpbb_topics" => ''),
'WHERE' => 'topic_id IS NOT NULL',
)
)
// Now
sql_build_query('SELECT',
array(
'SELECT' => "COUNT(topic_id) AS num_topics",
'FROM' => array("phpbb_topics" => ''),
'WHERE' =>
array('topic_id', 'IS NOT', 'NULL'),
)
)
Code: Select all
'WHERE' => 'forum_id = 1',
'WHERE' => array('forum_id', '=', 1),
// Or, if you want to negate it:
'WHERE' => 'NOT ( forum_id = 1)',
'WHERE' =>
array('NOT',
array('forum_id', '=', 1),
),
source: https://github.com/phpbb/phpbb/blob/rel ... m.php#L277
Code: Select all
// original
" WHERE forum_id = 51
AND (topic_last_post_time >= $min_post_time
OR topic_type = " . POST_ANNOUNCE . '
OR topic_type = ' . POST_GLOBAL . ')
AND 1=1'
// Becomes
'WHERE' =>
array('AND',
array('forum_id', '=', 51),
array('OR',
array('topic_last_post_time', '>=', 1409240111),
array('topic_type', '=', POST_ANNOUNCE),
array('topic_type', '=', POST_GLOBAL),
),
array('NOT',
array('AND',
array('topic_poster', '=', 48),
array(1, '=', 1),
),
),
)
Source: https://github.com/phpbb/phpbb/blob/rel ... m.php#L445
Code: Select all
// Original
'WHERE' => '(t.forum_id = 3
AND t.topic_type = 3) OR
(' . sql_in_set('t.forum_id', array(1,2,3,4,5,6)) . '
AND t.topic_type = 4)',
// Becomes
'WHERE' =>
array('OR',
array('AND',
array('t.forum_id', '=', 3),
array('t.topic_type', '=', 0),
),
array('AND',
array('t.forum_id', 'IN', array(1,2,3,4,5,6)),
array('t.topic_type', '=', 0),
),
),
Feel free to discuss to your hearts content. Any constructive opinion is welcome.
ticket: https://tracker.phpbb.com/browse/PHPBB3-13652
PR: https://github.com/phpbb/phpbb/pull/3441