Skip to content

Commit

Permalink
Add PostgreSQL Support (#24)
Browse files Browse the repository at this point in the history
Add PostgreSQL Support
- Updated workflow to include PostgreSQL matrix
- Updated Functions to use `withVariable`, `withParameter`, `withDataUse` & `withDeterminism`
- Updated Handler tests to use migration files from /tests/Migrations for PostgreSQL & MySQL

Authored-by: @beaudurrant
  • Loading branch information
beaudurrant authored Nov 30, 2021
1 parent cfa7367 commit e044faf
Show file tree
Hide file tree
Showing 30 changed files with 1,529 additions and 618 deletions.
65 changes: 62 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,67 @@ on:
branches: '*'

jobs:
test:

postgresql_tests:

runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
php-versions: [ '7.4', '8.0' ]
postgresql-versions: [ '12', '14' ]
name: PHP ${{ matrix.php-versions }} with postgreSQL ${{ matrix.postgresql-versions }}

services:
postgres:
image: postgres:${{ matrix.postgresql-versions }}
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: rootpassword
POSTGRES_DB: test
ports:
[ '5432:5432' ]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2
name: Check Out Code

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: pdo_pgsql

- name: Validate composer.json and composer.lock
run: composer validate

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress --no-suggest

- name: Setup Database
run: |
sudo apt update
cp tests/db.yml.example tests/db.yml
- name: Run test suite
run: ./vendor/bin/phpunit

mysql_tests:

runs-on: ubuntu-latest
timeout-minutes: 10
Expand Down Expand Up @@ -36,6 +96,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: pdo_mysql

- name: Validate composer.json and composer.lock
run: composer validate
Expand All @@ -56,8 +117,6 @@ jobs:
- name: Setup Database
run: |
sudo apt update
sudo apt install -y default-mysql-client
echo 'CREATE DATABASE IF NOT EXISTS test' | mysql -h 127.0.0.1 -u root -prootpassword
cp tests/db.yml.example tests/db.yml
- name: Run test suite
Expand Down
2 changes: 1 addition & 1 deletion doc/02-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ $pdo = new PDO('mysql:dbname=tenant_1234;host=dbhost', 'user', 'pass');
$handler = new Handler($pdo, $history);

// Migrate from version '1' to '2'
$handler->migrate('1', '2', true);
$handler->migrate(['1'], '2', true);
```
74 changes: 54 additions & 20 deletions src/FunctionMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ final class FunctionMigration implements MigrationInterface
private bool $deterministic;

/**
* @var bool
* @var string
*/
private string $dataUse;

/**
* @var string
*/
private bool $readsSqlData;
private string $language;

/**
* @var ParameterOperation[]
Expand Down Expand Up @@ -86,21 +91,23 @@ public static function drop(string $name): FunctionMigration
/**
* FunctionMigration constructor.
*
* @param string $name
* @param string $operation
* @param ?ReturnTypeOperation $returnType
* @param bool $deterministic
* @param bool $readsSqlData
* @param array $parameterOperations
* @param array $variableOperations
* @param string|null $body
* @param string $name
* @param string $operation
* @param ?ReturnTypeOperation $returnType
* @param bool $deterministic
* @param string $dataUse
* @param string $language
* @param array $parameterOperations
* @param array $variableOperations
* @param string|null $body
*/
private function __construct(
string $name,
string $operation,
ReturnTypeOperation $returnType = null,
bool $deterministic = false,
bool $readsSqlData = false,
string $dataUse = 'READS SQL DATA',
string $language = 'plpgsql',
array $parameterOperations = [],
array $variableOperations = [],
string $body = null
Expand All @@ -109,7 +116,8 @@ private function __construct(
$this->operation = $operation;
$this->returnType = $returnType;
$this->deterministic = $deterministic;
$this->readsSqlData = $readsSqlData;
$this->dataUse = $dataUse;
$this->language = $language;
$this->parameterOperations = $parameterOperations;
$this->variableOperations = $variableOperations;
$this->body = $body;
Expand All @@ -121,7 +129,7 @@ private function __construct(
* @param bool $deterministic
* @return $this
*/
public function isDeterministic(bool $deterministic): FunctionMigration
public function withDeterminism(bool $deterministic): FunctionMigration
{
if ($this->operation === FunctionOperation::DROP) {
throw new LogicException('Cannot set deterministic property in a drop migration.');
Expand All @@ -135,16 +143,41 @@ public function isDeterministic(bool $deterministic): FunctionMigration
/**
* Sets the reads sql data property of the function.
*
* @param bool $readsSqlData
* @param string $dataUse
* @return $this
*/
public function withDataUse(string $dataUse): FunctionMigration
{
if ($this->operation === FunctionOperation::DROP) {
throw new LogicException('Cannot set dataUse property in a drop migration.');
}

if (!in_array($dataUse, ['CONTAINS SQL', 'NO SQL', 'READS SQL DATA', 'MODIFIES SQL DATA'])) {
throw new LogicException('Cannot set dataUse, not a valid option.');
}

$this->dataUse = $dataUse;

return $this;
}

/**
* Sets the language property of the function.
*
* @param string $language
* @return $this
*/
public function readsSqlData(bool $readsSqlData): FunctionMigration
public function withLanguage(string $language): FunctionMigration
{
if ($this->operation === FunctionOperation::DROP) {
throw new LogicException('Cannot set readsSqlData property in a drop migration.');
throw new LogicException('Cannot set language property in a drop migration.');
}

if (!in_array($language, ['SQL', 'plpgsql'])) {
throw new LogicException('Cannot set language, not a valid option.');
}

$this->readsSqlData = $readsSqlData;
$this->language = $language;

return $this;
}
Expand Down Expand Up @@ -174,7 +207,7 @@ public function withReturnType(string $type, array $options = []): FunctionMigra
* @param array $options
* @return $this
*/
public function addParameter(string $name, array $options = []): FunctionMigration
public function withParameter(string $name, array $options = []): FunctionMigration
{
if ($this->operation === FunctionOperation::DROP) {
throw new LogicException('Cannot add parameters in a view drop migration.');
Expand All @@ -199,7 +232,7 @@ public function addParameter(string $name, array $options = []): FunctionMigrati
* @param array $options
* @return $this
*/
public function addVariable(string $name, array $options = []): FunctionMigration
public function withVariable(string $name, array $options = []): FunctionMigration
{
if ($this->operation === FunctionOperation::DROP) {
throw new LogicException('Cannot add variables in a view drop migration.');
Expand Down Expand Up @@ -249,7 +282,8 @@ public function getOperation(): FunctionOperation
$this->operation,
$this->returnType,
$this->deterministic,
$this->readsSqlData,
$this->dataUse,
$this->language,
$this->parameterOperations,
$this->variableOperations,
$this->body
Expand Down
3 changes: 3 additions & 0 deletions src/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Exo\Operation\ExecOperation;
use Exo\Operation\OperationInterface;
use Exo\Statement\MysqlStatementBuilder;
use Exo\Statement\PostgresqlStatementBuilder;
use Exo\Statement\StatementBuilder;
use InvalidArgumentException;
use PDO;
Expand Down Expand Up @@ -169,6 +170,8 @@ private function getBuilder()
switch ($driver) {
case 'mysql':
return new MysqlStatementBuilder();
case 'pgsql':
return new PostgresqlStatementBuilder();
default:
throw new InvalidArgumentException(sprintf('Unsupported driver "%s".', $driver));
}
Expand Down
52 changes: 35 additions & 17 deletions src/Operation/FunctionOperation.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ final class FunctionOperation extends AbstractOperation implements ReversibleOpe
private bool $deterministic;

/**
* @var bool
* @var string
*/
private string $dataUse;

/**
* @var string
*/
private bool $readsSqlData;
private string $language;

/**
* @var ParameterOperation[]
Expand All @@ -48,21 +53,23 @@ final class FunctionOperation extends AbstractOperation implements ReversibleOpe
/**
* FunctionOperation constructor.
*
* @param string $name
* @param string $operation
* @param ReturnTypeOperation|null $returnType
* @param bool $deterministic
* @param bool $readsSqlData
* @param array $parameterOperations
* @param array $variableOperations
* @param string|null $body
* @param string $name
* @param string $operation
* @param ReturnTypeOperation|null $returnType
* @param bool $deterministic
* @param string $dataUse
* @param string $language
* @param array $parameterOperations
* @param array $variableOperations
* @param string|null $body
*/
public function __construct(
string $name,
string $operation,
ReturnTypeOperation $returnType = null,
bool $deterministic = false,
bool $readsSqlData = false,
string $dataUse = 'READS SQL DATA',
string $language = 'plpgsql',
array $parameterOperations = [],
array $variableOperations = [],
string $body = null
Expand All @@ -71,7 +78,8 @@ public function __construct(
$this->operation = $operation;
$this->returnType = $returnType ?? new ReturnTypeOperation('string', ReturnTypeOperation::ADD);
$this->deterministic = $deterministic;
$this->readsSqlData = $readsSqlData;
$this->dataUse = $dataUse;
$this->language = $language;
$this->parameterOperations = $parameterOperations;
$this->variableOperations = $variableOperations;
$this->body = $body;
Expand Down Expand Up @@ -152,19 +160,29 @@ public function getReturnType(): ?ReturnTypeOperation
*
* @return bool
*/
public function getDeterministic(): bool
public function getDeterminism(): bool
{
return $this->deterministic;
}

/**
* Returns the readsSqlData flag.
* Returns the dataUse characteristic.
*
* @return bool
* @return string
*/
public function getDataUse(): string
{
return $this->dataUse;
}

/**
* Returns the language characteristic.
*
* @return string
*/
public function getReadsSqlData(): bool
public function getLanguage(): string
{
return $this->readsSqlData;
return $this->language;
}

/**
Expand Down
Loading

0 comments on commit e044faf

Please sign in to comment.