From 897e5532b39e2046c2e9a592b8e27ded0cfa5f63 Mon Sep 17 00:00:00 2001 From: fogelito Date: Mon, 6 Mar 2023 16:08:49 +0200 Subject: [PATCH 1/9] Dynamic collection Id --- src/Database/Adapter/MariaDB.php | 1 + src/Database/Adapter/Postgres.php | 1 + src/Database/Adapter/SQL.php | 4 ++++ src/Database/Database.php | 7 ++++++- src/Database/Validator/Structure.php | 4 ++++ tests/Database/Base.php | 26 ++++++++++++++++++++++++-- 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index c1cef9de4..70dea5928 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -1063,6 +1063,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true): str return "VARCHAR({$size})"; + case Database::VAR_INTSTRING: case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554 $signed = ($signed) ? '' : ' UNSIGNED'; diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index c0c77c700..1572c534c 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -1057,6 +1057,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true): str return "VARCHAR({$size})"; break; + case Database::VAR_INTSTRING: case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554 if ($size >= 8) { // INT = 4 bytes, BIGINT = 8 bytes diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index 3fad2572d..abbdc15dd 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -362,6 +362,10 @@ public function getAttributeWidth(Document $collection): int case Database::VAR_DATETIME: $total += 19; // 2022-06-26 14:46:24 break; + + case Database::VAR_INTSTRING: + $total += 8; + break; default: throw new Exception('Unknown Type'); break; diff --git a/src/Database/Database.php b/src/Database/Database.php index 557b7b4e6..b8d89ebcf 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -22,6 +22,7 @@ class Database const VAR_STRING = 'string'; // Simple Types const VAR_INTEGER = 'integer'; + const VAR_INTSTRING = 'intstring'; const VAR_FLOAT = 'double'; const VAR_BOOLEAN = 'boolean'; const VAR_DATETIME = 'datetime'; @@ -757,7 +758,8 @@ public function createAttribute(string $collection, string $id, string $type, in case self::VAR_FLOAT: case self::VAR_BOOLEAN: case self::VAR_DATETIME: - break; + case self::VAR_INTSTRING: + break; default: throw new Exception('Unknown attribute type: ' . $type); break; @@ -1995,6 +1997,9 @@ public function casting(Document $collection, Document $document): Document case self::VAR_INTEGER: $node = (int)$node; break; + case self::VAR_INTSTRING: + // let's keeps it string at this point as it comes out from the DB can be used by all + break; case self::VAR_FLOAT: $node = (float)$node; break; diff --git a/src/Database/Validator/Structure.php b/src/Database/Validator/Structure.php index ece18ce0d..8e0116ef7 100644 --- a/src/Database/Validator/Structure.php +++ b/src/Database/Validator/Structure.php @@ -252,6 +252,10 @@ public function isValid($document): bool $validator = new Integer(); break; + case Database::VAR_INTSTRING: + $validator = new Text(50, min: 0); + break; + case Database::VAR_FLOAT: $validator = new FloatValidator(); break; diff --git a/tests/Database/Base.php b/tests/Database/Base.php index e2e56956a..ba8912088 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -336,6 +336,15 @@ public function testCreateCollectionWithSchema() 'array' => false, 'filters' => [], ]), + new Document([ + '$id' => ID::custom('collection_id'), + 'type' => Database::VAR_INTSTRING, + 'size' => 8, + 'required' => true, + 'signed' => false, + 'array' => false, + 'filters' => [], + ]), ]; $indexes = [ @@ -360,6 +369,13 @@ public function testCreateCollectionWithSchema() 'lengths' => [], 'orders' => ['DESC', 'ASC'], ]), + new Document([ + '$id' => ID::custom('index4'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['collection_id'], + 'lengths' => [], + 'orders' => ['DESC', 'ASC'], + ]), ]; $collection = static::getDatabase()->createCollection('withSchema', $attributes, $indexes); @@ -368,7 +384,7 @@ public function testCreateCollectionWithSchema() $this->assertEquals('withSchema', $collection->getId()); $this->assertIsArray($collection->getAttribute('attributes')); - $this->assertCount(3, $collection->getAttribute('attributes')); + $this->assertCount(4, $collection->getAttribute('attributes')); $this->assertEquals('attribute1', $collection->getAttribute('attributes')[0]['$id']); $this->assertEquals(Database::VAR_STRING, $collection->getAttribute('attributes')[0]['type']); $this->assertEquals('attribute2', $collection->getAttribute('attributes')[1]['$id']); @@ -377,7 +393,7 @@ public function testCreateCollectionWithSchema() $this->assertEquals(Database::VAR_BOOLEAN, $collection->getAttribute('attributes')[2]['type']); $this->assertIsArray($collection->getAttribute('indexes')); - $this->assertCount(3, $collection->getAttribute('indexes')); + $this->assertCount(4, $collection->getAttribute('indexes')); $this->assertEquals('index1', $collection->getAttribute('indexes')[0]['$id']); $this->assertEquals(Database::INDEX_KEY, $collection->getAttribute('indexes')[0]['type']); $this->assertEquals('index2', $collection->getAttribute('indexes')[1]['$id']); @@ -385,6 +401,12 @@ public function testCreateCollectionWithSchema() $this->assertEquals('index3', $collection->getAttribute('indexes')[2]['$id']); $this->assertEquals(Database::INDEX_KEY, $collection->getAttribute('indexes')[2]['type']); + $doc = static::getDatabase()->createDocument('withSchema', new Document([ + 'collection_id' => $collection->getInternalId() + ])); + + $this->assertIsString($doc->getAttribute('collection_id')); + static::getDatabase()->deleteCollection('withSchema'); // Test collection with dash (+attribute +index) From eb00fa7aa160955eef2d44a9e5a9b0f0bba5ca35 Mon Sep 17 00:00:00 2001 From: fogelito Date: Tue, 7 Mar 2023 08:51:08 +0200 Subject: [PATCH 2/9] VAR_INTSTRING type INT(11) UNSIGNED --- src/Database/Adapter/MariaDB.php | 2 ++ tests/Database/Base.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index 70dea5928..8c28fbca6 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -1064,6 +1064,8 @@ protected function getSQLType(string $type, int $size, bool $signed = true): str return "VARCHAR({$size})"; case Database::VAR_INTSTRING: + return 'INT(11) UNSIGNED'; // Same as Primary Key + case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554 $signed = ($signed) ? '' : ' UNSIGNED'; diff --git a/tests/Database/Base.php b/tests/Database/Base.php index ba8912088..23ac71e81 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -339,7 +339,7 @@ public function testCreateCollectionWithSchema() new Document([ '$id' => ID::custom('collection_id'), 'type' => Database::VAR_INTSTRING, - 'size' => 8, + 'size' => 0, 'required' => true, 'signed' => false, 'array' => false, From c7bc96988c2ba8a9c68e49516a1b51e3fbbe1a1f Mon Sep 17 00:00:00 2001 From: fogelito Date: Tue, 7 Mar 2023 09:27:58 +0200 Subject: [PATCH 3/9] int type without size --- src/Database/Adapter/MariaDB.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index 8c28fbca6..3f915358c 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -1064,7 +1064,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true): str return "VARCHAR({$size})"; case Database::VAR_INTSTRING: - return 'INT(11) UNSIGNED'; // Same as Primary Key + return 'INT UNSIGNED'; // Same as Primary Key Sqlite does not allow INT(11) case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554 $signed = ($signed) ? '' : ' UNSIGNED'; From d7cfb36b60f22ab5222f9af9f5b5013df2a631c4 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 8 Mar 2023 11:27:35 +0200 Subject: [PATCH 4/9] VAR_ID --- src/Database/Adapter/MariaDB.php | 2 +- src/Database/Adapter/Postgres.php | 4 +++- src/Database/Adapter/SQL.php | 8 +++++--- src/Database/Database.php | 8 ++++---- src/Database/Validator/Structure.php | 4 ++-- tests/Database/Base.php | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index 3f915358c..c60dd2efa 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -1063,7 +1063,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true): str return "VARCHAR({$size})"; - case Database::VAR_INTSTRING: + case Database::VAR_ID: return 'INT UNSIGNED'; // Same as Primary Key Sqlite does not allow INT(11) case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554 diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index 1572c534c..db77c2b9f 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -1057,7 +1057,9 @@ protected function getSQLType(string $type, int $size, bool $signed = true): str return "VARCHAR({$size})"; break; - case Database::VAR_INTSTRING: + case Database::VAR_ID: + return 'INTEGER'; + case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554 if ($size >= 8) { // INT = 4 bytes, BIGINT = 8 bytes diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index abbdc15dd..4ccd7bbbd 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -344,6 +344,11 @@ public function getAttributeWidth(Document $collection): int $total += 4; // INT takes 4 bytes } break; + + case Database::VAR_ID: + $total += 4; + break; + case Database::VAR_FLOAT: // DOUBLE takes 8 bytes $total += 8; @@ -363,9 +368,6 @@ public function getAttributeWidth(Document $collection): int $total += 19; // 2022-06-26 14:46:24 break; - case Database::VAR_INTSTRING: - $total += 8; - break; default: throw new Exception('Unknown Type'); break; diff --git a/src/Database/Database.php b/src/Database/Database.php index b8d89ebcf..87ae121a9 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -22,10 +22,10 @@ class Database const VAR_STRING = 'string'; // Simple Types const VAR_INTEGER = 'integer'; - const VAR_INTSTRING = 'intstring'; const VAR_FLOAT = 'double'; const VAR_BOOLEAN = 'boolean'; const VAR_DATETIME = 'datetime'; + const VAR_ID = 'id'; // Relationships Types const VAR_DOCUMENT = 'document'; @@ -758,7 +758,7 @@ public function createAttribute(string $collection, string $id, string $type, in case self::VAR_FLOAT: case self::VAR_BOOLEAN: case self::VAR_DATETIME: - case self::VAR_INTSTRING: + case self::VAR_ID: break; default: throw new Exception('Unknown attribute type: ' . $type); @@ -1997,8 +1997,8 @@ public function casting(Document $collection, Document $document): Document case self::VAR_INTEGER: $node = (int)$node; break; - case self::VAR_INTSTRING: - // let's keeps it string at this point as it comes out from the DB can be used by all + case self::VAR_ID: + // Not sure, maybe string as it fetched from DB? break; case self::VAR_FLOAT: $node = (float)$node; diff --git a/src/Database/Validator/Structure.php b/src/Database/Validator/Structure.php index 8e0116ef7..01b26cdaf 100644 --- a/src/Database/Validator/Structure.php +++ b/src/Database/Validator/Structure.php @@ -252,8 +252,8 @@ public function isValid($document): bool $validator = new Integer(); break; - case Database::VAR_INTSTRING: - $validator = new Text(50, min: 0); + case Database::VAR_ID: + $validator = new Text(20, min: 0); break; case Database::VAR_FLOAT: diff --git a/tests/Database/Base.php b/tests/Database/Base.php index 23ac71e81..90c67e406 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -338,7 +338,7 @@ public function testCreateCollectionWithSchema() ]), new Document([ '$id' => ID::custom('collection_id'), - 'type' => Database::VAR_INTSTRING, + 'type' => Database::VAR_ID, 'size' => 0, 'required' => true, 'signed' => false, From 50227c24df8c5d35d5b1eff97a2b80619dbc8325 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 8 Mar 2023 12:18:45 +0200 Subject: [PATCH 5/9] VAR_ID --- src/Database/Database.php | 2 +- src/Database/Validator/Structure.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 87ae121a9..55c319e65 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1998,7 +1998,7 @@ public function casting(Document $collection, Document $document): Document $node = (int)$node; break; case self::VAR_ID: - // Not sure, maybe string as it fetched from DB? + // String? since int can be string, but string can't be int? break; case self::VAR_FLOAT: $node = (float)$node; diff --git a/src/Database/Validator/Structure.php b/src/Database/Validator/Structure.php index 01b26cdaf..681559f43 100644 --- a/src/Database/Validator/Structure.php +++ b/src/Database/Validator/Structure.php @@ -253,7 +253,7 @@ public function isValid($document): bool break; case Database::VAR_ID: - $validator = new Text(20, min: 0); + $validator = new Text(24, min: 0); // Mongo Id length break; case Database::VAR_FLOAT: From fd54c01a78f5febf796bbcd58fb7c515fe93ee8f Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 8 Mar 2023 15:27:15 +0200 Subject: [PATCH 6/9] Some tests for VAR_ID --- tests/Database/Base.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/Database/Base.php b/tests/Database/Base.php index d1c615f9c..20b9c8cba 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -572,7 +572,7 @@ public function testCreateCollectionValidator(): void public function testCreateDocument(): Document { - static::getDatabase()->createCollection('documents'); + $collection = static::getDatabase()->createCollection('documents'); $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'string', Database::VAR_STRING, 128, true)); $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'integer', Database::VAR_INTEGER, 0, true)); @@ -582,6 +582,7 @@ public function testCreateDocument(): Document $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'colors', Database::VAR_STRING, 32, true, null, true, true)); $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'empty', Database::VAR_STRING, 32, false, null, true, true)); $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'with-dash', Database::VAR_STRING, 128, false, null)); + $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'collection_id', Database::VAR_ID, 4, false)); $document = static::getDatabase()->createDocument('documents', new Document([ '$permissions' => [ @@ -606,6 +607,7 @@ public function testCreateDocument(): Document 'colors' => ['pink', 'green', 'blue'], 'empty' => [], 'with-dash' => 'Works', + 'collection_id' => $collection->getInternalId(), ])); $this->assertNotEmpty(true, $document->getId()); @@ -623,6 +625,7 @@ public function testCreateDocument(): Document $this->assertEquals(['pink', 'green', 'blue'], $document->getAttribute('colors')); $this->assertEquals([], $document->getAttribute('empty')); $this->assertEquals('Works', $document->getAttribute('with-dash')); + $this->assertEquals($collection->getInternalId(), $document->getAttribute('collection_id')); return $document; } From e760c2d71e667d62638b2699039a4a47841717ac Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 8 Mar 2023 15:29:54 +0200 Subject: [PATCH 7/9] casting VAR_ID --- src/Database/Database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 300e8a054..a4c3d4003 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -2042,7 +2042,7 @@ public function casting(Document $collection, Document $document): Document $node = (int)$node; break; case self::VAR_ID: - // String? since int can be string, but string can't be int? + // Default as fetched is string, int can be string, but string can't be int break; case self::VAR_FLOAT: $node = (float)$node; From 4c962974e4b77a49da3c1f0fe124bf4ce3f9b116 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 8 Mar 2023 15:42:01 +0200 Subject: [PATCH 8/9] size is always internal --- src/Database/Database.php | 3 --- tests/Database/Base.php | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index a4c3d4003..99a8a7133 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -2041,9 +2041,6 @@ public function casting(Document $collection, Document $document): Document case self::VAR_INTEGER: $node = (int)$node; break; - case self::VAR_ID: - // Default as fetched is string, int can be string, but string can't be int - break; case self::VAR_FLOAT: $node = (float)$node; break; diff --git a/tests/Database/Base.php b/tests/Database/Base.php index 20b9c8cba..c1ed5ab16 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -582,7 +582,7 @@ public function testCreateDocument(): Document $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'colors', Database::VAR_STRING, 32, true, null, true, true)); $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'empty', Database::VAR_STRING, 32, false, null, true, true)); $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'with-dash', Database::VAR_STRING, 128, false, null)); - $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'collection_id', Database::VAR_ID, 4, false)); + $this->assertEquals(true, static::getDatabase()->createAttribute('documents', 'collection_id', Database::VAR_ID, 0, false)); $document = static::getDatabase()->createDocument('documents', new Document([ '$permissions' => [ From 0f1cce0c64e1bed5b8329fdb0d2da623dc7f999c Mon Sep 17 00:00:00 2001 From: Shmuel Fogel Date: Sun, 15 Oct 2023 11:32:12 +0300 Subject: [PATCH 9/9] Update src/Database/Database.php Co-authored-by: Jake Barnby --- src/Database/Database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 99a8a7133..fb57567b9 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -761,7 +761,7 @@ public function createAttribute(string $collection, string $id, string $type, in case self::VAR_BOOLEAN: case self::VAR_DATETIME: case self::VAR_ID: - break; + break; default: throw new Exception('Unknown attribute type: ' . $type); }