From 2549ca2e16b06ff23076c7e60520dfd46e473346 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 16:19:14 -0400 Subject: [PATCH 01/12] Create query validator --- src/Database/Validator/Query.php | 124 +++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/Database/Validator/Query.php diff --git a/src/Database/Validator/Query.php b/src/Database/Validator/Query.php new file mode 100644 index 000000000..3ee6e690c --- /dev/null +++ b/src/Database/Validator/Query.php @@ -0,0 +1,124 @@ +schema = $schema; + } + + /** + * Get Description. + * + * Returns validator description + * + * @return string + */ + public function getDescription() + { + return $this->message; + } + + /** + * Is valid. + * + * Returns true if query typed according to schema. + * + * @param Query $query + * + * @return bool + */ + public function isValid(Query $query) + { + // Validate operator + if (!in_array($query->getOperator(), $this->operators)) { + $this->message = 'Query operator invalid'; + return false; + } + + // Validate attribute by name and type + $attributes = $this->schema['attributes']; + + if (!in_array($query->getAttribute(), $attributes)) { + $this->message = 'Attribute not found in schema'; + return false; + } + + // Extract the type of desired attribute from collection $schema + $attributeType = $this->schema[array_search($query->getAttribute(), array_column($this->schema, '$id'))]['type']; + + if ($attributeType !== gettype($query->getValue())) { + $this->message = 'Query type does not match schema'; + return false; + } + + // Ensure values are array + if (is_array($query->getValues())) { + return true; + } + + return false; + } + /** + * Is array + * + * Function will return true if object is array. + * + * @return bool + */ + public function isArray(): bool + { + return false; + } + + /** + * Get Type + * + * Returns validator type. + * + * @return string + */ + public function getType(): string + { + return self::TYPE_OBJECT; + } +} From e16e3981c3c2734d38f308cf05e9fe4709c2ba53 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 16:21:55 -0400 Subject: [PATCH 02/12] Remove unused import --- src/Database/Validator/Query.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Database/Validator/Query.php b/src/Database/Validator/Query.php index 3ee6e690c..f9e99d47d 100644 --- a/src/Database/Validator/Query.php +++ b/src/Database/Validator/Query.php @@ -3,7 +3,6 @@ namespace Utopia\Database\Validator; use Utopia\Validator; -use Utopia\Database\Database; use Utopia\Database\Query; class Query extends Validator From 1ebfacb466b9c4bf9b510d2eb3e965bc12e177d4 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 17:28:50 -0400 Subject: [PATCH 03/12] Rename to avoid namespace conflict --- .../{Query.php => QueryValidator.php} | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) rename src/Database/Validator/{Query.php => QueryValidator.php} (74%) diff --git a/src/Database/Validator/Query.php b/src/Database/Validator/QueryValidator.php similarity index 74% rename from src/Database/Validator/Query.php rename to src/Database/Validator/QueryValidator.php index f9e99d47d..9f65f986e 100644 --- a/src/Database/Validator/Query.php +++ b/src/Database/Validator/QueryValidator.php @@ -5,7 +5,7 @@ use Utopia\Validator; use Utopia\Database\Query; -class Query extends Validator +class QueryValidator extends Validator { /** * @var string @@ -62,11 +62,11 @@ public function getDescription() * * Returns true if query typed according to schema. * - * @param Query $query + * @param $query * * @return bool */ - public function isValid(Query $query) + public function isValid($query) { // Validate operator if (!in_array($query->getOperator(), $this->operators)) { @@ -74,28 +74,30 @@ public function isValid(Query $query) return false; } - // Validate attribute by name and type - $attributes = $this->schema['attributes']; + // Search for attribute in schema + $attributeIndex = array_search($query->getAttribute(), array_column($this->schema, '$id')); - if (!in_array($query->getAttribute(), $attributes)) { - $this->message = 'Attribute not found in schema'; + if ($attributeIndex === false) { + $this->message = 'Attribute not found in schema: ' . $query->getAttribute(); return false; } // Extract the type of desired attribute from collection $schema $attributeType = $this->schema[array_search($query->getAttribute(), array_column($this->schema, '$id'))]['type']; - if ($attributeType !== gettype($query->getValue())) { - $this->message = 'Query type does not match schema'; - return false; + foreach ($query->getValues() as $value) { + if (gettype($value) ==! $attributeType) { + $this->message = 'Query type does not match expected' . $attributeType; + return false; + } } // Ensure values are array - if (is_array($query->getValues())) { - return true; + if (!is_array($query->getValues())) { + return false; } - return false; + return true; } /** * Is array From 78ed2c00686fef5ff38f31671820da3124c84d75 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 17:29:12 -0400 Subject: [PATCH 04/12] Test query validator --- .../Database/Validator/QueryValidatorTest.php | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 tests/Database/Validator/QueryValidatorTest.php diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php new file mode 100644 index 000000000..775045450 --- /dev/null +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -0,0 +1,90 @@ + 'title', + 'type' => Database::VAR_STRING, + 'size' => 256, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'description', + 'type' => Database::VAR_STRING, + 'size' => 1000000, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'rating', + 'type' => Database::VAR_INTEGER, + 'size' => 5, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'price', + 'type' => Database::VAR_FLOAT, + 'size' => 5, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'published', + 'type' => Database::VAR_BOOLEAN, + 'size' => 5, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'tags', + 'type' => Database::VAR_STRING, + 'size' => 55, + 'required' => true, + 'signed' => true, + 'array' => true, + 'filters' => [], + ], + ]; + + public function setUp(): void + { + } + + public function tearDown(): void + { + } + + public function testQuery() + { + $validator = new QueryValidator($this->schema); + + $query = Query::parse('title.equal("Iron Man")'); + var_dump($query); + + $this->assertEquals(true, $validator->isValid($query)); + } + +} From 8b3d3cb7f714db14030a60f4bc5cbcb91722eba5 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 17:29:51 -0400 Subject: [PATCH 05/12] Remove debugging code --- tests/Database/Validator/QueryValidatorTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php index 775045450..a9d08a19e 100644 --- a/tests/Database/Validator/QueryValidatorTest.php +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -82,7 +82,6 @@ public function testQuery() $validator = new QueryValidator($this->schema); $query = Query::parse('title.equal("Iron Man")'); - var_dump($query); $this->assertEquals(true, $validator->isValid($query)); } From 767c225c52523fcdfd79790ef5a55614f6eb17f3 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 17:51:40 -0400 Subject: [PATCH 06/12] Remove unnecessary validation --- src/Database/Validator/QueryValidator.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Database/Validator/QueryValidator.php b/src/Database/Validator/QueryValidator.php index 9f65f986e..f98f25346 100644 --- a/src/Database/Validator/QueryValidator.php +++ b/src/Database/Validator/QueryValidator.php @@ -92,11 +92,6 @@ public function isValid($query) } } - // Ensure values are array - if (!is_array($query->getValues())) { - return false; - } - return true; } /** From 949c9d390e4e4d35c51caec3d0625fbd3501fcbe Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 17:54:30 -0400 Subject: [PATCH 07/12] Test error handling --- src/Database/Validator/QueryValidator.php | 6 ++--- .../Database/Validator/QueryValidatorTest.php | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Database/Validator/QueryValidator.php b/src/Database/Validator/QueryValidator.php index f98f25346..e3246a1b1 100644 --- a/src/Database/Validator/QueryValidator.php +++ b/src/Database/Validator/QueryValidator.php @@ -70,7 +70,7 @@ public function isValid($query) { // Validate operator if (!in_array($query->getOperator(), $this->operators)) { - $this->message = 'Query operator invalid'; + $this->message = 'Query operator invalid: ' . $query->getOperator(); return false; } @@ -86,8 +86,8 @@ public function isValid($query) $attributeType = $this->schema[array_search($query->getAttribute(), array_column($this->schema, '$id'))]['type']; foreach ($query->getValues() as $value) { - if (gettype($value) ==! $attributeType) { - $this->message = 'Query type does not match expected' . $attributeType; + if (gettype($value) !== $attributeType) { + $this->message = 'Query type does not match expected: ' . $attributeType; return false; } } diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php index a9d08a19e..6c62c67b4 100644 --- a/tests/Database/Validator/QueryValidatorTest.php +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -84,6 +84,31 @@ public function testQuery() $query = Query::parse('title.equal("Iron Man")'); $this->assertEquals(true, $validator->isValid($query)); + public function testInvalidOperator() + { + $validator = new QueryValidator($this->schema); + + $validator->isValid(Query::parse('title.eqqual("Iron Man")')); + + $this->assertEquals('Query operator invalid: eqqual', $validator->getDescription()); } + public function testAttributeNotFound() + { + $validator = new QueryValidator($this->schema); + + $validator->isValid(Query::parse('name.equal("Iron Man")')); + + $this->assertEquals('Attribute not found in schema: name', $validator->getDescription()); + } + + public function testAttributeWrongType() + { + $validator = new QueryValidator($this->schema); + + $query = Query::parse('title.equal(1776)'); + $validator->isValid($query); + + $this->assertEquals('Query type does not match expected: string', $validator->getDescription()); + } } From 49dba960989a1f15b39d2b261c703e33aa6885b5 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 17:54:37 -0400 Subject: [PATCH 08/12] Test for success --- tests/Database/Validator/QueryValidatorTest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php index 6c62c67b4..fbf3f3a37 100644 --- a/tests/Database/Validator/QueryValidatorTest.php +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -81,9 +81,11 @@ public function testQuery() { $validator = new QueryValidator($this->schema); - $query = Query::parse('title.equal("Iron Man")'); + $this->assertEquals(true, $validator->isValid(Query::parse('title.equal("Iron Man")'))); + $this->assertEquals(true, $validator->isValid(Query::parse('title.equal("Iron Man", "Ant Man")'))); + $this->assertEquals(true, $validator->isValid(Query::parse('rating.greater(4)'))); + } - $this->assertEquals(true, $validator->isValid($query)); public function testInvalidOperator() { $validator = new QueryValidator($this->schema); From 7366f853a529301145d8c6d9d84f58b81bfcea9b Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 18:05:08 -0400 Subject: [PATCH 09/12] Test various types of queries --- tests/Database/Validator/QueryValidatorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php index fbf3f3a37..0d1d646eb 100644 --- a/tests/Database/Validator/QueryValidatorTest.php +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -81,8 +81,8 @@ public function testQuery() { $validator = new QueryValidator($this->schema); - $this->assertEquals(true, $validator->isValid(Query::parse('title.equal("Iron Man")'))); - $this->assertEquals(true, $validator->isValid(Query::parse('title.equal("Iron Man", "Ant Man")'))); + $this->assertEquals(true, $validator->isValid(Query::parse('title.notEqual("Iron Man", "Ant Man")'))); + $this->assertEquals(true, $validator->isValid(Query::parse('description.equal("Best movie ever")'))); $this->assertEquals(true, $validator->isValid(Query::parse('rating.greater(4)'))); } From ea0c62237fea1b66c238a9477c32810a7de711a2 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 28 Apr 2021 18:08:20 -0400 Subject: [PATCH 10/12] Test floats - gettype returns double for legacy reasons --- src/Database/Database.php | 2 +- tests/Database/Validator/QueryValidatorTest.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index f9b176b9c..c087a6f93 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -13,7 +13,7 @@ class Database // Simple Types const VAR_STRING = 'string'; const VAR_INTEGER = 'integer'; - const VAR_FLOAT = 'float'; + const VAR_FLOAT = 'double'; const VAR_BOOLEAN = 'boolean'; // Relationships Types diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php index 0d1d646eb..4769f1752 100644 --- a/tests/Database/Validator/QueryValidatorTest.php +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -84,6 +84,13 @@ public function testQuery() $this->assertEquals(true, $validator->isValid(Query::parse('title.notEqual("Iron Man", "Ant Man")'))); $this->assertEquals(true, $validator->isValid(Query::parse('description.equal("Best movie ever")'))); $this->assertEquals(true, $validator->isValid(Query::parse('rating.greater(4)'))); + + // Debugging floats + // $query = Query::parse('price.lesserEqual(6.50)'); + // $validator->isValid(Query::parse('price.lesserEqual(6.50)')); + // var_dump($validator->getDescription()); + + $this->assertEquals(true, $validator->isValid(Query::parse('price.lesserEqual(6.50)'))); } public function testInvalidOperator() From 25aed1bcbad7857adcc121c0a90f46bafdeab161 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Thu, 29 Apr 2021 11:14:51 -0400 Subject: [PATCH 11/12] Add assertions for validator response --- tests/Database/Validator/QueryValidatorTest.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php index 4769f1752..39a345848 100644 --- a/tests/Database/Validator/QueryValidatorTest.php +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -97,8 +97,9 @@ public function testInvalidOperator() { $validator = new QueryValidator($this->schema); - $validator->isValid(Query::parse('title.eqqual("Iron Man")')); + $response = $validator->isValid(Query::parse('title.eqqual("Iron Man")')); + $this->assertEquals(false, $response); $this->assertEquals('Query operator invalid: eqqual', $validator->getDescription()); } @@ -106,8 +107,9 @@ public function testAttributeNotFound() { $validator = new QueryValidator($this->schema); - $validator->isValid(Query::parse('name.equal("Iron Man")')); + $response = $validator->isValid(Query::parse('name.equal("Iron Man")')); + $this->assertEquals(false, $response); $this->assertEquals('Attribute not found in schema: name', $validator->getDescription()); } @@ -115,9 +117,9 @@ public function testAttributeWrongType() { $validator = new QueryValidator($this->schema); - $query = Query::parse('title.equal(1776)'); - $validator->isValid($query); + $response = $validator->isValid(Query::parse('title.equal(1776)')); + $this->assertEquals(false, $response); $this->assertEquals('Query type does not match expected: string', $validator->getDescription()); } } From 1c6daa33488a501653759c43aa5092e3e56fbbe7 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Thu, 29 Apr 2021 11:22:51 -0400 Subject: [PATCH 12/12] Remove debugging code --- tests/Database/Validator/QueryValidatorTest.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/Database/Validator/QueryValidatorTest.php b/tests/Database/Validator/QueryValidatorTest.php index 39a345848..4ad863158 100644 --- a/tests/Database/Validator/QueryValidatorTest.php +++ b/tests/Database/Validator/QueryValidatorTest.php @@ -85,11 +85,6 @@ public function testQuery() $this->assertEquals(true, $validator->isValid(Query::parse('description.equal("Best movie ever")'))); $this->assertEquals(true, $validator->isValid(Query::parse('rating.greater(4)'))); - // Debugging floats - // $query = Query::parse('price.lesserEqual(6.50)'); - // $validator->isValid(Query::parse('price.lesserEqual(6.50)')); - // var_dump($validator->getDescription()); - $this->assertEquals(true, $validator->isValid(Query::parse('price.lesserEqual(6.50)'))); }