Skip to content

Commit

Permalink
Added some table related methods (#12)
Browse files Browse the repository at this point in the history
- createTable
- dropTable
- truncateTable

Added circleci badge
  • Loading branch information
mmoreram authored Feb 25, 2020
1 parent aed7233 commit 3bbe4b4
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 136 deletions.
61 changes: 58 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# DBAL for ReactPHP

This is a DBAL on top of ReactPHP SQL libraries and Doctrine QueryBuilder
implementation.
[![CircleCI](https://circleci.com/gh/driftphp/reactphp-dbal.svg?style=svg)](https://circleci.com/gh/driftphp/reactphp-dbal)

This is a DBAL on top of ReactPHP SQL clients and Doctrine model implementation.
You will be able to use

- Doctrine QueryBuilder model
- Doctrine Schema model
- Easy-to-use shortcuts for common operations
- and much more support is being added right now

> Attention. Only for proof of concept ATM. Do not use this library on
> production until the first stable version is tagged.
Expand Down Expand Up @@ -183,6 +190,54 @@ $connection
});
```

### Create table

You can easily create a new table with basic information. Needs the table name
and an array of fields and types. Strings are considered with length `255`.
First field position in the array will be considered as primary key. Returns a
Promise with, eventually, the connection.

```php
$connection->createTable('test', [
'id' => 'string',
'name' => 'string',
]);
```

This is a basic table creation method. To create more complex tables, you can
use Doctrine's Schema model. You can execute all Schema SQLs generated by using
this method inside Connection named `executeSchema`. You'll find more
information about this Schema model in
[Doctrine documentation](https://www.doctrine-project.org/projects/doctrine-dbal/en/2.10/reference/schema-representation.html)

```php
$schema = new Schema();
$table = $schema->createTable('test');
$table->addColumn('id', 'string');
// ...

$connection->executeSchema($schema);
```

### Drop table

You can easily drop an existing table. Needs just the table name, and returns,
eventually, the connection.

```php
$connection->dropTable('test');
```

### Truncate table

You can easily truncate an existing table. Needs just the table name, and returns,
eventually, the connection.

```php
$connection->truncateTable('test');
```

## Tests

You can run tests by running `docker-compose up` and by doing `phpunit`.
You can run tests by running `docker-compose up` and by doing
`php vendor/bin/phpunit`.
118 changes: 118 additions & 0 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\DBAL\Schema\Schema;
use Drift\DBAL\Driver\Driver;
use Drift\DBAL\Mock\MockedDBALConnection;
use Drift\DBAL\Mock\MockedDriver;
use React\Promise\PromiseInterface;
use function React\Promise\map;

/**
* Class Connection.
Expand Down Expand Up @@ -154,6 +158,40 @@ public function queryBySQL(string $sql, array $parameters = []): PromiseInterfac
->query($sql, $parameters);
}

/**
* Execute, sequentially, an array of sqls
*
* @param string[] $sqls
*
* @return PromiseInterface<Connection>
*/
public function executeSQLs(array $sqls): PromiseInterface
{
return
map($sqls, function(string $sql) {
return $this->queryBySQL($sql);
})
->then(function() {
return $this;
});
}

/**
* Execute an schema
*
* @param Schema $schema
*
* @return PromiseInterface<Connection>
*/
public function executeSchema(Schema $schema): PromiseInterface
{
return $this
->executeSQLs($schema->toSql($this->platform))
->then(function() {
return $this;
});
}

/**
* Shortcuts.
*/
Expand Down Expand Up @@ -309,6 +347,86 @@ public function upsert(
});
}

/**
* Table related shortcuts
*/

/**
* Easy shortcut for creating tables. Fields is just a simple key value,
* being the key the name of the field, and the value the type. By default,
* Varchar types have length 255.
*
* First field is considered as primary key.
*
* @param string $name
* @param array $fields
*
* @return PromiseInterface<Connection>
*
* @throws InvalidArgumentException
* @throws TableExistsException
*/
public function createTable(
string $name,
array $fields
) : PromiseInterface
{
if (empty($fields)) {
throw InvalidArgumentException::fromEmptyFieldsArray();
}

$schema = new Schema();
$table = $schema->createTable($name);
foreach ($fields as $field => $type) {
$extra = [];
if ($type = 'string') {
$extra = ['length' => 255];
}

$table->addColumn($field, $type, $extra);
}

$table->setPrimaryKey([array_key_first($fields)]);

return $this->executeSchema($schema);
}

/**
* @param string $name
*
* @return PromiseInterface<Connection>
*
* @throws TableNotFoundException
*/
public function dropTable(string $name) : PromiseInterface
{
return $this
->queryBySQL("DROP TABLE $name")
->then(function() {
return $this;
});
}

/**
* @param string $name
*
* @return PromiseInterface<Connection>
*
* @throws TableNotFoundException
*/
public function truncateTable(string $name) : PromiseInterface
{
$truncateTableQuery = $this
->platform
->getTruncateTableSQL($name);

return $this
->queryBySQL($truncateTableQuery)
->then(function() {
return $this;
});
}

/**
* Get result by where clause.
*
Expand Down
6 changes: 2 additions & 4 deletions src/Driver/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
namespace Drift\DBAL\Driver;

use Drift\DBAL\Credentials;
use Drift\DBAL\Result;
use React\Promise\PromiseInterface;

/**
Expand All @@ -27,9 +28,6 @@ interface Driver
* Attempts to create a connection with the database.
*
* @param Credentials $credentials
* @param array $options
*
* @return PromiseInterface
*/
public function connect(Credentials $credentials);

Expand All @@ -39,7 +37,7 @@ public function connect(Credentials $credentials);
* @param string $sql
* @param array $parameters
*
* @return PromiseInterface
* @return PromiseInterface<Result>
*/
public function query(
string $sql,
Expand Down
36 changes: 28 additions & 8 deletions tests/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

namespace Drift\DBAL\Tests;

use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Drift\DBAL\Connection;
Expand Down Expand Up @@ -46,26 +47,45 @@ abstract class ConnectionTest extends TestCase
abstract protected function getConnection(LoopInterface $loop): Connection;

/**
* Create database and table.
*
* @param Connection $connection
*
* @return PromiseInterface
*/
abstract protected function createInfrastructure(Connection $connection): PromiseInterface;
protected function createInfrastructure(Connection $connection): PromiseInterface
{
return $connection
->createTable('test', [
'id' => 'string',
'field1' => 'string',
'field2' => 'string'
])
->otherwise(function(TableExistsException $_) use ($connection) {
// Silent pass

return $connection;
})
->then(function (Connection $connection) {
return $connection->truncateTable('test');
});
}

/**
* Drop infrastructure.
*
* @param Connection $connection
*
* @return PromiseInterface
*/
abstract protected function dropInfrastructure(Connection $connection): PromiseInterface;
protected function dropInfrastructure(Connection $connection): PromiseInterface
{
return $connection
->dropTable('test')
->otherwise(function (TableNotFoundException $_) use ($connection) {
// Silent pass

return $connection;
});
}

/**
* Create database and table.
*
* @param Connection $connection
*
* @return PromiseInterface
Expand Down
40 changes: 0 additions & 40 deletions tests/MysqlConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,44 +45,4 @@ protected function getConnection(LoopInterface $loop): Connection
'test'
), $mysqlPlatform);
}

/**
* Create database and table.
*
* @param Connection $connection
*
* @return PromiseInterface
*/
protected function createInfrastructure(Connection $connection): PromiseInterface
{
return $connection
->queryBySQL('CREATE TABLE IF NOT EXISTS test (id VARCHAR(255) PRIMARY KEY, field1 VARCHAR(255), field2 VARCHAR (255))')
->then(function () use ($connection) {
return $connection
->queryBySQL('TRUNCATE TABLE test')
->then(function () use ($connection) {
return $connection;
});
});
}

/**
* Drop infrastructure.
*
* @param Connection $connection
*
* @return PromiseInterface
*/
protected function dropInfrastructure(Connection $connection): PromiseInterface
{
return $connection
->queryBySQL('DROP TABLE test')
->then(function () use ($connection) {
return $connection;
}, function (TableNotFoundException $exception) use ($connection) {
// Silent pass

return $connection;
});
}
}
Loading

0 comments on commit 3bbe4b4

Please sign in to comment.