Skip to content

Commit

Permalink
Merge pull request #492 from utopia-php/schema-attributes
Browse files Browse the repository at this point in the history
Get schema attributes
  • Loading branch information
abnegate authored Dec 9, 2024
2 parents d3a8cae + 3fb18da commit 9cdcb8a
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,13 @@ abstract public function getSupportForSchemas(): bool;
*/
abstract public function getSupportForAttributes(): bool;

/**
* Are schema attributes supported?
*
* @return bool
*/
abstract public function getSupportForSchemaAttributes(): bool;

/**
* Is index supported?
*
Expand Down Expand Up @@ -1022,4 +1029,13 @@ abstract public function getConnectionId(): string;
* @return array<string>
*/
abstract public function getInternalIndexesKeys(): array;

/**
* Get Schema Attributes
*
* @param string $collection
* @return array<Document>
* @throws DatabaseException
*/
abstract public function getSchemaAttributes(string $collection): array;
}
52 changes: 52 additions & 0 deletions src/Database/Adapter/MariaDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,7 @@ public function updateDocuments(string $collection, Document $updates, array $do

$permissionsStmt->execute();
$permissions = $permissionsStmt->fetchAll();
$permissionsStmt->closeCursor();

$initial = [];
foreach (Database::PERMISSIONS as $type) {
Expand Down Expand Up @@ -2433,4 +2434,55 @@ protected function processException(PDOException $e): \Exception

return $e;
}

/**
* Get Schema Attributes
*
* @param string $collection
* @return array<Document>
* @throws DatabaseException
*/
public function getSchemaAttributes(string $collection): array
{
$schema = $this->getDatabase();
$collection = $this->getNamespace().'_'.$this->filter($collection);

try {
$stmt = $this->getPDO()->prepare('
SELECT
COLUMN_NAME as columnName,
COLUMN_DEFAULT as columnDefault,
IS_NULLABLE as isNullable,
DATA_TYPE as dataType,
CHARACTER_MAXIMUM_LENGTH as characterMaximumLength,
NUMERIC_PRECISION as numericPrecision,
NUMERIC_SCALE as numericScale,
DATETIME_PRECISION as datetimePrecision,
COLUMN_TYPE as columnType,
COLUMN_KEY as columnKey,
EXTRA as extra
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = :schema AND TABLE_NAME = :table
');
$stmt->bindParam(':schema', $schema);
$stmt->bindParam(':table', $collection);
$stmt->execute();
$results = $stmt->fetchAll();
$stmt->closeCursor();

foreach ($results as $index => $document) {
$results[$index] = new Document($document);
}

return $results;

} catch (PDOException $e) {
throw new DatabaseException('Failed to get schema attributes', $e->getCode(), $e);
}
}

public function getSupportForSchemaAttributes(): bool
{
return true;
}
}
15 changes: 15 additions & 0 deletions src/Database/Adapter/Mongo.php
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,16 @@ public function getSupportForGetConnectionId(): bool
return false;
}

/**
* Is get schema attributes supported?
*
* @return bool
*/
public function getSupportForSchemaAttributes(): bool
{
return false;
}

/**
* Get current attribute count from collection document
*
Expand Down Expand Up @@ -1942,4 +1952,9 @@ public function getInternalIndexesKeys(): array
{
return [];
}

public function getSchemaAttributes(string $collection): array
{
return [];
}
}
10 changes: 10 additions & 0 deletions src/Database/Adapter/Postgres.php
Original file line number Diff line number Diff line change
Expand Up @@ -2397,6 +2397,16 @@ public function getSupportForJSONOverlaps(): bool
return false;
}

/**
* Is get schema attributes supported?
*
* @return bool
*/
public function getSupportForSchemaAttributes(): bool
{
return false;
}

/**
* @return string
*/
Expand Down
5 changes: 5 additions & 0 deletions src/Database/Adapter/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -1151,4 +1151,9 @@ protected function processException(PDOException $e): \Exception
{
return $e;
}

public function getSchemaAttributes(string $collection): array
{
return [];
}
}
10 changes: 10 additions & 0 deletions src/Database/Adapter/SQLite.php
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,16 @@ public function getSupportForGetConnectionId(): bool
return false;
}

/**
* Is get schema attributes supported?
*
* @return bool
*/
public function getSupportForSchemaAttributes(): bool
{
return false;
}

/**
* Get SQL Index Type
*
Expand Down
12 changes: 12 additions & 0 deletions src/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -6037,4 +6037,16 @@ public function analyzeCollection(string $collection): bool
{
return $this->adapter->analyzeCollection($collection);
}

/**
* Get Schema Attributes
*
* @param string $collection
* @return array<Document>
* @throws DatabaseException
*/
public function getSchemaAttributes(string $collection): array
{
return $this->adapter->getSchemaAttributes($collection);
}
}
63 changes: 63 additions & 0 deletions tests/e2e/Adapter/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,69 @@ public function testPurgeCollectionCache(): void
$this->assertArrayHasKey('age', $document);
}

public function testSchemaAttribute(): void
{
if (!$this->getDatabase()->getAdapter()->getSupportForSchemaAttributes()) {
$this->expectNotToPerformAssertions();
return;
}

$collection = 'schema_attributes';
$db = static::getDatabase();

$this->assertEmpty($db->getSchemaAttributes('no_such_collection'));

$db->createCollection($collection);

$db->createAttribute($collection, 'username', Database::VAR_STRING, 128, true);
$db->createAttribute($collection, 'story', Database::VAR_STRING, 20000, true);
$db->createAttribute($collection, 'string_list', Database::VAR_STRING, 128, true, null, true, true);
$db->createAttribute($collection, 'dob', Database::VAR_DATETIME, 0, false, '2000-06-12T14:12:55.000+00:00', true, false, null, [], ['datetime']);

$attributes = [];
foreach ($db->getSchemaAttributes($collection) as $attribute) {
/**
* @var Document $attribute
*/
$attributes[$attribute->getAttribute('columnName')] = $attribute;
}

$attribute = $attributes['username'];
$this->assertEquals('username', $attribute['columnName']);
$this->assertEquals('varchar', $attribute['dataType']);
$this->assertEquals('varchar(128)', $attribute['columnType']);
$this->assertEquals('128', $attribute['characterMaximumLength']);
$this->assertEquals('YES', $attribute['isNullable']);

$attribute = $attributes['story'];
$this->assertEquals('story', $attribute['columnName']);
$this->assertEquals('text', $attribute['dataType']);
$this->assertEquals('text', $attribute['columnType']);
$this->assertEquals('65535', $attribute['characterMaximumLength']);

$attribute = $attributes['string_list'];
$this->assertEquals('string_list', $attribute['columnName']);
$this->assertTrue(in_array($attribute['dataType'], ['json', 'longtext'])); // mysql vs maria
$this->assertTrue(in_array($attribute['columnType'], ['json', 'longtext']));
$this->assertTrue(in_array($attribute['characterMaximumLength'], [null, '4294967295']));
$this->assertEquals('YES', $attribute['isNullable']);

$attribute = $attributes['dob'];
$this->assertEquals('dob', $attribute['columnName']);
$this->assertEquals('datetime', $attribute['dataType']);
$this->assertEquals('datetime(3)', $attribute['columnType']);
$this->assertEquals(null, $attribute['characterMaximumLength']);
$this->assertEquals('3', $attribute['datetimePrecision']);

if ($db->getSharedTables()) {
$attribute = $attributes['_tenant'];
$this->assertEquals('_tenant', $attribute['columnName']);
$this->assertEquals('int', $attribute['dataType']);
$this->assertEquals('10', $attribute['numericPrecision']);
$this->assertTrue(in_array($attribute['columnType'], ['int unsigned', 'int(11) unsigned']));
}
}

public function testCreateDeleteAttribute(): void
{
static::getDatabase()->createCollection('attributes');
Expand Down

0 comments on commit 9cdcb8a

Please sign in to comment.