Skip to content

Commit

Permalink
fix : migration rollback, migrate, migratefresh
Browse files Browse the repository at this point in the history
  • Loading branch information
bxel07 committed Mar 22, 2024
1 parent eea6522 commit e988055
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 129 deletions.
1 change: 0 additions & 1 deletion Example/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
$config = 'mysql:host=localhost;dbname=databases';
$dsn = explode(';', $config);
$dbname = explode('=', $config);

$config = [
'dsn' => $config.";charset=utf8mb4",
'username' => 'root',
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
],
"require": {
"ext-pdo": "*",
"php": ">=8.2"
"php": ">=8.2",
"ext-mysqli": "*"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
Expand Down
22 changes: 20 additions & 2 deletions src/QueryBuilder/Migration/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Connection
* @param array<string|int, mixed> $config
* @throws Exception
*/
public function __construct(array $config)
public function __construct(private readonly array $config, private readonly string $dbname)
{
try {
$this->pdo = new PDO(
Expand All @@ -25,8 +25,26 @@ public function __construct(array $config)
);
$this->pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
}catch (PDOException $e){
throw new Exception($e->getMessage(), $e->getCode());

}
}

public function isDatabaseExists(): bool
{

$stmt = $this->pdo->prepare("SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = :db");
$stmt->execute([':db' => $this->dbname]);
return (bool)$stmt->fetch(PDO::FETCH_ASSOC);
}

public function createDatabase(): bool
{
if (!$this->isDatabaseExists()){
$sql = "CREATE DATABASE `{$this->dbname}`";
$this->pdo->exec($sql);
return true;
}
return false;
}

public function getConnection(): PDO
Expand Down
75 changes: 29 additions & 46 deletions src/QueryBuilder/Migration/MigrationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,29 +56,26 @@ private static function insertInterLockMigration(string $interlock): void
$conn->beginTransaction();

// ? check the migration already exist
$stmt = $conn->prepare("SELECT COUNT(*) FROM migrations WHERE migration = :migration");
$stmt = $conn->prepare("SELECT COUNT(migration) as migration_count FROM migrations WHERE migration = :migration");
$stmt->bindValue(":migration", $interlock);
$stmt->execute();

$result = $stmt->fetch(PDO::FETCH_ASSOC);

// ? do nothing if the migration exist
if (count($stmt->fetchAll()) > 0){
if ($result['migration_count'] === 0){
$stmt = $conn->prepare("INSERT INTO migrations (migration) VALUES (:migration)");
$stmt->bindValue(":migration", $interlock);
$stmt->execute();
$conn->commit();
return;
}

// ? insert
$stmt = $conn->prepare("INSERT INTO migrations (migration) VALUES (:migration)");
$stmt->bindValue(":migration", $interlock);
$stmt->execute();
$conn->commit();
}catch (PDOException $e){
$conn->rollBack();
throw new Exception($e->getMessage());
}

}


private static function isMigrationExist(): void
{
$conn = self::getPDO();
Expand Down Expand Up @@ -110,13 +107,9 @@ private static function rollbackInformation(): array
foreach ($currentMigration as $value){
$check = self::isTableExist($value);
if ($check){
$data = self::$list[$value];
$availableMigration[] = $data;
}else{
$availableMigration = [];
$availableMigration[] = $value;
}
}

return $availableMigration;
}

Expand All @@ -132,7 +125,7 @@ public static function rollback(string|int $step = '*'): void
try {
$currentMigration = [];
// $current Migrations
foreach (self::$list as $migration){
foreach (self::$list as $migration => $value){
if (count($currentMigration) < $step){
$currentMigration[] = $migration;
}else{
Expand All @@ -141,32 +134,25 @@ public static function rollback(string|int $step = '*'): void
}

if (count($availableMigration) > count($currentMigration)){
$currentData = array_diff($availableMigration, $currentMigration);
$data = array_diff($availableMigration, $currentMigration);

$currentData = array_intersect_key(self::$list, array_flip($data));
foreach ($currentData as $value){
$instance = new $value();
if ($instance instanceof Migration){
$instance->down();
if ($value instanceof Migration){
$value->down();
}else{
break;
}
}
}elseif(count($availableMigration) < count($currentMigration)){
$currentData = array_diff($currentMigration, $availableMigration);
foreach ($currentData as $value){
$instance = new $value();
if ($instance instanceof Migration){
$instance->up();
}else{
break;
}
}
}else{
$currentData = $availableMigration;

$data = array_diff($currentMigration, $availableMigration);

$currentData = array_intersect_key(self::$list, array_flip($data));

foreach ($currentData as $value){
$instance = new $value();
if ($instance instanceof Migration){
$instance->up();
if ($value instanceof Migration){
$value->up();
}else{
break;
}
Expand All @@ -176,10 +162,9 @@ public static function rollback(string|int $step = '*'): void
throw new Exception($e->getMessage());
}
}else{
foreach ($availableMigration as $value){
$instance = new $value();
if ($instance instanceof Migration){
$instance->down();
foreach (self::$list as $value){
if ($value instanceof Migration){
$value->down();
}else{
break;
}
Expand All @@ -193,11 +178,7 @@ public static function rollback(string|int $step = '*'): void
*/
public static function migrate(): void
{
/**
* Checkup the Migrations
*/
self::isMigrationExist();

foreach (self::$list as $key => $value){
try {
if ($value instanceof Migration){
Expand All @@ -215,16 +196,18 @@ public static function migrate(): void
*/
public static function freshMigrate(): void
{
/**
* Checkup the Migrations
*/
self::isMigrationExist();


/**
* Drop Migrations
*/
self::dropMigration();

/**
* Checkup the Migrations
*/
self::isMigrationExist();

foreach (self::$list as $key => $value){
try {
if ($value instanceof Migration){
Expand Down
6 changes: 4 additions & 2 deletions src/QueryBuilder/MigrationLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ public function load(): void
$className = pathinfo($file->getPathname(), PATHINFO_FILENAME);
$fullClassName = $this->namespace . '\\' . $className;
if (class_exists($fullClassName) && $className !== "migrations") {
$this->migrations[$className] = $fullClassName;
$instance = new $fullClassName();
$this->migrations[$className] = $instance;
}else{
$this->table[$className] = $fullClassName;
$instance = new $fullClassName();
$this->table[$className] = $instance;
}
}
}
Expand Down
20 changes: 3 additions & 17 deletions src/QueryBuilder/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use stdClass;
use Xel\DB\Contract\QueryBuilderInterface;
use Xel\DB\Contract\QueryBuilderResultInterface;
use Xel\DB\QueryBuilder\Exception\QueryBuilderException;

class QueryBuilder implements QueryBuilderInterface, QueryBuilderResultInterface
{
Expand Down Expand Up @@ -308,39 +307,26 @@ public function run(): false|string|PDOStatement
->execute($this->getQuery(), $this->getBinding());
}

/**
* @throws Exception
*/
private function fetchGenerator(int $mode):array|string|stdClass
{
$stmt = $this->executor();
$result = $stmt->fetch($mode);
if(empty($result)){
throw new QueryBuilderException('no data found');
}
return $result;
}

/**
* @return array<string|int, mixed>
* @throws Exception
*/
public function get(): array
{
return $this->fetchGenerator(PDO::FETCH_ASSOC);
return $this->executor()->fetchAll(PDO::FETCH_ASSOC);
}

/**
* @throws Exception
*/
public function toObject(): array|stdClass
{
return $this->fetchGenerator(PDO::FETCH_OBJ);
return $this->executor()->fetchAll(PDO::FETCH_OBJ);
}

public function toJson(bool $prettyPrint = false): false|string
{
$result = $this->fetchGenerator(PDO::FETCH_ASSOC);
$result = $this->executor()->fetchAll(PDO::FETCH_ASSOC);
return json_encode($result);
}

Expand Down
87 changes: 27 additions & 60 deletions src/QueryBuilder/QueryBuilderExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function __construct(private XgenConnector $connector, private bool $mode
*/
private function getConnection(): false|PDO
{
return $this->connector->getPoolConnection();
return $this->mode ? $this->connector->getPoolConnection() : $this->connector->getPersistentConnection() ;
}

/**
Expand All @@ -40,73 +40,40 @@ private function closeConnection(PDO $pdo): void
*/
public function execute(string $query, array $binding = []): false|string|PDOStatement
{
if ($this->mode){
$conn = $this->getConnection();
if ($conn === false){
throw new Exception('Failed to get valid database connection', 500);
}

try {
$conn->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
$conn->beginTransaction();
$stmt = $conn->prepare($query);
foreach ($binding as $item => $value) {
$paramType = is_int($value) ? PDO::PARAM_INT : (is_bool($value) ? PDO::PARAM_BOOL : PDO::PARAM_STR);
$stmt->bindValue($item, $value, $paramType);
}

$stmt->execute();

// commit
$conn->commit();

// Check if the query was a non-SELECT operation
$isNonSelect = strtoupper(substr(trim($query), 0, 6)) !== 'SELECT';

// Return the statement if it's a non-SELECT operation
if ($isNonSelect) {
return true; // Or any indication of success
}
$conn = $this->getConnection();
if ($conn === false){
throw new Exception('Failed to get valid database connection', 500);
}

return $stmt;
}catch (PDOException $e){
$conn->rollBack();
throw new QueryBuilderException($e->getMessage());
} finally {
$this->closeConnection($conn);
try {
$conn->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
$conn->beginTransaction();
$stmt = $conn->prepare($query);
foreach ($binding as $item => $value) {
$paramType = is_int($value) ? PDO::PARAM_INT : (is_bool($value) ? PDO::PARAM_BOOL : PDO::PARAM_STR);
$stmt->bindValue($item, $value, $paramType);
}
}else{

$conn = $this->connector->getPersistentConnection();
try {
$conn->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
$conn->beginTransaction();
$stmt = $conn->prepare($query);
foreach ($binding as $item => $value) {
$paramType = is_int($value) ? PDO::PARAM_INT : (is_bool($value) ? PDO::PARAM_BOOL : PDO::PARAM_STR);
$stmt->bindValue($item, $value, $paramType);
}

$stmt->execute();

// commit
$conn->commit();
$stmt->execute();

// Check if the query was a non-SELECT operation
$isNonSelect = strtoupper(substr(trim($query), 0, 6)) !== 'SELECT';
// commit
$conn->commit();

// Return the statement if it's a non-SELECT operation
if ($isNonSelect) {
return true; // Or any indication of success
}
// Check if the query was a non-SELECT operation
$isNonSelect = strtoupper(substr(trim($query), 0, 6)) !== 'SELECT';

return $stmt;
}catch (PDOException $e){
$conn->rollBack();
throw new QueryBuilderException($e->getMessage());
// Return the statement if it's a non-SELECT operation
if ($isNonSelect) {
return true; // Or any indication of success
}
}

return $stmt;
}catch (PDOException $e){
$conn->rollBack();
throw new QueryBuilderException($e->getMessage());
} finally {
$this->closeConnection($conn);
}

}
}

0 comments on commit e988055

Please sign in to comment.