Skip to content

Commit c1369ae

Browse files
committed
Update PicoDatabase
1 parent b0fdeac commit c1369ae

File tree

2 files changed

+181
-76
lines changed

2 files changed

+181
-76
lines changed

src/Database/PicoDatabase.php

Lines changed: 128 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PDOStatement;
99
use MagicObject\Exceptions\InvalidDatabaseConfiguration;
1010
use MagicObject\Exceptions\NullPointerException;
11+
use MagicObject\Exceptions\UnsupportedDatabaseException;
1112
use MagicObject\SecretObject;
1213
use ReflectionFunction;
1314
use stdClass;
@@ -397,73 +398,16 @@ private function connectRDMS($withDatabase = true)
397398
throw new InvalidDatabaseConfiguration("Database username may not be empty. Please check your database configuration!");
398399
}
399400

400-
$initialQueries = array();
401-
402401
// Get charset from the database credentials
403402
$charset = addslashes($this->databaseCredentials->getCharset());
404403

405404
// Handle PostgreSQL-specific connection settings
406405
if ($this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_PGSQL) {
407-
408-
// Set time zone for PostgreSQL
409-
$initialQueries[] = "SET TIMEZONE TO '$timeZoneOffset';";
410-
411-
// Set the client encoding (charset) for PostgreSQL
412-
if ($charset) {
413-
$initialQueries[] = "SET CLIENT_ENCODING TO '$charset';";
414-
}
415-
416-
// Set schema if provided for PostgreSQL
417-
if ($this->databaseCredentials->getDatabaseSchema() != null && $this->databaseCredentials->getDatabaseSchema() != "") {
418-
$initialQueries[] = "SET search_path TO " . $this->databaseCredentials->getDatabaseSchema() . ";";
419-
}
420-
421-
// PostgreSQL connection setup
422-
$this->databaseConnection = new PDO(
423-
$connectionString,
424-
$this->databaseCredentials->getUsername(),
425-
$this->databaseCredentials->getPassword(),
426-
[
427-
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
428-
]
429-
);
430-
431-
// Execute the initial queries (timezone, charset, schema) in PostgreSQL
432-
if (!empty($initialQueries)) {
433-
foreach($initialQueries as $initialQuery)
434-
{
435-
$this->databaseConnection->exec($initialQuery);
436-
}
437-
}
438-
406+
$this->connectPostgreSql($connectionString, $timeZoneOffset, $charset);
439407
}
440408
// Handle MySQL-specific connection settings
441409
else if ($this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_MARIADB || $this->getDatabaseType() == PicoDatabaseType::DATABASE_TYPE_MYSQL) {
442-
// Set time zone for MySQL
443-
$initialQueries[] = "SET time_zone='$timeZoneOffset';";
444-
445-
// Add charset to the initial queries for MySQL
446-
if ($charset) {
447-
$initialQueries[] = "SET NAMES '$charset';"; // Set charset for MySQL
448-
}
449-
450-
// MySQL connection setup
451-
$this->databaseConnection = new PDO(
452-
$connectionString,
453-
$this->databaseCredentials->getUsername(),
454-
$this->databaseCredentials->getPassword(),
455-
[
456-
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
457-
PDO::MYSQL_ATTR_FOUND_ROWS => true
458-
]
459-
);
460-
461-
if (!empty($initialQueries)) {
462-
foreach($initialQueries as $initialQuery)
463-
{
464-
$this->databaseConnection->exec($initialQuery);
465-
}
466-
}
410+
$this->connectMySql($connectionString, $timeZoneOffset, $charset);
467411
}
468412
// If the database type is neither MySQL nor PostgreSQL, throw an exception
469413
else {
@@ -480,22 +424,112 @@ private function connectRDMS($withDatabase = true)
480424
}
481425
return $connected;
482426
}
427+
428+
/**
429+
* Establish a connection to a MySQL or MariaDB database.
430+
*
431+
* This method sets up a connection to a MySQL or MariaDB database, configuring the time zone
432+
* and character set (charset) as needed. It runs initial queries to set the correct time zone
433+
* and charset, and then establishes a PDO connection to the database.
434+
*
435+
* @param string $connectionString The connection string used to connect to the database.
436+
* @param string $timeZoneOffset The time zone offset to be used in the database session.
437+
* @param string $charset The character set (charset) to be used for the database connection.
438+
*
439+
* @return void
440+
*
441+
* @throws PDOException If there is an error while establishing the connection or executing the initial queries.
442+
*/
443+
private function connectMySql($connectionString, $timeZoneOffset, $charset)
444+
{
445+
$initialQueries = array();
446+
// Set time zone for MySQL
447+
$initialQueries[] = "SET time_zone='$timeZoneOffset';";
448+
449+
// Add charset to the initial queries for MySQL
450+
if ($charset) {
451+
$initialQueries[] = "SET NAMES '$charset';"; // Set charset for MySQL
452+
}
453+
454+
// MySQL connection setup
455+
$this->databaseConnection = new PDO(
456+
$connectionString,
457+
$this->databaseCredentials->getUsername(),
458+
$this->databaseCredentials->getPassword(),
459+
[
460+
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
461+
PDO::MYSQL_ATTR_FOUND_ROWS => true
462+
]
463+
);
464+
465+
if (!empty($initialQueries)) {
466+
foreach($initialQueries as $initialQuery)
467+
{
468+
$this->databaseConnection->exec($initialQuery);
469+
}
470+
}
471+
}
472+
473+
/**
474+
* Establish a connection to a PostgreSQL database.
475+
*
476+
* This method sets up a connection to a PostgreSQL database, configuring the time zone,
477+
* character set (charset), and schema (search path) as needed. It runs initial queries
478+
* to set the correct time zone, charset, and schema for the session, and then establishes
479+
* a PDO connection to the database.
480+
*
481+
* @param string $connectionString The connection string used to connect to the PostgreSQL database.
482+
* @param string $timeZoneOffset The time zone offset to be used in the database session.
483+
* @param string $charset The character set (charset) to be used for the PostgreSQL connection.
484+
*
485+
* @return void
486+
*
487+
* @throws PDOException If there is an error while establishing the connection or executing the initial queries.
488+
*/
489+
private function connectPostgreSql($connectionString, $timeZoneOffset, $charset)
490+
{
491+
$initialQueries = array();
492+
// Set time zone for PostgreSQL
493+
$initialQueries[] = "SET TIMEZONE TO '$timeZoneOffset';";
494+
495+
// Set the client encoding (charset) for PostgreSQL
496+
if (isset($charset) && !empty($charset)) {
497+
$initialQueries[] = "SET CLIENT_ENCODING TO '$charset';";
498+
}
499+
500+
// Set schema if provided for PostgreSQL
501+
if ($this->databaseCredentials->getDatabaseSchema() != null && $this->databaseCredentials->getDatabaseSchema() != "") {
502+
$initialQueries[] = "SET search_path TO " . $this->databaseCredentials->getDatabaseSchema() . ";";
503+
}
504+
505+
// PostgreSQL connection setup
506+
$this->databaseConnection = new PDO(
507+
$connectionString,
508+
$this->databaseCredentials->getUsername(),
509+
$this->databaseCredentials->getPassword(),
510+
[
511+
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
512+
]
513+
);
514+
515+
// Execute the initial queries (timezone, charset, schema) in PostgreSQL
516+
if (!empty($initialQueries)) {
517+
foreach($initialQueries as $initialQuery)
518+
{
519+
$this->databaseConnection->exec($initialQuery);
520+
}
521+
}
522+
}
483523

484524
/**
485-
* Determine the database type based on the provided database type string.
486-
*
487-
* This method evaluates the given string to identify common database type names
488-
* (e.g., SQLite, PostgreSQL, MariaDB, MySQL) and returns the corresponding
489-
* constant from the `PicoDatabaseType` class that represents the type of database.
490-
* The function performs case-insensitive string matching using `stripos` to check for
491-
* keywords like "sqlite", "postgre", "pgsql", "maria", and defaults to MySQL if no match is found.
492-
*
493-
* @param string $databaseType The database type string to evaluate, such as 'SQLite', 'PostgreSQL', 'MariaDB', or 'MySQL'.
494-
* @return string The corresponding database type constant from `PicoDatabaseType`:
495-
* - `PicoDatabaseType::DATABASE_TYPE_SQLITE`
496-
* - `PicoDatabaseType::DATABASE_TYPE_PGSQL`
497-
* - `PicoDatabaseType::DATABASE_TYPE_MARIADB`
498-
* - `PicoDatabaseType::DATABASE_TYPE_MYSQL`
525+
* Determine the database type from a string.
526+
*
527+
* This method evaluates the provided string to identify common database types (e.g., SQLite, PostgreSQL, MariaDB, MySQL)
528+
* and returns the corresponding constant from the `PicoDatabaseType` class.
529+
*
530+
* @param string $databaseType The database type string (e.g., 'SQLite', 'PostgreSQL', 'MariaDB', 'MySQL').
531+
* @return string The corresponding `PicoDatabaseType` constant.
532+
* @throws UnsupportedDatabaseException If the database type is unsupported.
499533
*/
500534
private static function getDbType($databaseType) // NOSONAR
501535
{
@@ -511,10 +545,14 @@ private static function getDbType($databaseType) // NOSONAR
511545
{
512546
return PicoDatabaseType::DATABASE_TYPE_MARIADB;
513547
}
514-
else
548+
else if(stripos($databaseType, 'mysql') !== false)
515549
{
516550
return PicoDatabaseType::DATABASE_TYPE_MYSQL;
517551
}
552+
else
553+
{
554+
throw new UnsupportedDatabaseException("Unsupported database type: $databaseType");
555+
}
518556
}
519557

520558
/**
@@ -643,6 +681,20 @@ public function setAudoCommit($autocommit)
643681
return $this->databaseConnection->setAttribute(PDO::ATTR_AUTOCOMMIT, $this->autocommit ? 1 : 0);
644682
}
645683

684+
/**
685+
* Start a new database transaction.
686+
*
687+
* This method begins a new transaction, allowing subsequent database operations
688+
* to be grouped together. The changes made during the transaction are not permanent
689+
* until the transaction is committed.
690+
*
691+
* @return bool Returns `true` if the transaction was successfully started, `false` otherwise.
692+
*/
693+
public function startTransaction()
694+
{
695+
return $this->databaseConnection->query((new PicoDatabaseQueryBuilder($this))->startTransaction());
696+
}
697+
646698
/**
647699
* Commit the current transaction.
648700
*
@@ -652,7 +704,7 @@ public function setAudoCommit($autocommit)
652704
*/
653705
public function commit()
654706
{
655-
return $this->databaseConnection->commit();
707+
return $this->databaseConnection->query((new PicoDatabaseQueryBuilder($this))->commit());
656708
}
657709

658710
/**
@@ -664,7 +716,7 @@ public function commit()
664716
*/
665717
public function rollback()
666718
{
667-
return $this->databaseConnection->rollback();
719+
return $this->databaseConnection->query((new PicoDatabaseQueryBuilder($this))->rollback());
668720
}
669721

670722
/**
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
namespace MagicObject\Exceptions;
3+
4+
use Exception;
5+
use Throwable;
6+
7+
/**
8+
* Class UnsupportedDatabaseException
9+
*
10+
* Custom exception class for handling null reference errors
11+
* in the application. This exception is typically thrown when
12+
* an operation is attempted on a variable that is null,
13+
* indicating that the application is trying to access or modify
14+
* an object or variable that has not been initialized.
15+
* This exception helps in identifying issues related to null
16+
* values, ensuring better debugging and error handling.
17+
*
18+
* @author Kamshory
19+
* @package MagicObject\Exceptions
20+
* @link https://github.com/Planetbiru/MagicObject
21+
*/
22+
class UnsupportedDatabaseException extends Exception
23+
{
24+
/**
25+
* Previous exception
26+
*
27+
* @var Throwable|null
28+
*/
29+
private $previous;
30+
31+
/**
32+
* Constructor for UnsupportedDatabaseException.
33+
*
34+
* @param string $message Exception message
35+
* @param int $code Exception code
36+
* @param Throwable|null $previous Previous exception
37+
*/
38+
public function __construct($message, $code = 0, $previous = null)
39+
{
40+
parent::__construct($message, $code, $previous);
41+
$this->previous = $previous;
42+
}
43+
44+
/**
45+
* Get the previous exception.
46+
*
47+
* @return Throwable|null
48+
*/
49+
public function getPreviousException()
50+
{
51+
return $this->previous;
52+
}
53+
}

0 commit comments

Comments
 (0)