diff --git a/src/Query/Aggregation/Max.php b/src/Query/Aggregation/Max.php index 9102a6e..9376c06 100644 --- a/src/Query/Aggregation/Max.php +++ b/src/Query/Aggregation/Max.php @@ -4,7 +4,7 @@ namespace TBolier\RethinkQL\Query\Aggregation; use TBolier\RethinkQL\Query\AbstractQuery; -use TBolier\RethinkQL\Query\Logic\LogicTrait; +use TBolier\RethinkQL\Query\Manipulation\LogicTrait; use TBolier\RethinkQL\Query\Operation\OperationTrait; use TBolier\RethinkQL\Query\QueryInterface; use TBolier\RethinkQL\Query\Transformation\TransformationTrait; diff --git a/src/Query/Builder.php b/src/Query/Builder.php index dd7ad3a..8ab9459 100644 --- a/src/Query/Builder.php +++ b/src/Query/Builder.php @@ -70,7 +70,7 @@ public function ordening(string $key): Ordening return $this->ordering; } - public function row(string $value): Row + public function row(string $value = null): Row { $this->row = new Row($this->rethink, $value); diff --git a/src/Query/Logic/LogicTrait.php b/src/Query/Logic/LogicTrait.php deleted file mode 100644 index c46679c..0000000 --- a/src/Query/Logic/LogicTrait.php +++ /dev/null @@ -1,12 +0,0 @@ -rethink, $field, $this->query); - } -} diff --git a/src/Query/Logic/GetFieldLogic.php b/src/Query/Manipulation/GetField.php similarity index 94% rename from src/Query/Logic/GetFieldLogic.php rename to src/Query/Manipulation/GetField.php index 8cb7bf2..5830d92 100644 --- a/src/Query/Logic/GetFieldLogic.php +++ b/src/Query/Manipulation/GetField.php @@ -1,6 +1,6 @@ rethink = $rethink; + $this->query = $query; + $this->keys = $keys; + } + + public function toArray(): array + { + if (\count($this->keys) === 1) { + $keysQuery = implode($this->keys); + } else { + $keysQuery = [ + TermType::MAKE_ARRAY, + array_values($this->keys) + ]; + } + + return [ + TermType::HAS_FIELDS, + [ + $this->query->toArray(), + $keysQuery + ] + ]; + } +} diff --git a/src/Query/Manipulation/Keys.php b/src/Query/Manipulation/Keys.php new file mode 100644 index 0000000..0f2d433 --- /dev/null +++ b/src/Query/Manipulation/Keys.php @@ -0,0 +1,43 @@ +query = $query; + $this->rethink = $rethink; + } + + public function toArray(): array + { + return [ + TermType::KEYS, + [ + $this->query->toArray() + ] + ]; + } +} diff --git a/src/Query/Manipulation/LogicTrait.php b/src/Query/Manipulation/LogicTrait.php new file mode 100644 index 0000000..724d9f3 --- /dev/null +++ b/src/Query/Manipulation/LogicTrait.php @@ -0,0 +1,12 @@ +rethink, $field, $this->query); + } +} diff --git a/src/Query/Manipulation/ManipulationTrait.php b/src/Query/Manipulation/ManipulationTrait.php new file mode 100644 index 0000000..dacc378 --- /dev/null +++ b/src/Query/Manipulation/ManipulationTrait.php @@ -0,0 +1,29 @@ +rethink, /** @scrutinizer ignore-type */ $this, $keys); + } + + public function without(...$keys): Without + { + return new Without($this->rethink, /** @scrutinizer ignore-type */ $this, $keys); + } + + public function keys(): Keys + { + return new Keys($this->rethink, /** @scrutinizer ignore-type */ $this); + } + + public function values(): Values + { + return new Values($this->rethink, /** @scrutinizer ignore-type */ $this); + } +} diff --git a/src/Query/Manipulation/Pluck.php b/src/Query/Manipulation/Pluck.php new file mode 100644 index 0000000..7bcd624 --- /dev/null +++ b/src/Query/Manipulation/Pluck.php @@ -0,0 +1,61 @@ +query = $query; + $this->rethink = $rethink; + $this->keys = $keys; + } + + public function toArray(): array + { + if (\count($this->keys) === 1) { + $keysQuery = implode($this->keys); + } else { + $keysQuery = [ + TermType::MAKE_ARRAY, + array_values($this->keys) + ]; + } + + return [ + TermType::PLUCK, + [ + $this->query->toArray(), + $keysQuery + ] + ]; + } +} diff --git a/src/Query/Manipulation/RowHasFields.php b/src/Query/Manipulation/RowHasFields.php new file mode 100644 index 0000000..980497a --- /dev/null +++ b/src/Query/Manipulation/RowHasFields.php @@ -0,0 +1,52 @@ +keys = $keys; + $this->rethink = $rethink; + } + + public function toArray(): array + { + if (\count($this->keys) === 1) { + $keysQuery = implode($this->keys); + } else { + $keysQuery = [ + TermType::MAKE_ARRAY, + array_values($this->keys) + ]; + } + + return [ + TermType::HAS_FIELDS, + [ + [ + TermType::IMPLICIT_VAR + ], + $keysQuery + ] + ]; + } +} diff --git a/src/Query/Manipulation/Values.php b/src/Query/Manipulation/Values.php new file mode 100644 index 0000000..70607af --- /dev/null +++ b/src/Query/Manipulation/Values.php @@ -0,0 +1,49 @@ +query = $query; + $this->rethink = $rethink; + } + + public function toArray(): array + { + return [ + TermType::VALUES, + [ + $this->query->toArray() + ], + ]; + } +} diff --git a/src/Query/Manipulation/Without.php b/src/Query/Manipulation/Without.php new file mode 100644 index 0000000..904f26a --- /dev/null +++ b/src/Query/Manipulation/Without.php @@ -0,0 +1,61 @@ +query = $query; + $this->rethink = $rethink; + $this->keys = $keys; + } + + public function toArray(): array + { + if (\count($this->keys) === 1) { + $keysQuery = implode($this->keys); + } else { + $keysQuery = [ + TermType::MAKE_ARRAY, + array_values($this->keys) + ]; + } + + return [ + TermType::WITHOUT, + [ + $this->query->toArray(), + $keysQuery + ] + ]; + } +} diff --git a/src/Query/Operation/Filter.php b/src/Query/Operation/Filter.php index 6c3814d..899003b 100644 --- a/src/Query/Operation/Filter.php +++ b/src/Query/Operation/Filter.php @@ -5,6 +5,7 @@ use TBolier\RethinkQL\Query\AbstractQuery; use TBolier\RethinkQL\Query\Aggregation\AggregationTrait; +use TBolier\RethinkQL\Query\Manipulation\ManipulationTrait; use TBolier\RethinkQL\Query\QueryInterface; use TBolier\RethinkQL\Query\Transformation\TransformationTrait; use TBolier\RethinkQL\RethinkInterface; @@ -15,6 +16,7 @@ class Filter extends AbstractQuery use TransformationTrait; use OperationTrait; use AggregationTrait; + use ManipulationTrait; /** * @var array diff --git a/src/Query/Operation/FilterByRow.php b/src/Query/Operation/FilterByRow.php index 92e6f56..41ffce3 100644 --- a/src/Query/Operation/FilterByRow.php +++ b/src/Query/Operation/FilterByRow.php @@ -4,6 +4,7 @@ namespace TBolier\RethinkQL\Query\Operation; use TBolier\RethinkQL\Query\AbstractQuery; +use TBolier\RethinkQL\Query\Manipulation\ManipulationTrait; use TBolier\RethinkQL\Query\QueryInterface; use TBolier\RethinkQL\Query\Transformation\TransformationTrait; use TBolier\RethinkQL\RethinkInterface; @@ -13,6 +14,7 @@ class FilterByRow extends AbstractQuery { use TransformationTrait; use OperationTrait; + use ManipulationTrait; /** * @var QueryInterface diff --git a/src/Query/Operation/Get.php b/src/Query/Operation/Get.php index 8173469..3b3369e 100644 --- a/src/Query/Operation/Get.php +++ b/src/Query/Operation/Get.php @@ -4,12 +4,15 @@ namespace TBolier\RethinkQL\Query\Operation; use TBolier\RethinkQL\Query\AbstractQuery; +use TBolier\RethinkQL\Query\Manipulation\ManipulationTrait; use TBolier\RethinkQL\Query\QueryInterface; use TBolier\RethinkQL\RethinkInterface; use TBolier\RethinkQL\Types\Term\TermType; class Get extends AbstractQuery { + use ManipulationTrait; + /** * @var string|int */ diff --git a/src/Query/Operation/GetAll.php b/src/Query/Operation/GetAll.php index 626871a..d26b916 100644 --- a/src/Query/Operation/GetAll.php +++ b/src/Query/Operation/GetAll.php @@ -5,6 +5,7 @@ use TBolier\RethinkQL\Query\AbstractQuery; use TBolier\RethinkQL\Query\Aggregation\AggregationTrait; +use TBolier\RethinkQL\Query\Manipulation\ManipulationTrait; use TBolier\RethinkQL\Query\QueryInterface; use TBolier\RethinkQL\Query\Transformation\TransformationTrait; use TBolier\RethinkQL\RethinkInterface; @@ -15,6 +16,7 @@ class GetAll extends AbstractQuery use AggregationTrait; use OperationTrait; use TransformationTrait; + use ManipulationTrait; /** * @var array diff --git a/src/Query/Operation/OperationTrait.php b/src/Query/Operation/OperationTrait.php index cd2b388..abf0186 100644 --- a/src/Query/Operation/OperationTrait.php +++ b/src/Query/Operation/OperationTrait.php @@ -15,7 +15,7 @@ public function delete(): QueryInterface public function filter($value) { - if ($value instanceof Row) { + if (\is_object($value)) { return new FilterByRow($this->rethink, /** @scrutinizer ignore-type */ $this, $value); } diff --git a/src/Query/Row.php b/src/Query/Row.php index eec091c..ff7c415 100644 --- a/src/Query/Row.php +++ b/src/Query/Row.php @@ -7,7 +7,6 @@ use TBolier\RethinkQL\Query\Logic\AndLogic; use TBolier\RethinkQL\Query\Logic\EqualLogic; use TBolier\RethinkQL\Query\Logic\FuncLogic; -use TBolier\RethinkQL\Query\Logic\GetFieldLogic; use TBolier\RethinkQL\Query\Logic\GreaterThanLogic; use TBolier\RethinkQL\Query\Logic\GreaterThanOrEqualToLogic; use TBolier\RethinkQL\Query\Logic\LowerThanLogic; @@ -15,10 +14,15 @@ use TBolier\RethinkQL\Query\Logic\NotEqualLogic; use TBolier\RethinkQL\Query\Logic\NotLogic; use TBolier\RethinkQL\Query\Logic\OrLogic; +use TBolier\RethinkQL\Query\Manipulation\GetField; +use TBolier\RethinkQL\Query\Manipulation\RowHasFields; +use TBolier\RethinkQL\Query\Manipulation\ManipulationTrait; use TBolier\RethinkQL\RethinkInterface; class Row extends AbstractQuery { + use ManipulationTrait; + /** * @var QueryInterface */ @@ -36,7 +40,7 @@ class Row extends AbstractQuery public function __construct( RethinkInterface $rethink, - string $value + ?string $value ) { parent::__construct($rethink); @@ -55,7 +59,7 @@ public function eq($value): Row $this->function = new EqualLogic( $this->rethink, - new GetFieldLogic($this->rethink, $this->value), + new GetField($this->rethink, $this->value), $value ); @@ -78,7 +82,7 @@ public function ne($value): Row $this->function = new NotEqualLogic( $this->rethink, - new GetFieldLogic($this->rethink, $this->value), + new GetField($this->rethink, $this->value), $value ); @@ -101,7 +105,7 @@ public function lt($value): Row $this->function = new LowerThanLogic( $this->rethink, - new GetFieldLogic($this->rethink, $this->value), + new GetField($this->rethink, $this->value), $value ); @@ -124,7 +128,7 @@ public function le($value): Row $this->function = new LowerThanOrEqualToLogic( $this->rethink, - new GetFieldLogic($this->rethink, $this->value), + new GetField($this->rethink, $this->value), $value ); @@ -147,7 +151,7 @@ public function gt($value): Row $this->function = new GreaterThanLogic( $this->rethink, - new GetFieldLogic($this->rethink, $this->value), + new GetField($this->rethink, $this->value), $value ); @@ -170,7 +174,7 @@ public function ge($value): Row $this->function = new GreaterThanOrEqualToLogic( $this->rethink, - new GetFieldLogic($this->rethink, $this->value), + new GetField($this->rethink, $this->value), $value ); @@ -229,6 +233,21 @@ public function not(): Row return $this; } + public function hasFields(...$keys) + { + $this->function = new RowHasFields( + $this->rethink, + $keys + ); + + $this->query = new FuncLogic( + $this->rethink, + $this->function + ); + + return $this; + } + public function toArray(): array { return $this->query->toArray(); diff --git a/src/Query/Table.php b/src/Query/Table.php index 08aed77..ba2fc41 100644 --- a/src/Query/Table.php +++ b/src/Query/Table.php @@ -4,6 +4,8 @@ namespace TBolier\RethinkQL\Query; use TBolier\RethinkQL\Query\Aggregation\AggregationTrait; +use TBolier\RethinkQL\Query\Manipulation\HasFields; +use TBolier\RethinkQL\Query\Manipulation\ManipulationTrait; use TBolier\RethinkQL\Query\Operation\Get; use TBolier\RethinkQL\Query\Operation\IndexCreate; use TBolier\RethinkQL\Query\Operation\IndexDrop; @@ -40,7 +42,7 @@ public function __construct(string $name, RethinkInterface $rethink) ]; } - public function get($key): AbstractQuery + public function get($key): Get { return new Get($this->rethink, $this, $key); } @@ -65,6 +67,11 @@ public function indexRename(string $oldValue, string $newValue): AbstractQuery return new IndexRename($this->rethink, $this, $oldValue, $newValue); } + public function hasFields(...$keys) + { + return new HasFields($this->rethink, $this, $keys); + } + public function toArray(): array { return $this->query; diff --git a/src/Rethink.php b/src/Rethink.php index 7192855..693d124 100644 --- a/src/Rethink.php +++ b/src/Rethink.php @@ -67,7 +67,7 @@ public function asc($key): Ordening return $this->builder->ordening($key)->asc($key); } - public function row(string $value): Row + public function row(?string $value = null): Row { return $this->builder->row($value); } diff --git a/src/RethinkInterface.php b/src/RethinkInterface.php index fe76d36..ca70e81 100644 --- a/src/RethinkInterface.php +++ b/src/RethinkInterface.php @@ -27,5 +27,5 @@ public function desc($key): Ordening; public function asc($key): Ordening; - public function row(string $value): Row; + public function row(?string $value = null): Row; } diff --git a/test/integration/AbstractTestCase.php b/test/integration/AbstractTestCase.php index 7fa805c..1d48f19 100644 --- a/test/integration/AbstractTestCase.php +++ b/test/integration/AbstractTestCase.php @@ -37,6 +37,9 @@ protected function setUp() { Mockery::getConfiguration()->allowMockingNonExistentMethods(false); + // Make sure we destroy a failed previous unit test database schema + $this->tearDown(); + parent::setUp(); } diff --git a/test/integration/Manipulation/HasFieldsTest.php b/test/integration/Manipulation/HasFieldsTest.php new file mode 100644 index 0000000..54dd5bd --- /dev/null +++ b/test/integration/Manipulation/HasFieldsTest.php @@ -0,0 +1,86 @@ +insertDocument(1); + $this->insertDocument(2); + $this->insertDocumentWithNumber(3, 1); + + /** @var Cursor $cursor */ + $cursor = $this->r() + ->table('tabletest') + ->hasFields('number') + ->run(); + + $this->assertInstanceOf(\Iterator::class, $cursor); + $this->assertEquals(1, $cursor->count()); + } + + /** + * @throws \Exception + */ + public function testHasField() + { + $this->insertDocument(1); + $this->insertDocument(2); + $this->insertDocumentWithNumber(3, 1); + + /** @var Cursor $cursor */ + $cursor = $this->r() + ->table('tabletest') + ->filter($this->r()->row()->hasFields('number')) + ->run(); + + $this->assertInstanceOf(\Iterator::class, $cursor); + $this->assertEquals(1, $cursor->count()); + } + + /** + * @throws \Exception + */ + public function testHasFields() + { + $this->insertDocument(1); + $this->insertDocument(2); + $this->insertDocumentWithNumber(3, 1); + + /** @var Cursor $cursor */ + $cursor = $this->r() + ->table('tabletest') + ->filter($this->r()->row()->hasFields('id', 'number')) + ->run(); + + $this->assertInstanceOf(\Iterator::class, $cursor); + $this->assertEquals(1, $cursor->count()); + } + + /** + * @throws \Exception + */ + public function testHasFieldsNot() + { + $this->insertDocument(1); + $this->insertDocument(2); + $this->insertDocumentWithNumber(3, 1); + + /** @var Cursor $cursor */ + $cursor = $this->r() + ->table('tabletest') + ->filter($this->r()->row()->hasFields('id', 'number')->not()) + ->run(); + + $this->assertInstanceOf(\Iterator::class, $cursor); + $this->assertEquals(2, $cursor->count()); + } +} diff --git a/test/integration/Manipulation/KeysTest.php b/test/integration/Manipulation/KeysTest.php new file mode 100644 index 0000000..5671722 --- /dev/null +++ b/test/integration/Manipulation/KeysTest.php @@ -0,0 +1,28 @@ +insertDocumentWithNumber(1, 1); + + /** @var ResponseInterface $response */ + $response = $this->r() + ->table('tabletest') + ->get(1) + ->keys() + ->run(); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertCount(4, $response->getData()); + } +} diff --git a/test/integration/Manipulation/PluckTest.php b/test/integration/Manipulation/PluckTest.php new file mode 100644 index 0000000..c23452c --- /dev/null +++ b/test/integration/Manipulation/PluckTest.php @@ -0,0 +1,30 @@ +insertDocumentWithNumber(1, 1); + + /** @var ResponseInterface $response */ + $response = $this->r() + ->table('tabletest') + ->get(1) + ->pluck('id', 'description') + ->run(); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertCount(2, $response->getData()); + $this->assertArrayHasKey('id', $response->getData()); + $this->assertArrayHasKey('description', $response->getData()); + } +} diff --git a/test/integration/Manipulation/ValuesTest.php b/test/integration/Manipulation/ValuesTest.php new file mode 100644 index 0000000..4580098 --- /dev/null +++ b/test/integration/Manipulation/ValuesTest.php @@ -0,0 +1,29 @@ +insertDocumentWithNumber(1, 777); + + /** @var ResponseInterface $cursor */ + $response = $this->r() + ->table('tabletest') + ->get(1) + ->values() + ->run(); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertCount(4, $response->getData()); + $this->assertArraySubset([2 => 777], $response->getData()); + } +} diff --git a/test/integration/Manipulation/WithoutTest.php b/test/integration/Manipulation/WithoutTest.php new file mode 100644 index 0000000..82abc33 --- /dev/null +++ b/test/integration/Manipulation/WithoutTest.php @@ -0,0 +1,30 @@ +insertDocumentWithNumber(1, 1); + + /** @var ResponseInterface $cursor */ + $response = $this->r() + ->table('tabletest') + ->get(1) + ->without('title', 'number') + ->run(); + + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertCount(2, $response->getData()); + $this->assertArrayNotHasKey('title', $response->getData()); + $this->assertArrayNotHasKey('number', $response->getData()); + } +}