diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ec142b46..6f69caa19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. ## [4.4.0] - unreleased +* Implement `Builder::toSql` using JSON representation of the MQL by @GromNaN in [#2931](https://github.com/mongodb/laravel-mongodb/pull/2931) * Support collection name prefix by @GromNaN in [#2930](https://github.com/mongodb/laravel-mongodb/pull/2930) ## [4.3.0] - 2024-04-26 diff --git a/src/Eloquent/Builder.php b/src/Eloquent/Builder.php index 22dcfd081..255bc8751 100644 --- a/src/Eloquent/Builder.php +++ b/src/Eloquent/Builder.php @@ -55,6 +55,8 @@ class Builder extends EloquentBuilder 'raw', 'sum', 'tomql', + 'tosql', + 'torawsql', ]; /** diff --git a/src/Query/Builder.php b/src/Query/Builder.php index 89faa4b17..86e9fb460 100644 --- a/src/Query/Builder.php +++ b/src/Query/Builder.php @@ -18,6 +18,7 @@ use InvalidArgumentException; use LogicException; use MongoDB\BSON\Binary; +use MongoDB\BSON\Document; use MongoDB\BSON\ObjectID; use MongoDB\BSON\Regex; use MongoDB\BSON\UTCDateTime; @@ -1446,16 +1447,26 @@ public function __call($method, $parameters) return parent::__call($method, $parameters); } - /** @internal This method is not supported by MongoDB. */ + /** + * Return the JSON representation of the MongoDB Query. + * Naming is inherited and used for compatibility with third-party packages. + * + * @internal + */ public function toSql() { - throw new BadMethodCallException('This method is not supported by MongoDB. Try "toMql()" instead.'); + return Document::fromPHP($this->toMql())->toCanonicalExtendedJSON(); } - /** @internal This method is not supported by MongoDB. */ + /** + * Return the JSON representation of the MongoDB Query. + * Naming is inherited and used for compatibility with third-party packages. + * + * @internal + */ public function toRawSql() { - throw new BadMethodCallException('This method is not supported by MongoDB. Try "toMql()" instead.'); + return $this->toSql(); } /** @internal This method is not supported by MongoDB. */ @@ -1535,4 +1546,10 @@ public function orWhereIntegerNotInRaw($column, $values, $boolean = 'and') { throw new BadMethodCallException('This method is not supported by MongoDB'); } + + /** @internal This method is not supported by MongoDB. */ + public function insertUsing(array $columns, $query) + { + throw new BadMethodCallException('This method is not supported by MongoDB'); + } } diff --git a/tests/Eloquent/CallBuilderTest.php b/tests/Eloquent/CallBuilderTest.php index fa4cb4580..0b36d808c 100644 --- a/tests/Eloquent/CallBuilderTest.php +++ b/tests/Eloquent/CallBuilderTest.php @@ -24,34 +24,36 @@ protected function tearDown(): void } #[Dataprovider('provideFunctionNames')] - public function testCallingABuilderMethodDoesNotReturnTheBuilderInstance(string $method, string $className, $parameters = []): void + public function testCallingABuilderMethodDoesNotReturnTheBuilderInstance(string $method, $parameters = []): void { $builder = User::query()->newQuery(); assert($builder instanceof Builder); - self::assertNotInstanceOf(expected: $className, actual: $builder->{$method}(...$parameters)); + self::assertNotInstanceOf(Builder::class, $builder->{$method}(...$parameters)); } public static function provideFunctionNames(): Generator { - yield 'does not exist' => ['doesntExist', Builder::class]; - yield 'get bindings' => ['getBindings', Builder::class]; - yield 'get connection' => ['getConnection', Builder::class]; - yield 'get grammar' => ['getGrammar', Builder::class]; - yield 'insert get id' => ['insertGetId', Builder::class, [['user' => 'foo']]]; - yield 'to Mql' => ['toMql', Builder::class]; - yield 'average' => ['average', Builder::class, ['name']]; - yield 'avg' => ['avg', Builder::class, ['name']]; - yield 'count' => ['count', Builder::class, ['name']]; - yield 'exists' => ['exists', Builder::class]; - yield 'insert' => ['insert', Builder::class, [['name']]]; - yield 'max' => ['max', Builder::class, ['name']]; - yield 'min' => ['min', Builder::class, ['name']]; - yield 'pluck' => ['pluck', Builder::class, ['name']]; - yield 'pull' => ['pull', Builder::class, ['name']]; - yield 'push' => ['push', Builder::class, ['name']]; - yield 'raw' => ['raw', Builder::class]; - yield 'sum' => ['sum', Builder::class, ['name']]; + yield 'does not exist' => ['doesntExist']; + yield 'get bindings' => ['getBindings']; + yield 'get connection' => ['getConnection']; + yield 'get grammar' => ['getGrammar']; + yield 'insert get id' => ['insertGetId', [['user' => 'foo']]]; + yield 'to Mql' => ['toMql']; + yield 'to Sql' => ['toSql']; + yield 'to Raw Sql' => ['toRawSql']; + yield 'average' => ['average', ['name']]; + yield 'avg' => ['avg', ['name']]; + yield 'count' => ['count', ['name']]; + yield 'exists' => ['exists']; + yield 'insert' => ['insert', [['name']]]; + yield 'max' => ['max', ['name']]; + yield 'min' => ['min', ['name']]; + yield 'pluck' => ['pluck', ['name']]; + yield 'pull' => ['pull', ['name']]; + yield 'push' => ['push', ['name']]; + yield 'raw' => ['raw']; + yield 'sum' => ['sum', ['name']]; } #[Test] @@ -79,14 +81,7 @@ public static function provideUnsupportedMethods(): Generator yield 'insert using' => [ 'insertUsing', BadMethodCallException::class, - 'This method is not supported by MongoDB. Try "toMql()" instead', - [[['name' => 'Jane']], fn (QueryBuilder $builder) => $builder], - ]; - - yield 'to sql' => [ - 'toSql', - BadMethodCallException::class, - 'This method is not supported by MongoDB. Try "toMql()" instead', + 'This method is not supported by MongoDB', [[['name' => 'Jane']], fn (QueryBuilder $builder) => $builder], ]; } diff --git a/tests/Query/BuilderTest.php b/tests/Query/BuilderTest.php index 4076b3028..cf2d41919 100644 --- a/tests/Query/BuilderTest.php +++ b/tests/Query/BuilderTest.php @@ -1396,6 +1396,18 @@ public static function provideExceptions(): iterable ]; } + public function testToSql() + { + $builder = self::getBuilder(); + $builder + ->where('foo', 'bar') + ->limit(10); + + $expected = '{ "find" : [ { "foo" : "bar" }, { "limit" : { "$numberInt" : "10" }, "typeMap" : { "root" : "array", "document" : "array" } } ] }'; + $this->assertSame($expected, $builder->toSql()); + $this->assertSame($expected, $builder->toRawSql()); + } + /** @dataProvider getEloquentMethodsNotSupported */ public function testEloquentMethodsNotSupported(Closure $callback) { @@ -1412,9 +1424,6 @@ public static function getEloquentMethodsNotSupported() // Most of this methods can be implemented using aggregation framework // whereInRaw, whereNotInRaw, orWhereInRaw, orWhereNotInRaw, whereBetweenColumns - yield 'toSql' => [fn (Builder $builder) => $builder->toSql()]; - yield 'toRawSql' => [fn (Builder $builder) => $builder->toRawSql()]; - /** @see DatabaseQueryBuilderTest::testBasicWhereColumn() */ /** @see DatabaseQueryBuilderTest::testArrayWhereColumn() */ yield 'whereColumn' => [fn (Builder $builder) => $builder->whereColumn('first_name', 'last_name')];