Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 6 additions & 19 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM composer:2.0 AS composer
FROM composer:2.8 AS composer

WORKDIR /usr/local/src/

Expand All @@ -11,13 +11,12 @@ RUN composer install \
--no-plugins \
--no-scripts \
--prefer-dist
FROM php:8.3.10-cli-alpine3.20 AS compile

FROM php:8.3.19-cli-alpine3.21 AS compile

ENV PHP_REDIS_VERSION="6.0.2" \
PHP_SWOOLE_VERSION="v5.1.3" \
PHP_MONGO_VERSION="1.16.1" \
PHP_XDEBUG_VERSION="3.3.2"
PHP_SWOOLE_VERSION="v5.1.7" \
PHP_XDEBUG_VERSION="3.4.2"

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

Expand Down Expand Up @@ -58,20 +57,10 @@ RUN \
&& ./configure --enable-http2 \
&& make && make install

## MongoDB Extension
FROM compile AS mongodb
RUN \
git clone --depth 1 --branch $PHP_MONGO_VERSION https://github.com/mongodb/mongo-php-driver.git \
&& cd mongo-php-driver \
&& git submodule update --init \
&& phpize \
&& ./configure \
&& make && make install

## PCOV Extension
FROM compile AS pcov
RUN \
git clone https://github.com/krakjoe/pcov.git \
git clone --depth 1 https://github.com/krakjoe/pcov.git \
&& cd pcov \
&& phpize \
&& ./configure --enable-pcov \
Expand All @@ -97,7 +86,6 @@ WORKDIR /usr/src/code

RUN echo extension=redis.so >> /usr/local/etc/php/conf.d/redis.ini
RUN echo extension=swoole.so >> /usr/local/etc/php/conf.d/swoole.ini
RUN echo extension=mongodb.so >> /usr/local/etc/php/conf.d/mongodb.ini
RUN echo extension=pcov.so >> /usr/local/etc/php/conf.d/pcov.ini
RUN echo extension=xdebug.so >> /usr/local/etc/php/conf.d/xdebug.ini

Expand All @@ -110,7 +98,6 @@ RUN echo "memory_limit=1024M" >> $PHP_INI_DIR/php.ini
COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor
COPY --from=swoole /usr/local/lib/php/extensions/no-debug-non-zts-20230831/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
COPY --from=redis /usr/local/lib/php/extensions/no-debug-non-zts-20230831/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
COPY --from=mongodb /usr/local/lib/php/extensions/no-debug-non-zts-20230831/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
COPY --from=pcov /usr/local/lib/php/extensions/no-debug-non-zts-20230831/pcov.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
COPY --from=xdebug /usr/local/lib/php/extensions/no-debug-non-zts-20230831/xdebug.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/

Expand Down
11 changes: 0 additions & 11 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,6 @@ services:
- "8704:3306"
environment:
- MYSQL_ROOT_PASSWORD=password

mongo:
image: mongo:5.0
container_name: utopia-mongo
networks:
- database
ports:
- "8705:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example

mysql:
image: mysql:8.0.33
Expand Down
36 changes: 33 additions & 3 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ abstract class Adapter

protected ?int $tenant = null;

protected bool $tenantPerDocument = false;

protected int $inTransaction = 0;

/**
Expand Down Expand Up @@ -190,6 +192,34 @@ public function getTenant(): ?int
return $this->tenant;
}

/**
* Set Tenant Per Document.
*
* Set whether to use a different tenant for each document
*
* @param bool $tenantPerDocument
*
* @return bool
*/
public function setTenantPerDocument(bool $tenantPerDocument): bool
{
$this->tenantPerDocument = $tenantPerDocument;

return true;
}

/**
* Get Tenant Per Document.
*
* Get whether to use a different tenant for each document
*
* @return bool
*/
public function getTenantPerDocument(): bool
{
return $this->tenantPerDocument;
}

/**
* Set metadata for query comments
*
Expand Down Expand Up @@ -261,7 +291,7 @@ abstract public function setTimeout(int $milliseconds, string $event = Database:
public function clearTimeout(string $event): void
{
// Clear existing callback
$this->before($event, 'timeout', null);
$this->before($event, 'timeout');
}

/**
Expand Down Expand Up @@ -301,7 +331,6 @@ abstract public function rollbackTransaction(): bool;
* Check if a transaction is active.
*
* @return bool
* @throws DatabaseException
*/
public function inTransaction(): bool
{
Expand Down Expand Up @@ -482,7 +511,7 @@ abstract public function createAttribute(string $collection, string $id, string
* @param int $size
* @param bool $signed
* @param bool $array
* @param string $newKey
* @param string|null $newKey
*
* @return bool
*/
Expand Down Expand Up @@ -620,6 +649,7 @@ abstract public function createDocuments(string $collection, array $documents):
* Update Document
*
* @param string $collection
* @param string $id
* @param Document $document
*
* @return Document
Expand Down
22 changes: 9 additions & 13 deletions src/Database/Adapter/MariaDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,9 @@ public function createAttribute(string $collection, string $id, string $type, in
* @param int $size
* @param bool $signed
* @param bool $array
* @param string $newKey
* @param string|null $newKey
* @return bool
* @throws Exception
* @throws PDOException
* @throws DatabaseException
*/
public function updateAttribute(string $collection, string $id, string $type, int $size, bool $signed = true, bool $array = false, ?string $newKey = null): bool
{
Expand Down Expand Up @@ -854,7 +853,7 @@ public function createDocument(string $collection, Document $document): Document
$attributes['_permissions'] = \json_encode($document->getPermissions());

if ($this->sharedTables) {
$attributes['_tenant'] = $this->tenant;
$attributes['_tenant'] = $document->getTenant();
}

$name = $this->filter($collection);
Expand Down Expand Up @@ -897,13 +896,13 @@ public function createDocument(string $collection, Document $document): Document

$attributeIndex = 0;
foreach ($attributes as $value) {
if (is_array($value)) {
$value = json_encode($value);
if (\is_array($value)) {
$value = \json_encode($value);
}

$bindKey = 'key_' . $attributeIndex;
$attribute = $this->filter($attribute);
$value = (is_bool($value)) ? (int)$value : $value;
$value = (\is_bool($value)) ? (int)$value : $value;
$stmt->bindValue(':' . $bindKey, $value, $this->getPDOType($value));
$attributeIndex++;
}
Expand Down Expand Up @@ -942,13 +941,13 @@ public function createDocument(string $collection, Document $document): Document
$stmtPermissions = $this->getPDO()->prepare($sqlPermissions);

if ($this->sharedTables) {
$stmtPermissions->bindValue(':_tenant', $this->tenant);
$stmtPermissions->bindValue(':_tenant', $document->getTenant());
}
}

$stmt->execute();

$document['$internalId'] = $this->getDocument($collection, $document->getId(), [Query::select(['$internalId'])])->getInternalId();
$document['$internalId'] = $this->pdo->lastInsertId();

Comment thread
abnegate marked this conversation as resolved.
if (empty($document['$internalId'])) {
throw new DatabaseException('Error creating document empty "$internalId"');
Expand Down Expand Up @@ -1016,9 +1015,6 @@ public function createDocuments(string $collection, array $documents): array
$documentIds = [];

foreach ($documents as $document) {
/**
* @var Document $document
*/
$attributes = $document->getAttributes();
$attributes['_uid'] = $document->getId();
$attributes['_createdAt'] = $document->getCreatedAt();
Expand All @@ -1033,7 +1029,7 @@ public function createDocuments(string $collection, array $documents): array
}

if ($this->sharedTables) {
$attributes['_tenant'] = $this->tenant;
$attributes['_tenant'] = $document->getTenant();
}

$bindKeys = [];
Expand Down
2 changes: 1 addition & 1 deletion src/Database/Adapter/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public function getDocument(string $collection, string $id, array $queries = [],
unset($document['_uid']);
}
if (\array_key_exists('_tenant', $document)) {
$document['$tenant'] = $document['_tenant'];
$document['$tenant'] = (int)$document['_tenant'];
unset($document['_tenant']);
}
if (\array_key_exists('_createdAt', $document)) {
Expand Down
60 changes: 59 additions & 1 deletion src/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,29 @@ public function withTenant(?int $tenant, callable $callback): mixed
}
}

/**
* Set whether to allow creating documents with tenant set per document.
*
* @param bool $enabled
* @return static
*/
public function setTenantPerDocument(bool $enabled): static
{
$this->adapter->setTenantPerDocument($enabled);

return $this;
}

/**
* Get whether to allow creating documents with tenant set per document.
*
* @return bool
*/
public function getTenantPerDocument(): bool
{
return $this->adapter->getTenantPerDocument();
}

public function getPreserveDates(): bool
{
return $this->preserveDates;
Expand Down Expand Up @@ -3346,11 +3369,19 @@ public function createDocument(string $collection, Document $document): Document
if (
$collection !== self::METADATA
&& $this->adapter->getSharedTables()
&& !$this->adapter->getTenantPerDocument()
&& empty($this->adapter->getTenant())
) {
throw new DatabaseException('Missing tenant. Tenant must be set when table sharing is enabled.');
}

if (
!$this->adapter->getSharedTables()
&& $this->adapter->getTenantPerDocument()
) {
throw new DatabaseException('Shared tables must be enabled if tenant per document is enabled.');
}

$collection = $this->silent(fn () => $this->getCollection($collection));

if ($collection->getId() !== self::METADATA) {
Expand All @@ -3372,7 +3403,16 @@ public function createDocument(string $collection, Document $document): Document
->setAttribute('$updatedAt', empty($updatedAt) || !$this->preserveDates ? $time : $updatedAt);

if ($this->adapter->getSharedTables()) {
$document['$tenant'] = (string)$this->adapter->getTenant();
Comment thread
abnegate marked this conversation as resolved.
if ($this->adapter->getTenantPerDocument()) {
if (
$collection->getId() !== static::METADATA
&& $document->getTenant() === null
) {
throw new DatabaseException('Missing tenant. Tenant must be set when tenant per document is enabled.');
}
} else {
$document->setAttribute('$tenant', $this->adapter->getTenant());
}
}

$document = $this->encode($collection, $document);
Expand Down Expand Up @@ -3419,12 +3459,20 @@ public function createDocument(string $collection, Document $document): Document
* @param array<Document> $documents
* @param int $batchSize
* @return array<Document>
* @throws AuthorizationException
* @throws StructureException
* @throws NotFoundException
* @throws \Throwable
*/
public function createDocuments(
string $collection,
array $documents,
int $batchSize = self::INSERT_BATCH_SIZE,
): array {
if (!$this->adapter->getSharedTables() && $this->adapter->getTenantPerDocument()) {
throw new DatabaseException('Shared tables must be enabled if tenant per document is enabled.');
}

if (empty($documents)) {
return [];
}
Expand Down Expand Up @@ -3455,6 +3503,16 @@ public function createDocuments(
->setAttribute('$createdAt', empty($createdAt) || !$this->preserveDates ? $time : $createdAt)
->setAttribute('$updatedAt', empty($updatedAt) || !$this->preserveDates ? $time : $updatedAt);

if ($this->adapter->getSharedTables()) {
if ($this->adapter->getTenantPerDocument()) {
if ($document->getTenant() === null) {
throw new DatabaseException('Missing tenant. Tenant must be set when tenant per document is enabled.');
}
} else {
$document->setAttribute('$tenant', $this->adapter->getTenant());
}
}

$document = $this->encode($collection, $document);

$validator = new Structure(
Expand Down
12 changes: 12 additions & 0 deletions src/Database/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@ public function getUpdatedAt(): ?string
return $this->getAttribute('$updatedAt');
}

/**
* @return int|null
*/
public function getTenant(): ?int
{
$tenant = $this->getAttribute('$tenant');
if ($tenant !== null) {
return (int)$tenant;
}
return null;
}

/**
* Get Document Attributes
*
Expand Down
6 changes: 3 additions & 3 deletions src/Database/Validator/Structure.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ class Structure extends Validator
],
[
'$id' => '$tenant',
'type' => Database::VAR_STRING,
'size' => 36,
'type' => Database::VAR_INTEGER,
'size' => 8,
'required' => false,
'default' => null,
'signed' => true,
'signed' => false,
'array' => false,
'filters' => [],
],
Expand Down
Loading