-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to check exists through tables with "through" key. #30
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,28 +95,51 @@ private function buildSubclauseQuery($query, $rule, $value, $condition) | |
|
||
$not = array_key_exists('not_exists', $subclause) && $subclause['not_exists']; | ||
|
||
// Create a where exists clause to join to the other table, and find results matching the criteria | ||
$query = $query->whereExists( | ||
/** | ||
* @param Builder $query | ||
*/ | ||
function(Builder $query) use ($subclause) { | ||
|
||
$q = $query->selectRaw(1) | ||
->from($subclause['to_table']) | ||
->whereRaw($subclause['to_table'].'.'.$subclause['to_col'] | ||
.' = ' | ||
.$subclause['from_table'].'.'.$subclause['from_col']); | ||
|
||
if (array_key_exists('to_clause', $subclause)) { | ||
$q->where($subclause['to_clause']); | ||
} | ||
|
||
$this->buildSubclauseInnerQuery($subclause, $q); | ||
}, | ||
$condition, | ||
$not | ||
); | ||
if ( $not ) { | ||
// Create a where exists clause to join to the other table, and find results matching the criteria | ||
$query = $query->whereExists( | ||
/** | ||
* @param Builder $query | ||
*/ | ||
function(Builder $query) use ($subclause, $not, $condition) { | ||
$q = $query->selectRaw(1) | ||
->from($subclause['to_table']) | ||
->whereRaw($subclause['to_table'].'.'.$subclause['to_col'] | ||
.' = ' | ||
.$subclause['from_table'].'.'.$subclause['from_col']); | ||
if ( ! isset( $subclause["through"] ) ) { | ||
if ( array_key_exists( 'to_clause', $subclause ) ) { | ||
$q->where( $subclause['to_clause'] ); | ||
} | ||
$this->buildSubclauseInnerQuery( $subclause, $q ); | ||
} else { | ||
$this->buildSubclauseThroughQuery( $subclause, $not, $condition, $q ); | ||
} | ||
|
||
}, | ||
$condition, | ||
$not | ||
); | ||
} else { | ||
// Create a join clause to join to the other table, and find results matching the criteria | ||
|
||
$query = $query->join( $subclause["to_table"], $subclause['to_table'] . '.' . $subclause['to_col'], '=', $subclause['from_table'] . '.' . $subclause['from_col'] ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please try to keep lines < 80 characters long. This line of code wraps in my browser. |
||
$first_from_col = $subclause['from_col']; | ||
$first_from = $subclause['from_table']; | ||
//Loop through the 'through' key to access through multiple tables | ||
while ( isset( $subclause['through'] ) ) { | ||
$subclause["through"]["require_array"] = $subclause["require_array"]; | ||
$subclause["through"]["operator"] = $subclause["operator"]; | ||
$subclause["through"]["value"] = $subclause["value"]; | ||
$subclause = $subclause["through"]; | ||
$query = $query->join( $subclause["to_table"], $subclause['to_table'] . '.' . $subclause['to_col'], '=', $subclause['from_table'] . '.' . $subclause['from_col'] ); | ||
} | ||
if (array_key_exists('to_clause', $subclause)) { | ||
$query->where($subclause['to_clause']); | ||
} | ||
$this->buildSubclauseInnerQuery( $subclause, $query ); | ||
$query->groupBy( $first_from.".".$first_from_col ); | ||
} | ||
|
||
return $query; | ||
} | ||
|
@@ -206,4 +229,36 @@ private function buildSubclauseWithNull($subclause, Builder $query, $isNotNull = | |
return $query->whereNull($subclause['to_value_column']); | ||
} | ||
|
||
private function buildSubclauseThroughQuery($subclause, $not, $condition, Builder $q) { | ||
$subclause["through"]["require_array"] = $subclause["require_array"]; | ||
$subclause["through"]["operator"] = $subclause["operator"]; | ||
$subclause["through"]["value"] = $subclause["value"]; | ||
$subclause = $subclause["through"]; | ||
|
||
$q->whereExists( | ||
function ( \Illuminate\Database\Query\Builder $query ) use ( $subclause, $not, $condition, $q ) { | ||
|
||
$q = $query->selectRaw( 1 ) | ||
->from( $subclause['to_table'] ) | ||
->whereRaw( $subclause['to_table'] . '.' . $subclause['to_col'] | ||
. ' = ' | ||
. $subclause['from_table'] . '.' . $subclause['from_col'] ); | ||
|
||
|
||
|
||
if ( ! isset( $subclause["through"] ) ) { | ||
if ( array_key_exists( 'to_clause', $subclause ) ) { | ||
$q->where( $subclause['to_clause'] ); | ||
} | ||
$this->buildSubclauseInnerQuery( $subclause, $q ); | ||
} else { | ||
$this->buildSubclauseThroughQuery( $subclause, $not, $condition, $q ); | ||
} | ||
}, | ||
$condition, | ||
$not | ||
); | ||
return $q; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,21 @@ private function getJoinFields() | |
'to_value_column' => 's_value', | ||
'to_clause' => array('othercol' => 'value'), | ||
), | ||
'join2through' => array( | ||
'from_table' => 'master2', | ||
'from_col' => 'm2_col', | ||
'to_table' => 'subtable2', | ||
'to_col' => 's2_col', | ||
'to_value_column' => 's2_value', | ||
'not_exists' => true, | ||
'through' => array( | ||
'from_table' => 'subtable2', | ||
'from_col' => 's2_col', | ||
'to_table' => 'subtable3', | ||
'to_col' => 's3_col', | ||
'to_value_column' => 's3_value', | ||
) | ||
), | ||
); | ||
} | ||
|
||
|
@@ -328,4 +343,17 @@ public function testDateNotBetween() | |
$this->assertEquals(22, $bindings[0]->day); | ||
$this->assertEquals(28, $bindings[1]->day); | ||
} | ||
|
||
public function testJoinNotExistsInThrough() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, with this project, we are trying to stick to |
||
{ | ||
$json = '{"condition":"AND","rules":[{"id":"join2through","field":"join2through","type":"text","input":"select","operator":"in","value":["a","b"]}]}'; | ||
|
||
$builder = $this->createQueryBuilder(); | ||
|
||
$parser = $this->getParserUnderTest(); | ||
$parser->parse($json, $builder); | ||
|
||
$this->assertEquals('select * where not exists (select 1 from `subtable2` where subtable2.s2_col = master2.m2_col and not exists (select 1 from `subtable3` where subtable3.s3_col = subtable2.s2_col and `s3_value` in (?, ?)))', | ||
$builder->toSql()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing that I am cautious of is that this code looks like it will change the behavior for other users of this class.
Can we separate out the code inside the
if() {...}
block into two separate functions to ensure that the length of this function (buildSubclauseQuery
) is not too long?