88use PDOStatement ;
99use MagicObject \Exceptions \InvalidDatabaseConfiguration ;
1010use MagicObject \Exceptions \NullPointerException ;
11+ use MagicObject \Exceptions \UnsupportedDatabaseException ;
1112use MagicObject \SecretObject ;
1213use ReflectionFunction ;
1314use 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 /**
0 commit comments