Skip to content

Commit

Permalink
#24 all SQLite tests now pass + several bug fixes for altering databa…
Browse files Browse the repository at this point in the history
…se schema on the fly
  • Loading branch information
TRPB committed Aug 7, 2015
1 parent db84f81 commit 7052180
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 30 deletions.
2 changes: 1 addition & 1 deletion maphper/datasource/mysqladapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public function addIndex($table, array $fields) {
$keyName = $this->quote(implode('_', $fields));

$results = $this->pdo->query('SHOW INDEX FROM ' . $this->quote($table) . ' WHERE Key_Name = "' . $keyName . '"');
if ($results && count($results->fetchAll()) == 0) $this->pdo->query('CREATE INDEX ' . $keyName . ' ON ' . $this->quote($table) . '(' . implode(', ', $fields) . ')');
if ($results && count($results->fetchAll()) == 0) $this->pdo->query('CREATE INDEX ' . $keyName . ' ON ' . $this->quote($table) . ' (' . implode(', ', $fields) . ')');
}

public function optimiseColumns($table) {
Expand Down
41 changes: 35 additions & 6 deletions maphper/datasource/sqliteadapter.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php
namespace Maphper\DataSource;

class SqliteAdapter implements DatabaseAdapter {
private $pdo;
private $queryCache = [];
Expand Down Expand Up @@ -69,8 +70,8 @@ private function buildSaveQuery($data, $prependField = false) {
public function insert($table, array $primaryKey, $data) {
$query = $this->buildSaveQuery($data);
$result = $this->query('INSERT INTO ' . $this->quote($table) . ' ('.implode(', ', array_keys($query['args'])).') VALUES ( ' . implode(', ', $query['sql']). ' )', $query['args']);

if ($result->errorCode() > 0) {
if ($result->errorCode() > 0) {
$query = $this->buildSaveQuery($data, true);
$where = [];
foreach($primaryKey as $field) $where[] = $this->quote($field) . ' = :' . $field;
Expand Down Expand Up @@ -101,7 +102,12 @@ private function query($query, $args = []) {
else return $stmt;
}
catch (\Exception $e) {
return $stmt;
//SQLite causes an error if when the DB schema changes, rebuild $stmt and try again.
if ($e->getMessage() == 'SQLSTATE[HY000]: General error: 17 database schema has changed') {
unset($this->queryCache[$queryId]);
return $this->query($query, $args);
}
else return $stmt;
}
}
}
Expand All @@ -119,7 +125,7 @@ private function getType($val) {
else return 'VARCHAR(255)';
}

protected function tableExists($name) {
private function tableExists($name) {
$result = $this->pdo->query('SELECT name FROM sqlite_master WHERE type="table" and name="'. $name.'"');
return count($result->fetchAll()) == 1;
}
Expand All @@ -135,6 +141,10 @@ private function getColumns($table) {

//Alter the database so that it can store $data
public function alterDatabase($table, array $primaryKey, $data) {
//Unset query cache, otherwise it causes:
// SQLSTATE[HY000]: General error: 17 database schema has changed
$this->queryCache = [];

$affix = '_'.substr(md5($table), 0, 6);
$this->createTable($table . $affix, $primaryKey, $data);
$fields = [];
Expand All @@ -144,14 +154,17 @@ public function alterDatabase($table, array $primaryKey, $data) {
$columns = implode(', ', $this->getColumns($table));

$this->pdo->query('INSERT INTO ' . $this->quote($table . $affix) . '(' . $columns . ') SELECT ' . $columns . ' FROM ' . $this->quote($table));
$this->pdo->query('DROP TABLE ' . $table );
$this->pdo->query('DROP TABLE IF EXISTS ' . $table );
}
}
catch (\PDOException $e) {
// No data to copy
echo $e->getMessage();
}

$this->pdo->query('DROP TABLE IF EXISTS ' . $table );
$this->pdo->query('ALTER TABLE ' . $table . $affix. ' RENAME TO '. $table );

}

public function createTable($table, array $primaryKey, $data) {
Expand All @@ -177,8 +190,24 @@ public function createTable($table, array $primaryKey, $data) {
}
}


public function addIndex($table, array $fields) {
//TODO
if (empty($fields)) return false;

//SQLite doesn't support ASC/DESC indexes, remove the keywords
foreach ($fields as &$field) $field = str_ireplace([' desc', ' asc'], '', $field);
sort($fields);
$fields = array_map('strtolower', $fields);
$fields = array_map('trim', $fields);
$keyName = implode('_', $fields);


try {
$this->pdo->query('CREATE INDEX IF NOT EXISTS ' . $keyName . ' ON ' . $table . ' (' . implode(', ', $fields) . ')');
}
catch (\Exception $e) {

}
}

public function optimiseColumns($table) {
Expand Down
6 changes: 5 additions & 1 deletion maphper/maphper.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,14 @@ public function offsetGet($offset) {
}

public function createNew($data = []) {

$obj = (is_callable($this->settings['resultClass'])) ? call_user_func($this->settings['resultClass']) : new $this->settings['resultClass'];
$writeClosure = function($field, $value) { $this->$field = $value; };
$write = $writeClosure->bindTo($obj, $obj);
foreach ($data as $key => $value) $write($key, $this->dataSource->processDates($value));
if ($data != null) {
foreach ($data as $key => $value) $write($key, $this->dataSource->processDates($value));
}

return $obj;
}

Expand Down
Binary file modified test.db
Binary file not shown.
51 changes: 29 additions & 22 deletions tests/MySqlDatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
*/
class MySqlDatabaseTest extends PHPUnit_Framework_TestCase {

private $maphper;
private $pdo;
protected $maphper;
protected $pdo;

public function __construct() {
parent::__construct();
Expand All @@ -20,26 +20,31 @@ protected function setUp() {
protected function tearDown() {

}



private function getDataSource($name, $primaryKey = 'id', array $options = []) {

protected function getDataSource($name, $primaryKey = 'id', array $options = []) {
return new \Maphper\DataSource\Database($this->pdo, $name, $primaryKey, $options);
}





private function tableExists($name) {
protected function tableExists($name) {
$result = $this->pdo->query('SHOW TABLES LIKE "' . $name . '"');
return $result->rowCount() == 1;
}

private function dropTable($name) {
protected function dropTable($name) {
$this->pdo->query('DROP TABLE IF EXISTS ' . $name);
}

protected function getColumnType($table, $column) {
$result = $this->pdo->query('SHOW COLUMNS FROM ' . $table . ' WHERE field = "' . $column . '"')->fetch();
return $result['Type'];
}

protected function hasIndex($table, $column) {
$result = $this->pdo->query('SHOW INDEX FROM ' . $table . ' WHERE Column_name = "' . $column . '"')->fetchAll();
return count($result) > 0;
}

public function testCreateTable() {

if ($this->tableExists('foo')) {
Expand Down Expand Up @@ -517,7 +522,8 @@ public function testMultiPkUnset() {
$this->assertEquals(0, $result['count']);

}




public function testDateColumnCreate() {
$this->dropTable('blog');
Expand All @@ -529,8 +535,8 @@ public function testDateColumnCreate() {

$mapper[] = $blog;

$result = $this->pdo->query('SHOW COLUMNS FROM blog WHERE field = "date"')->fetch();
$this->assertEquals('datetime', strtolower($result['Type']));

$this->assertEquals('datetime', strtolower($this->getColumnType('blog', 'date')));
}

public function testDateColumnSave() {
Expand Down Expand Up @@ -748,6 +754,7 @@ public function testChangeColumnType() {
$this->assertEquals('ten', $result['title']);
}



public function testIndexCreation() {
$this->dropTable('blog');
Expand All @@ -757,16 +764,16 @@ public function testIndexCreation() {


//Check there is no index on the field already
$result = $this->pdo->query('SHOW INDEX FROM blog WHERE Column_name = "title"')->fetchAll();
$this->assertEquals(0, count($result));
$this->assertFalse($this->hasIndex('blog', 'title'));
//Do a lookup on the title field to trigger an index creation on it
$blogs = $mapper->filter(['title' => 'blog number 4']);
foreach ($blogs as $blog) {

}

$result = $this->pdo->query('SHOW INDEX FROM blog WHERE Column_name = "title"')->fetchAll();
$this->assertEquals(1, count($result));
//$result = $this->pdo->query('SHOW INDEX FROM blog WHERE Column_name = "title"')->fetchAll();
//$this->assertEquals(1, count($result));
$this->assertTrue($this->hasIndex('blog', 'title'));
}


Expand All @@ -778,17 +785,17 @@ public function testIndexCreationSort() {


//Check there is no index on the field already
$result = $this->pdo->query('SHOW INDEX FROM blog WHERE Column_name = "title"')->fetchAll();
$this->assertEquals(0, count($result));
//$result = $this->pdo->query('SHOW INDEX FROM blog WHERE Column_name = "title"')->fetchAll();
//$this->assertEquals(0, count($result));
$this->assertFalse($this->hasIndex('blog', 'title'));


$blogs = $mapper->sort('title desc');
$blogs->rewind();
$blog = $blogs->current();
$this->assertEquals($blog->title, 'blog number 9');

$result = $this->pdo->query('SHOW INDEX FROM blog WHERE Column_name = "title"')->fetchAll();
$this->assertEquals(1, count($result));
$this->assertTrue($this->hasIndex('blog', 'title'));
}

public function testCountEmpty() {
Expand Down

0 comments on commit 7052180

Please sign in to comment.