diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index e3732bf500c..7680be44a55 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -825,24 +825,15 @@ public function whereIn($column, $values, $boolean = 'and', $not = false) { $type = $not ? 'NotIn' : 'In'; - if ($values instanceof EloquentBuilder) { - $values = $values->getQuery(); - } - // If the value is a query builder instance we will assume the developer wants to // look for any values that exists within this given query. So we will add the // query accordingly so that this query is properly executed when it is run. - if ($values instanceof self) { - return $this->whereInExistingQuery( - $column, $values, $boolean, $not - ); - } + if ($values instanceof self || $values instanceof EloquentBuilder || $values instanceof Closure) { + [$query, $bindings] = $this->createSub($values); + + $values = [new Expression($query)]; - // If the value of the where in clause is actually a Closure, we will assume that - // the developer is using a full sub-select for this "in" statement, and will - // execute those Closures, then we can re-construct the entire sub-selects. - if ($values instanceof Closure) { - return $this->whereInSub($column, $values, $boolean, $not); + $this->addBinding($bindings, 'where'); } // Next, if the value is Arrayable we need to cast it to its raw array form so we @@ -857,11 +848,7 @@ public function whereIn($column, $values, $boolean = 'and', $not = false) // Finally we'll add a binding for each values unless that value is an expression // in which case we will just skip over it since it will be the query as a raw // string and not as a parameterized place-holder to be replaced by the PDO. - foreach ($values as $value) { - if (! $value instanceof Expression) { - $this->addBinding($value, 'where'); - } - } + $this->addBinding($this->cleanBindings($values), 'where'); return $this; } @@ -903,51 +890,6 @@ public function orWhereNotIn($column, $values) return $this->whereNotIn($column, $values, 'or'); } - /** - * Add a where in with a sub-select to the query. - * - * @param string $column - * @param \Closure $callback - * @param string $boolean - * @param bool $not - * @return $this - */ - protected function whereInSub($column, Closure $callback, $boolean, $not) - { - $type = $not ? 'NotInSub' : 'InSub'; - - // To create the exists sub-select, we will actually create a query and call the - // provided callback with the query so the developer may set any of the query - // conditions they want for the in clause, then we'll put it in this array. - call_user_func($callback, $query = $this->forSubQuery()); - - $this->wheres[] = compact('type', 'column', 'query', 'boolean'); - - $this->addBinding($query->getBindings(), 'where'); - - return $this; - } - - /** - * Add an external sub-select to the query. - * - * @param string $column - * @param \Illuminate\Database\Query\Builder|static $query - * @param string $boolean - * @param bool $not - * @return $this - */ - protected function whereInExistingQuery($column, $query, $boolean, $not) - { - $type = $not ? 'NotInSub' : 'InSub'; - - $this->wheres[] = compact('type', 'column', 'query', 'boolean'); - - $this->addBinding($query->getBindings(), 'where'); - - return $this; - } - /** * Add a "where null" clause to the query. * diff --git a/src/Illuminate/Database/Query/Grammars/Grammar.php b/src/Illuminate/Database/Query/Grammars/Grammar.php index 27367839515..53c93d27f39 100755 --- a/src/Illuminate/Database/Query/Grammars/Grammar.php +++ b/src/Illuminate/Database/Query/Grammars/Grammar.php @@ -273,30 +273,6 @@ protected function whereNotIn(Builder $query, $where) return '1 = 1'; } - /** - * Compile a where in sub-select clause. - * - * @param \Illuminate\Database\Query\Builder $query - * @param array $where - * @return string - */ - protected function whereInSub(Builder $query, $where) - { - return $this->wrap($where['column']).' in ('.$this->compileSelect($where['query']).')'; - } - - /** - * Compile a where not in sub-select clause. - * - * @param \Illuminate\Database\Query\Builder $query - * @param array $where - * @return string - */ - protected function whereNotInSub(Builder $query, $where) - { - return $this->wrap($where['column']).' not in ('.$this->compileSelect($where['query']).')'; - } - /** * Compile a "where null" clause. * diff --git a/src/Illuminate/Database/Query/JoinClause.php b/src/Illuminate/Database/Query/JoinClause.php index 4b32df29e99..267854e74df 100755 --- a/src/Illuminate/Database/Query/JoinClause.php +++ b/src/Illuminate/Database/Query/JoinClause.php @@ -56,7 +56,7 @@ public function __construct(Builder $parentQuery, $type, $table) * * will produce the following SQL: * - * on `contacts`.`user_id` = `users`.`id` and `contacts`.`info_id` = `info`.`id` + * on `contacts`.`user_id` = `users`.`id` and `contacts`.`info_id` = `info`.`id` * * @param \Closure|string $first * @param string|null $operator diff --git a/tests/Database/DatabaseEloquentBuilderTest.php b/tests/Database/DatabaseEloquentBuilderTest.php index ba0ee0e14f6..16f07c18a92 100755 --- a/tests/Database/DatabaseEloquentBuilderTest.php +++ b/tests/Database/DatabaseEloquentBuilderTest.php @@ -989,6 +989,15 @@ public function testWhereKeyNotMethodWithCollection() $builder->whereKeyNot($collection); } + public function testWhereIn() + { + $model = new EloquentBuilderTestNestedStub; + $this->mockConnectionForModel($model, ''); + $query = $model->newQuery()->withoutGlobalScopes()->whereIn('foo', $model->newQuery()->select('id')); + $expected = 'select * from "table" where "foo" in (select "id" from "table" where "table"."deleted_at" is null)'; + $this->assertEquals($expected, $query->toSql()); + } + public function testLatestWithoutColumnWithCreatedAt() { $model = $this->getMockModel();