gnu-social/docs/developer/src/database.md

88 KiB

Database

GNU social has to store a large collection of data for rapid search and retrieval.

GNU social can use different Relational Database Management Systems, namely PostgreSQL and MariaDB.

The storage is interfaced using an Object-Relational Mapper (ORM) paradigm. As the term ORM already hints at, this allows to simplify the translation between database rows and the PHP object model.

Transactions

An EntityManager and the underlying UnitOfWork employ a strategy called transactional write-behind that delays the execution of SQL statements in order to execute them in the most efficient way and at the end of a transaction so that all write locks are quickly released. You should see Doctrine as a tool to synchronize your in-memory objects with the database in well defined units of work. Work with your objects and modify them as usual. For the most part, Doctrine ORM already takes care of proper transaction demarcation for you: All the write operations (INSERT/UPDATE/DELETE) are queued until EntityManager#flush() is invoked which wraps all of these changes in a single transaction.

Declaring an Entity

<?php
namespace Plugin\Embed\Entity;

use App\Core\Entity;
use DateTimeInterface;
class AttachmentEmbed extends Entity
{
    // These tags are meant to be literally included and will be populated with the appropriate fields, setters and getters by `bin/generate_entity_fields`
    // {{{ Autocode
    // }}} Autocode
        
    
    public static function schemaDef()
    {
        return [
            'name'   => 'attachment_embed',
            'fields' => [
                'attachment_id' => ['type' => 'int', 'not null' => true, 'foreign key' => true, 'target' => 'Attachment.id', 'multiplicity' => 'one to one', 'description' => 'Embed for that URL/file'],
                'mimetype'      => ['type' => 'varchar', 'length' => 50, 'description' => 'mime type of resource'],
                'filename'      => ['type' => 'varchar', 'length' => 191, 'description' => 'file name of resource when available'],
                'media_url'     => ['type' => 'text', 'description' => 'URL for this Embed resource when applicable (photo, link)'],
                'modified'      => ['type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'],
            ],
            'primary key'  => ['attachment_id'],
        ];
    }
}

Retrieving an entity

use App\Core\DB\DB;
use App\Util\Exception\NotFoundException;
use App\Util\Exception\DuplicateFoundException;

/// ...

try {
    $object = DB::findOneBy('attachment_embed', ['attachment_id' => $attachment->getId()]);
} catch (NotFoundException) {
    // Not found
} catch (DuplicateFoundException) {
    // Integrety compromised
}

Deleting an Entity

DB::delete($object);

Creating an Entity

$embed_data['attachment_id'] = $attachment->getId();
DB::persist(Entity\AttachmentEmbed::create($embed_data));
DB::flush();

Querying the database --------------------- When the ORM isn't powerful enough to satisfy your needs, you can resort to Doctrine Query Language, which is preferred and has been extended so you can use table names rather than class names, or Doctrine QueryBuilder.