style fixes, create table fixes, MariaDB fixes

This commit is contained in:
Joby 2020-08-26 09:52:25 -06:00
parent 62102fbf9f
commit 4bf591804c
21 changed files with 250 additions and 136 deletions

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr;
use \Flatrr\FlatArray;
@ -15,7 +15,7 @@ class DSO extends FlatArray implements DSOInterface
protected $changes;
protected $removals;
public function __construct(array $data = null, DSOFactoryInterface &$factory = null)
public function __construct(array $data = null, DSOFactoryInterface $factory = null)
{
$this->resetChanges();
parent::__construct($data);
@ -111,7 +111,7 @@ class DSO extends FlatArray implements DSOInterface
}
}
public function factory(DSOFactoryInterface &$factory = null) : ?DSOFactoryInterface
public function factory(DSOFactoryInterface $factory = null) : ?DSOFactoryInterface
{
if ($factory) {
$this->factory = $factory;

View file

@ -1,19 +1,19 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr;
interface DSOFactoryInterface
{
public function __construct(Drivers\DSODriverInterface &$driver, string $table);
public function __construct(Drivers\DSODriverInterface $driver, string $table);
public function class(array $data) : ?string;
public function createTable() : bool;
public function create(array $data = array()) : DSOInterface;
public function read(string $value, string $field = 'dso.id', $deleted = false) : ?DSOInterface;
public function insert(DSOInterface &$dso) : bool;
public function update(DSOInterface &$dso, bool $sneaky = false) : bool;
public function delete(DSOInterface &$dso, bool $permanent = false) : bool;
public function insert(DSOInterface $dso) : bool;
public function update(DSOInterface $dso, bool $sneaky = false) : bool;
public function delete(DSOInterface $dso, bool $permanent = false) : bool;
public function quote(string $str) : string;
public function search() : Search;

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr;
use Flatrr\FlatArrayInterface;
@ -11,8 +11,8 @@ use Flatrr\FlatArrayInterface;
*/
interface DSOInterface extends FlatArrayInterface
{
public function __construct(array $data = null, DSOFactoryInterface &$factory = null);
public function factory(DSOFactoryInterface &$factory = null) : ?DSOFactoryInterface;
public function __construct(array $data = null, DSOFactoryInterface $factory = null);
public function factory(DSOFactoryInterface $factory = null) : ?DSOFactoryInterface;
public function set(string $name = null, $value, $force=false);

View file

@ -1,12 +1,13 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr;
class DriverFactory
{
public static $map = [
'mariadb' => Drivers\MariaDBDriver::class,
'mysql' => Drivers\MySQLDriver::class,
'sqlite' => LegacyDrivers\SQLiteDriver::class
'sqlite' => LegacyDrivers\SQLiteDriver::class,
];
public static function factory(string $dsn, string $username = null, string $password = null, array $options = null, string $type = null): ?Drivers\DSODriverInterface
@ -22,7 +23,7 @@ class DriverFactory
}
}
public static function factoryFromPDO(\PDO &$pdo, string $type = null) : ?Drivers\DSODriverInterface
public static function factoryFromPDO(\PDO $pdo, string $type = null): ?Drivers\DSODriverInterface
{
if (!$type) {
$type = $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);

View file

@ -1,9 +1,10 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr\Drivers;
use Destructr\DSOInterface;
use Destructr\Search;
use PDO;
//TODO: Caching? It should happen somewhere in this class I think.
abstract class AbstractDriver implements DSODriverInterface
@ -22,9 +23,11 @@ abstract class AbstractDriver implements DSODriverInterface
}
}
public function &pdo(\PDO &$pdo=null) : ?\PDO
public function pdo(\PDO $pdo = null): ?\PDO
{
if ($pdo) {
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo = $pdo;
}
return $this->pdo;
@ -54,7 +57,7 @@ abstract class AbstractDriver implements DSODriverInterface
{
$sql = $this->sql_ddl([
'table' => $table,
'virtualColumns'=>$virtualColumns
'virtualColumns' => $virtualColumns,
]);
return $this->pdo->exec($sql) !== false;
}
@ -70,7 +73,7 @@ abstract class AbstractDriver implements DSODriverInterface
);
return $s->execute([
':dso_id' => $dso['dso.id'],
':data' => json_encode($dso->get())
':data' => json_encode($dso->get()),
]);
}
@ -81,7 +84,7 @@ abstract class AbstractDriver implements DSODriverInterface
['table' => $table]
);
return $s->execute([
':dso_id' => $dso['dso.id']
':dso_id' => $dso['dso.id'],
]);
}

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr\Drivers;
use Destructr\DSOInterface;
@ -8,7 +8,7 @@ use Destructr\Search;
interface DSODriverInterface
{
public function __construct(string $dsn=null, string $username=null, string $password=null, array $options=null);
public function &pdo(\PDO &$pdo=null) : ?\PDO;
public function pdo(\PDO $pdo=null) : ?\PDO;
public function createTable(string $table, array $virtualColumns) : bool;
public function select(string $table, Search $search, array $params);

View file

@ -0,0 +1,108 @@
<?php
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr\Drivers;
/**
* What this driver supports: MariaDB >= 10.2
*/
class MariaDBDriver extends AbstractDriver
{
/**
* Within the search we expand strings like ${dso.id} into JSON queries.
* Note that the Search will have already had these strings expanded into
* column names if there are virtual columns configured for them. That
* happens in the Factory before it gets here.
*/
protected function sql_select($args)
{
//extract query parts from Search and expand paths
$where = $this->expandPaths($args['search']->where());
$order = $this->expandPaths($args['search']->order());
$limit = $args['search']->limit();
$offset = $args['search']->offset();
//select from
$out = ["SELECT * FROM `{$args['table']}`"];
//where statement
if ($where !== null) {
$out[] = "WHERE ".$where;
}
//order statement
if ($order !== null) {
$out[] = "ORDER BY ".$order;
}
//limit
if ($limit !== null) {
$out[] = "LIMIT ".$limit;
}
//offset
if ($offset !== null) {
$out[] = "OFFSET ".$offset;
}
//return
return implode(PHP_EOL, $out).';';
}
protected function sql_count($args)
{
//extract query parts from Search and expand paths
$where = $this->expandPaths($args['search']->where());
//select from
$out = ["SELECT count(dso_id) FROM `{$args['table']}`"];
//where statement
if ($where !== null) {
$out[] = "WHERE ".$where;
}
//return
return implode(PHP_EOL, $out).';';
}
protected function sql_ddl($args=array())
{
$out = [];
$out[] = "CREATE TABLE IF NOT EXISTS `{$args['table']}` (";
$lines = [];
$lines[] = "`json_data` JSON DEFAULT NULL";
foreach ($args['virtualColumns'] as $path => $col) {
$line = "`{$col['name']}` {$col['type']} GENERATED ALWAYS AS (".$this->expandPath($path).")";
if (@$col['primary']) {
//this needs to be "PERSISTENT" for MariaDB -- I guess there are going to be two drivers now
$line .= ' STORED';
} else {
$line .= ' VIRTUAL';
}
$lines[] = $line;
}
foreach ($args['virtualColumns'] as $path => $col) {
if (@$col['primary']) {
$lines[] = "UNIQUE KEY (`{$col['name']}`)";
} elseif (@$col['unique'] && $as = @$col['index']) {
$lines[] = "UNIQUE KEY `{$args['table']}_{$col['name']}_idx` (`{$col['name']}`) USING $as";
} elseif ($as = @$col['index']) {
$lines[] = "KEY `{$args['table']}_{$col['name']}_idx` (`{$col['name']}`) USING $as";
}
}
$out[] = implode(','.PHP_EOL, $lines);
$out[] = ") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
return implode(PHP_EOL, $out);
}
protected function expandPath(string $path) : string
{
return "JSON_UNQUOTE(JSON_EXTRACT(`json_data`,'$.{$path}'))";
}
protected function sql_setJSON($args)
{
return 'UPDATE `'.$args['table'].'` SET `json_data` = :data WHERE `dso_id` = :dso_id;';
}
protected function sql_insert($args)
{
return "INSERT INTO `{$args['table']}` (`json_data`) VALUES (:data);";
}
protected function sql_delete($args)
{
return 'DELETE FROM `'.$args['table'].'` WHERE `dso_id` = :dso_id;';
}
}

View file

@ -1,12 +1,9 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr\Drivers;
/**
* What this driver supports: MySQL and MariaDB databases new enough to support
* JSON functions. This means:
* * MySQL >= 5.7
* * MariaDB >= 10.2
* What this driver supports: MySQL >= 5.7
*/
class MySQLDriver extends AbstractDriver
{
@ -62,7 +59,7 @@ class MySQLDriver extends AbstractDriver
protected function sql_ddl($args=array())
{
$out = [];
$out[] = "CREATE TABLE `{$args['table']}` (";
$out[] = "CREATE TABLE IF NOT EXISTS `{$args['table']}` (";
$lines = [];
$lines[] = "`json_data` JSON DEFAULT NULL";
foreach ($args['virtualColumns'] as $path => $col) {

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr;
use mofodojodino\ProfanityFilter\Check;
@ -73,7 +73,7 @@ class Factory implements DSOFactoryInterface
]
];
public function __construct(Drivers\DSODriverInterface &$driver, string $table)
public function __construct(Drivers\DSODriverInterface $driver, string $table)
{
$this->driver = $driver;
$this->table = $table;
@ -84,7 +84,7 @@ class Factory implements DSOFactoryInterface
return $this->driver->pdo()->quote($str);
}
protected function hook_create(DSOInterface &$dso)
protected function hook_create(DSOInterface $dso)
{
if (!$dso->get('dso.id')) {
$dso->set('dso.id', static::generate_id(static::ID_CHARS, static::ID_LENGTH), true);
@ -97,18 +97,27 @@ class Factory implements DSOFactoryInterface
}
}
protected function hook_update(DSOInterface &$dso)
protected function hook_update(DSOInterface $dso)
{
$dso->set('dso.modified.date', time());
$dso->set('dso.modified.user', ['ip'=>@$_SERVER['REMOTE_ADDR']]);
}
/**
* Override this function to allow a factory to create different
* sub-classes of DSO based on attributes of the given object's
* data. For example, you could use a property like dso.class to
* select a class from an associative array.
*
* @param array $data
* @return string|null
*/
public function class(array $data) : ?string
{
return null;
}
public function delete(DSOInterface &$dso, bool $permanent = false) : bool
public function delete(DSOInterface $dso, bool $permanent = false) : bool
{
if ($permanent) {
return $this->driver->delete($this->table, $dso);
@ -117,7 +126,7 @@ class Factory implements DSOFactoryInterface
return $this->update($dso, true);
}
public function undelete(DSOInterface &$dso) : bool
public function undelete(DSOInterface $dso) : bool
{
unset($dso['dso.deleted']);
return $this->update($dso, true);
@ -153,7 +162,7 @@ class Factory implements DSOFactoryInterface
return @$vcols[$path]['name'];
}
public function update(DSOInterface &$dso, bool $sneaky = false) : bool
public function update(DSOInterface $dso, bool $sneaky = false) : bool
{
if (!$dso->changes() && !$dso->removals()) {
return true;
@ -221,7 +230,7 @@ class Factory implements DSOFactoryInterface
return null;
}
public function insert(DSOInterface &$dso) : bool
public function insert(DSOInterface $dso) : bool
{
$this->hook_update($dso);
$dso->hook_update();

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr\LegacyDrivers;
use Destructr\Drivers\AbstractDriver;

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr\LegacyDrivers;
use Destructr\DSOInterface;
@ -16,7 +16,7 @@ use Destructr\Factory;
*/
class SQLiteDriver extends AbstractLegacyDriver
{
public function &pdo(\PDO &$pdo=null) : ?\PDO
public function pdo(\PDO $pdo=null) : ?\PDO
{
if ($pdo) {
$this->pdo = $pdo;
@ -73,7 +73,7 @@ class SQLiteDriver extends AbstractLegacyDriver
protected function sql_ddl($args=array())
{
$out = [];
$out[] = "CREATE TABLE `{$args['table']}` (";
$out[] = "CREATE TABLE IF NOT EXISTS `{$args['table']}` (";
$lines = [];
$lines[] = "`json_data` TEXT DEFAULT NULL";
foreach (Factory::CORE_VIRTUAL_COLUMNS as $path => $col) {

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr;
use Destructr\DSOFactoryInterface;
@ -13,7 +13,7 @@ class Search implements \Serializable
protected $limit;
protected $offset;
public function __construct(DSOFactoryInterface &$factory=null)
public function __construct(DSOFactoryInterface $factory=null)
{
$this->factory = $factory;
}

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare(strict_types=1);
namespace Destructr;

View file

@ -1,13 +1,11 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare (strict_types = 1);
namespace Destructr\Drivers;
use PHPUnit\Framework\TestCase;
use PHPUnit\DbUnit\TestCaseTrait;
use Destructr\DSO;
use Destructr\Search;
use Destructr\Factory;
use PHPUnit\DbUnit\TestCaseTrait;
use PHPUnit\Framework\TestCase;
abstract class AbstractDriverIntegrationTest extends TestCase
{
@ -116,22 +114,22 @@ abstract class AbstractDriverIntegrationTest extends TestCase
$factory->create([
'testSearch' => 'a',
'a' => '1',
'b' => '2'
'b' => '2',
])->insert();
$factory->create([
'testSearch' => 'b',
'a' => '2',
'b' => '1'
'b' => '1',
])->insert();
$factory->create([
'testSearch' => 'c',
'a' => '3',
'b' => '4'
'b' => '4',
])->insert();
$factory->create([
'testSearch' => 'a',
'a' => '4',
'b' => '3'
'b' => '3',
])->insert();
//there should now be four more rows
$this->assertEquals($startRowCount + 4, $this->getConnection()->getRowCount(static::TEST_TABLE));

View file

@ -1,12 +1,12 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare (strict_types = 1);
namespace Destructr\Drivers;
use PHPUnit\Framework\TestCase;
use PHPUnit\DbUnit\TestCaseTrait;
use Destructr\DSO;
use Destructr\Search;
use PHPUnit\DbUnit\TestCaseTrait;
use PHPUnit\Framework\TestCase;
/**
* This class tests a factory in isolation. In the name of simplicity it's a bit
@ -28,18 +28,18 @@ abstract class AbstractDriverTest extends TestCase
'name' => 'dso_id',
'type' => 'VARCHAR(16)',
'index' => 'BTREE',
'unique' => true
'unique' => true,
],
'dso.type' => [
'name' => 'dso_type',
'type' => 'VARCHAR(30)',
'index'=>'BTREE'
'index' => 'BTREE',
],
'dso.deleted' => [
'name' => 'dso_deleted',
'type' => 'BIGINT',
'index'=>'BTREE'
]
'index' => 'BTREE',
],
];
public function testCreateTable()
@ -128,22 +128,22 @@ abstract class AbstractDriverTest extends TestCase
$driver->insert('testDelete', new DSO([
'dso' => ['id' => 'item-a-1', 'type' => 'type-a'],
'foo' => 'bar',
'sort'=>'a'
'sort' => 'a',
]));
$driver->insert('testDelete', new DSO([
'dso' => ['id' => 'item-a-2', 'type' => 'type-a'],
'foo' => 'baz',
'sort'=>'c'
'sort' => 'c',
]));
$driver->insert('testDelete', new DSO([
'dso' => ['id' => 'item-b-1', 'type' => 'type-b'],
'foo' => 'buz',
'sort'=>'b'
'sort' => 'b',
]));
$driver->insert('testDelete', new DSO([
'dso' => ['id' => 'item-b-2', 'type' => 'type-b', 'deleted' => 100],
'foo' => 'quz',
'sort'=>'d'
'sort' => 'd',
]));
}
@ -153,22 +153,22 @@ abstract class AbstractDriverTest extends TestCase
$driver->insert('testSelect', new DSO([
'dso' => ['id' => 'item-a-1', 'type' => 'type-a'],
'foo' => 'bar',
'sort'=>'a'
'sort' => 'a',
]));
$driver->insert('testSelect', new DSO([
'dso' => ['id' => 'item-a-2', 'type' => 'type-a'],
'foo' => 'baz',
'sort'=>'c'
'sort' => 'c',
]));
$driver->insert('testSelect', new DSO([
'dso' => ['id' => 'item-b-1', 'type' => 'type-b'],
'foo' => 'buz',
'sort'=>'b'
'sort' => 'b',
]));
$driver->insert('testSelect', new DSO([
'dso' => ['id' => 'item-b-2', 'type' => 'type-b', 'deleted' => 100],
'foo' => 'quz',
'sort'=>'d'
'sort' => 'd',
]));
}

View file

@ -1,15 +1,14 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare (strict_types = 1);
namespace Destructr\Drivers\MySQL;
use PHPUnit\Framework\TestCase;
use Destructr\Drivers\AbstractDriverIntegrationTest;
use Destructr\Drivers\MySQLDriver;
class MySQLDriverIntegrationTest extends AbstractDriverIntegrationTest
{
const DRIVER_CLASS = \Destructr\Drivers\MySQLDriver::class;
const DRIVER_CLASS = MySQLDriver::class;
const DRIVER_DSN = 'mysql:host=127.0.0.1;dbname=test';
const DRIVER_USERNAME = 'root';
const DRIVER_PASSWORD = '';

View file

@ -1,9 +1,8 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare (strict_types = 1);
namespace Destructr\Drivers\MySQL;
use PHPUnit\Framework\TestCase;
use Destructr\Drivers\AbstractDriverTest;
use Destructr\Drivers\MySQLDriver;

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare(strict_types=1);
namespace Destructr;

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
namespace Destructr;
class HarnessDriver implements Drivers\DSODriverInterface
@ -14,7 +14,7 @@ class HarnessDriver implements Drivers\DSODriverInterface
{
}
public function &pdo(\PDO &$pdo=null) : ?\PDO {
public function pdo(\PDO $pdo=null) : ?\PDO {
return null;
}

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare(strict_types=1);
namespace Destructr\LegacyDrivers\SQLite;

View file

@ -1,5 +1,5 @@
<?php
/* Destructr | https://gitlab.com/byjoby/destructr | MIT License */
/* Destructr | https://github.com/jobyone/destructr | MIT License */
declare(strict_types=1);
namespace Destructr\LegacyDrivers\SQLite;